howanghk / homebridge-ewelink

Homebridge plugin to control Sonoff relays with OEM firmware
MIT License
81 stars 46 forks source link

2/3 gang wall switch going crazy #96

Closed ozzyobr closed 4 years ago

ozzyobr commented 4 years ago

First, thanks for the plugin, it is awesome

I've searched and I was not able to find another issue like this, so I'm creating a new one.

Background:

  1. I've multiple sonoff wall switches (1, 2, 3 gang) and they all work just fine with Alexa/Google/IFTTT
  2. After installing homebridge / hoobs, every time I touch ONE (CH1) button in a 3 or 2 gang wall switch it WORKS just fine
  3. When I touch ONE (CH1) button and then a SECOND (CH2) they go crazy. They turn on then off in a random order
  4. This also happens if I do it in the ewelink app (same behavior)
  5. This also happens if I use a routine in alexa to turn on and off multiple channels in the same wall switch.
  6. When I stop the homebridge, they go back to their normal behavior Video: https://youtu.be/CsK0ynwNQjg Log (restarted before recording the video): firstvideo_log.log

What I did:

  1. upgraded all firmwares
  2. upgraded homebridge and the plugin
  3. removed the ewelink from Alexa and removed the service from google assistant
  4. unshared all devices in ewelink (I've created an account for this plugin based on the instructions)
  5. deleted the cache in homebridge
  6. erased everything, started from scratch, tested in my Ubuntu and in a raspberry pi

The funny thing is: if I touch the buttons slowly (like with a second after each touch) they work just fine :roll_eyes: Video: https://youtu.be/bUEYP57nBZ8 Log (restarted before recording the video): secondvideo_log.log

Configuration file

{ "bridge": { "name": "Homebridge B77B", "username": "0E", "port": 51255, "pin": "400-81" }, "accessories": [], "platforms": [ { "platform": "eWeLink", "name": "eWeLink", "countryCode": "55", "email": "my-e-mail", "password": "ha", "imei": "some random thing" }, { "name": "Config", "port": 8581, "auth": "form", "theme": "dark-mode", "tempUnits": "c", "lang": "auto", "platform": "config" } ] }

I hope this is something I'm doing wrong, I'm really looking forward to make this work with my new apple devices :)

PS: not a coder, but can donate :moneybag: to help with the development, just let me know

ozzyobr commented 4 years ago

I thought this could be related to a timing/delay issue, since if you touch the wall switch giving it enough time it works fine. So, after digging on the code following the log structure, I was able to find some locations where "I think" it is calling the api.

I’ve added some “delay”, thinking that if we send commands “slowly” it would work as the same way of the wall switch. Obviously, that did not solve the problem, it only added a delay to it. Oh well, at least I’ve learned something new.

One question, once you touch the wall switch we get an “update” from the API, why do we need to send data back to the api? Shouldn’t we just update Homebridge with the new status?

Remember newbie here, learning on the fly

ozzyobr commented 4 years ago

OK, also found that Sonoff 4CH R2 is also impacted by this.

Apparently, when you press a button in ewelink (or on the switch) it will

  1. "notify the plugin"
  2. the plugin will change the accessory state in homebridger
  3. the plugin will send an update back to ewelink to set the same configuration?

looks like I'm talking to myself... 🤔

ozzyobr commented 4 years ago

@howanghk I think I've found the solution but I would like to hear your opinion :)

Every time we receive an update from ewelink through platform.wsc.onmessage we process it, update the accessory state and send a message back to ewelink telling it to update the device state again. In a nutshell we are setting state in ewelink after getting a message from ewelink telling us to update our state and we don't need to do that.

The multi switch is going crazy (check the youtube video in the original post) because when we touch a channel, ewelink sends a message to the plugin and the plugin tells ewelink to execute the same command, that is to turn on/off the same device/channel again. The problem will happen if you touch a second channel in the same device quickly.

Sequence of events:

In order to solve the problem I created a new boolean “global variable” to know if we are dealing with an external update or not.

So when a call is made to updatePowerStateCharacteristic I set the variable to “true” meaning it is an external call. When eWeLink.prototype.setPowerState is called it will check if the variable is true, and will not send it back to ewelink.

This resolved all the issues, all my ewelink devices work like a charm (2 and 3 gang, the 4ch pro, mini, basic) including ewelink scenarios to cross turn on and off devices.

I’ve also reconnected Alexa to ewelink and it is working. Now I can use eWelink, Alexa, Homebridge and Home app at the same time.

I know this is not a great way to do it and I should pass it as a parameter but I’m working on it. I was not able to understand how eWeLink.prototype.setPowerState is called after eWeLink.prototype.updatePowerStateCharacteristic.

Let me know if you want to talk about this, looking forward giving back to the community.

ozzyobr commented 4 years ago

no aswer? 😒

bwp91 commented 4 years ago

I would be interested in seeing your solution!

ozzyobr commented 4 years ago

I would be interested in seeing your solution!

Awesome! I'm swamped with work this week, I'll come back to it during the weekend. thanks!

bwp91 commented 4 years ago

I would be interested in seeing your solution!

Awesome! I'm swamped with work this week, I'll come back to it during the weekend. thanks!

I'm going through this package line by line trying to improve how some things work. I'd be interested to see how you have solved this issue as it is troubling me. I am not great at coding, but given a template I can sometimes make some changes.

bwp91 commented 4 years ago

I have (finally!) found a solution myself which seems to work. I'd still be interested to see your fix.

ozzyobr commented 4 years ago

Thanks for replying... I'm looking at it now.

The way I implemented it earlier (and it worked perfectly) was to define a " global" variable and set it to true when we get an external update and test it in the setPowerState. That works and it is easy to implement, the problem is that it is not the best way.

Options I found:

  1. add an extra parameter on setpowerstate (but that means we need to update multiple items in .setCharacteristic(Characteristic.On, isOn) (for each device type)
  2. change all update*Characteristic to do not call .setCharacteristic
  3. keep the global variable in setpower state and be done 🙄

What is your solution? (maybe we work on this together - zoom session maybe, I've a fork https://github.com/ozzyobr/homebridge-ewelink)

(I also purchased a 3gang switch just to test this, wife was not happy with me messing with the lights all the time, LOL)

bwp91 commented 4 years ago

@ozzyobr how can i contact you?

ozzyobr commented 4 years ago

This issue is fixed on https://github.com/thepotterfamily/homebridge-ewelink-beta