Skip to content
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

Consistenly assign Broadlink.devices keys with macAddress.toString('hex') #22

Merged
merged 5 commits into from
Jul 5, 2024

Conversation

octavifs
Copy link

@octavifs octavifs commented Mar 3, 2024

Hi Cameron,

I'm a heavy user of homebridge-broadlink-rm, with 4 of those devices at home, and I had been struggling with auto device discoverability for a while. Your library always found 3 of my 4 devices, and not necessarily the same 3. Initially, I thought it was the broadlink hardware entering locked mode, but when using python-broadlink I always managed to find the 4 of them. So, I finally spent some time today to dig into it, and it seems that I found out the root cause.

Essentially, there is an expectation on the onMessage() handler that the key for Broadlink.devices will be generated as macAddress.toString('hex'), but during the addDevice() method we directly assign the buffer value as the key: this.devices[macAddress] = device

That, in itself, seems innocent enough. The check to prevent re-adding existing devices is wasted, since macAddress.toString('hex') != String(macAddress), but the resulting Device object is the same.

Now, here's the interesting part, String(macAddress) can return the same string, for different buffer values. And that's exactly what was happening in my case. I had 2 devices, with 2 different mac addresses, that resulted in the same value when stringified. This script demonstrates the bug:

const assert = require('node:assert').strict;

let macAStr = 'ec0bae9e9d8b'
let macBStr = 'ec0bae9eb0b4'

let macABuff = Buffer.from(macAStr, 'hex')
let macBBuff = Buffer.from(macBStr, 'hex')

let devices = {}
devices[macABuff] = macABuff
devices[macBBuff] = macBBuff

assert.strictEqual(macABuff, macABuff, "Buffer A value matches itself")
assert.strictEqual(macBBuff, macBBuff, "Buffer B value matches itself")
assert.notStrictEqual(macABuff, macBBuff, "Buffer A and B values are different")
assert.notStrictEqual(macABuff.toString('hex'), macBBuff.toString('hex'), "Buffer A and B .toString('hex') values are different")
assert.strictEqual(String(macABuff), String(macBBuff), "String(Buffer A) and String(Buffer B) values are the same!!!")
assert.strictEqual(Object.keys(devices).length, 1, "devices Object has only 1 key!")
assert.strictEqual(Object.keys(devices)[0], String(macABuff), "devices key matches String(macABuff)")

The PR simply ensures that broadlink.devices are assigned with macAddress.toString('hex'). That ensures the serialization is safe, and also prevents from re-adding devices that were already discovered. I've been trying this fix on my homebridge installation and has been working like a charm so far. Would be very grateful if you could merge it in, and include it in a future release of homebridge-broadlink-rm. Let me know if you need any modifications on the PR, add tests, etc.

Thank you very much for your software!

kiwi-cam and others added 4 commits July 22, 2022 08:05
* Adds support for 0x520b and 0x520c Devices
…ing('hex')

Otherwise, Broadlink.addDevice check always fail to match any existing devices.

Moreover, String(macAddress) can return clashing string values, even if the buffer values are different, so it is not a safe function to have unique keys from the buffer value.
@banboobee
Copy link

I believe your observation is reasonable. Implicit conversion to index the devices uses default encoding of utf-8, and potentially becomes identical for different mac addresses. Thus, need to specify hex explicitly.

Copy link
Owner

@kiwi-cam kiwi-cam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved for BETA release

@kiwi-cam
Copy link
Owner

kiwi-cam commented Jul 4, 2024

I'll look at a new BETA release in the next day or two

@kiwi-cam kiwi-cam added the enhancement New feature or request label Jul 4, 2024
@kiwi-cam kiwi-cam merged commit fb25648 into kiwi-cam:beta Jul 5, 2024
@octavifs
Copy link
Author

octavifs commented Jul 5, 2024

Thanks! Much appreciated!

@banboobee
Copy link

homebridge-broadlink-rm-pro@4.4.16-beta.2 doesn't refer this beta.

$ sudo npm install -g homebridge-broadlink-rm-pro@4.4.16-beta.2
$ cd homebridge-broadlink-rm-pro
$ grep -i version node_modules/kiwicam-broadlinkjs-rm/package.json
"version": "0.9.19",

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants