-
-
Save andrewcchen/f16eb20d19ea64d9f997c470e2addeaa to your computer and use it in GitHub Desktop.
| /* | |
| Encode an NEC IR command into code for Tuya ZS06/ZS08/TS1201 | |
| Usage: encode_nec("<four bytes in hex, two bytes of address followed by two bytes of command>") | |
| If your address and/or command is just one byte (8 bits), append the complement of the byte after it to make it two bytes. | |
| Example: | |
| encode_nec("04fb08f7") // encodes nec address 0x04 and command 0x08 | |
| See: | |
| https://www.sbprojects.net/knowledge/ir/nec.php | |
| https://www.zigbee2mqtt.io/devices/ZS06.html | |
| https://github.com/Koenkk/zigbee2mqtt/issues/11633 | |
| mildsunrise describes how the encoding works in: | |
| https://gist.github.com/mildsunrise/1d576669b63a260d2cff35fda63ec0b5 | |
| In short, the signal is described in terms of alternating on/off (first on) times in microseconds encoded in little-endian 16-bit integers, which is then compressed with FastLZ. | |
| This encoded only generates literal blocks, which are up to 32 bytes of data long each, prefixed by a 1 byte length field. | |
| */ | |
| function encode_nec(hex) { | |
| function le(x) { | |
| x = x & 0xffff; | |
| return [ x & 0xff, x >> 8 ]; | |
| } | |
| // for NECx2 devices (e.g. samsung tv) replace 9000 with 4500 | |
| let output = [ 4-1, ...le(9000), ...le(4500) ]; | |
| for (const x of Buffer.from(hex, 'hex')) { | |
| output.push(32-1); | |
| for (let i = 0; i < 8; i++) { | |
| output.push(...le(560)); | |
| if (x & (1 << i)) { | |
| output.push(...le(2250-560)); | |
| } else { | |
| output.push(...le(1125-560)); | |
| } | |
| } | |
| } | |
| output.push(2-1, ...le(560)); | |
| return Buffer.from(new Uint8Array(output)).toString('base64'); | |
| } |
I found a description of the broadlink encoding here: https://www.reddit.com/r/homeassistant/comments/pl03cj/add_custom_codes_to_broadlink/hc8n0dj
Looks like it's also encoding the duration of the pulses, so you don't have to decoded it fully to nec commands, instead you can decode it to pulse duration, and encode it for tuya like I described in the comment above (please do note for tuya the max length of a block is 32 bytes).
I tried to test it with Tuya TS1201 for DUNE HD Player and failed. @andrewcchen, could you please prompt me where I was wrong?
The documentation of Dune HD player says:
All Dune HD IR Remotes use NEC IR protocol. Different generations of Remotes use different NEC IR customer codes:
...
Previous generation (Premium IR Remote + discontinued models): 00 BF
...
IR HEX codes (latest Remote models use CF CF instead 00 BF):
...
POWER 00 BF 43 BC
I called the script with "00bf32bc" and it returned "AygjlBEfMAI1AjACNQIwAjUCMAI1AjACNQIwAjUCMAI1AjACNQIfMAKaBjACmgYwApoGMAKaBjACmgYwApoGMAI1AjACmgYfMAKaBjACmgYwAjUCMAI1AjACNQIwAjUCMAKaBjACNQIfMAI1AjACNQIwApoGMAKaBjACmgYwApoGMAI1AjACmgYBMAI=". I sent it but DUNE HD Player did not respond. I tried "cfcf43bc" and "01be43bc", but it did not help as well.
The sequence generated by the script does not look like the sequence I captured: "B08jRhFwAvsB4BUDAVwG4A0DQDfgAxtAD+ADA0Ab4AcPQBPAAwf7AXACXAZwAg==".
@mak-42 Some codes online have bit endian order swapped (per byte), try 00df2cd3
The captured sequences uses commands that I haven't managed to decoded to encode more efficiently.
Thank you for the answer. I tried "00df2cd3" (AygjlBEfMAI1AjACNQIwAjUCMAI1AjACNQIwAjUCMAI1AjACNQIfMAKaBjACmgYwApoGMAKaBjACmgYwAjUCMAKaBjACmgYfMAI1AjACNQIwApoGMAKaBjACNQIwApoGMAI1AjACNQIfMAKaBjACmgYwAjUCMAI1AjACmgYwAjUCMAKaBjACmgYBMAI=), "3f3f2cd3" (AygjlBEfMAKaBjACmgYwApoGMAKaBjACmgYwApoGMAI1AjACNQIfMAKaBjACmgYwApoGMAKaBjACmgYwApoGMAI1AjACNQIfMAI1AjACNQIwApoGMAKaBjACNQIwApoGMAI1AjACNQIfMAKaBjACmgYwAjUCMAI1AjACmgYwAjUCMAKaBjACmgYBMAI=) and "08d72cd3" (AygjlBEfMAI1AjACNQIwAjUCMAKaBjACNQIwAjUCMAI1AjACNQIfMAKaBjACmgYwApoGMAI1AjACmgYwAjUCMAKaBjACmgYfMAI1AjACNQIwApoGMAKaBjACNQIwApoGMAI1AjACNQIfMAKaBjACmgYwAjUCMAI1AjACmgYwAjUCMAKaBjACmgYBMAI=). The last one is a representation "01be34bc" used by very old DUNE players. Unfortunately, the player didn't respond for any of the sequences.
Just used this to convert the Loxjie D30/A30 DAC IR codes and worked like a charm, thanks!
I've added this line to the bottom of the script for easier usage:
console.log(encode_nec(process.argv));
Then copy pasted it onto https://stackblitz.com/edit/node-trcord?file=index.js
Reference:
https://www.audiosciencereview.com/forum/index.php?attachments/1630327364341-png.150422/
volume down:
node index.js 22220Ff7
volume up:
node index.js 22220Ef7
power:
node index.js 222201f7
input:
node index.js 222207f7
for anyone landing here: I've managed to understand the weird compression scheme used by this thing!
I've documented everything here:
https://gist.github.com/mildsunrise/1d576669b63a260d2cff35fda63ec0b5
and also provided a function to decompress the signal in case someone wants to investigate what's in their learnt codes.
Do you know if it would be possible to somehow convert Broadlink B64 commands to Tuya ZS06/ZS08/TS1201 commands? I tried using an online convert but haven't found a way to get Broadlink commands into NEC format for me to then use your code to convert it to work with the Tuya IR device.
Would be handy as I have a fair amount of Broadlink RM codes in Home Assistant already. It would mean I wouldn't have to get out all the remotes and teach the Tuya device the IR codes.