Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for newer IR devices, and several IR format converters #228

Merged
merged 4 commits into from
Dec 3, 2022

Conversation

uzlonewolf
Copy link
Collaborator

Also adds set_multiple_values() to core as the newer devices require everything to be in one packet. I also updated turn_on() and turn_off() to return the received data instead of just dropping it on the floor while I was in there.

Documentation for new format converters and head/key sending in examples/Contrib/IRRemoteControlDevice-example.py

Closes #225 and I'm also going to say Closes #74 and Closes #27

@anar4732
Copy link

anar4732 commented Dec 2, 2022

thank you for the patch! it looks like work but sometimes i see this error on console. idk if it is about this or not.

DEBUG:Network connection error in _send_receive() - retry 1/5
Traceback (most recent call last):
  File "C:\Users\ANAR\AppData\Local\Programs\Python\Python310\lib\site-packages\tinytuya\core.py", line 795, in _send_receive
    rmsg = self._receive()
  File "C:\Users\ANAR\AppData\Local\Programs\Python\Python310\lib\site-packages\tinytuya\core.py", line 712, in _receive
    data = self._recv_all(header_len+ret_end_len)
  File "C:\Users\ANAR\AppData\Local\Programs\Python\Python310\lib\site-packages\tinytuya\core.py", line 690, in _recv_all
    newdata = self.socket.recv(length)
ConnectionResetError: [WinError 10054] an existing connection was forcibly closed by the remote host

@uzlonewolf
Copy link
Collaborator Author

@anar4732 Yeah, sometimes the devices just close the connection for no apparent reason. I have no idea why they do that, but tinytuya sees it and retries automatically so it's not a big deal.

@jasonacox jasonacox merged commit ce0e428 into jasonacox:master Dec 3, 2022
@@ -1391,13 +1391,27 @@ def set_value(self, index, value, nowait=False):

return data

def set_multiple_values(self, data, nowait=False):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love this. Was on my old TODO so thank you! ;) I also think there was an issue for this - I'll see if I can find it.

@uzlonewolf uzlonewolf deleted the ir-format-convert branch December 4, 2022 11:50
@Xmister
Copy link

Xmister commented Apr 28, 2023

@uzlonewolf Sorry for the ping, but how hard would it be to add support for RF devices? Based on https://github.com/tuya-cloudcutter/tuya-cloudcutter.github.io/blob/3736ae997a30db7e8c379dd5472521922f6cd43f/devices/tuya-generic-ir-rf-universal-remote-controller-v2.0.8.json they must use the same DPS for RF as well.

@uzlonewolf
Copy link
Collaborator Author

@Xmister I'm not sure if you're asking about cloud or local. Local already works for both Zigbee and Bluetooth sub-devices so I would expect it to work for RF devices as well. Does https://github.com/jasonacox/tinytuya/blob/master/examples/zigbee_gateway.py do anything?

@Xmister
Copy link

Xmister commented Apr 30, 2023

@uzlonewolf I'm talking about local, but I was more interested in learning/sending raw 433MHz codes, like how this IR module does, instead of interacting with an already set up gw-child pair. (My ir-rf gateway is cut from the cloud, so I can't set up subdevices anymore)

@uzlonewolf
Copy link
Collaborator Author

Ah, I see what you mean now. I was thinking they were RF devices similar to how the Zigbee ones work.

It shouldn't be too hard to add, though I'm going to need a packet capture and/or a firmware dump to figure out the protocol. I know yours is cut from the cloud, but does it have any RF devices stored?

@Xmister
Copy link

Xmister commented May 1, 2023

Sadly, no. I was trying libretuya-esphome on it, but didn't realise it doesn't yet support spi on these devices, so communicating with the SH4 radio module is not possible.
I was able to get a factory app firmware without the device specific bits, so I can use tinytuya now for local control.
Would this firmware help in any way?
I've ordered a similar device for the same reason, so that I might be able to sniff the protocol somehow. But it will be weeks until it arrives.

@uzlonewolf
Copy link
Collaborator Author

