-
Notifications
You must be signed in to change notification settings - Fork 568
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
Initial work on refactoring pytuya #58
Conversation
5234f27
to
da6628b
Compare
Wow, amazing job! Still a bit unclear what you're aiming to with that "segno" but excellent code cleaning job. 💪 |
Each message has a sequence number that should be matched when receiving the answer. I'm not sure if it's used for anything practical, but it should be increased for every new message. At least in theory, two message could be sent in order and responses received in opposite order. Yeah, I'll let you know 👍 |
da6628b
to
c963a37
Compare
@rospogrigio Now would be a great time to test. I've made most of the changes I want, a few more are remaining and I will deal with those in due time. Want to get cracking on asyncio though. Tried to make everything more general and remove magic constants. So we parse more things than we use, but that's ok. |
Still lots of things to improve, but it's a start. Will continue with receive code.
c963a37
to
0c953be
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just something to think about, in case of RGBW lights, we may need to send multiple dps at the same time.
We may need to have a method to send all theses dps in a single message.
Sending them in a sequence will produce weird effects as the light may flash or quickly change color.
Yeah, you can do that by calling |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comments, almost working...
dev_type, | ||
self.dev_type, | ||
) | ||
return self.exchange(command, data) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is giving problems, since you are using the same variable (data) that is used to receive the data from the device, so if I print out the json_data of the payload I get:
DEBUG:localtuya.pytuya:json_data={'devId': 'bf4ce0d8be2bc62e2fgdoy', 'uid': 'bf4ce0d8be2bc62e2fgdoy', 't': '1601443774', 'dps': b'\x00\x00U\xaa\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00,\x00\x00\x00\x01\x82\x86>el\xe2\xd1\xe5\xe90(\x05\x9b\xc8\xea\x8aA\xd1\xfb\xc0\x98)Z\x1e\x8er\x05dd?5UTH^\xc4\x00\x00\xaaU'}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, yes, that's not very good.
try: | ||
data = self.status() | ||
except Exception as e: | ||
_LOGGER.warning("Failed to get status: [{}]", e) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the warning and error messages for Exceptions trigger the following errors:
Traceback (most recent call last):
File "/usr/lib/python3.7/logging/init.py", line 1034, in emit
msg = self.format(record)
File "/usr/lib/python3.7/logging/init.py", line 880, in format
return fmt.format(record)
File "/usr/lib/python3.7/logging/init.py", line 619, in format
record.message = record.getMessage()
File "/usr/lib/python3.7/logging/init.py", line 380, in getMessage
msg = msg % self.args
TypeError: not all arguments converted during string formatting
Call stack:
File "./tuyadebug/test.py", line 42, in
localtuya.devicePrint(DEVID, DEVIP, DEVKEY, DEVVERS)
File "/root/tuyadebug/localtuya/init.py", line 162, in devicePrint
err,data,dev_type = deviceInfo(deviceid, ip, key, vers)
File "/root/tuyadebug/localtuya/init.py", line 108, in deviceInfo
data = d.detect_available_dps()
File "/root/tuyadebug/localtuya/pytuya/init.py", line 274, in detect_available_dps
_LOGGER.error("Failed to get status: [{}]", e)
Message: 'Failed to get status: [{}]'
Arguments: (TypeError('Object of type bytes is not JSON serializable'),)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bad formatting of course, will fix.
@@ -301,40 +343,20 @@ def generate_payload(self, command, data=None): | |||
json_data["dps"] = data | |||
if command_hb == "0d": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now this should be
if command_hb == 0x0d:
It took a lot to figure it out!!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, moved from strings to integer instead where possible.
Should be fixed now! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything works on my side.
Merging to master, I also updated the tuyadebug.tgz package.
Merged #58 into master. |
Great! Moving steadily with the port to asyncio, let's see if I have something that can be tested today or tomorrow. |
OK I'll update #55 to fix the "bouncing" effect and ask for your review. |
That'd be great! |
I think I'm more or less done with the pytuya changes for asyncio, seems to work in my little test case. Just need to adjust the rest. I still haven't decided exactly how to deal with connection problems and re-connects, but I'm starting with a simple approach. If we have an open connection (when needed), use that otherwise connect again. |
Another short status update.... Today I learned something new. I had some problems with the device suddenly started to respond with status updates using sequence number 0, mainly after changing a datapoint (the regular status polling worked as expected). I kinda ran into what we have a workaround for today, right here: This message is actually the ACK message to I looked at the tuyapi code and figured it out that way. Here is the ACK message: https://github.com/codetheweb/tuyapi/blob/6b50f74842cd61b40935ef7646f7185172d8c8c8/index.js#L430 And here is the update: https://github.com/codetheweb/tuyapi/blob/6b50f74842cd61b40935ef7646f7185172d8c8c8/index.js#L447 This means that we can scrap the polling part altogether. We just poll status one time at start, then we rely on push updates. We need to add heart beat and send at an interval, but that is trivial. Pretty good discovery I would say, but it requires a few changes. |
Wow, this looks very interesting. Couple of questions though:
|
I would expect it to be the same, message type 0x08 is used for status updates. Should have something you can try tomorrow (maybe) to be sure. I will modify what I currently have to work with push updates only. This is a TCP connection, we can't miss updates (unless there is bug in the tuya firmware). |
One thing that came to my mind now is fields like power consumption. I need to verify if we get updates when they change. |
I hooked things up and I have verified that updates are sent when any DP changes. Even so for power consumption, which means we are good! |
I'm not entirely done yet, I want to work a bit on the "receive" code as I haven't touched that yet. But I wanted to share what I'm working on, to give an idea where I'm heading (@rospogrigio ).