jangxx / node-magichome

An incomplete implementation of the functionality of the "Magic Home" app. Partially a port of https://github.com/Danielhiversen/flux_led to Node.js
ISC License
124 stars 26 forks source link

Whenever changing light color on Light instance, only first change occurs. #10

Closed NoxPhoenix closed 5 years ago

NoxPhoenix commented 5 years ago

I think there is something strange with the transport socket connection when changing lights, unless I am doing something wrong.

calling light.color() the first time works as expected, but then later if I call light.color() nothing happens, and in the queue property I see pnding promises has increased to 1, and in the transport socket I see connecting: false

Do you have any idea what is happening?

Logging light.color() appears the promise always remains pending... never resolves.

jangxx commented 5 years ago

I have not yet looked into your specific problem, as I have a question first. Are you sure you are on the correct Issues page? As much as I have planned to eventually rework this library to use Promises, the current implementation (of the Control class at least) is entirely callback-based. I saw one guy forking this repo and building Promise support themselves (https://github.com/petschekr/node-magichome), but as for this repo, there is not proper Promise support as of right now.

Using stuff like util.promisify might work, but I have not tested it myself.

NoxPhoenix commented 5 years ago

Thank you for responding. Sorry, I forgot about that completely. I promisify this library with Bluebird's promisifyAll. So I am calling the Async suffixed methods. Further digging leads me to think that they maybe different versions of the magic-home network devices, since it seems like the real issue is the async generator is never resolved, which I believe to only be happening because the magic home device I am communicating with never responds. Perhaps it just eats the request and then never responds?

Is there a good way you can point me to test that?

P.S. I also implemented with CBs and the CB is never called either.

jangxx commented 5 years ago

You are right, there are different versions and behaviors to these Magic Home devices. For this reason, the Control constructor takes a second argument characteristics, to deal with this. You can try to create your control instance with

let light = new Control('1.2.3.4', { wait_for_reply: false });

This way the callback gets called immediately after the command is sent out. You can see the other characteristics (and the default values), in the cli testapp.

NoxPhoenix commented 5 years ago

Thank you for the responses, this worked beautifully. How do I know whether or not to mess with the min ww or the set magic bytes characteristics?

jangxx commented 5 years ago

As I've stated in the readme:

unfortunately these parameters have to be found out through trial and error

Sadly, I have no idea either. The current solution is obviously a band aid, which I only put in after I bought a second controller, which behaved very differently than the first one. You can basically do two things: Just work with the defaults and then adjust the characteristics if something doesn't work (like in your case), or you use a tool like Wireshark to inspect the packets and look at their format.

For the first option, I can give you a hint: Try to set the color to an RGB value, where at least one of the color components should be 0. Use query to read the values back and see if the component value is actually 0 or 1.

To figure out the magic bytes, you pretty much need to use Wireshark however. I don't even know what they do, I only know that using different values lead to unexpected behavior. I think there are only three valid values for each of the bytes however (0x00,0xf0 and 0x0f), so you could check all six possibilities by hand.

I'm pretty sure we could extract all this information by looking at the model number returned in the discovery. After all, the Magic Home app seems to know what these numbers mean and it even displays a different icon for different controllers. Unfortunately, my sample size is two, so I don't think I could start building my own database based on that. Looking at other implementations of the protocol in other languages (like the original Python one, or this one written in Go) did not lead to new insights either, so until someone figures this out, the band aid needs to do and we just have to trial-and-error our way through it.