Question:
Using a Smartthings Edge driver, how can I present the user with available zigbee dimmable lights to select for pairing with my custom zigbee dimeer in the smartthings app?
Background / Detail:
I’m working on an open-source sample zigbee library (GitHub - stevenlovegrove/xbeeduino: Zigbee SmartThings Sample) and am implementing a wireless dimmer switch for remotely controlling zigbee dimmable lights. I can successfully ‘mirror’ the switch and light using the SmartLighting automation app, but this is difficult to setup for a user and the round-trip time from dimmer to hub to bulb is quite long and it feels laggy. I can hardcode the dimmer to talk to the bulb directly by specifying the zigbee address in code, but this wont work for end users. I would like a way for the SmartThings hub in its roll as coordinator to facilitate getting the bulb’s zigbee address to the wireless dimmer during setup somehow. Any suggestions or pointers on how to do this?
Thanks, that looks useful though it doesn’t seem like there is a device selection widget in there? I could use a string field, but the device address is hard to find unless you’re a developer or enthusiast (you can’t see it from the app, right?).
For the device preferences, can the enumeration option get updated by the driver? It looks like it’s fixed yaml, but if it could then perhaps it could get populated with devices. In that case, perhaps Driver — SmartThings Edge Device Drivers documentation would be useful. I can’t tell from the documentation - does that return all devices connected to the hub, or just ones using this driver?
EDIT: just tried it and driver:get_devices() only returns the devices running this driver, which I guess is unsurprising. Perhaps there is a way to enumerate Drivers to find them that way?
EDIT2: just tried a test setting a preference dynamically (I’m new to Edge and Lua, so I could be doing something wrong), but I can’t find an API and setting it in the Device object directly doesn’t seem to be allowed:
local device_init = function(self, device)
log.debug('Attempting to add preference')
device.preferences = {
testPreference = {
title = "Testing",
name = testPreference,
description = "testing driver set preferences",
required = false,
preferenceType = string,
definition = {
minLength = 0,
maxLength = 10,
stringType = text,
default = "my default"
}
}
}
end
yields:
DEBUG Attempting to add preference
ERROR thread encountered error: [string "st.device"]:154: Device table access is readonly. Use set_field to add a new field to the device.
Your implementation sounds really interesting and I’d like to add a few notes:
In general, submitting your devices for certification, but since we’re still on Beta, the process hasn’t been defined yet. You’ll hear more about it as soon as we’re ready to certificate Edge Devices.
Now, about this:
If I understood this correctly, you want your Zigbee Dimmer to keep control of the Bulbs behaving like a bridge/router between the Hub and Bulbs, right? e.g.:
Hub (driver) <<Zigbee Dimmer>> Zigbee Bulbs
I believe that you could achieve this implementation supporting multiple profiles, and allowing your device/board to dynamically report fingerprints in the discovery process. This way you’ll be able to actually enable different components for each Bulb you Zigbee Dimmer has discovered previously.
However, I’m not really sure if reporting fingerprints dynamically is actually possible, but I’ll ask our engineers about it!
UPDATE: Totally possible as long as the device sticks to the spec.
Finally, is there any particular reason to avoid following the current model Edge Development model?
Thanks for your reply, @erickv - my reply below may be a bit complicated and I’m not sure it will make it clearer but I’ll try! Thanks for your time!
Unless you mean there is some other API available for certified devices(?), then I think I didn’t explain clearly enough and you think I mean having my device listed in the ‘by brand’ list when adding a device - that is not really my question. What I really want is for my device to be connected to the hub ordinarily, and for there to be a ‘Device Preference’ or something that lets the user select another zigbee device already connected to the hub which the driver can then forward the address of onto my dimmer (it could then use the device address and talk to it directly if it wanted to).
Kind of - I actually imagine both the bulb and dimmer connected directly to the hub so that smart bulbs etc can be used ordinarily through SmartThings. The problems I’m trying to solve is how to have the bulb react to the dimmer very quickly and for user setup to be very easy. If this were just a switch, I could use the automation rule system (with if/then) to connect the switch to the bulb, but that doesn’t seem to allow forwarding of the level value. The only method I have found with SmartThings is to use the ‘Smart Lighting’ SmartApp which can mirror the dimmer value to the bulb, but there are some problems:
It reacts too slowly - my dimmer is a physical slider (which can move itself) and I want it to have no lag like an ordinary (dumb) dimmer. This is not like many other paddle up/down dimmers that exist.
It is difficult to setup. The user has to find the app themselves and manually select the mirror option for every light and bulb
mirroring is only one way - if the user changes the bulb, the dimmer isn’t updated. The user has to add a second mirror rule and make sure all the mirror rules are kept up to date
My understanding is that SmartApps are being subset.
If I understand correctly, you’re describing the case where the bulbs connect only to my device and my device exposes separate components for each bulb so that SmartThings can still interact with them. That could work but I end up with the same problem of how I manage selecting each bulb to use with my dimmer - the user would have to undertake some series of actions on the dimmer itself to find and select each bulb (with dimmer flicks or hidden buttons etc) which could get quite complicated for a house full of bulbs and dimmers. It might also get a bit complicated for multiple dimmers to operate the same set of bulbs (such as for stairs etc).
I would like to avoid having my device be responsible for the bulb joining the network or having to perform any kind of bulb selection routine and leverage smartthings for that. The main motivation for connecting directly is just to achieve the low-latency updates (which is very compelling when you use it)
Since device preferences are a read-only table, I’d suggest setting the preference to the Bulbs instead of the Dimmer, this way you can command it whether to communicate with the Hub or with your Dimmer. However, this seems to be a bit out of the scope of the application layer, since you would be forcing the protocol/network layer to select a Router over a Coordinator or to overlap PAN Ids.
With that in mind, I’d stick with the multi-component approach:
Integrating your Dimmer through the Zigbee Driver as the master device under the SmartThings Hub PAN.
And integrate the slave devices (Bulbs) under your Dimmer’s PAN(but this might require multi-threading two different Zigbee modules).
Finally, by patching the master device’s metadata through the device.try_update_metadata method (see documentation) you could provide an interface to these bulbs dinamically.
The device to control could be any thirdparty level controllable device so I’m not sure it would be practical to create custom drivers for those devices to have a special preference if that is what you mean?
I’m a little unclear on this. If I understand, the device.try_update_metadata would let me replace the profile for the device with a yaml profile already packaged, not an entirely runtime defined one. That would mean I’d have to have all combinations of profile pre-packaged and it would presumably make it difficult to interact with unknown third-party controllable devices?
Regarding dynamically changing the fingerprint, I guess you mean the dimmer would change it’s manufacturer / model string based on what controllable devices are connected so that the appropriate pre-packaged profile is chosen during device-add time. To add or change a bulb for the dimmer, the user would have to remove the dimmer from smartthings, pair the new devices with the dimmer directly somehow, and then re-add the dimmer to smartthings?
Regarding the seperate PAN, the zigbee module is the dominant component cost and area size in the dimmer and it isn’t too practical (form factor, cost and power) to use two of them if that is your suggestion to maintain a seperate PAN. I don’t see a disadvantage to having all devices on the same PAN (of smartthings) - there is nothing that prevents one end-device from issuing commands to another without using the coordinator. The coordinators main role is for forming a network, and that is exactly the bit I don’t want someone to have to do without the aid of the smartthings app because it would be very tricky for the user. If the bulb is only reporting its status (when controlled via the app for example) to smartthings and not my dimmer, I think that is fine because it isn’t latency critical. The dimmer could just poll very infrequently or something, or have a smartthings type hook (like some equivalent of the SmartLighting mirror option) forward the message somehow.
Instead of a preference, is there any capability which supports elements that change at runtime? Instead of smartthings enumerating available bulbs / devices (since that doesn’t seem possible from within a driver), the dimmer could query the network and provide a list which the user could perhaps select somehow in a capability. The simplest implementation I could imagine would be just a slider with max_value equal to the number of found bulbs - as the user slides the slider, the corresponding bulb could blink. A button capability could be used to ‘select’ the bulb and have the dimmer remember it. I think this would work, but it seems quite hacky.
Hmm… You have a really good point there, I had in mind a fully custom integration and hadn’t considered interoperability.
True, but since edge drivers only provide interface for application layer-specific actions, this couldn’t be enabled from the driver itself.
This seems to be an interesting approach, but unfortunately, the range of the slider would reach the same limitation, as the range is a static value.
However, you could create a custom capability supporting either textField or numberField display types to allow user inputs and provide an interface to the setup process you describe.
Thanks for your thoughts. Hopefully a Samsung engineer will see this conversation and have some thoughts for how the API or ecosystem can grow to include lower latency use cases.
SmartThings lets users connect devices to each other through If / then rules etc so I would argue a driver exposing other devices to the user for more advanced rules should not necessarily be below the application layer, but I can imagine it would complicate many things including security.
Ideally the SmartThings app would allow continuous level variables to be forwarded within the If/Then system natively and there would be a best practice mechanism for creating lower latency control.