Correct way to call preferences

looking the some code examples and noticed some people call preferences differently. Im assuming the execution difference is minimal (both work) but which is the most efficient for the hub to process.

input 'DevIn', 'capability.motionSensor', title: 'input devices to average', required: true, multiple: true

for (com.hubitat.app.DeviceWrapper sensor in settings.DevIn) {
OR
for (com.hubitat.app.DeviceWrapper sensor in DevIn) {

I usually do devin.each{…} for this sort of thing but I don’t think one is more efficient than the other

thanks. I was actually thinking about the call up for the preferences

settings.DevIn
vs just
DevIn

There are cases (I don't remember them exactly) where DevIn doesn't resolve, but settings.DevIn does, however I doubt there's any substantive execution differential between them.

Decided to test but without having a blank hub doing nothing else id say the same.

void mastSwitchState(evt){
    if (evt.value == 'on'){

        def date1 = new Date()
        /// loop
        for (i in 1..10000) {
        	for (com.hubitat.app.DeviceWrapper dev in settings.mastSwitch){
            	def id = dev.deviceId //some simple work
        	}
        }
        // loop end
        def date2 = new Date()
        log.debug "runtime settings ${date2.getTime() - date1.getTime()}"
        
       date1 = new Date()
        /// loop
        for (i in 1..10000) {
        	for (com.hubitat.app.DeviceWrapper dev in mastSwitch){
            	def id = dev.deviceId //some simple work
        	}
        }
        // loop end
        date2 = new Date()
        log.debug "runtime no settings ${date2.getTime() - date1.getTime()}"
    }
}

image
Don't know how scientific my test was.

well that's probably how I would have tested it, but as you can see there's no repeatable difference, probably the outliers being due to the hub allocating CPU to something else at that time

2 Likes

i tested your .each instead for for, and a lot faster
image

however when i rolled it out it didn't work with the return command it just carried on running the rest of the code.

def motioncheck(){
    //log.debug "${app.label} motionCheck"

    for (com.hubitat.app.DeviceWrapper  sensor in settings.DevIn) { 
            if (sensor.currentMotion == "active"){
                //log.debug "${sensor.currentMotion} active - returning"
                return
            }
        }

/* This does not work retrun dosnt work
    DevIn.each {
        if (it.currentMotion == "active"){
            log.debug "${app.label} - $it active - returning"
            return
        }
    }
*/
    DevOut.motionInactive()
    //log.debug "${app.label} - motion inactive sent to $DevOut"
}

maybe let it complete the iteration, and set a boolean if active (vs the return), then check that after the .each

That's because you're inside a Closure (essentially an anonymous method), which each takes as a parameter, so return just returns from that and keeps going. So, it won't be useful to stop the iteration.

If this is what you're doing, I think something like settingName.any { it.currentMotion == "active" } would be a Groovy-ier way to get where you're going -- but if this is just one example, there are lots of Groovy methods you can use on collections to do different things, these being two examples.

Would this work?
If (settingName.any { it.currentMotion == "active" }){
return
{

Yes, it should.