BrettSheleski / SmartThingsPublic

36 stars 23 forks source link

Expand to Support 4CH Pro? #6

Closed GeorgeIoak closed 6 years ago

GeorgeIoak commented 6 years ago

I was doing some initial testing and got my device configured with ST but this appears to be supporting only a 1 channel device. How would I go about making this work for the 4 channel version?

BrettSheleski commented 6 years ago

That is currently not supported. I do have an idea for developing an all-purpose set of Tasmota device handlers, but currently that has not been devleoped.

GeorgeIoak commented 6 years ago

OK, that's what I thought but I figured I would double check. I'm not a great programmer but I have a little time I could invest in this. Could you point me in the direction you were thinking of going and perhaps I can help.

BrettSheleski commented 6 years ago

You could modify the current device handler pretty simply to handle multiple channels. Basically just define on2() / off2() ... On4()/off4() functions and have them send the power1, power2, power3 or power4 command with either on or off.

BrettSheleski commented 6 years ago

I cranked out a new device handler for the 4CH.

https://github.com/BrettSheleski/SmartThingsPublic/blob/master/devicetypes/BrettSheleski/sonoff-tasmota-4ch.src/sonoff-tasmota-4ch.groovy

I don't have a 4CH to do any testing with, but I believe it might work.

Personally I'd prefer to have a different SmartThings device for each channel. I have some ideas to resolve this, but until then, this may do the trick. Let me know how it works for ya.

mikejclark commented 6 years ago

I have a few of the TH16 with the AM2301 sensor. How much work would it be to create a device handler for this? I'd also be happy to give this a go

GeorgeIoak commented 6 years ago

Thanks for jumping on this, sorry I missed your post from yesterday. I just did a quick test and it's almost working. I have the web page of the Sonoff open and then on my mobile I've got the ST app open. If I look at the status on the ST app all 4 channels will show as being on yet on the web interface of the Sonoff they are OFF. If I touch a channel in the app the web page changes from OFF to ON and the app still shows ON. Touch the app a 2nd time and the app shows OFF and the web page also shows OFF.

Then If I use the web page to turn a channel on the app does not change state, even if I hit the refresh button on the bottom.

Perhaps this is just a timing related issue so I'll run some additional experiments but I wanted to make a post and thank you, as well as provide some feedback.

I did some additional testing and this does appear to be working but the syncing in my current setup causes the delayed response between the Sonoff web interface and ST. I'll have to investigate further into this.

This is my 1st time with the Sonoff as well as with openHAB. I'm going to use this 4CH Pro to control a garage air filtration system which has a 3 speed fan. The 4CH has a mode called Interlock which only allows 1 channel to be active at a time which is exactly what I need. Right now I'm experimenting with just a ESP8266 module flashed with the Tasmota firmware.

BrettSheleski commented 6 years ago

It's a known issue with the status SmartThings that reports may be inaccurate. The status should be corrected whenever SmartThings decides to call the Poll() method. But there's reports that that's not always working either.

Can you come firm the following:

Are you able to trigger each channel using the SmartThings app?

Are the statuses ever updated within the SmartThings app after triggering any channel using the SmartThings app?

If triggering any channel by other means (NOT using the SmartThings app) does the SmartThings app report the correct status after pressing the refresh button in the app?

GeorgeIoak commented 6 years ago

I am able to trigger each channel using the ST app. When you hit the refresh in the ST app I can see the following in the Sonoff Console:

04:38:09 MQT: stat/sonoff/STATUS = {"Status":{"Module":23,"FriendlyName":"Sonoff1","Topic":"sonoff","ButtonTopic":"0","Power":7,"PowerOnState":3,"LedState":1,"SaveData":1,"SaveState":1,"ButtonRetain":0,"PowerRetain":0}}

When the Sonoff publishes it looks like this:

04:37:47 MQT: tele/sonoff/STATE = {"Time":"2018-02-12T04:37:47","Uptime":"0T00:05:14","Vcc":3.026,"POWER1":"ON","POWER2":"ON","POWER3":"ON","POWER4":"OFF","Wifi":{"AP":1,"SSId":"xxxxxx","RSSI":100,"APMac":"xx:xx:xx:xx"}}

In this publish you can see that POWER4 is OFF but in the ST app it still shows that it is ON, even after several refreshes and more than 1 minute of waiting.

When I touch a channel in the ST app it goes from ON to OFF and I see this in the console:

04:42:08 MQT: stat/sonoff/RESULT = {"POWER2":"OFF"} 04:42:08 MQT: stat/sonoff/POWER2 = OFF

