Device Data vs Attributes vs State?

devices

(codersaur) #1

While browsing the properties of devices in the IDE I’ve noticed that devices have “Data” properties, which are distinct from “Current States” (Attributes), and presumably also different to internal device.state.

Looking into the relevent device handlers (e.g. Aeon Multisensor 6) I can see that it is possible to get and set data using updateDataValue() and getDataValue(). E.g.

private setConfigured(configure) {
	updateDataValue("configured", configure)
}

private isConfigured() {
	getDataValue("configured") == "true"
}

I can’t see that this is documented anywhere (no mention here), so I’m wondering what Data is, how it’s different to Attributes and device.state, and what the relevant use cases are?

I am guessing that Data is like an externally visible version of device.state, but doesn’t support historical values and subscriptions like Attributes do?

Is anyone able to clarify?


(Keith) #2

I have the same question. I’m enhancing an existing device type that uses “Data” to set the number of endpoints. Apparently this is visible to SmartApps because the ST Multi-channel smartApp is sensitive to this particular value. Whatever value I give it, the SmartApp creates the same number of virtual switches (which is exactly what I hoped). Like you, I’ve had no luck finding this documented and of course wonder what other capabilities this can be used to expose.

@Duncan, any insight on this question? Also, any info on how to play nice with the ST Multi-channel SmartApp?


(Duncan) #3

The Multi-channel control app uses attribute values, not deviceData. The epInfo event is what it looks at for the number of endpoint devices to create. The Zw Multichannel capability is not documented because it’s slated to be replaced by true native support for multi-channel Z-Wave devices.

def installed() {
    def enabledEndpoints = []
    def endpointDescList = util.parseJson(rootDevice.currentValue("epInfo") ?: "[]")
    def delay = 400
    log.debug "endpointDescList: ${endpointDescList.inspect()}"
    endpointDescList.eachWithIndex { desc, i ->
        def num = i + 1
        if (desc instanceof String && desc.size() >= 4) {
            String typeName
            String displayName
            switch (desc[0..1]) {
                case "10":
                case "31":
                    typeName = "Switch Endpoint"
                    break
                case "11":
                    typeName = "Dimmer Endpoint"
                    break
                case "08":
                    //typeName = "Thermostat Endpoint"
                    //break
                case "21":
                    typeName = "Multi Sensor Endpoint"
                    break
                case "20":
                case "A1":
                    typeName = "Sensor Endpoint"
                    break
            }
            if (typeName) {
                try {
                    String dni = "${rootDevice.deviceNetworkId}ep${num}"
                    displayName = (displayName ?: typeName) + " ${num}"
                    addChildDevice(typeName, dni, rootDevice.hub.id, [name: displayName])
                    enabledEndpoints << num.toString()
                    log.debug "Endpoint $num ($desc) added as $displayName"
                } catch (e) {
                    log.warn "Failed to add endpoint $num ($desc) as $typeName - $e"
                }
            } else {
                log.debug "Endpoint $num ($desc) ignored"
            }
            if (desc.size() >= 6) {
                def cmds = desc[4..-1].findAll(/../).collect { cc ->
                    ["30": "3002FF", "71": "7107", "31": "3104", "32": "3201", "8E": "8E05", "85": "8505"][cc]
                }.findAll()
                if (cmds) {
                    rootDevice.epCmd(num, "delay $delay," + cmds.join(",delay 200,"))
                    delay += cmds.size() * 200
                }
            }
        }
    }
    subscribe(rootDevice, "epEvent", endpointEvent)
    rootDevice.enableEpEvents(enabledEndpoints.join(","))
}

I’d recommend continuing to use state to store internal info. Device data is meant more for platform-related stuff, though it is used in other situations too. I’m not sure why it’s not documented. If you want info to be available to a SmartApp, pass it as the value to an event of a custom attribute.


(Keith) #4

