-
-
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 | |
Tuya ZS06 uses a custom encoding of ir codes. I figured enough of the encoding to generate arbitary ir codes, but there are additional encoding features to save bytes that I haven't figured out. | |
The encoding is base64 encoding of any number of concatenated command blocks, where each block is: | |
- 1 byte of [length]-1 (length <= 32 bytes is supported) | |
- [length] number of bytes of little endian 16 bit integers | |
- Each integer describes the length of time in microseconds to keep the tramsitter's current on/off state, before flipping | |
The initial state is on, so the first 16 bit integer describes on time, the second off time, the third on time again, etc. | |
*/ | |
function encode_nec(hex) { | |
function le(x) { | |
x = x & 0xffff; | |
return [ x & 0xff, x >> 8 ]; | |
} | |
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'); | |
} |
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.
@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.