Then I tried to toggle Channel 1 using the ST app and the app always showed that the channel was OFF yet the correct commands were sent to the Sonoff:

04:43:20 MQT: stat/sonoff/RESULT = {"POWER1":"OFF"} 04:43:20 MQT: stat/sonoff/POWER1 = OFF 04:43:40 MQT: stat/sonoff/RESULT = {"POWER1":"ON"} 04:43:40 MQT: stat/sonoff/POWER1 = ON 04:43:51 MQT: stat/sonoff/RESULT = {"POWER1":"OFF"} 04:43:51 MQT: stat/sonoff/POWER1 = OFF

But oddly this seems to be only for channel 1. I was able to toggle each of the other channels and they responded correctly in the Sonoff console as well as in the ST app but currently the ST app is stuck showing that Channel 1 is OFF yet it does know the correct toggle state to send with each touch.

The app does not appear to update if I toggle a channel using the Sonoff console, even if I hit refresh in the ST app. I can see that the Sonoff publishes every 5 minutes but even after waiting for a new publish event to occur and another refresh in the ST app the ST app still shows all channels as being OFF yet I currently have channels 1 and 2 ON

BrettSheleski commented 6 years ago

The SmartThings app does not speak MQTT, so even though the Sonoff is sending out the information via MQTT whenever an output is toggled, the SmartThings device handler isn't listening.

