Help Comprehending the function of a childdevice and value assignment

My goal is to write an app to read a temperature sensor & a humidity sensor, calculate the Dew Point and Heat Index. Then put the results somewhere a dashboard tile can access the data.

My understanding is the creation of a ChildDevice is needed to store each result. Is this correct?
Is there a way to store two results in one ChildDevice?

I envision the ChildDevice is only some code that creates an object in the data base where a number/text can be assigned.

In this line:

averageDev.setLux(avg)

I don't understand the assignment of a value to the ChildDevice. In the above line from the code at the end of this post appears to be setting the "averageDev" object to a value "avg".
What has me completely baffled is the " .setLux " modifier. Nowhere in the code are the letters setLux defined as anything. If it was just "set" I could see how it might be just an assignment modifier but I have no idea where "setLux" came from.

Below is an excerpt from Hubitat Example Code

def initialize() {
	def averageDev = getChildDevice("AverageLux_${app.id}")
	if(!averageDev) averageDev = addChildDevice("hubitat", "Virtual Illuminance Sensor", "AverageLux_${app.id}", null, [label: thisName, name: thisName])
	averageDev.setLux(averageLux())
	subscribe(luxSensors, "illuminance", handler)
}

def averageLux() {
	def total = 0
	def n = luxSensors.size()
	luxSensors.each {total += it.currentIlluminance}
	return (total / n).toDouble().round(0).toInteger()
}

def handler(evt) {
	def averageDev = getChildDevice("AverageLux_${app.id}")
	def avg = averageLux()
	averageDev.setLux(avg)                         <<<<<<<<<<<<<<<<<<<<<<<<<<<<
	log.info "Average illuminance = $avg lux"
}

Not necessarily, but if you want to use "standard" attributes (i.e., attributes that are part of capabilities), then you'll need to use a child device--or some other way to get the data out there--if the parent device is already using the "standard" attribute(s). If not, you could just use the standard attribute on the parent device. I suppose you'll also run into this problem if you need two attributes of the same name, say, temperature. There isn't really any standard attribute I can think of that would mean specifically dew point or heat index, so the temperature attribute (from the TemperatureMeasurement capability) is probably your best bet if you want to stick to standard attributes, and child devices (one for dew point with a temperature attribute that represents it, and one for humidity that works similarly) would probably be the best way to do that.

But if you don't care about standard attributes, you could use custom attributes on the parent device--say, heatIndex and dewPoint. Dashboard can display any attribute (custom or not) on a tile via the "Attribute" template, so there's no strict need to use a standard attribute just for that. But, sometimes the other kinds of templates give you a better display (not sure that would really apply here, except I'm not sure if you'll get units without the "Temperature" template or something else meant specifically for that). And if you plan on using these devices/measurements in non-custom apps (and even lots of custom apps, at least ones you didn't write), standard attributes are more likely to work, so I'm not saying this is a good idea in all cases--just another option.

For the second part of your question: child device or not, as you may have surmised by now, you can store as many values as you need. But they do need to be distinct attributes; you can only have one attribute with a given name for any device.

In the initialize() method, you can see that the device that averageDev refers to is of type "Virtual Illuminance Sensor," using Hubitat's built-in driver of that name. This device exposes a command called setLux() that takes one parameter, a number corresponding to the lux/illuminance value. In general, when you have a reference to a device (technically a DeviceWrapper object, though you don't really need to know that to do this), you can call any command on it by using a similar syntax: mySwitchDevice.on(), myDimmerDevice.setLevel(50), and so on. This is the same as that: just running a command on the device--or, as it is from the Groovy side, just calling a method on that object. This is defined in the child device, whose code we can't really see, but we know this method exists because it's exposed as a command on the device page for that child device. (In parent/child situations, I'm pretty sure you can also call any method on the child device, even ones that aren't specifically commands in the Hubitat sense, but for arbitrary devices, I know this isn't the case.)

4 Likes

Download the Hubitat app