Virtual Container appCreateDevice() Documentation

I decided to create a separate topic for this portion of the driver so that it did not clutter the other thread. This thread is for developers that would like to use Virtual Containers within their smartApps.

As of v1.1.20181118 VC allow smartApps to dynamically create a container, populate them with child devices and also allow these child devices to communicate through their container back to the smartApp that created them.

Currently only one child parameter can be passed through the Virtual Container

The following methods can be utilized for this function

  1. appCreateDevice("childDeviceLabel", "driverName", "driverNameSpace", "uniqueIdentifier") - method for use by smartApps to dynamically create a child device within a Virtual Container. The "uniqueIdentifier" parameter allows the smartapp to index all the children in some way.

  2. childList() - to be used by parent smartApps to request a list of all the container's childDevices.

  3. childComm("Command to execute", "parameter", "Child Device Id") - this method needs to be used from the child driver code. It allows child devices to communicate through the container and back up to the parent smartApp (single parameter only). This is only possible with custom (non hubitat) child drivers for obvious reasons.

Sample Code uses a Playlist Container that houses "Preset Stations" as child devices

Part 1A. Sample code for creating a container with you smartApp:

def createContainer(){
	def container = getChildDevices().find{it.typeName == "Virtual Container"}
		if(!container){
			log.info "Creating Playlist Virtual Container"
			try {
				container = addChildDevice("stephack", "Virtual Container", "Playlist${app.id}", null, [name: "Playlist-Container", label: "Playlist-Container", completedSetup: true]) 
			} catch (e) {
				log.error "Container device creation failed with error = ${e}"
			}
		}
}

The above will create a Virtual Container with:
label - "Playlist-Container"
deviceNetworkId - "Playlist${app.id}"

Part 1B. Sample code for creating a child within the above container (appCreateDevice method):

def createVchild(uniqueIdentifier){
	def container = getChildDevices().find{it.typeName == "Virtual Container"}
		if(container){
			container.appCreateDevice("My Container Child Playlist l", "stephack", "Sonos Playlist", uniqueIdentifier)
		}
}

The above will create a Virtual Container child device with:
label - "My Container Child Playlist l"
driver - type is "Sonos Playlist" in namespace "stephack"
data value "vcId" - the vcId data value will hold the unique identifier that can reference a specific child in the container.

Part 2. Sample code to retrieve a list of child devices stored in the Virtual Container (childList method):

def getContainerChildren(){
	def container = getChildDevices().find{it.typeName == "Virtual Container"}
        def vChildren = container.childList()
        	if(vChildren.find{it.data.vcId == "stationID"}){
        		log.info "Found the Play List with Station ID 'stationID' that you are looking for"
        	}
}

Part 3. Custom Driver Sample Code:
Continuing from the example above, let's say you want one of the child devices to execute playTrack(uri) method in your smartApp. The code in the child driver would look something like this

def sendUri(stationURI) {
	log.debug "Playing track = '${stationURI}'"
    	def childID = device.data.vcId
    	if(childID) parent.childComm("play", stationURI, childID)
}

This will tell the container device that you would like to execute the play(stationURI, childID) command from the parent smartApp.
To link back to the appCreateDevice command in Part 1B that created the child in the first place....childId would have a value of "uniqueIdentifier" when you created the device.

Part 4. smartApp sample code:

def play(stationURI, childId){
	log.info "Starting PlayList ${childId}"
	playTrack(stationURI)
}

The above will play the track that the child device requested.

2 Likes

Is it possible to add current devices to the container ?

Unfortunately not (at least not a way that I know of). The parent/child link is made when the parent device creates the component device. I remember there was someone who did some DNI swap magic to get a zigbee device into a container. I don't know if it was completely successful though.

See the discussion here on the driver thread.

@Royski might be able to provide some insight.

2 Likes

The one thing I miss from ST.... groups/rooms

1 Like

Yeah...that was kinda what this driver did before the 2.0 update. Initially the only device you would see was the container on the main page and the child/component devices could only be seen when you opened the container. In 2.0 they made big UI changes that visually ungrouped everything....essentially removing the benefit of the VC driver altogether. Thankfully the HE team compromised and added the indented structure you see today. Not ideal but it at least groups the devices together.

2 Likes

Maybe you guys can encourage the HE guys to code in floating rows so we could arrange devices into groups ! Ajax way....

Mine was a bit of a fluke, but it did work :wink:

1 Like