Thank-you @Duncan for the information on the ZW Multichannel SA. This helped immensely. I also removed all references to the get/updateDataValue per your recommendation and I now have a very nice Multichannel integration. I do have a couple of follow up questions:

  1. Since I need to send events from both commands and the parse() method, I am returning events in the response List when called from Parse, but using sendEvent() to send events from commands. Is there any benefit to returning events from Parse versus always using sendEvent()? (Just looking for consistency and reuse within my DTH)

  2. Speaking of the response List, I am returning ZW commands both from parse() as well as commands (like swOn(), configure() and refresh() ). However I have had no success in returning ZW commands from a system call to a runIn method. Should that work for ZW commands? if not, is there an alternate way to initiate a ZW command directly? (akin to using sendEvent() versus createEvent() and returning in response)

  3. Should I also be able to return ZW commands from the poll() method? Not working right now but could be my own issue.

Thank-you very much for your help!


(Ty) #5

Hi, I am currently developing a Zigbee DTH with 2 endpoints. It currently has 3 different temperature inputs to it, and also 2 different switch on/off outputs for it. Question is, I have the device handler working just fine, and everything shows up, reports, binds etc in the custome device type handler and works. However, I’m unclear how to make those items show up when using other smartapps as individual items? For example, turn something on/off when the temperature reaches->setpoint. Will this only work if you write a custom smartapp for only the custom device?

I would like to make this device show its in/out devices (all from this one unit if they select this unit) show up to any other smartapp as temp1, temp2, switch1, switch2 etc (or if they can name these individual items on the device) for the end user so they can use any of the already published Smart apps. and select it from the switch list, or temperature list? I’ve spent quite a bit of time searching through things on the internet and the community here, but can’t determine for sure if this is even possible? Can you provide any insight on this? Is it even possible to have these individual items be visible as a selection item to any other general Smartthings app? Thank you. Ty


(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #6

Currently a single SmartThings Device Instance can only claim a single instance of any particular “Capability”.

In other words, if your single DTH is: swtich, switch1, switch2 … Standard SmartApps will only see the first “switch”. There is no Capability called “Switch2” (etc.). SmartThings does not support handling of multiple attribute instances within the same DTH.

###The Solution?
The standard solution is to spawn virtual/child Devices (with a synchronizing Device Manager SmartApp), one for each switch channel in the real Device.

Philips Hue is one example of this, but there are many more… multi-channel Quirky or Aeon power-bar I think?

And I’ve written this answer a few times before!


(Ty) #7

Ok thank you for the confirmation on that. I will look at those examples and see how that works. Much appreciated!


(Keith) #8

Ty, I enhanced a DTH for an Intermatic PE653 Pool Controller that has 5 endpoints to control various pool related functions (pumps, valves, etc). These 5 endpoints are exposed from the device as Z-wave multi-channel endpoints. The original author had designed the DTH to pass these through to SmartApps using the ST provided “Multi-Channel Control” (in Marketplace -> SmarApps -> More ). The key here is implementing capability “Zw Multichannel” and adding epCmd() and enableEpEvents() as well as issuing events back to the SmarpApp such as epInfo and epEvent.

I extended the Multi-Channel capability by implementing additional “virtual endpoints” above and beyond the 5 that are directly implemented in the physical device. In fact, you could implement the Multi-channel SmartApp in a DTH that does not even implement ANY multi-channel endpoints directly by mapping virtual endpoints onto functions controlled by other Z-wave commands. I did a combination of both: the 5 native channels plus 5 more for other functions.

In the end I have 10 “SmartApp endpoints” that appear in the mobile App list of Things, which means you can control them from other SmartApps as simply “switches”.

For an example you can take a look at my DTH here:

or follow the thread in the community here:

There’s also a valuable code snipit above in this thread from inside the Multi-channel SA…

Good luck!


(Ty) #9

Thank you very much for sharing @keithR. I’ll have to look more at this code. Not too familiar with Zwave items, but I’m assuming the concepts are similiar to Zigbee. I appreciate the information as I"m finding this side is the hardest to implement with the device, but this helps greatly!