As long as it has the JSON parsing bits in it it should work. I'm currently digging through my universal hub firmware dump to see if it knows about the RF commands, and I have a IR+RF gateway coming from Amazon in a couple days https://www.amazon.com/gp/product/B0BY2C68BJ/

@Xmister
Copy link

Xmister commented May 1, 2023

@uzlonewolf
Copy link
Collaborator Author

Making some progress. Looks like if you set the key rf_type (any value, it's not actually looked at) it puts the parser into RF mode. The command is then in the control key with the options rf_study, rfstudy_exit, rfstudy_send, send_pair, and send_cmd. Still looking into what data those commands expect.

@Xmister
Copy link

Xmister commented May 1, 2023

Since, this is a 2 band RF controller, I guess rf_study_feq would set the actual frequency to listen/send over. (315 vs 433). I've also seen rf_shortstudy when running strings over the binary.
How do you set rf_type is that over the 201 DP as well?
If you wish I can open a port for you to connect to my device with tinytuya until you have your own.

@uzlonewolf
Copy link
Collaborator Author

uzlonewolf commented May 1, 2023 via email

@uzlonewolf
Copy link
Collaborator Author

Ok, my device came in and I was able to get some packet captures.

First, I added 2 random curtains to see what "known device" data looks like:

 to   'eb####tb' v3.3 cmd: 13 (0D) len(543)  b'...{"dps":{"201":"{\\"rf_type\\":\\"sub_2g\\",\\"mode\\":8,\\"key1\\":{\\"code\\":\\"ffffc01fa4934924924924924d34924da4936db0\\",\\"delay\\":0,\\"intervals\\":0,\\"times\\":5},\\"feq\\":0,\\"rate\\":0,\\"cfg\\":{\\"b\\":[2,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,96,255,0,0,31,16],\\"c\\":[0,102,236,28,240,128,20,8,145,2,2,208],\\"s\\":[174,224,53,0,0,244,16,226,66,32,0,129],\\"d\\":[63,30,128,204,0,0,0,0,0,0,0,41,192,218,33,75,5,0,80,45,0,1,5,5],\\"t\\":[81,154,12,0,12,176,0,31,4,63,127],\\"f\\":[66,113,206,28,66,91,28,28]},\\"control\\":\\"send_pair\\"}"}}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(575)  b'...{"dps":{"201":"{\\"rf_type\\":\\"sub_2g\\",\\"mode\\":2,\\"key1\\":{\\"code\\":\\"924924fffcd349369249249249249269249a4924924924924d369a6d36c000\\",\\"delay\\":0,\\"intervals\\":0,\\"times\\":6},\\"feq\\":0,\\"rate\\":0,\\"cfg\\":{\\"b\\":[2,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,96,255,2,0,31,16],\\"c\\":[0,102,236,28,240,128,20,8,145,2,2,208],\\"s\\":[174,224,53,0,0,244,16,226,66,32,0,129],\\"d\\":[71,34,144,204,0,0,0,0,0,0,0,41,192,223,29,91,7,0,80,45,0,1,6,6],\\"t\\":[81,38,3,0,10,176,0,31,4,63,127],\\"f\\":[66,166,231,28,66,144,53,28]},\\"control\\":\\"send_pair\\"}"}}'

After that I mashed the buttons a bit:

 to   'eb####tb' v3.3 cmd: 13 (0D) len(543)  b'...{"dps":{"201":"{\\"rf_type\\":\\"sub_2g\\",\\"mode\\":8,\\"key1\\":{\\"code\\":\\"ffffc01fa4934924924924934934924da4926930\\",\\"delay\\":0,\\"intervals\\":0,\\"times\\":5},\\"feq\\":0,\\"rate\\":0,\\"cfg\\":{\\"b\\":[2,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,96,255,0,0,31,16],\\"c\\":[0,102,236,28,240,128,20,8,145,2,2,208],\\"s\\":[174,224,53,0,0,244,16,226,66,32,0,129],\\"d\\":[63,30,128,204,0,0,0,0,0,0,0,41,192,218,33,75,5,0,80,45,0,1,5,5],\\"t\\":[81,154,12,0,12,176,0,31,4,63,127],\\"f\\":[66,113,206,28,66,91,28,28]},\\"control\\":\\"send_cmd\\"}"}}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(543)  b'...{"dps":{"201":"{\\"rf_type\\":\\"sub_2g\\",\\"mode\\":8,\\"key1\\":{\\"code\\":\\"ffffc01fa4934924924924924db4924da4936d30\\",\\"delay\\":0,\\"intervals\\":0,\\"times\\":5},\\"feq\\":0,\\"rate\\":0,\\"cfg\\":{\\"b\\":[2,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,96,255,0,0,31,16],\\"c\\":[0,102,236,28,240,128,20,8,145,2,2,208],\\"s\\":[174,224,53,0,0,244,16,226,66,32,0,129],\\"d\\":[63,30,128,204,0,0,0,0,0,0,0,41,192,218,33,75,5,0,80,45,0,1,5,5],\\"t\\":[81,154,12,0,12,176,0,31,4,63,127],\\"f\\":[66,113,206,28,66,91,28,28]},\\"control\\":\\"send_cmd\\"}"}}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(543)  b'...{"dps":{"201":"{\\"rf_type\\":\\"sub_2g\\",\\"mode\\":8,\\"key1\\":{\\"code\\":\\"ffffc01fa4934924924924934d34924da4926db0\\",\\"delay\\":0,\\"intervals\\":0,\\"times\\":5},\\"feq\\":0,\\"rate\\":0,\\"cfg\\":{\\"b\\":[2,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,96,255,0,0,31,16],\\"c\\":[0,102,236,28,240,128,20,8,145,2,2,208],\\"s\\":[174,224,53,0,0,244,16,226,66,32,0,129],\\"d\\":[63,30,128,204,0,0,0,0,0,0,0,41,192,218,33,75,5,0,80,45,0,1,5,5],\\"t\\":[81,154,12,0,12,176,0,31,4,63,127],\\"f\\":[66,113,206,28,66,91,28,28]},\\"control\\":\\"send_cmd\\"}"}}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(543)  b'...{"dps":{"201":"{\\"rf_type\\":\\"sub_2g\\",\\"mode\\":8,\\"key1\\":{\\"code\\":\\"ffffc01fa4934924924924934934924da4926930\\",\\"delay\\":0,\\"intervals\\":0,\\"times\\":5},\\"feq\\":0,\\"rate\\":0,\\"cfg\\":{\\"b\\":[2,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,96,255,0,0,31,16],\\"c\\":[0,102,236,28,240,128,20,8,145,2,2,208],\\"s\\":[174,224,53,0,0,244,16,226,66,32,0,129],\\"d\\":[63,30,128,204,0,0,0,0,0,0,0,41,192,218,33,75,5,0,80,45,0,1,5,5],\\"t\\":[81,154,12,0,12,176,0,31,4,63,127],\\"f\\":[66,113,206,28,66,91,28,28]},\\"control\\":\\"send_cmd\\"}"}}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(543)  b'...{"dps":{"201":"{\\"rf_type\\":\\"sub_2g\\",\\"mode\\":8,\\"key1\\":{\\"code\\":\\"ffffc01fa4934924924924934d34924da4926db0\\",\\"delay\\":0,\\"intervals\\":0,\\"times\\":5},\\"feq\\":0,\\"rate\\":0,\\"cfg\\":{\\"b\\":[2,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,96,255,0,0,31,16],\\"c\\":[0,102,236,28,240,128,20,8,145,2,2,208],\\"s\\":[174,224,53,0,0,244,16,226,66,32,0,129],\\"d\\":[63,30,128,204,0,0,0,0,0,0,0,41,192,218,33,75,5,0,80,45,0,1,5,5],\\"t\\":[81,154,12,0,12,176,0,31,4,63,127],\\"f\\":[66,113,206,28,66,91,28,28]},\\"control\\":\\"send_cmd\\"}"}}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(543)  b'...{"dps":{"201":"{\\"rf_type\\":\\"sub_2g\\",\\"mode\\":8,\\"key1\\":{\\"code\\":\\"ffffc01fa49349249249249249b4924da49369b0\\",\\"delay\\":0,\\"intervals\\":0,\\"times\\":5},\\"feq\\":0,\\"rate\\":0,\\"cfg\\":{\\"b\\":[2,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,96,255,0,0,31,16],\\"c\\":[0,102,236,28,240,128,20,8,145,2,2,208],\\"s\\":[174,224,53,0,0,244,16,226,66,32,0,129],\\"d\\":[63,30,128,204,0,0,0,0,0,0,0,41,192,218,33,75,5,0,80,45,0,1,5,5],\\"t\\":[81,154,12,0,12,176,0,31,4,63,127],\\"f\\":[66,113,206,28,66,91,28,28]},\\"control\\":\\"send_cmd\\"}"}}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(543)  b'...{"dps":{"201":"{\\"rf_type\\":\\"sub_2g\\",\\"mode\\":8,\\"key1\\":{\\"code\\":\\"ffffc01fa49349249249249249b4924da49369b0\\",\\"delay\\":0,\\"intervals\\":0,\\"times\\":5},\\"feq\\":0,\\"rate\\":0,\\"cfg\\":{\\"b\\":[2,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,96,255,0,0,31,16],\\"c\\":[0,102,236,28,240,128,20,8,145,2,2,208],\\"s\\":[174,224,53,0,0,244,16,226,66,32,0,129],\\"d\\":[63,30,128,204,0,0,0,0,0,0,0,41,192,218,33,75,5,0,80,45,0,1,5,5],\\"t\\":[81,154,12,0,12,176,0,31,4,63,127],\\"f\\":[66,113,206,28,66,91,28,28]},\\"control\\":\\"send_cmd\\"}"}}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(543)  b'...{"dps":{"201":"{\\"rf_type\\":\\"sub_2g\\",\\"mode\\":8,\\"key1\\":{\\"code\\":\\"ffffc01fa4934924924924924db4924da4936d30\\",\\"delay\\":0,\\"intervals\\":0,\\"times\\":5},\\"feq\\":0,\\"rate\\":0,\\"cfg\\":{\\"b\\":[2,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,96,255,0,0,31,16],\\"c\\":[0,102,236,28,240,128,20,8,145,2,2,208],\\"s\\":[174,224,53,0,0,244,16,226,66,32,0,129],\\"d\\":[63,30,128,204,0,0,0,0,0,0,0,41,192,218,33,75,5,0,80,45,0,1,5,5],\\"t\\":[81,154,12,0,12,176,0,31,4,63,127],\\"f\\":[66,113,206,28,66,91,28,28]},\\"control\\":\\"send_cmd\\"}"}}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(543)  b'...{"dps":{"201":"{\\"rf_type\\":\\"sub_2g\\",\\"mode\\":8,\\"key1\\":{\\"code\\":\\"ffffc01fa4934924924924934d34924da4926db0\\",\\"delay\\":0,\\"intervals\\":0,\\"times\\":5},\\"feq\\":0,\\"rate\\":0,\\"cfg\\":{\\"b\\":[2,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,96,255,0,0,31,16],\\"c\\":[0,102,236,28,240,128,20,8,145,2,2,208],\\"s\\":[174,224,53,0,0,244,16,226,66,32,0,129],\\"d\\":[63,30,128,204,0,0,0,0,0,0,0,41,192,218,33,75,5,0,80,45,0,1,5,5],\\"t\\":[81,154,12,0,12,176,0,31,4,63,127],\\"f\\":[66,113,206,28,66,91,28,28]},\\"control\\":\\"send_cmd\\"}"}}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(543)  b'...{"dps":{"201":"{\\"rf_type\\":\\"sub_2g\\",\\"mode\\":8,\\"key1\\":{\\"code\\":\\"ffffc01fa4934924924924934934924da4926930\\",\\"delay\\":0,\\"intervals\\":0,\\"times\\":5},\\"feq\\":0,\\"rate\\":0,\\"cfg\\":{\\"b\\":[2,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,96,255,0,0,31,16],\\"c\\":[0,102,236,28,240,128,20,8,145,2,2,208],\\"s\\":[174,224,53,0,0,244,16,226,66,32,0,129],\\"d\\":[63,30,128,204,0,0,0,0,0,0,0,41,192,218,33,75,5,0,80,45,0,1,5,5],\\"t\\":[81,154,12,0,12,176,0,31,4,63,127],\\"f\\":[66,113,206,28,66,91,28,28]},\\"control\\":\\"send_cmd\\"}"}}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(543)  b'...{"dps":{"201":"{\\"rf_type\\":\\"sub_2g\\",\\"mode\\":8,\\"key1\\":{\\"code\\":\\"ffffc01fa4934924924924934d34924da4926db0\\",\\"delay\\":0,\\"intervals\\":0,\\"times\\":5},\\"feq\\":0,\\"rate\\":0,\\"cfg\\":{\\"b\\":[2,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,96,255,0,0,31,16],\\"c\\":[0,102,236,28,240,128,20,8,145,2,2,208],\\"s\\":[174,224,53,0,0,244,16,226,66,32,0,129],\\"d\\":[63,30,128,204,0,0,0,0,0,0,0,41,192,218,33,75,5,0,80,45,0,1,5,5],\\"t\\":[81,154,12,0,12,176,0,31,4,63,127],\\"f\\":[66,113,206,28,66,91,28,28]},\\"control\\":\\"send_cmd\\"}"}}'

Then I learned a 2-button remote. After learning each key it had me test them:

 to   'eb####tb' v3.3 cmd: 13 (0D) len(127)  b'...{"dps":{"201":"{\\"rf_type\\":\\"sub_2g\\",\\"control\\":\\"rf_study\\",\\"study_feq\\":\\"433\\",\\"ver\\":\\"2\\"}"}}'
 from 'eb####tb' v3.3 cmd:  8 (08) len(319)  b'...{"dps":{"202":"eyJudW0iOjEsInZlciI6IjIiLCJzdHVkeV9mZXEiOiI0MzMiLCJkYXRhMCI6InRpU2RBek1CTXdHZEE1MERNd0V6QVowRG5RTXpBVE1CblFNekFaMERNd0dkQTUwRE13RXpBWjBEblFNekFaMERNd0V6QVowRE13R2RBek1CblFPZEF6TUJuUU16QVRNQm5RT2RBek1CTXdHZEF6TUJuUU16QVowRE13R2RBNTBETXdFekFRPT0iLCJsdiI6WzBdfQ=="},"t":1683050684}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(127)  b'...{"dps":{"201":"{\\"rf_type\\":\\"sub_2g\\",\\"control\\":\\"rfstudy_exit\\",\\"study_feq\\":\\"433\\",\\"ver\\":\\"2\\"}"}}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(127)  b'...{"dps":{"201":"{\\"rf_type\\":\\"sub_2g\\",\\"control\\":\\"rfstudy_exit\\",\\"study_feq\\":\\"433\\",\\"ver\\":\\"2\\"}"}}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(463)  b'...{"dps":{"201":"{\\"ver\\":\\"2\\",\\"rf_type\\":\\"sub_2g\\",\\"control\\":\\"rfstudy_send\\",\\"study_feq\\":\\"433\\",\\"key1\\":{\\"code\\":\\"eyJudW0iOjEsInZlciI6IjIiLCJzdHVkeV9mZXEiOiI0MzMiLCJkYXRhMCI6InRpU2RBek1CTXdHZEE1MERNd0V6QVowRG5RTXpBVE1CblFNekFaMERNd0dkQTUwRE13RXpBWjBEblFNekFaMERNd0V6QVowRE13R2RBek1CblFPZEF6TUJuUU16QVRNQm5RT2RBek1CTXdHZEF6TUJuUU16QVowRE13R2RBNTBETXdFekFRPT0iLCJsdiI6WzBdfQ==\\",\\"times\\":6,\\"delay\\":0,\\"intervals\\":0}}"}}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(463)  b'...{"dps":{"201":"{\\"ver\\":\\"2\\",\\"rf_type\\":\\"sub_2g\\",\\"control\\":\\"rfstudy_send\\",\\"study_feq\\":\\"433\\",\\"key1\\":{\\"code\\":\\"eyJudW0iOjEsInZlciI6IjIiLCJzdHVkeV9mZXEiOiI0MzMiLCJkYXRhMCI6InRpU2RBek1CTXdHZEE1MERNd0V6QVowRG5RTXpBVE1CblFNekFaMERNd0dkQTUwRE13RXpBWjBEblFNekFaMERNd0V6QVowRE13R2RBek1CblFPZEF6TUJuUU16QVRNQm5RT2RBek1CTXdHZEF6TUJuUU16QVowRE13R2RBNTBETXdFekFRPT0iLCJsdiI6WzBdfQ==\\",\\"times\\":6,\\"delay\\":0,\\"intervals\\":0}}"}}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(127)  b'...{"dps":{"201":"{\\"rf_type\\":\\"sub_2g\\",\\"control\\":\\"rfstudy_exit\\",\\"study_feq\\":\\"433\\",\\"ver\\":\\"2\\"}"}}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(127)  b'...{"dps":{"201":"{\\"rf_type\\":\\"sub_2g\\",\\"control\\":\\"rf_study\\",\\"study_feq\\":\\"433\\",\\"ver\\":\\"2\\"}"}}'
 from 'eb####tb' v3.3 cmd:  8 (08) len(319)  b'...{"dps":{"202":"eyJudW0iOjEsInZlciI6IjIiLCJzdHVkeV9mZXEiOiI0MzMiLCJkYXRhMCI6Ind5U2RBelFCTkFHZEE1MEROQUUwQVowRG5RTTBBVFFCblFNMEFaMEROQUdkQTUwRE5BRTBBWjBEblFNMEFaMEROQUUwQVowRE5BR2RBelFCblFPZEF6UUJuUU5YQVRRQm5RT2RBelFCTkFHZEF6UUJuUU0wQVowRG5RTlhBVFFCblFNMEFRPT0iLCJsdiI6WzBdfQ=="},"t":1683050700}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(127)  b'...{"dps":{"201":"{\\"rf_type\\":\\"sub_2g\\",\\"control\\":\\"rfstudy_exit\\",\\"study_feq\\":\\"433\\",\\"ver\\":\\"2\\"}"}}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(127)  b'...{"dps":{"201":"{\\"rf_type\\":\\"sub_2g\\",\\"control\\":\\"rfstudy_exit\\",\\"study_feq\\":\\"433\\",\\"ver\\":\\"2\\"}"}}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(463)  b'...{"dps":{"201":"{\\"ver\\":\\"2\\",\\"rf_type\\":\\"sub_2g\\",\\"control\\":\\"rfstudy_send\\",\\"study_feq\\":\\"433\\",\\"key1\\":{\\"code\\":\\"eyJudW0iOjEsInZlciI6IjIiLCJzdHVkeV9mZXEiOiI0MzMiLCJkYXRhMCI6Ind5U2RBelFCTkFHZEE1MEROQUUwQVowRG5RTTBBVFFCblFNMEFaMEROQUdkQTUwRE5BRTBBWjBEblFNMEFaMEROQUUwQVowRE5BR2RBelFCblFPZEF6UUJuUU5YQVRRQm5RT2RBelFCTkFHZEF6UUJuUU0wQVowRG5RTlhBVFFCblFNMEFRPT0iLCJsdiI6WzBdfQ==\\",\\"times\\":6,\\"delay\\":0,\\"intervals\\":0}}"}}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(463)  b'...{"dps":{"201":"{\\"ver\\":\\"2\\",\\"rf_type\\":\\"sub_2g\\",\\"control\\":\\"rfstudy_send\\",\\"study_feq\\":\\"433\\",\\"key1\\":{\\"code\\":\\"eyJudW0iOjEsInZlciI6IjIiLCJzdHVkeV9mZXEiOiI0MzMiLCJkYXRhMCI6Ind5U2RBelFCTkFHZEE1MEROQUUwQVowRG5RTTBBVFFCblFNMEFaMEROQUdkQTUwRE5BRTBBWjBEblFNMEFaMEROQUUwQVowRE5BR2RBelFCblFPZEF6UUJuUU5YQVRRQm5RT2RBelFCTkFHZEF6UUJuUU0wQVowRG5RTlhBVFFCblFNMEFRPT0iLCJsdiI6WzBdfQ==\\",\\"times\\":6,\\"delay\\":0,\\"intervals\\":0}}"}}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(463)  b'...{"dps":{"201":"{\\"ver\\":\\"2\\",\\"rf_type\\":\\"sub_2g\\",\\"control\\":\\"rfstudy_send\\",\\"study_feq\\":\\"433\\",\\"key1\\":{\\"code\\":\\"eyJudW0iOjEsInZlciI6IjIiLCJzdHVkeV9mZXEiOiI0MzMiLCJkYXRhMCI6Ind5U2RBelFCTkFHZEE1MEROQUUwQVowRG5RTTBBVFFCblFNMEFaMEROQUdkQTUwRE5BRTBBWjBEblFNMEFaMEROQUUwQVowRE5BR2RBelFCblFPZEF6UUJuUU5YQVRRQm5RT2RBelFCTkFHZEF6UUJuUU0wQVowRG5RTlhBVFFCblFNMEFRPT0iLCJsdiI6WzBdfQ==\\",\\"times\\":6,\\"delay\\":0,\\"intervals\\":0}}"}}'
 to   'eb####tb' v3.3 cmd: 13 (0D) len(127)  b'...{"dps":{"201":"{\\"rf_type\\":\\"sub_2g\\",\\"control\\":\\"rfstudy_exit\\",\\"study_feq\\":\\"433\\",\\"ver\\":\\"2\\"}"}}'

Oddly enough, decoding that base64 results in another JSON string:

{"num":1,"ver":"2","study_feq":"433","data0":"wySdAzQBNAGdA50DNAE0AZ0DnQM0ATQBnQM0AZ0DNAGdA50DNAE0AZ0DnQM0AZ0DNAE0AZ0DNAGdAzQBnQOdAzQBnQNXATQBnQOdAzQBNAGdAzQBnQM0AZ0DnQNXATQBnQM0AQ==","lv":[0]}

Decoding that base64 and displaying the result as hex results in:

00000000  c3 24 9d 03 34 01 34 01  9d 03 9d 03 34 01 34 01  |.$..4.4.....4.4.|
00000010  9d 03 9d 03 34 01 34 01  9d 03 34 01 9d 03 34 01  |....4.4...4...4.|
00000020  9d 03 9d 03 34 01 34 01  9d 03 9d 03 34 01 9d 03  |....4.4.....4...|
00000030  34 01 34 01 9d 03 34 01  9d 03 34 01 9d 03 9d 03  |4.4...4...4.....|
00000040  34 01 9d 03 57 01 34 01  9d 03 9d 03 34 01 34 01  |4...W.4.....4.4.|
00000050  9d 03 34 01 9d 03 34 01  9d 03 9d 03 57 01 34 01  |..4...4.....W.4.|
00000060  9d 03 34 01                                       |..4.|

@Xmister
Copy link

Xmister commented May 2, 2023

Looks great! Can you show me the messages for the curtain pairing as well? With rf_study, I can get an encoded code, but sending back the same with rfstudy_send doesn't work. I wonder if curtain pairing somehow returns a similar data structure to your first 2 messages.

@uzlonewolf
Copy link
Collaborator Author

There wasn't any pairing, just Add -> Curtain -> [select random brand] -> [select random model] -> "Does it work? [y/n]". Those 2 commands I posted above are the only ones it sent.

What does your send function look like? It should be something like:

import json
import tinytuya

d = tinytuya.Device(..., persist=True)

cmd = {
  "rf_type": "sub_2g",
  "control": "rfstudy_exit",
  "study_feq": "433",
  "ver": "2"
}

d.set_value( 201, json.dumps(cmd).replace(" ", "") )

cmd = {
  "ver": "2",
  "rf_type": "sub_2g",
  "control": "rfstudy_send",
  "study_feq": "433",
  "key1": {
    "code":"eyJudW0iOjEsInZlciI6IjIiLCJzdHVkeV9mZXEiOiI0MzMiLCJkYXRhMCI6Ind5U2RBelFCTkFHZEE1MEROQUUwQVowRG5RTTBBVFFCblFNMEFaMEROQUdkQTUwRE5BRTBBWjBEblFNMEFaMEROQUUwQVowRE5BR2RBelFCblFPZEF6UUJuUU5YQVRRQm5RT2RBelFCTkFHZEF6UUJuUU0wQVowRG5RTlhBVFFCblFNMEFRPT0iLCJsdiI6WzBdfQ==",
    "times": 6,
    "delay": 0,
    "intervals": 0
  }
}

d.set_value( 201, json.dumps(cmd).replace(" ", "") )

With that "code" replaced with what rfstudy returned in 202.

@Xmister
Copy link

Xmister commented May 3, 2023

I was trying the following way:

d._send_receive(d.generate_payload(tinytuya.CONTROL, {201: json.dumps({"rf_type": "sub_2g", "control": "send_cmd", "ver": "2", "key1": {"code": "eyJudW0iOjEsInZlciI6IjIiLCJzdHVkeV9mZXEiOiI0MzMiLCJkYXRhMCI6ImlSNU1FbUFGVVFIV0FvSUIxZ0xXQWxFQjFnSlJBZFlDVVFIV0FsRUIxZ0pSQWRZQ2dnSFdBbEVCMWdLQ0FZSUIxZ0tDQWRZQ2dnSFdBdFlDZ2dIV0FsRUJnZ0hXQXRZQ1VRR0NBZFlDMWdKUkFZSUIxZ0xXQW9JQjFnS0NBWUlCMWdLQ0FkWUNnZ0hXQW9JQjFnS0NBZFlDZ2dIV0FvSUIxZ0xXQW9JQlVRSFdBdFlDZ2dGUkFkWUMxZ0pSQVlJQjFnTFdBb0lCZ2dIV0F0WUNVUUdDQWRZQzFnST0iLCJsdiI6WzBdfQ==", "times": "6", "delay": "0", "intervals": "0"}}).replace(" ", "")}))

It did flash the light, so I thought it's working fine. However your code actually moves the curtain, so thank you for that.

@uzlonewolf
Copy link
Collaborator Author

Glad it's working.

Looking at the command you were sending, it looks like the differences are "rfstudy_send" vs "send_cmd", the inclusion of "study_feq", key1 numbers as integers vs strings, and the DP ID as a string vs integer (d.set_value() casts it to a string as that's what devices normally expect).

Now that you have it working, where do we go from here? Is a new device type still needed/useful?

@Xmister
Copy link

Xmister commented May 3, 2023

Well, I did try with rfstudy_send as well in the same format without luck, so it's possible that the field types was the issue.
I mean, I can use it the way it is now, but I think a similar RFRemoteControlDevice would be helpful for a lot of folks

@uzlonewolf
Copy link
Collaborator Author

I don't mind making it, though I have my doubts that "lots" of people will use it. What functions do you want it to have? At this point I think I only have enough info to implement .receive_button() and .send_button().

@Xmister
Copy link

Xmister commented May 3, 2023

I think that's good enough for start. Good RF bridges are high in demand, this class could make these devices a simple one.

@uzlonewolf
Copy link
Collaborator Author

Added in #343

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unable to control Universal IR Device IR REMOTE CONTROL Multiple DPS
4 participants