TheAgentK / tuya-mqtt

Nodejs-Script to combine tuyaapi and openhab via mqtt
MIT License
173 stars 81 forks source link

tuya-mqtt correctly publishes state, but fails on command messages #56

Closed HollowedEmpire closed 3 years ago

HollowedEmpire commented 3 years ago

I'm having some errors and general issues sending messages to a device using 'command'. Either it is acknowledged and nothing happens, or there is an error reported during debug.

tuya-mqtt acknowledges commands with debug logging, but does not actually perform any action when using the dps commands. Additionally, it receives an error when using the higher level command, or when calling the higher level state to query the device.

I can interact with the device via tuya-cli without problems, so these issues are localized to tuya-mqtt specifically. I can also use the dps state command, and verify states are changing, so it does not seem to be a mqtt sever issue either.

The device in question is a humidifier/oil diffuser, which is named 'Office Diffuser' (office_diffuser). I can provide more information on it if needed, but it seems to be at least correctly recognized by tuya-mqtt since it can publish state changes.


Issue 1 - high level command causes an error

I redacted the full file path for a heads up

tuya-mqtt:command Received MQTT message ->  {"topic":"device/tuya/office_diffuser/command","message":"{'dps':1,'set':'false'}"} +1s
tuya-mqtt:error TypeError: Cannot read property 'processDpsCommand' of undefined
tuya-mqtt:error     at MqttClient.<anonymous> (tuya-mqtt/tuya-mqtt.js:163:32)
tuya-mqtt:error     at MqttClient.emit (events.js:198:13)
tuya-mqtt:error     at MqttClient._handlePublish (tuya-mqtt/node_modules/mqtt/lib/client.js:1271:12)
tuya-mqtt:error     at MqttClient._handlePacket (tuya-mqtt/node_modules/mqtt/lib/client.js:410:12)
tuya-mqtt:error     at work (tuya-mqtt/node_modules/mqtt/lib/client.js:321:12)
tuya-mqtt:error     at Writable.writable._write (tuya-mqtt/node_modules/mqtt/lib/client.js:335:5)
tuya-mqtt:error     at doWrite (tuya-mqtt/node_modules/readable-stream/lib/_stream_writable.js:428:64)
tuya-mqtt:error     at writeOrBuffer (tuya-mqtt/node_modules/readable-stream/lib/_stream_writable.js:417:5)
tuya-mqtt:error     at Writable.write (tuya-mqtt/node_modules/readable-stream/lib/_stream_writable.js:334:11)
tuya-mqtt:error     at Socket.ondata (_stream_readable.js:710:20) +1s

Issue 2 - DPS command is received, but nothing happens

The following message is logged, but the device does not shut off like it is supposed to. Additionally, tuya-cli can correctly turn it on and off.

tuya-mqtt:command Received MQTT message ->  {"topic":"device/tuya/office_diffuser/dps/1/command","message":"false"} +3m

Issue 3 - State/subscription works (but only at DPS level)

I can correctly subscribe to the device and get messages back. Here, I turned it on and off via an app. However, using the higher level "/device/tuya/office_diffuser/state does not do anything

mosquitto_sub -L mqtts://name:pass@ip:port/device/tuya/office_diffuser/dps/1/state
false
true

Here is my devices.conf file too, with actual data redacted. However it does not seem to be the problem since tuya-mqtt does see the device and correctly publishes power on/off changes for the device.

[
 {
    name: 'Office Diffuser',
    id: 'xxxxxxxxx',
    key: 'xxxxxxxx',
    ip: '10.0.x.xx',
    version: '3.3'
  }
]

Let me know if you'd like to see anything else reported from the debug logging or if I can provide anything else. Thanks!

tsightler commented 3 years ago

It appears you added an extra topic level as I see you are issuing commands to device/tuya/office_diffuser/command instead of tuya/office_diffuser/command. While you can choose to use a top level topic other that tuya/ the code currently can't deal with adding an entire additional topic level, so that might be part of the problem.

However, for issue #1 & #3, you didn't define the device type which means it's being recognized as only a generic device so you can't use any friendly topics for commands since, which is why that command does not work. Generic device support only works with DPS topics. It looks like you may be just trying to do a simple "on/off" function so I would try defining the device as a SimpleSwitch type and try again as this should get the friendly topic working.

For issue #2, the DPS topic, the problem is that for generic DPS topics the code has no way to know if the DPS value type is a string, bool or number type, and, from MQTT, it is always a string so you are sending "false" as a string (because that's all MQTT can send), and the code tries to send "false" as a string to that DPS, but it should be a bool. To correct this you need to define a template and define that DPS as bool value, but you don't really need to do this if you simply define the device as SimpleSwitch as noted above because then it will use the SimpleSwitch template intead.

I plan to attempt to add some better "guessing" code in the future to better be able to handle direct data to DPS values, but for now, it always sends the data as string and the only way to override that is to use a pre-defined device type or define a custom template for your device.

HollowedEmpire commented 3 years ago

Ah, okay that explains quite a bit! Thanks for that. It seems the template/typing will fix most, if not all, of my issues. The TypeError makes a lot more sense in this context as well.

I had thought specifying the generic type wasn't required, as the sample devices.conf in the section Setting up devices.conf did not specify any types for the devices. That section also concluded saying you should have a working setup at that point, so this was the reason I thought something was wrong. But thanks for the clarification, it makes a lot more sense now.

I'll also see about removing the top topic level as well, though very interesting it was still partially working even if the code isn't designed for additional topic levels. Unless you know for sure it won't fully work, I might leave the higher topic level for now and let you know if it things appear to be working after getting the template issue resolved. I could get that checked into more tomorrow if so.

Anyway, thanks again for the clarification on everything.

tsightler commented 3 years ago

Well, you don't have to define the generic type, obviously the code is working, but the generic type doesn't have any friendly topics at all so you can only use the DPS topics and those currently only support string value types so if a DPS happens to required bool or number, they don't work. I plan to implement "type guessing" in a future version, but for now you can just create a template.

If you don't want to create a template the other option is to use the dps/command topic, which accepts tuya style JSON commands. These will work without a template.

If your device only as a single DPS with on/off as true/false, then the "SimpleSwitch" type should work just fine. Otherwise, use the generic type and a template and you should be good to go.

I appreciate the feedback on the documentation, the docs were very rushed as I was running out of time to work on this project and wanted to just get it out there. It's difficult to describe all of the available options in a way that is simple enough to use. I will try to improve it based on your feedback once I manage to claw a little time for this project again.

HollowedEmpire commented 3 years ago

You're welcome! And I definitely understand the issue of finding time for side projects. :P

Also, I found out the extra topic level I had was causing problems with sending the JSON values. Originally publishing the JSON did not work for me, but after removing the extra topic level it works fine.

Anyway, thanks again! I'll go ahead and close this.

tsightler commented 3 years ago

Good to know it was the topic level that caused those issues. I should probably just document this limitation, or take the time to fix it. It should be pretty easy to fix, it's mainly a side effect of lazy coding and an assumption that most people would never change the default topic.