The SmartThings device handler is simply sending HTTP commands to the Sonoff and parsing the response. This happens in 3 different situations:

  1. When the user turns on, turns off, or toggles an output from the SmartThings app. This sends the http command in the format http://ip-of-sonoff/cm?cmnd=Power<X>%20On or http://ip-of-sonoff/cm?cmnd=Power<X>%20Off or http://ip-of-sonoff/cm?cmnd=Power<X>%20Toggle (where <X> is the channel number to toggle)
  2. When the user presses the refresh button in the SmartThings app. This calls the Refresh function and ends up sending the following http command http://ip-of-sonoff/cm?cmnd=Status
  3. The device handler implements the Polling capability (see: https://smartthings.developer.samsung.com/develop/api-ref/capabilities.html#Polling). This ends up calling the Poll() method, which again just triggers the following http command: http://ip-of-sonoff/cm?cmnd=Status (I do not know when SmartThings decides to call the Poll() function)

So, in short, the SmartThings app only updates it's status when parsing the response to one of the above. The Sonoff device knows nothing about SmartThings. Therefore if the Sonoff is triggered somehow else (not using the SmartThings app), SmartThings is not aware of it.

At this point I do not know of a good way of solving this problem that does not involve modifying the Tasmota firmware itself.

BrettSheleski commented 6 years ago

I updated the device handler to update the status of Channel 1 using Power1 (instead of just Power).

Upon further research, it appears that polling in SmartThings simply isn't reliable. Apparently SmartThings just doesn't automatically call the poll() function. Therefore I added a runEvery1Minute() call to call the poll() function every minute. This should help at least.

See commit 097d3a1114c0150a2675a0181097c687716b8409

GeorgeIoak commented 6 years ago

Thanks for the explanation and sorry about my confusion. I just ran a quick test with your latest changes and the ST app does respond like it did with my changes so as long as the ST app is the only one controlling the Sonoff it displays the correct state. Even with the 1 minute polling I did not see the ST app get the updated status if I made a change through the web interface of the Sonoff. I waited more than 1 minute as well as hitting the refresh button in the ST app. If I have time today I'll fire up the actual 4CH Pro and run it with the Stock firmware and see if anything is different. Sounds like I may have to fire up Wireshark and sniff some packets to see what's really going on rather than rely on the MQTT messages as I have been

BrettSheleski commented 6 years ago

SmartThings documentation is pretty spotty at best. So getting information, and assuming that information is actually accurate, is a fun job.

Even getting the HTTP response within the SmartThings device handler is finicky. I wouldn't be surprised if it just is deciding not to handle the responses for no good reason.

BrettSheleski commented 6 years ago

My guess is that the contents of the response to the status command is not what is expected.

Looking at what you sent previously, you posted:

04:38:09 MQT: stat/sonoff/STATUS = {"Status":{"Module":23,"FriendlyName":"Sonoff1","Topic":"sonoff","ButtonTopic":"0","Power":7,"PowerOnState":3,"LedState":1,"SaveData":1,"SaveState":1,"ButtonRetain":0,"PowerRetain":0}}

The important thing here is "Power": 7. My guess now is that all the power statuses are binary-OR'd into an integer value. I'll dive into Tasmota code and try to decipher this to make sure, but I'm pretty sure it makes sense that the 4 outputs are binary-or'd into a single integer value (0111 --> 7).

If you turn them all on, does status of Power become 15? (1111 --> 15)

BrettSheleski commented 6 years ago

See commit 3fcfe8d2e7c8cd5151bdba8b40841acd99a2b532.

Let me know if that works. (btw, I did zero testing to make sure it even compiles, so be aware)

GeorgeIoak commented 6 years ago

Pretty good assumption, here an all ON response when the ST app turns ON all 4 channels and hits a refresh: 17:45:39 MQT: stat/sonoff/STATUS = {"Status":{"Module":23,"FriendlyName":"Sonoff1","Topic":"sonoff","ButtonTopic":"0","Power":15,"PowerOnState":3,"LedState":1,"SaveData":1,"SaveState":1,"ButtonRetain":0,"PowerRetain":0}}

Here's 1,2,3 ON with 4 OFF just for confirmation: 17:46:51 MQT: stat/sonoff/STATUS = {"Status":{"Module":23,"FriendlyName":"Sonoff1","Topic":"sonoff","ButtonTopic":"0","Power":7,"PowerOnState":3,"LedState":1,"SaveData":1,"SaveState":1,"ButtonRetain":0,"PowerRetain":0}}

ON-OFF-ON-ON looks like: 17:47:56 MQT: stat/sonoff/STATUS = {"Status":{"Module":23,"FriendlyName":"Sonoff1","Topic":"sonoff","ButtonTopic":"0","Power":13,"PowerOnState":3,"LedState":1,"SaveData":1,"SaveState":1,"ButtonRetain":0,"PowerRetain":0}}

So I'll pull your latest code changes and check now

GeorgeIoak commented 6 years ago

Well unfortunately the ST app still does not sync properly when I change a state through the Sonoff Web interface. When I hit the refresh in the ST app I see the "correct" response posted in the Sonoff console but perhaps they MQTT response is different than the HTTP response?

BrettSheleski commented 6 years ago

If you open the device handler in the simulator in the SmartThings IDE it may shed some light on the situation. It might be spitting something out to the debug log.

GeorgeIoak commented 6 years ago

Yep, here's what happens when I hit a refresh in the ST app:

`c1aa646c-b200-48f9-8e9b-9984adddf966 9:16:49 AM: error groovy.lang.MissingMethodException: No signature of method: java.lang.Integer.and() is applicable for argument types: (java.lang.Boolean) values: [true] Possible solutions: and(java.lang.Number), any(), any(groovy.lang.Closure), abs(), find(), find(groovy.lang.Closure) @line 172 (parse)

c1aa646c-b200-48f9-8e9b-9984adddf966 9:16:48 AM: debug sendCommand(Status:null) to device at 192.168.10.46:80

c1aa646c-b200-48f9-8e9b-9984adddf966 9:16:48 AM: debug REFRESH`

BrettSheleski commented 6 years ago

Looks like it's an issue with the following line(s):

...
setSwitchState(power & p1On == p1On);
...

My guess it's a goofy order-of-operations issue. I just committed a small change adding parantheses. Try that.

GeorgeIoak commented 6 years ago

Out of curiosity, why is the first switch defined with an action of momentary.switch and the others have their own command? I'll try your new code now...

No, still, the same error

BrettSheleski commented 6 years ago

Mainly to remain "compatible" with the Momentary and Switch capabilities. These two capabilities define push, on, and off commands.

Without doing so, would mean this device would no longer be able to be used by other devices and/or SmartApps.

If a device using this device handler were to be used in another device/SmartApp it would only control Channel 1, but at least that's better than nothing.

Ideally each channel would be it's own device, each implementing the Momentary and Switch capabilities. But until then (I have ideas), this is what we got.

GeorgeIoak commented 6 years ago

Been staring at the code and I can't seem to figure out why that error is being thrown. Guess I'll walk away for a bit and come back with another look unless you've got a good idea.

BTW, I do agree with you on each channel being it's own device. Even in my case it would be a better solution but I would need logic (or rely on the Interlock mode) so only 1 channel is on at the same time (fan speeds of low, medium, and fast connected to channels 1-3). Since that leaves an unused channel it might be nice to add a light on that channel or something else.

GeorgeIoak commented 6 years ago

OK, your latest change DOES work but you do need to hit refresh in the ST app as the polling does not update the app status (not sure why). Here's what the simulator console looks like:

`Logs c1aa646c-b200-48f9-8e9b-9984adddf966 10:10:33 AM: debug sendCommand(Status:null) to device at 192.168.10.46:80 c1aa646c-b200-48f9-8e9b-9984adddf966 10:10:33 AM: debug POLL c1aa646c-b200-48f9-8e9b-9984adddf966 10:09:33 AM: debug sendCommand(Status:null) to device at 192.168.10.46:80 c1aa646c-b200-48f9-8e9b-9984adddf966 10:09:33 AM: debug POLL c1aa646c-b200-48f9-8e9b-9984adddf966 10:08:33 AM: debug sendCommand(Status:null) to device at 192.168.10.46:80 c1aa646c-b200-48f9-8e9b-9984adddf966 10:08:33 AM: debug POLL

c1aa646c-b200-48f9-8e9b-9984adddf966 10:07:42 AM: info switch is OFF c1aa646c-b200-48f9-8e9b-9984adddf966 10:07:42 AM: info switch is ON c1aa646c-b200-48f9-8e9b-9984adddf966 10:07:42 AM: info switch is ON c1aa646c-b200-48f9-8e9b-9984adddf966 10:07:41 AM: info switch is ON

c1aa646c-b200-48f9-8e9b-9984adddf966 10:07:41 AM: debug sendCommand(Status:null) to device at 192.168.10.46:80 c1aa646c-b200-48f9-8e9b-9984adddf966 10:07:41 AM: debug REFRESH c1aa646c-b200-48f9-8e9b-9984adddf966 10:07:33 AM: debug sendCommand(Status:null) to device at 192.168.10.46:80 c1aa646c-b200-48f9-8e9b-9984adddf966 10:07:33 AM: debug POLL c1aa646c-b200-48f9-8e9b-9984adddf966 10:06:35 AM: debug sendCommand(Status:null) to device at 192.168.10.46:80 c1aa646c-b200-48f9-8e9b-9984adddf966 10:06:35 AM: debug POLL c1aa646c-b200-48f9-8e9b-9984adddf966 10:05:33 AM: debug sendCommand(Status:null) to device at 192.168.10.46:80 c1aa646c-b200-48f9-8e9b-9984adddf966 10:05:33 AM: debug POLL

c1aa646c-b200-48f9-8e9b-9984adddf966 10:05:19 AM: info switch is ON c1aa646c-b200-48f9-8e9b-9984adddf966 10:05:19 AM: info switch is ON c1aa646c-b200-48f9-8e9b-9984adddf966 10:05:19 AM: info switch is ON c1aa646c-b200-48f9-8e9b-9984adddf966 10:05:18 AM: info switch is ON `

GeorgeIoak commented 6 years ago

Have you seen this implementation, (https://community.smartthings.com/t/release-sonoff-sonoff-th-s20-dual-4ch-pow-touch-device-handler-smartapp-5-10-smart-switches/45957)

He also adds a service to ST. The thread is about a mile long so I was trying to sort through it and see what his ESP8266 code looked like.

BrettSheleski commented 6 years ago

I think I looked at that a long time ago, but was uninterested as it requires a special firmware for it to work.

I want to stick with Tasmota, hence my device handler(s).

GeorgeIoak commented 6 years ago

OK, just hunting around and found some additional information here, http://smartlife.tech/blog/2016/04/21/sonoff-wifi-switch-smartthings/

They configured Domoticz with the ST hub IP address. The Tasmota firmware doesn't allow you change that from the web interface (the IP address) so later I'll recompile the Tasmota firmware and use the ST hub IP and see if that enables 2-way communication.

Right now I'm playing around with openHAB as I'm looking for something to consolidate all my devices. I tried Home assistant but couldn't get it to run properly on my WHS 2011 that I still run. I use it to do PC backups and serve up movies for the kids so it runs 24/7 and has been for many years. I could break out a Raspberry Pi and use it for all of this but that might be "too easy"!!

BrettSheleski commented 6 years ago

My plan is to modify the Tasmota firmware allowing the user to specify a URL (as well as any HTTP headers & values). Then whenever Tasmota sends off the MQTT messages, it will also do an HTTP Post to the specified URL (along with headers) containing the Status JSON.

Then I'd create a SmartThings SmartApp which ends up creating an HTTP endpoint. The SmartApp would then spawn a child device (a new Device Handler implementation). This new SmartThings device would end up spawning more child devices depending on the Sonoff module and/or GPIO configuration (more new device handlers). Therefore, in your case with the 4CH, it would create 5 devices (1 'master' device, and a device corresponding to each channel).

What this would allow is for Tasmota to do an HTTP-Post to the SmartApp endpoint URL. The SmartApp would basically just forward the Status JSON to the 'master' device. The 'master' device would then forward the Status JSON to each of it's children. The child devices would then update their statuses however appropriate.

The SmartApp is basically there just to have an HTTP endpoint to be called by others.

The 'master' device is there due to a technical limitation of the SmartThings ecosystem.

I think this would be the best situation. Sonoff 4CH modules would appear as 4 separate devices each implementing the Momentary and Switch capabilities. Sonoff TH devices would appear as three devices: one Momentary/Switch, one temperature sensor, and one humidity sensor. The Sonoff RF Bridge would show up as 16 Momentary devices. Etc.. The number of devices would also vary depending on GPIO configuration as well.

Actually, come to think of it, a modification to Tasmota would not be necessary as I could do everything it would doing within Node-Red tons easier.

GeorgeIoak commented 6 years ago

I like your thinking and agree however I've never messed with Node-Red so I wouldn't be much help other than as a tester. I like how you can expand using the GPIO pins so I was thinking of adding a temp or a temp/humidity sensor. Looks like Sonoff removed the header for accessing the pins but I'm much better soldering that coding so it would be easy to tack something in.

I wonder what the message looks like when I replace the Domoticz with the ST hub IP address? I think I'll give that a try and see if that adds anything to this..

GeorgeIoak commented 6 years ago

One thing that is odd is that when the runEvery1Minute(poll) command runs I can see the POLL command in the simulator window of the ST IDE yet the app doesn't update. If I hit the POLL button on the right side of the ST IDE I see the exact same command in the debug console but the app DOES update.

` c1aa646c-b200-48f9-8e9b-9984adddf966 3:41:31 PM: debug sendCommand(Status:null) to device at 192.168.10.46:80 c1aa646c-b200-48f9-8e9b-9984adddf966 3:41:31 PM: debug POLL c1aa646c-b200-48f9-8e9b-9984adddf966 3:40:33 PM: debug sendCommand(Status:null) to device at 192.168.10.46:80 c1aa646c-b200-48f9-8e9b-9984adddf966 3:40:33 PM: debug POLL c1aa646c-b200-48f9-8e9b-9984adddf966 3:39:31 PM: debug sendCommand(Status:null) to device at 192.168.10.46:80 c1aa646c-b200-48f9-8e9b-9984adddf966 3:39:31 PM: debug POLL

c1aa646c-b200-48f9-8e9b-9984adddf966 3:38:57 PM: info switch 4 is OFF c1aa646c-b200-48f9-8e9b-9984adddf966 3:38:56 PM: info switch 3 is OFF c1aa646c-b200-48f9-8e9b-9984adddf966 3:38:56 PM: info switch 2 is ON c1aa646c-b200-48f9-8e9b-9984adddf966 3:38:56 PM: info switch 1 is ON

c1aa646c-b200-48f9-8e9b-9984adddf966 3:38:54 PM: debug sendCommand(Status:null) to device at 192.168.10.46:80 c1aa646c-b200-48f9-8e9b-9984adddf966 3:38:54 PM: debug POLL c1aa646c-b200-48f9-8e9b-9984adddf966 3:38:31 PM: debug sendCommand(Status:null) to device at 192.168.10.46:80 c1aa646c-b200-48f9-8e9b-9984adddf966 3:38:31 PM: debug POLL `

BrettSheleski commented 6 years ago

I couldn't tell you why the poll-call isn't updating the status. My guess is that it's being called on some other thread under-the-hood and the http response handler only operates on the main thread. Who knows though.

As for devices, I'm a proponent of just grabbing some Wemos D1 minis and flashing them with Tasmota and hooking up whatever sensors you want to it. It works pretty well (and cheap). However Sonoff devices are still the best in some situations.

GeorgeIoak commented 6 years ago

Yeah, not sure about the POLL command either. I tried to sniff my network but for some reason I wasn't seeing the traffic. I could see the ST Hub talk to the Philips Hue a bunch of times but nothing between the Hub and the Sonoff.

That's a good idea about using the Wemos D1 with the Tasmota firmware, I hadn't though of that option. Since the 4CH has some free GPIO pins I thought I'd try to use them but first gotta get this stuff working right!

GeorgeIoak commented 6 years ago

I see you've been busy and made some changes to how things work. How can I help test now?

BrettSheleski commented 6 years ago

There's a new SmartApp and set of Device Handlers. It's still a total work in progress, but should work for Sonoff-Basic and 4CH devices.

See Issue #9