Trying to generate a device multi select input for several device types: I don't think that's possible so I think I'll have to build the list myself for presentation via an input.
Suppose I have a multi select device input list using type:'Virtual Contact Sensor' and another with type: 'Virtual Motion Sensor' held in settings?.contact and settings?.motion - how could I concatenate those two 'device object' lists to create another that can then be used in another multi select input ?
along the lines of...
Well, I know it is possible because certain apps do it. For example, the maker API just has one big list of all of your devices. I was just looking to try and do this on Sunday and couldn't figure it out either. Eagerly awaiting any possible solutions to this one.
As a fall-back, you can always do two lists, one using the actuator capability and one using the sensor capability. Everything should fall into one of those two capabilities. Of course, that's only a workaround.
Glad someone else is interested .. I worked out how to get a list of all devices using capability.* but I just want an input listing all the 'official virtual devices' which comprise 22 different types:
My understanding of the input "capability.foo" is part of the "security" model where you're permitting apps access to devices based on the user input. So they have to go through the input at one point. So at very least you'll have to a capability.* then a 2nd filtered list following it.
Don't use device names or labels. Those are not unique, use the device id which is unique. Event though it's confusing I could have 50 devices labeled "Lights" but only one with id 487.
Should be easy with the enum input....now I feel like trying to do it. @bptworld has a good working solution, but I don't like all the search and replaces....I wonder...
Oooh thanks @asj this is really helpful.. I'm going to need to filter on device type but that should be easily adapted. I already have a 'select all' input so I have all the devices - I'll just get the user to click the 'select all'.
Haven't looked yet but is the second list you create a list of device objects ? Something I can do a lookup (by networkDeviceId) into to get the matching device object returned (and hence find the deviceType) and so that I can then issue commands to the device ?
Otherwise I should be able to do that against the 'all devices' list still .. but I think that would require a long loop search and performance is key (I'm reacting to incoming MQTT messages)
Should read better - you have a device object lookup function - that's all ideal @asj - thanks so much for your help here.
The all device is already a list of device objects. So I can loop that and compare deviceIud to what's in alldevices. I don't create this, it's part of the input from settings.
If you're worried about load and interating the list constantly, you can add a @Field map to the device, look at my other hubitat github apps for examples. The map would have the key be the deviceid and the value the object. You try doing a lookup in the map for deviceId to get the object, if the lookup fails then you iterate the list and update the map. The field will be free'd when the hub needs ram, so it'll empty now and then, but if you're doing a good bit of traffic then you'll have a pretty good hit rate based on my experience.
I've thought about this and approached it differently to avoid the repeated lookup loops each time an MQTT message arrives.
Using your code I also create another atomicState map. This one has my 'key' and then the 'value' is the actual device object. I get this by looking up the device in allDevices when the user first enables the device. Thus it's immediately available next time.
I'm still going to research the @Field usage too as my Groovy language learning continues because I would really like my filtered list to have device objects available via input. But I still have that issue then of not displaying object names in the dropdown instead seeing [object, Object] . This might be because it should be a map with an object/displayname basis i.e. with the device object as the key if that's workable.
I have one question - when I create a long map where the values are device objects is that taking a lot of space or am I right assuming the value is just a pointer to the device object ?
I'm guessing the map should just hold references to the object, and not full/deep copies. So you should be fine. Couple of things to keep in mind:
state can only hold serializable types since it's stored in a db. So things like strings, numbers, etc. But not objects. Just something to keep in mind.
Not sure about putting an object into a map as a key. I'm not familiar enough with Java/Groovy, but being a map that imposes certain restrictions regardless of the language, and that's the key has to be hashable. Not sure objects, especially the InstalledDeviceWrapper (or what ever it is) is hashable, or if groovy can use anything but strings. Anyways, this is beyond my groovy knowledge.
I have found that once I retrieve the device object via state map (atomicState actually) then although I can read it's attributes I can't execute any methods on the object so I'm back to trying to make that second filtered list return just one settings containing all the filtered devices that I can iterate over.
I've a lot to do still in my MQTT app because I'd really like a Xmas availability of beta1 so at the moment I am iterating allDevices - I'll try and look back when I get a moment and optimise this just to 'filtered' devices which for me is all devices using one of the 22 Hubitat virtual drivers.
Is it possible to have two device selector inputs and combine (merge) the settings variables used into another to use in another ‘enum’ type input ? I am trying to identify all enabled selections from your 22 different virtual drivers and then combine these devices into another list that I can create a subset from, or even a single select.
I had hoped for a capability ‘virtual’ which would make this easy but the feedback from Hubitat is no that won’t happen.