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
Add Philips Hue Adapter #99
Conversation
7e6a446
to
7ec6560
Compare
I figure out the issue! It turns out that @dhylands This should be good to go whenever you're available |
b574c60
to
6445650
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had an issue when I initially paired the hub. One of 3 lights showed up, but I when I clicked Save, nothing happened. When I cancelled out of adding, and re-entered then my 3 hue bulbs showed up and the save worked as expected.
@@ -0,0 +1,233 @@ | |||
/** | |||
* | |||
* PhilipsHueAdapter - an adapter for controlling TP-Link Smart Lights |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo? (reference to TP-Link?)
'use strict'; | ||
|
||
var PhilipsHueAdapter = require('./philips-hue-adapter'); | ||
var rp = require('request-promise-native'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
request (a dependency of request-promise-native) appears to be missing from package.json
tip: When adding lots of new stuff, I generally like to clone the repository into another directory and verify that it runs from a fresh clone.
That helps to identify missing dependencies as well as files you may have forgotten to add to the PR (one of my favorite tricks).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the heads-up! I assumed incorrectly that request-promise-native would have request as a dependency instead of a peer dependency.
this.pairing = true; | ||
var endTime = Date.now() + timeoutSeconds * 1000; | ||
|
||
var attemptPairing = () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I don't understand why you create a function and then call it rather than just put the contents inline?
return storage.init(); | ||
}).then(() => { | ||
return storage.getItem(KNOWN_BRIDGE_USERNAMES); | ||
}).then(knownBridgeUsernames => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't knownBridgeNames have parens around it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally believe the code looks cleaner without them, especially in cases like catch(e => {})
. I can add them here, but is there a style guide I should be following?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For me, I guess it was more a case of not realizing that you could even do it that way.
The only style guide that we really have is the suggestions from the linter, and this passed the linter. @benfrancis may have an opinion, but otherwise I think its fine.
var attemptPairing = () => { | ||
this.pair().then(username => { | ||
this.username = username; | ||
return this.discoverLights(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It also isn't clear to me why you're returning anything when the return value isn't used?
I've seen this being used before - and I'm probably just not getting something.
} | ||
knownBridgeUsernames[this.bridge.id] = this.username; | ||
return storage.setItem(KNOWN_BRIDGE_USERNAMES, knownBridgeUsernames); | ||
}).catch(e => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find it useful to do console.error(e) this then prints a complete backtrace when e is an error. When you add anything else (like in the line below) then it prints the string representation of e which doesn't include the backtrace.
|
||
/** | ||
* Perform a single attempt at pairing | ||
* @return {Promise} Resolved with username if pairing succeeds |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this paring the hub? or pairing a light?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pairing a hub then discovering lights, I updated the comment to be a bit more clear
The problem where 1 light shows up and can't be added is related to the way that startPairing works. I'm trying to write a test to demonstrate this, but the behavior I've found is that only one device can be added during an instance of pairing. It gets this one device from models/action.js handling the 'pair'. AdapterManager.addNewThing().then(function(thing) {
Things.handleNewThing(thing);
action.status = 'completed';
})... Once the Hue hub is paired and can create lights, the mechanism that causes those multiple devices to show up is the I don't really know how to fix this issue, although I could probably fix the issue causing the one device that shows up to be unable to be saved. |
There were two issues in play. First, the "Send Thing instead of description" allows the user to save Things that are dynamically added while the Add New Things menu is open. Second, the Things/Actions models now properly work together to communicate all newly available Things instead of just the first that appears. Actions was using the Promise resolution as its only source of new things, meaning that all of the pairing attempts would "race" to be the first to resolve the Promise. The winning Thing would then be sent via I'm now looking at how to write a test that will demonstrate this behavior. (there was a bit of delay after I spilled half a cup of tea on my computer causing its display to short out and its keyboard to die, but the passage of time is a perfect panacea) |
@benfrancis I think you probably have some opinions on the movement of |
522172f
to
c14533c
Compare
Since the changes to AdapterManager, NewThingsController, and the Actions model are pretty far removed from the Philips Hue adapter I've moved them to #103 |
Only being able to pair one "Thing" at a time was actually an intentional design decision. IIRC this is because the push button commissioning method used by ZigBee and Z-Wave creates a security vulnerability in that the pairing mechanism allows any device to connect to the hub while in pairing mode without any form of authentication. A malicious device could try to pair with the hub while it is in pairing mode and go unnoticed by the user as they add the device they intended to add. By locking this down to only allow one device to be paired at a time it makes it much more obvious to the user when a device was added unintentionally. However, with the UI we ended up with this does get confusing because you can still have multiple devices displayed in the "add device" dialog and "pairing" and "adding" have become separate user interactions. So maybe its right to re-visit this decision. I guess this becomes more of an issue when you pair the gateway with another hub which may have multiple devices already connected to it. I personally don't like the idea of a "hub of hubs" and think we should focus on supporting standards like ZigBee, Z-Wave and Bluetooth, but I know Dave feels differently about this. I'm sure there will be demand for a Phillips Hue adapter and the encryption used by the Zigbee Light Link profile makes it tricky to support the bulbs directly. Regardless, our pairing UI is probably going to need some refinement to support the quirks of the various pairing mechanisms used by devices! See my review in #103 for the specifics around the changes to /new_things |
Okay, so if I understand correctly the ZigBee and Z-wave The interpretation of |
ZigBee always allows multiple devices to join for the duration that the controller is pairing. What the adapter does is that it uses the first one to resolve the promise. Remaining devices that get added are just added to the adapter manager and will be visible the next time you enter the Add Thing screen. I think that having the new devices be posted via a web socket would allow them to appear in real-time. |
I also think that we need to think of a way that the adapter can tell the UI that it needs user input. For Zigbee, adding a new device doesn't require pressing a button. If the adapter is in pariing mode and you plug in an unparied device, it will automatically get added with no button press required. For Hue, it would be nice to prompt the user that the hub needs to be paired (perhaps at the very beginning of the add process). For ZWave, you actually need to press a button on the device, and if the user was used to the ZigBee behaviour of not having to press a button, then they might not realize that they're supposed to press a button. |
Yeah it doesn't really make sense as currently implemented. The original intention was that adding and pairing would be the same thing and you could only add/pair one device at a time. The reality turned out to be different as the underlying protocols allow multiple devices to be paired and we just don't show them, which is much worse. "Adding" (to the database) is currently a separate interaction to "pairing" (with the dongle) and we currently have no UI for "unpairing", only "removing". This can definitely be improved but I'm hesitant to try to make major changes to the way it works a week before release. I'd suggest we fix the bugs we find (like the one James seems to have found, and the fact we don't show all the devices that are paired) and hold off adding new features (including new adapters that require major changes to the core) until the next release. As an aside, I think it was someone from Develco who suggested only allowing one ZigBee device to pair at a time, as a mitigation for using push button commissioning without requiring the entry of a serial number in the UI as an extra security measure. |
c14533c
to
7769e4a
Compare
7769e4a
to
dff1ca4
Compare
Codecov Report
@@ Coverage Diff @@
## master #99 +/- ##
======================================
Coverage 82.6% 82.6%
======================================
Files 30 30
Lines 920 920
======================================
Hits 760 760
Misses 160 160
Continue to review full report at Codecov.
|
@hobinjk what's the current status of this PR? Would we be able to demo this feature too? |
@andrenatal I've spun it off into https://github.com/hobinjk/philips-hue-adapter and the current plan is to use the adapter API once it's finished although for now I've been manually adding the adapter to |
It exposes each light as an onOffSwitch.
There's currently an issue in the first run where the bridge pairs then shows only one device which is missing the
id
key required for being saved as a thing.This should be ready once that issue is fixed.