Rule Machine bug [not]

@bravenel I think I found a bug in Rule machine. I have a humidity fan that is controlled by a HomeSeer 200 series switch, and a multisensor 6 mounted flush in the ceiling above the shower. The Multisensor 6 is USB powered and is there to report humidity and presence in the shower.

I created a trigger to turn the fan on at 80% humidity, and another trigger to turn the fan off at 65% humidity.

What happens:
When the humidity reaches 80%, the fan turns on
When the humidity reaches 100% the fan turns off.
When the humidity lowers back down to 99%, the fan turns back on.

It's like it sees 100% as eather 10% or 0%

Here is a screenshot of the triggers

This is interesting! What driver are you using for the multisensor? I suspect this is a driver issue, and that what is happening is that when humidity reaches 100, the driver is reporting 0. Rule Machine doesn't care about the value, it just does a comparison of the incoming value against the value you specified. So the odds are that the incoming value is not 100.

Can you turn on all of the logging available for the multisensor in the device details for it. Then have logs open when you repeat this, so we can see what the device is actually reporting.

Meanwhile, I will look into the driver situation, but it's necessary to know what driver you are using.

One more thing to do: Rule Machine logs every event that fires a trigger. So have logs turned on, and show those log entries.

I am using the MultiSensor (Advanced) driver. There are a few floating around in the community, and this one seemed to work the best. The built in Hubitat driver does not give enough control over the parameters to be useful. Unfortunately it doesn't seem to support logging. I typed "True" into the enable logging property, but no logs were generated. Maybe I should try a "1". I did notice that the Hubitat dashboard was reporting that the humidity was 100%. Exactly 3 min after 100% was reported, the fan turned off, then turned back on imediately when 99% was achieved.

Driver

/**
 *
 *  Aeon Multisensor 6 (Advanced)
 *   
 *	github: Eric Maycock (erocm123)
 *	email: erocmail@gmail.com
 *	Date: 2017-03-08 6:45 PM
 *	Copyright Eric Maycock
 *
 *  Code has elements from other community sources @CyrilPeponnet, @Robert_Vandervoort. Greatly reworked and 
 *  optimized for improved battery life (hopefully) :) and ease of advanced configuration. I tried to get it
 *  as feature rich as possible. 
 *
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 *  in compliance with the License. You may obtain a copy of the License at:
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
 *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
 *  for the specific language governing permissions and limitations under the License.
 *
 */

 metadata {
	definition (name: "Aeon Multisensor 6 (Advanced)", namespace: "erocm123", author: "Eric Maycock") {
		capability "Motion Sensor"
		capability "Acceleration Sensor"
		capability "Temperature Measurement"
		capability "Relative Humidity Measurement"
		capability "Illuminance Measurement"
		capability "Ultraviolet Index" 
		capability "Configuration"
		capability "Sensor"
		capability "Battery"
        capability "Refresh"
        capability "Tamper Alert"
        capability "Health Check"
        
        command "resetBatteryRuntime"
        command "resetTamperAlert"
		
        attribute   "needUpdate", "string"
        
        fingerprint deviceId: "0x2101", inClusters: "0x5E,0x86,0x72,0x59,0x85,0x73,0x71,0x84,0x80,0x30,0x31,0x70,0x98,0x7A,0x5A" // 1.07 & 1.08 Secure
        fingerprint deviceId: "0x2101", inClusters: "0x5E,0x86,0x72,0x59,0x85,0x73,0x71,0x84,0x80,0x30,0x31,0x70,0x7A,0x5A" // 1.07 & 1.08
        
        fingerprint deviceId: "0x2101", inClusters: "0x5E,0x86,0x72,0x59,0x85,0x73,0x71,0x84,0x80,0x30,0x31,0x70,0x7A", outClusters: "0x5A" // 1.06
        
        fingerprint mfr:"0086", prod:"0102", model:"0064", deviceJoinName: "Aeon MultiSensor 6"

	}
    preferences {
        input description: "Once you change values on this page, the corner of the \"configuration\" icon will change orange until all configuration parameters are updated.", title: "Settings", displayDuringSetup: false, type: "paragraph", element: "paragraph"
		generate_preferences(configuration_model())
    }
	simulator {
	}
	tiles (scale: 2) {
		multiAttributeTile(name:"main", type:"generic", width:6, height:4) {
			tileAttribute("device.temperature", key: "PRIMARY_CONTROL") {
            	attributeState "temperature",label:'${currentValue}°', backgroundColors:[
                	[value: 31, color: "#153591"],
                    [value: 44, color: "#1e9cbb"],
                    [value: 59, color: "#90d2a7"],
					[value: 74, color: "#44b621"],
					[value: 84, color: "#f1d801"],
					[value: 95, color: "#d04e00"],
					[value: 96, color: "#bc2323"]
				]
            }
            tileAttribute ("statusText", key: "SECONDARY_CONTROL") {
				attributeState "statusText", label:'${currentValue}'
			}
		}
        standardTile("motion","device.motion", inactiveLabel: false, width: 2, height: 2) {
                state "inactive",label:'no motion',icon:"st.motion.motion.inactive",backgroundColor:"#ffffff"
                state "active",label:'motion',icon:"st.motion.motion.active",backgroundColor:"#00a0dc"
		}

		valueTile("humidity","device.humidity", inactiveLabel: false, width: 2, height: 2) {
           	state "humidity",label:'RH ${currentValue} %'
		}
		valueTile("illuminance", "device.illuminance", inactiveLabel: false, width: 2, height: 2) {
           state "luminosity", label:'${currentValue} lux', unit:"lux", 
                backgroundColors:[
                	[value: 0, color: "#000000"],
                    [value: 1, color: "#060053"],
                    [value: 3, color: "#3E3900"],
                    [value: 12, color: "#8E8400"],
					[value: 24, color: "#C5C08B"],
					[value: 36, color: "#DAD7B6"],
					[value: 128, color: "#F3F2E9"],
                    [value: 1000, color: "#FFFFFF"]
				]
		}
        
		valueTile(
        	"ultravioletIndex","device.ultravioletIndex", inactiveLabel: false, width: 2, height: 2) {
				state "ultravioletIndex",label:'${currentValue} UV INDEX',unit:""
		}
		standardTile("acceleration", "device.acceleration", inactiveLabel: false, width: 2, height: 2) {
			state("inactive", label:'clear', icon:"st.motion.acceleration.inactive", backgroundColor:"#ffffff")
            state("active", label:'tamper', icon:"st.motion.acceleration.active", backgroundColor:"#f39c12")
		}
        standardTile("tamper", "device.tamper", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
			state("clear", label:'clear', icon:"st.contact.contact.closed", backgroundColor:"#cccccc", action: "resetTamperAlert")
            state("detected", label:'tamper', icon:"st.contact.contact.open", backgroundColor:"#e86d13", action: "resetTamperAlert")
		}
		valueTile("battery", "device.battery", inactiveLabel: false, width: 2, height: 2) {
			state "battery", label:'${currentValue}% battery', unit:""
		}
        valueTile("batteryTile", "device.batteryTile", inactiveLabel: false, width: 2, height: 2) {
			state "batteryTile", label:'${currentValue}', unit:""
		}
        valueTile(
			"currentFirmware", "device.currentFirmware", inactiveLabel: false, width: 2, height: 2) {
			state "currentFirmware", label:'Firmware: v${currentValue}', unit:""
		}
        standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
			state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
		}
        standardTile("configure", "device.needUpdate", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
            state "NO" , label:'', action:"configuration.configure", icon:"st.secondary.configure"
            state "YES", label:'', action:"configuration.configure", icon:"https://github.com/erocm123/SmartThingsPublic/raw/master/devicetypes/erocm123/qubino-flush-1d-relay.src/configure@2x.png"
        }
        standardTile(
			"batteryRuntime", "device.batteryRuntime", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
			state "batteryRuntime", label:'Battery: ${currentValue} Double tap to reset counter', unit:"", action:"resetBatteryRuntime"
		}
        standardTile(
			"statusText2", "device.statusText2", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
			state "statusText2", label:'${currentValue}', unit:"", action:"resetBatteryRuntime"
		}
        
		main([
        	"main", "motion"
            ])
		details([
        	"main",
            "humidity","illuminance","ultravioletIndex",
            "motion","tamper","batteryTile", 
            "refresh", "configure", "statusText2", 
            ])
	}
}

def parse(String description)
{
	def result = []
    switch(description){
        case ~/Err 106.*/:
			state.sec = 0
			result = createEvent( name: "secureInclusion", value: "failed", isStateChange: true,
			descriptionText: "This sensor failed to complete the network security key exchange. If you are unable to control it via SmartThings, you must remove it from your network and add it again.")
        break
		case "updated":
        	result = createEvent( name: "Inclusion", value: "paired", isStateChange: true,
			descriptionText: "Update is hit when the device is paired")
            result << response(zwave.wakeUpV1.wakeUpIntervalSet(seconds: 3600, nodeid:zwaveHubNodeId).format())
            result << response(zwave.batteryV1.batteryGet().format())
            result << response(zwave.versionV1.versionGet().format())
            result << response(zwave.manufacturerSpecificV2.manufacturerSpecificGet().format())
            result << response(configure())
        break
        default:
			def cmd = zwave.parse(description, [0x31: 5, 0x30: 2, 0x84: 1])
			if (cmd) {
                try {
				result += zwaveEvent(cmd)
                } catch (e) {
                log.debug "error: $e cmd: $cmd description $description"
                }
			}
        break
	}
    
    updateStatus()

	if ( result[0] != null ) { result }
}

def zwaveEvent(hubitat.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
	def encapsulatedCommand = cmd.encapsulatedCommand([0x31: 5, 0x30: 2, 0x84: 1])
	state.sec = 1
	if (encapsulatedCommand) {
		zwaveEvent(encapsulatedCommand)
	} else {
		log.warn "Unable to extract encapsulated cmd from $cmd"
		createEvent(descriptionText: cmd.toString())
	}
}

def zwaveEvent(hubitat.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) {
	response(configure())
}

def zwaveEvent(hubitat.zwave.commands.configurationv2.ConfigurationReport cmd) {
    if (cmd.parameterNumber.toInteger() == 81 && cmd.configurationValue == [255]) {
        update_current_properties([parameterNumber: "81", configurationValue: [1]])
        logging("${device.displayName} parameter '${cmd.parameterNumber}' with a byte size of '${cmd.size}' is set to '1'")
    } else {
        update_current_properties(cmd)
        logging("${device.displayName} parameter '${cmd.parameterNumber}' with a byte size of '${cmd.size}' is set to '${cmd2Integer(cmd.configurationValue)}'")
    }
}

def zwaveEvent(hubitat.zwave.commands.wakeupv1.WakeUpIntervalReport cmd)
{
	logging("WakeUpIntervalReport ${cmd.toString()}")
    state.wakeInterval = cmd.seconds
}

def zwaveEvent(hubitat.zwave.commands.batteryv1.BatteryReport cmd) {
    logging("Battery Report: $cmd")
    def events = []
	def map = [ name: "battery", unit: "%" ]
	if (cmd.batteryLevel == 0xFF) {
		map.value = 1
		map.descriptionText = "${device.displayName} battery is low"
		map.isStateChange = true
	} else {
		map.value = cmd.batteryLevel
	}
    if(settings."101" == null || settings."101" == "241") {
        try {
            events << createEvent([name: "batteryTile", value: "Battery ${map.value}%", displayed:false])
        } catch (e) {
            logging("$e")
        }
    }
    events << createEvent(map)
    
    state.lastBatteryReport = now()
    return events
}

def zwaveEvent(hubitat.zwave.commands.sensormultilevelv5.SensorMultilevelReport cmd)
{
	def map = [:]
	switch (cmd.sensorType) {
		case 1:
			map.name = "temperature"
			def cmdScale = cmd.scale == 1 ? "F" : "C"
            state.realTemperature = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision)
			map.value = getAdjustedTemp(state.realTemperature)
			map.unit = getTemperatureScale()
            logging("Temperature Report: $map.value")
			break;
		case 3:
			map.name = "illuminance"
            state.realLuminance = cmd.scaledSensorValue.toInteger()
			map.value = getAdjustedLuminance(cmd.scaledSensorValue.toInteger())
			map.unit = "lux"
            logging("Illuminance Report: $map.value")
			break;
        case 5:
			map.name = "humidity"
            state.realHumidity = cmd.scaledSensorValue.toInteger()
			map.value = getAdjustedHumidity(cmd.scaledSensorValue.toInteger())
			map.unit = "%"
            logging("Humidity Report: $map.value")
			break;
		case 27:
        	map.name = "ultravioletIndex"
            state.realUV = cmd.scaledSensorValue.toInteger()
            map.value = getAdjustedUV(cmd.scaledSensorValue.toInteger())
            map.unit = ""
            logging("UV Report: $map.value")
            break;
		default:
			map.descriptionText = cmd.toString()
	}
    
    def request = update_needed_settings()
    
    if(request != []){
        return [response(commands(request)), createEvent(map)]
    } else {
        return createEvent(map)
    }

}

def motionEvent(value) {
	def map = [name: "motion"]
	if (value) {
		map.value = "active"
		map.descriptionText = "$device.displayName detected motion"
	} else {
		map.value = "inactive"
		map.descriptionText = "$device.displayName motion has stopped"
	}
	createEvent(map)
}

def zwaveEvent(hubitat.zwave.commands.sensorbinaryv2.SensorBinaryReport cmd) {
    logging("SensorBinaryReport: $cmd")
	motionEvent(cmd.sensorValue)
}

def zwaveEvent(hubitat.zwave.commands.basicv1.BasicSet cmd) {
    logging("BasicSet: $cmd")
	motionEvent(cmd.value)
}

def zwaveEvent(hubitat.zwave.commands.notificationv3.NotificationReport cmd) {
    logging("NotificationReport: $cmd")
	def result = []
	if (cmd.notificationType == 7) {
		switch (cmd.event) {
			case 0:
				//result << motionEvent(0)
				result << createEvent(name: "tamper", value: "clear", descriptionText: "$device.displayName tamper cleared")
                result << createEvent(name: "acceleration", value: "inactive", descriptionText: "$device.displayName tamper cleared", displayed:false)
				break
			case 3:
				result << createEvent(name: "tamper", value: "detected", descriptionText: "$device.displayName was tampered")
                result << createEvent(name: "acceleration", value: "active", descriptionText: "$device.displayName was moved", displayed:false)
				break
			case 7:
				//result << motionEvent(1)
				break
		}
	} else {
        logging("Need to handle this cmd.notificationType: ${cmd.notificationType}")
		result << createEvent(descriptionText: cmd.toString(), isStateChange: false)
	}
	result
}

def zwaveEvent(hubitat.zwave.commands.wakeupv1.WakeUpNotification cmd)
{
    logging("Device ${device.displayName} woke up")
    
    def request = update_needed_settings()

    if(request != []){
       response(commands(request) + ["delay 5000", zwave.wakeUpV1.wakeUpNoMoreInformation().format()])
    } else {
       logging("No commands to send")
       response([zwave.wakeUpV1.wakeUpNoMoreInformation().format()])
    }
}

def zwaveEvent(hubitat.zwave.commands.versionv1.VersionReport cmd) {
	def firmware = "${cmd.applicationVersion}.${cmd.applicationSubVersion.toString().padLeft(2,'0')}${location.getTemperatureScale() == 'C' ? 'EU':''}"
    state.needfwUpdate = "false"
    updateDataValue("firmware", firmware)
    createEvent(name: "currentFirmware", value: firmware)
}

def zwaveEvent(hubitat.zwave.Command cmd) {
    logging("Unknown Z-Wave Command: ${cmd.toString()}")
}

def refresh() {
   	logging("$device.displayName refresh()")

    def request = []
    if (state.lastRefresh != null && now() - state.lastRefresh < 5000) {
        logging("Refresh Double Press")
        state.currentProperties."111" = null
        state.wakeInterval = null
        def configuration = new XmlSlurper().parseText(configuration_model())
        configuration.Value.each
        {
            if ( "${it.@setting_type}" == "zwave" ) {
                request << zwave.configurationV1.configurationGet(parameterNumber: "${it.@index}".toInteger())
            }
        } 
        request << zwave.versionV1.versionGet()
        request << zwave.wakeUpV1.wakeUpIntervalGet()
    } else {
        request << zwave.batteryV1.batteryGet()
        request << zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType:1, scale:1)
        request << zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType:3, scale:1)
        request << zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType:5, scale:1)
        request << zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType:27, scale:1)
    }

    state.lastRefresh = now()
    
    commands(request)
}

def ping() {
   	logging("$device.displayName ping()")

    def request = []
    request << zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType:1, scale:1)
    request << zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType:3, scale:1)
    request << zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType:5, scale:1)
    request << zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType:27, scale:1)
    
    commands(request)
}

def configure() {
    state.enableDebugging = settings.enableDebugging
    logging("Configuring Device For SmartThings Use")
    def cmds = []

    cmds = update_needed_settings()
    
    if (cmds != []) commands(cmds)
}

def updated()
{
    state.enableDebugging = settings.enableDebugging
    sendEvent(name: "checkInterval", value: 6 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
    logging("updated() is being called")
    if(settings."101" != null && settings."101" == "240") { 
        sendEvent(name:"batteryTile", value: "USB Powered", displayed:false)
    } else {
        try {
            sendEvent(name:"batteryTile", value: "Battery ${(device.currentValue("battery") == null ? '?' : device.currentValue("battery"))}%", displayed:false)
        } catch (e) {
            logging("$e")
            sendEvent(name:"battery", value: "100", displayed:false)
            sendEvent(name:"batteryTile", value: "Battery ${(device.currentValue("battery") == null ? '?' : device.currentValue("battery"))}%", displayed:false)
        }
    }

    state.needfwUpdate = ""
    
    if (state.realTemperature != null) sendEvent(name:"temperature", value: getAdjustedTemp(state.realTemperature))
    if (state.realHumidity != null) sendEvent(name:"humidity", value: getAdjustedHumidity(state.realHumidity))
    if (state.realLuminance != null) sendEvent(name:"illuminance", value: getAdjustedLuminance(state.realLuminance))
    if (state.realUV != null) sendEvent(name:"ultravioletIndex", value: getAdjustedUV(state.realUV))
    
    def cmds = update_needed_settings()
    
    if (device.currentValue("battery") == null) cmds << zwave.batteryV1.batteryGet()
    if (device.currentValue("temperature") == null) cmds << zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType:1, scale:1)
    if (device.currentValue("humidity") == null) cmds << zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType:3, scale:1)
    if (device.currentValue("illuminance") == null) cmds << zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType:5, scale:1)
    if (device.currentValue("ultravioletIndex") == null) cmds << zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType:27, scale:1)
        
    updateStatus()
    
    sendEvent(name:"needUpdate", value: device.currentValue("needUpdate"), displayed:false, isStateChange: true)
    
    response(commands(cmds))
}

def resetTamperAlert() {
    sendEvent(name: "tamper", value: "clear", descriptionText: "$device.displayName tamper cleared")
    sendEvent(name: "acceleration", value: "inactive", descriptionText: "$device.displayName tamper cleared")
    sendEvent(name: "motion", value: "inactive", descriptionText: "$device.displayName motion has stopped")
}

def convertParam(number, value) {
	switch (number){
        case 41:
            //Parameter difference between firmware versions
        	if (settings."41".toInteger() != null && device.currentValue("currentFirmware") != null) {
                if (device.currentValue("currentFirmware") == "1.07" || device.currentValue("currentFirmware") == "1.08" || device.currentValue("currentFirmware") == "1.09") {
                    (value * 256) + 2
                } else if (device.currentValue("currentFirmware") == "1.10") {
                    (value * 65536) + 512
                } else if (device.currentValue("currentFirmware") == "1.10EU" || device.currentValue("currentFirmware") == "1.11EU") {
                    (value * 65536) + 256
                } else if (device.currentValue("currentFirmware") == "1.07EU" || device.currentValue("currentFirmware") == "1.08EU" || device.currentValue("currentFirmware") == "1.09EU") {
                    (value * 256) + 1
                } else {
                    value
                }	
            } else {
                value
            }
        break
        case 45:
            //Parameter difference between firmware versions
        	if (settings."45".toInteger() != null && device.currentValue("currentFirmware") != null && device.currentValue("currentFirmware") != "1.08")
            	2
            else
                value
        break
        case 101:
        	if (settings."40".toInteger() != null) {
                if (settings."40".toInteger() == 1) {
                   0
                } else {
                   value
                }	
            } else {
                241
            }
        break
    	case 201:
        	if (value < 0)
            	256 + value
        	else if (value > 100)
            	value - 256
            else
            	value
        break
        case 202:
        	if (value < 0)
            	256 + value
        	else if (value > 100)
            	value - 256
            else
            	value
        break
        case 203:
            if (value < 0)
            	65536 + value
        	else if (value > 1000)
            	value - 65536
            else
            	value
        break
        case 204:
        	if (value < 0)
            	256 + value
        	else if (value > 100)
            	value - 256
            else
            	value
        break
        default:
        	value
        break
    }
}

def update_current_properties(cmd)
{
    def currentProperties = state.currentProperties ?: [:]
    
    currentProperties."${cmd.parameterNumber}" = cmd.configurationValue

    if (settings."${cmd.parameterNumber}" != null)
    {   
            if (convertParam("${cmd.parameterNumber}".toInteger(), settings."${cmd.parameterNumber}".toInteger()) == cmd2Integer(cmd.configurationValue))
            {
                sendEvent(name:"needUpdate", value:"NO", displayed:false, isStateChange: true)
            }
            else
            {
                sendEvent(name:"needUpdate", value:"YES", displayed:false, isStateChange: true)
            }
    }

    state.currentProperties = currentProperties
}

def update_needed_settings()
{
    def cmds = []
    def currentProperties = state.currentProperties ?: [:]
     
    def configuration = new XmlSlurper().parseText(configuration_model())
    def isUpdateNeeded = "NO"
    
    if(!state.needfwUpdate || state.needfwUpdate == "") {
       logging("Requesting device firmware version")
       cmds << zwave.versionV1.versionGet()
    }

    if (state.currentProperties?."252" != [0]) {
        logging("Unlocking configuration.")
        cmds << zwave.configurationV1.configurationSet(configurationValue: integer2Cmd(0, 1), parameterNumber: 252, size: 1)
        cmds << zwave.configurationV1.configurationGet(parameterNumber: 252)
    }

    if(state.wakeInterval == null || state.wakeInterval != getAdjustedWake()){
        logging("Setting Wake Interval to ${getAdjustedWake()}")
        cmds << zwave.wakeUpV1.wakeUpIntervalSet(seconds: getAdjustedWake(), nodeid:zwaveHubNodeId)
        cmds << zwave.wakeUpV1.wakeUpIntervalGet()
    }

    configuration.Value.each
    {     
        if ("${it.@setting_type}" == "zwave"){
            if (currentProperties."${it.@index}" == null)
            {
                if (device.currentValue("currentFirmware") == null || "${it.@fw}".indexOf(device.currentValue("currentFirmware")) >= 0){
                    isUpdateNeeded = "YES"
                    logging("Current value of parameter ${it.@index} is unknown")
                    cmds << zwave.configurationV1.configurationGet(parameterNumber: it.@index.toInteger())
                }
            } 
            else if (settings."${it.@index}" != null && cmd2Integer(currentProperties."${it.@index}") != convertParam(it.@index.toInteger(), settings."${it.@index}".toInteger()))
            { 
                if (device.currentValue("currentFirmware") == null || "${it.@fw}".indexOf(device.currentValue("currentFirmware")) >= 0){
                    isUpdateNeeded = "YES"

                    logging("Parameter ${it.@index} will be updated to " + convertParam(it.@index.toInteger(), settings."${it.@index}".toInteger()))
                    
                    if (it.@index == "41") {
                        if (device.currentValue("currentFirmware") == "1.06" || device.currentValue("currentFirmware") == "1.06EU") {
                            cmds << zwave.configurationV1.configurationSet(configurationValue: integer2Cmd(convertParam(it.@index.toInteger(), settings."${it.@index}".toInteger()), 2), parameterNumber: it.@index.toInteger(), size: 2)
                        } else if (device.currentValue("currentFirmware") == "1.10" || device.currentValue("currentFirmware") == "1.10EU" || device.currentValue("currentFirmware") == "1.11EU") {
                            cmds << zwave.configurationV1.configurationSet(configurationValue: integer2Cmd(convertParam(it.@index.toInteger(), settings."${it.@index}".toInteger()), 4), parameterNumber: it.@index.toInteger(), size: 4)
                        } else {
                            cmds << zwave.configurationV1.configurationSet(configurationValue: integer2Cmd(convertParam(it.@index.toInteger(), settings."${it.@index}".toInteger()), 3), parameterNumber: it.@index.toInteger(), size: 3)
                        }
                    } else {
                        cmds << zwave.configurationV1.configurationSet(configurationValue: integer2Cmd(convertParam(it.@index.toInteger(), settings."${it.@index}".toInteger()), it.@byteSize.toInteger()), parameterNumber: it.@index.toInteger(), size: it.@byteSize.toInteger())
                    }

                    cmds << zwave.configurationV1.configurationGet(parameterNumber: it.@index.toInteger())
                }
            } 
        }
    }
    
    sendEvent(name:"needUpdate", value: isUpdateNeeded, displayed:false, isStateChange: true)
    return cmds
}

/**
* Convert 1 and 2 bytes values to integer
*/
def cmd2Integer(array) { 
try {
switch(array.size()) {
	case 1:
		array[0]
    break
	case 2:
    	((array[0] & 0xFF) << 8) | (array[1] & 0xFF)
    break
    case 3:
    	((array[0] & 0xFF) << 16) | ((array[1] & 0xFF) << 8) | (array[2] & 0xFF)
    break
	case 4:
    	((array[0] & 0xFF) << 24) | ((array[1] & 0xFF) << 16) | ((array[2] & 0xFF) << 8) | (array[3] & 0xFF)
	break
}
}catch (e) {
log.debug "Error: cmd2Integer $e"
}
}

def integer2Cmd(value, size) {
    try{
	switch(size) {
	case 1:
		[value]
    break
	case 2:
    	def short value1   = value & 0xFF
        def short value2 = (value >> 8) & 0xFF
        [value2, value1]
    break
    case 3:
    	def short value1   = value & 0xFF
        def short value2 = (value >> 8) & 0xFF
        def short value3 = (value >> 16) & 0xFF
        [value3, value2, value1]
    break
	case 4:
    	def short value1 = value & 0xFF
        def short value2 = (value >> 8) & 0xFF
        def short value3 = (value >> 16) & 0xFF
        def short value4 = (value >> 24) & 0xFF
		[value4, value3, value2, value1]
	break
	}
    } catch (e) {
        log.debug "Error: integer2Cmd $e Value: $value"
    }
}

private command(hubitat.zwave.Command cmd) {
    
	if (state.sec && cmd.toString() != "WakeUpIntervalGet()") {
		zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
	} else {
		cmd.format()
	}
}

private commands(commands, delay=1000) {
	delayBetween(commands.collect{ command(it) }, delay)
}

def generate_preferences(configuration_model)
{
    def configuration = new XmlSlurper().parseText(configuration_model)
   
    configuration.Value.each
    {
        switch(it.@type)
        {   
            case ["byte","short","four"]:
                input "${it.@index}", "number",
                    title:"${it.@label}\n" + "${it.Help}",
                    range: "${it.@min}..${it.@max}",
                    defaultValue: "${it.@value}",
                    displayDuringSetup: "${it.@displayDuringSetup}"
            break
            case "list":
                def items = []
                it.Item.each { items << ["${it.@value}":"${it.@label}"] }
                input "${it.@index}", "enum",
                    title:"${it.@label}\n" + "${it.Help}",
                    defaultValue: "${it.@value}",
                    displayDuringSetup: "${it.@displayDuringSetup}",
                    options: items
            break
            case "decimal":
               input "${it.@index}", "decimal",
                    title:"${it.@label}\n" + "${it.Help}",
                    range: "${it.@min}..${it.@max}",
                    defaultValue: "${it.@value}",
                    displayDuringSetup: "${it.@displayDuringSetup}"
            break
            case "boolean":
               input "${it.@index}", "boolean",
                    title:"${it.@label}\n" + "${it.Help}",
                    defaultValue: "${it.@value}",
                    displayDuringSetup: "${it.@displayDuringSetup}"
            break
        }  
    }
}

private getBatteryRuntime() {
   def currentmillis = now() - state.batteryRuntimeStart
   def days=0
   def hours=0
   def mins=0
   def secs=0
   secs = (currentmillis/1000).toInteger() 
   mins=(secs/60).toInteger() 
   hours=(mins/60).toInteger() 
   days=(hours/24).toInteger() 
   secs=(secs-(mins*60)).toString().padLeft(2, '0') 
   mins=(mins-(hours*60)).toString().padLeft(2, '0') 
   hours=(hours-(days*24)).toString().padLeft(2, '0') 
 

  if (days>0) { 
      return "$days days and $hours:$mins:$secs"
  } else {
      return "$hours:$mins:$secs"
  }
}

private getRoundedInterval(number) {
    double tempDouble = (number / 60)
    if (tempDouble == tempDouble.round())
       return (tempDouble * 60).toInteger()
    else 
       return ((tempDouble.round() + 1) * 60).toInteger()
}

private getAdjustedWake(){
    def wakeValue
    if (device.currentValue("currentFirmware") != null && settings."101" != null && settings."111" != null){
        if (device.currentValue("currentFirmware") == "1.08"){
            if (settings."101".toInteger() == 241){   
                if (settings."111".toInteger() <= 3600){
                    wakeValue = getRoundedInterval(settings."111")
                } else {
                    wakeValue = 3600
                }
            } else {
                wakeValue = 1800
            }
        } else {
            if (settings."101".toInteger() == 241){   
                if (settings."111".toInteger() <= 3600){
                    wakeValue = getRoundedInterval(settings."111")
                } else {
                    wakeValue = getRoundedInterval(settings."111".toInteger() / 2)
                }
            } else {
                wakeValue = 240
            }
        }
    } else {
        wakeValue = 3600
    }
    return wakeValue.toInteger()
}

private getAdjustedTemp(value) {
    
    value = Math.round((value as Double) * 100) / 100

	if (settings."201") {
	   return value =  value + Math.round(settings."201" * 100) /100
	} else {
       return value
    }
    
}

private getAdjustedHumidity(value) {
    
    value = Math.round((value as Double) * 100) / 100

	if (settings."202") {
	   return value =  value + Math.round(settings."202" * 100) /100
	} else {
       return value
    }
    
}

private getAdjustedLuminance(value) {
    
    value = Math.round((value as Double) * 100) / 100

	if (settings."203") {
	   return value =  value + Math.round(settings."203" * 100) /100
	} else {
       return value
    }
    
}

private getAdjustedUV(value) {
    
    value = Math.round((value as Double) * 100) / 100

	if (settings."204") {
	   return value =  value + Math.round(settings."204" * 100) /100
	} else {
       return value
    }
    
}

def resetBatteryRuntime() {
    if (state.lastReset != null && now() - state.lastReset < 5000) {
        logging("Reset Double Press")
        state.batteryRuntimeStart = now()
        updateStatus()
    }
    state.lastReset = now()
}

private updateStatus(){
   def result = []
   if(state.batteryRuntimeStart != null){
        sendEvent(name:"batteryRuntime", value:getBatteryRuntime(), displayed:false)
        if (device.currentValue('currentFirmware') != null){
            sendEvent(name:"statusText2", value: "Firmware: v${device.currentValue('currentFirmware')} - Battery: ${getBatteryRuntime()} Double tap to reset", displayed:false)
        } else {
            sendEvent(name:"statusText2", value: "Battery: ${getBatteryRuntime()} Double tap to reset", displayed:false)
        }
    } else {
        state.batteryRuntimeStart = now()
    }

    String statusText = ""
    if(device.currentValue('humidity') != null)
        statusText = "RH ${device.currentValue('humidity')}% - "
    if(device.currentValue('illuminance') != null)
        statusText = statusText + "LUX ${device.currentValue('illuminance')} - "
    if(device.currentValue('ultravioletIndex') != null)
        statusText = statusText + "UV ${device.currentValue('ultravioletIndex')} - "
        
    if (statusText != ""){
        statusText = statusText.substring(0, statusText.length() - 2)
        sendEvent(name:"statusText", value: statusText, displayed:false)
    }
}

private def logging(message) {
    if (state.enableDebugging == null || state.enableDebugging == "true") log.debug "$message"
}

def configuration_model()
{
'''
<configuration>
    <Value type="list" index="101" label="Battery or USB?" min="240" max="241" value="241" byteSize="4" setting_type="zwave" fw="1.06,1.07,1.08,1.09,1.10,1.06EU,1.07EU,1.08EU,1.09EU,1.10EU,1.11EU" displayDuringSetup="true">
    <Help>
Is the device powered by battery or usb?
    </Help>
        <Item label="Battery" value="241" />
        <Item label="USB" value="240" />
  </Value>
  <Value type="list" index="40" label="Enable selective reporting?" min="0" max="1" value="0" byteSize="1" setting_type="zwave" fw="1.06,1.07,1.08,1.09,1.10,1.06EU,1.07EU,1.08EU,1.09EU,1.10EU,1.11EU">
    <Help>
Enable/disable the selective reporting only when measurements reach a certain threshold or percentage set below. This is used to reduce network traffic.
Default: No (Enable for Better Battery Life)
    </Help>
        <Item label="No" value="0" />
        <Item label="Yes" value="1" />
  </Value>
  <Value type="short" byteSize="2" index="41" label="Temperature Threshold" min="1" max="5000" value="20" setting_type="zwave" fw="1.06,1.07,1.08,1.09,1.10,1.06EU,1.07EU,1.08EU,1.09EU,1.10EU,1.11EU">
    <Help>
Threshold change in temperature to induce an automatic report.
Range: 1~5000.
Default: 20
Note:
Only used if selective reporting is enabled.
1. The unit is Fahrenheit for US version, Celsius for EU/AU version.
2. The value contains one decimal point. E.g. if the value is set to 20, the threshold value =2.0 ℃ (EU/AU version) or 2.0 ℉ (US version). When the current temperature gap is more then 2.0, which will induce a temperature report to be sent out.
    </Help>
  </Value>
  <Value type="byte" byteSize="1" index="42" label="Humidity Threshold" min="1" max="255" value="10" setting_type="zwave" fw="1.06,1.07,1.08,1.09,1.10,1.06EU,1.07EU,1.08EU,1.09EU,1.10EU,1.11EU">
    <Help>
Threshold change in humidity to induce an automatic report.
Range: 1~255.
Default: 10
Note:
Only used if selective reporting is enabled.
1. The unit is %.
2. The default value is 10, which means that if the current humidity gap is more than 10%, it will send out a humidity report.
    </Help>
  </Value>
  <Value type="short" byteSize="2" index="43" label="Luminance Threshold" min="1" max="30000" value="100" setting_type="zwave" fw="1.06,1.07,1.08,1.09,1.10,1.06EU,1.07EU,1.08EU,1.09EU,1.10EU,1.11EU">
    <Help>
Threshold change in luminance to induce an automatic report.
Range: 1~30000.
Default: 100
Note:
Only used if selective reporting is enabled.
    </Help>
  </Value>
  <Value type="byte" byteSize="1" index="44" label="Battery Threshold" min="1" max="99" value="10" setting_type="zwave" fw="1.06,1.07,1.08,1.09,1.10,1.06EU,1.07EU,1.08EU,1.09EU,1.10EU,1.11EU">
    <Help>
Threshold change in battery level to induce an automatic report.
Range: 1~99.
Default: 10
Note:
Only used if selective reporting is enabled.
1. The unit is %.
2. The default value is 10, which means that if the current battery level gap is more than 10%, it will send out a battery report.
    </Help>
  </Value>
  <Value type="byte" byteSize="1" index="45" label="Ultraviolet Threshold" min="1" max="11" value="2" setting_type="zwave" fw="1.06,1.07,1.08,1.09,1.10,1.06EU,1.07EU,1.08EU,1.09EU,1.10EU,1.11EU">
    <Help>
Threshold change in ultraviolet to induce an automatic report.
Range: 1~11.
Default: 2
Note: Firmware 1.06 and 1.07 only support a value of 2.
Only used if selective reporting is enabled.
    </Help>
  </Value>
  <Value type="short" byteSize="2" index="3" label="PIR reset time" min="10" max="3600" value="240" setting_type="zwave" fw="1.06,1.07,1.08,1.09,1.10,1.06EU,1.07EU,1.08EU,1.09EU,1.10EU,1.11EU" displayDuringSetup="true">
    <Help>
Number of seconds to wait to report motion cleared after a motion event if there is no motion detected.
Range: 10~3600.
Default: 240 (4 minutes)
Note:
(1), The time unit is seconds if the value range is in 10 to 255.
(2), If the value range is in 256 to 3600, the time unit will be minute and its value should follow the below rules:
a), Interval time =Value/60, if the interval time can be divided by 60 and without remainder.
b), Interval time= (Value/60) +1, if the interval time can be divided by 60 and has remainder.
    </Help>
  </Value>
    <Value type="byte" byteSize="1" index="4" label="PIR motion sensitivity" min="0" max="5" value="5" setting_type="zwave" fw="1.06,1.07,1.08,1.09,1.10,1.06EU,1.07EU,1.08EU,1.09EU,1.10EU,1.11EU" displayDuringSetup="true">
    <Help>
A value from 0-5, from disabled to high sensitivity
Range: 0~5
Default: 5
    </Help>
  </Value>
    <Value type="byte" byteSize="4" index="111" label="Reporting Interval" min="5" max="2678400" value="3600" setting_type="zwave" fw="1.06,1.07,1.08,1.09,1.10,1.06EU,1.07EU,1.08EU,1.09EU,1.10EU,1.11EU" displayDuringSetup="true">
    <Help>
The interval time of sending reports in Report group 1
Range: 30~
Default: 3600 seconds
Note:
The unit of interval time is in seconds. Minimum interval time is 30 seconds when USB powered and 240 seconds (4 minutes) when battery powered.
    </Help>
  </Value>
  <Value type="decimal" byteSize="1" index="201" label="Temperature offset" min="*" max="*" value="">
    <Help>
Range: None
Default: 0
Note: 
1. The calibration value = standard value - measure value.
E.g. If measure value =85.3F and the standard value = 83.2F, so the calibration value = 83.2F - 85.3F = -2.1F.
If the measure value =60.1F and the standard value = 63.2F, so the calibration value = 63.2F - 60.1℃ = 3.1F. 
    </Help>
  </Value>
  <Value type="byte" byteSize="1" index="202" label="Humidity offset" min="*" max="*" value="">
    <Help>
Range: None
Default: 0
Note:
The calibration value = standard value - measure value.
E.g. If measure value = 80RH and the standard value = 75RH, so the calibration value = 75RH – 80RH = -5RH.
If the measure value = 85RH and the standard value = 90RH, so the calibration value = 90RH – 85RH = 5RH. 
    </Help>
  </Value>
    <Value type="byte" byteSize="2" index="203" label="Luminance offset" min="*" max="*" value="">
    <Help>
Range: None
Default: 0
Note:
The calibration value = standard value - measure value.
E.g. If measure value = 800Lux and the standard value = 750Lux, so the calibration value = 750 – 800 = -50.
If the measure value = 850Lux and the standard value = 900Lux, so the calibration value = 900 – 850 = 50.
    </Help>
  </Value>
    <Value type="byte" byteSize="1" index="204" label="Ultraviolet offset" min="*" max="*" value="">
    <Help>
Range: None
Default: 0
Note:
The calibration value = standard value - measure value.
E.g. If measure value = 9 and the standard value = 8, so the calibration value = 8 – 9 = -1.
If the measure value = 7 and the standard value = 9, so the calibration value = 9 – 7 = 2. 
    </Help>
  </Value>
  <Value type="list" index="5" label="Command Option" min="1" max="2" value="1" byteSize="1" setting_type="zwave" fw="1.06,1.07,1.08,1.09,1.10,1.06EU,1.07EU,1.08EU,1.09EU,1.10EU,1.11EU">
    <Help>
Which command should be sent when the motion sensor is triggered
Default: Basic Set
    </Help>
        <Item label="Basic Set" value="1" />
        <Item label="Sensor Binary" value="2" />
  </Value>
  <Value type="list" index="81" label="LED Options" min="0" max="1" value="0" byteSize="1" setting_type="zwave" fw="1.08,1.09,1.10,1.08EU,1.09EU,1.10EU,1.11EU">
    <Help>
Choose how the LED functions. (Option 1, 2 firmware v1.08+, Option 1, 2, 3 firmware v1.10+)
Default: Enabled
    </Help>
        <Item label="Fully Enabled" value="0" />
        <Item label="Disable When Motion" value="1" />
        <Item label="Fully Disabled" value="2" />
  </Value>
  <Value type="byte" index="8" label="Stay Awake Time?" min="8" max="255" value="30" byteSize="1" setting_type="zwave" fw="1.08,1.09,1.10,1.08EU,1.09EU,1.10EU,1.11EU">
    <Help>
Set the timeout of awake after the Wake Up CC is sent out. (Works on Firmware v1.08 only)
Range: 8~255
Default: 30
Note: May help if config parameters aren't making it before device goes back to sleep.
    </Help>
  </Value>
  <Value type="boolean" index="enableDebugging" label="Enable Debug Logging?" value="true" setting_type="preference" fw="1.06,1.07,1.08,1.09,1.10,1.06EU,1.07EU,1.08EU,1.09EU,1.10EU,1.11EU">
    <Help>
    </Help>
  </Value>
</configuration>
'''
}

So try this same test with the built in driver, and see if it fails the same way. I know you don't want to use it, but this will help isolate the issue.

If I remember right, I think the built in driver only reported humidity during its hourly report. Maybe it was every 30 min. Whatever it was, it was unusable for this application. It did not have any selective reporting.

Optionally, you can try this variant of the Driver.

> /**
>  *  Copyright 2015 SmartThings
>  *
>  *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
>  *  in compliance with the License. You may obtain a copy of the License at:
>  *
>  *      http://www.apache.org/licenses/LICENSE-2.0
>  *
>  *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
>  *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
>  *  for the specific language governing permissions and limitations under the License.
>  *
>  * LGK V1 of multisensor 6 with customizeable settings , changed some timeouts, also changed tamper to vibration so we can
>  * use that as well (based on stock device type and also some changes copied from Robert Vandervoort device type.
>  * Changes
>    1. changes colors of temp slightly, add colors to humidity, add color to battery level
>    2. remove tamper and instead use feature as contact and acceleration ie vibration sensor
>    3. slightly change reporting interval times. (also fix issue where 18 hours was wrong time)
>    4. add last update time.. sets when configured and whenever temp is reported. 
>       This is used so at a glance you see the last update time tile to know the device is still reporting easily without looking
>       at the logs.
>    5. add a temp and humidity offset -12 to 12 to enable tweaking the settings if they appear off.
>    6. added power status tile to display, currently was here but not displayed.
>    7. added configure and refresh tiles.
>    8. also added refresh capability so refresh can be forced from other smartapps like pollster. (refresh not currently working all the time for some reason)
>    9. changed the sensitivity to have more values than min max etc, now is integer 0 - 127. 
>    10. fix uv setting which in one release was value of 2 now it is 16.
>    11. added icons for temp and humidity
>    12. also change the default wakeup time to be the same as the report interval, 
>         otherwise when on battery it disregarded the report interval. (only if less than the default 5 minutes).
>    13. added a config option for the min change needed to report temp changes and set it in parameter 41.
>    14. incresed range and colors for lux values, as when mine is in direct sun outside it goes as high as 1900
>    15. support for celsius added. set in input options.
> */
> 
> metadata {
> 	definition (name: "Aeon Multisensor 6 V1", namespace: "lgkapps", author: "lgkapps") {
> 		capability "Motion Sensor"
> 		capability "Temperature Measurement"
> 		capability "Relative Humidity Measurement"
> 		capability "Illuminance Measurement"
> 		capability "Ultraviolet Index"
> 		capability "Configuration"
> 		capability "Sensor"
> 		capability "Battery"
>    		capability "Acceleration Sensor"
>    		capability "Contact Sensor"
> //        capability "refresh"
> 
> //		attribute "tamper", "enum", ["detected", "clear"]
> 		attribute "batteryStatus", "string"
> 		attribute "powerSupply", "enum", ["USB Cable", "Battery"]
>       
> 		fingerprint deviceId: "0x2101", inClusters: "0x5E,0x86,0x72,0x59,0x85,0x73,0x71,0x84,0x80,0x30,0x31,0x70,0x7A", outClusters: "0x5A"
> 	}
> 
> 
> 	preferences {
> 		//input description: "Please consult AEOTEC MULTISENSOR 6 operating manual for advanced setting options. You can skip this configuration to use default settings",
> 		//		title: "Advanced Configuration", displayDuringSetup: true, type: "paragraph", element: "paragraph"
> 		input "motionDelayTime", "enum", title: "Motion Sensor Delay Time?",
> 				options: ["20 seconds", "30 seconds", "1 minute", "2 minutes", "3 minutes", "4 minutes"], defaultValue: "1 minute", displayDuringSetup: true
> 		input "motionSensitivity", "number", title: "Motion Sensor Sensitivity? (0 = off, 1 = min., 3 = normal, 5 = max.)", range: "0..5", defaultValue: 3, displayDuringSetup: true
> 		input "reportInterval", "enum", title: "Sensors Report Interval?",
> 				options: ["20 seconds", "30 seconds", "1 minute", "2 minutes", "3 minutes", "4 minutes", "5 minutes", "10 minutes", "15 minutes", "30 minutes", "1 hour", "6 hours", "12 hours", "18 hours", "24 hours"], defaultValue: "5 minutes", displayDuringSetup: true
>  		input("TempOffset", "number", title: "Temperature Offset/Adjustment -10 to +10 in Degrees?",range: "-10..10", description: "If your temperature is innacurate this will offset/adjust it by this many degrees.", defaultValue: 0, required: false, displayDuringSetup: true)
>    		input("HumidOffset", "number", title: "Humidity Offset/Adjustment -10 to +10 in percent?",range: "-10..10", description: "If your humidty is innacurate this will offset/adjust it by this percent.", defaultValue: 0, required: false, displayDuringSetup: true)
>    		input("tzOffset", "number", title: "Time zone offset +/-x?", required: false, range: "-12..14", defaultValue:  -5, description: "Time Zone Offset ie -5.", displayDuringSetup: true)
> 		input("tempScale", "enum", title: "Temperature Scale?", options: ["F","C"], defaltValue: "F", description: "What is your temperature scale?", displayDuringSetup: true)
>      		input("TempChangeAmount", "number", title: "Temperature Change Amount (1 = .1 degree)?", range: "1..70",description: "The tenths of degrees the temperature must changes before a report is sent?", defaultValue: 2,required: false)
> 	   	input "debugOutput", "bool", 
> 	   	    title: "Enable debug logging?", 
> 	   	    defaultValue: true, 
> 	   	    required: false
>      }
> }
> 
> def updated() {
> 	log.debug "In Updated with settings: ${settings}"
> 	log.debug "${device.displayName} is now ${device.latestValue("powerSupply")}"  
>     
> if (settings.motionDelayTime == null)
>   settings.motionDelayTime = 60
> if (settings.reportInterval == null)
>   settings.reportInterval = 8*60
> if (settings.motionSensitivity == null)
>   settings.motionSensitivity = 3
> if (settings.TempOffset == null)
>   settings.TempOffset = 0
> if (settings.HumidOffset == null)
>   settings.HumidOffset = 0
> if (settings.tzOffset == null)
>   settings.tzOffset = -5
> if (settings.tempScale == null)
>   settings.tempScale = "F"
> if (settings.tempChangeAmount == null)
>   settings.tempChangeAmount = 2
>   
>   if (settings.motionSensitivity < 0)
>     {
>       log.debug "Illegal motion sensitivity ... resetting to 0!"
>       settings.motionSensitivity = 0
>     }
>     
>    if (settings.motionSensitivity > 5)
>     {
>       log.debug "Illegal motion sensitivity ... resetting to 5!"
>       settings.motionSensitivity = 5
>     }
>     
>    // fix tz offset
>  if (settings.tzOffset < -12)
>   {
>     settings.tzOffset = -12
>     log.debug "Timezone too low... resetting to -12"
>     }
>     
>  if (settings.tzOffset > 14)
>   {
>     settings.tzOffset = 14
>     log.debug "Timezone too high ... resetting to 14"
>     }
>     
>      // fix temp offset
>  if (settings.TempOffset < -10)
>   {
>     settings.TempOffset = -10
>     log.debug "Temperature Offset too low... resetting to -10"
>     }
>     
>  if (settings.TempOffset > 10)
>   {
>     settings.TempOffset = 10
>     log.debug "Temperature Adjusment too high ... resetting to 10"
>     }
> 
>      // fix temp offset
>  if (settings.HumidOffset < -10)
>   {
>     settings.HumidOffset = -10
>     log.debug "Humidity Offset too low... resetting to -10"
>     }
>     
>  if (settings.HumidOffset > 10)
>   {
>     settings.HumidOffset = 10
>     log.debug "Humidity Adjusment too high ... resetting to 10"
>     }
> 
> 	if (device.latestValue("powerSupply") == "USB Cable") {  //case1: USB powered
> 		response(configure())
> 	} else if (device.latestValue("powerSupply") == "Battery") {  //case2: battery powered
> 		// setConfigured("false") is used by WakeUpNotification
> 		setConfigured("false") //wait until the next time device wakeup to send configure command after user change preference
> 	} else { //case3: power source is not identified, ask user to properly pair the sensor again
> 		log.warn "power source is not identified, check it sensor is powered by USB, if so > configure()"
> 		def request = []
> 		request << zwave.configurationV1.configurationGet(parameterNumber: 101)
> 		response(commands(request))
> 	}
>     return(configure())
> }
> 
> private def logging(message) {
> 	if (settings?.debugOutput || settings?.debugOutput == null) log.debug "$message"
> }
> 
> def parse(String description) {
> 	// log.debug "parse() >> description: ${description}"
> 	def result = null
> 	if (description.startsWith("Err 106")) {
> 		log.debug "parse() >> Err 106"
> 		result = createEvent( name: "secureInclusion", value: "failed", isStateChange: true,
> 				descriptionText: "This sensor failed to complete the network security key exchange. If you are unable to control it via SmartThings, you must remove it from your network and add it again.")
> 	} else if (description != "updated") {
> 		//log.debug "parse3() >> zwave.parse(description)"
> 		def cmd = zwave.parse(description, [0x31: 5, 0x30: 2, 0x84: 1])
> 		if (cmd) {
> 			result = zwaveEvent(cmd)
> 		}
> 	}
> 	//log.debug "After zwaveEvent(cmd) >> Parsed '${description}' to ${result.inspect()}"
> 	return result
> }
> 
> //this notification will be sent only when device is battery powered
> def zwaveEvent(hubitat.zwave.commands.wakeupv1.WakeUpNotification cmd) {
> 	def result = [createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)]
> 	def cmds = []
> 	if (!isConfigured()) {
> 		log.debug("late configure")
> 		result << response(configure())
> 	} else {
> 		//log.debug("Device has been configured sending >> wakeUpNoMoreInformation()")
> 		cmds << zwave.wakeUpV1.wakeUpNoMoreInformation().format()
> 		result << response(cmds)
> 	}
> 	result
> }
> 
> def zwaveEvent(hubitat.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
> 	def encapsulatedCommand = cmd.encapsulatedCommand([0x31: 5, 0x30: 2, 0x84: 1])
> 	state.sec = 1
> 	log.debug "encapsulated: ${encapsulatedCommand}"
> 	if (encapsulatedCommand) {
> 		zwaveEvent(encapsulatedCommand)
> 	} else {
> 		log.warn "Unable to extract encapsulated cmd from $cmd"
> 		createEvent(descriptionText: cmd.toString())
> 	}
> }
> 
> def zwaveEvent(hubitat.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) {
> 	log.info "Executing zwaveEvent 98 (SecurityV1): 03 (SecurityCommandsSupportedReport) with cmd: $cmd"
> 	state.sec = 1
> }
> 
> def zwaveEvent(hubitat.zwave.commands.securityv1.NetworkKeyVerify cmd) {
> 	state.sec = 1
> 	log.info "Executing zwaveEvent 98 (SecurityV1): 07 (NetworkKeyVerify) with cmd: $cmd (node is securely included)"
> 	def result = [createEvent(name:"secureInclusion", value:"success", descriptionText:"Secure inclusion was successful", isStateChange: true)]
> 	result
> }
> 
> def zwaveEvent(hubitat.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
>  log.debug "in manuf specific cmd = $cmd"
>  
> 	log.info "Executing zwaveEvent 72 (ManufacturerSpecificV2) : 05 (ManufacturerSpecificReport) with cmd: $cmd"
> 	log.debug "manufacturerId:   ${cmd.manufacturerId}"
> 	log.debug "manufacturerName: ${cmd.manufacturerName}"
> 	log.debug "productId:        ${cmd.productId}"
> 	log.debug "productTypeId:    ${cmd.productTypeId}"
> 	def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
> 	updateDataValue("MSR", msr)
> }
> 
> def zwaveEvent(hubitat.zwave.commands.batteryv1.BatteryReport cmd) {
> 	def result = []
> 	def map = [ name: "battery", unit: "%" ]
> 	if (cmd.batteryLevel == 0xFF) {
> 		map.value = 1
> 		map.descriptionText = "${device.displayName} battery is low"
> 		map.isStateChange = true
> 	} else {
> 		map.value = cmd.batteryLevel
> 	}
> 	state.lastbatt = now()
> 	result << createEvent(map)
> 	if (device.latestValue("powerSupply") != "USB Cable"){
> 		result << createEvent(name: "batteryStatus", value: "${map.value} % battery", displayed: false)
> 	}
> 	result
> }
> 
> def zwaveEvent(hubitat.zwave.commands.sensormultilevelv5.SensorMultilevelReport cmd){
> // log.debug "\nin multi level report cmd = $cmd\n"
>  
> 	def map = [:]
> 	switch (cmd.sensorType) {
> 		case 1:
>             log.debug "raw temp = $cmd.scaledSensorValue"
>             
>             if (settings.tzOffset == null)
>  				settings.tzOffset = -5
>  
>             def now = new Date()
>             def tf = new java.text.SimpleDateFormat("MM/dd/yyyy h:mm a")
>             tf.setTimeZone(TimeZone.getTimeZone("GMT${settings.tzOffset}"))
>             def newtime = "${tf.format(now)}" as String   
>             sendEvent(name: "lastUpdate", value: newtime, descriptionText: "Last Update: $newtime")
>             
>             BigDecimal offset = settings.TempOffset
>             // now way to change to c in device so do differently
>             def startval =convertTemperatureIfNeeded(cmd.scaledSensorValue, cmd.scale == 1 ? "F" : "C", cmd.precision)
>             if (settings.tempScale == "C" && cmd.scale == 0)
>                startval = cmd.scaledSensorValue
>                
>             log.debug "scaled scaled sensor value = $cmd.scaledSensorValue scale = $cmd.scale"
>             log.debug "offset = $offset"
>             log.debug "startval = $startval"
> 			def thetemp = startval as BigDecimal
>             log.debug "the temp = $thetemp"
>             offset = offset ?: 0
>             def newValue = (Math.round((thetemp * 100) + (offset * 100)) / 100)
>             BigDecimal adjval = (thetemp + offset)
>             def dispval =  String.format("%5.1f", adjval)
>             def finalval = dispval as BigDecimal
>             map.value = finalval
>             map.unit = getTemperatureScale()
> 			map.name = "temperature"
> 			break
> 		case 3:
>             log.debug "raw illuminance = $cmd.scaledSensorValue"
> 			map.name = "illuminance"
> 			map.value = cmd.scaledSensorValue.toInteger()
> 			map.unit = "lux"
> 			break
> 		case 5:
>             log.debug "raw humidity = $cmd.scaledSensorValue"
>             settings.HumidOffset = settings.HumidOffset ?: 0
>             map.value = (cmd.scaledSensorValue.toInteger() + settings.HumidOffset)
> 			map.unit = "%"
> 			map.name = "humidity"
> 			break
> 		case 27:
>             log.debug "raw uv index = $cmd.scaledSensorValue"
> 			map.name = "ultravioletIndex"
> 			map.value = cmd.scaledSensorValue.toInteger()
> 			break
> 		default:
> 			map.descriptionText = cmd.toString()
> 	}
> 	createEvent(map)
> }
> 
> def motionEvent(value) {
> 	def map = [name: "motion"]
> 	if (value) {
>         log.debug "motion active"
> 		map.value = "active"
> 		map.descriptionText = "$device.displayName detected motion"
> 	} else {
>        log.debug "motion inactive"
> 		map.value = "inactive"
> 		map.descriptionText = "$device.displayName motion has stopped"
> 	}
> 	createEvent(map)
> }
> 
> def zwaveEvent(hubitat.zwave.commands.sensorbinaryv2.SensorBinaryReport cmd) {
> 	motionEvent(cmd.sensorValue)
> }
> 
> def zwaveEvent(hubitat.zwave.commands.basicv1.BasicSet cmd) {
> 	motionEvent(cmd.value)
> }
> 
> def zwaveEvent(hubitat.zwave.commands.notificationv3.NotificationReport cmd) {
> 	def result = []
> 	if (cmd.notificationType == 7) {
> 		switch (cmd.event) {
> 			case 0:
>            		sendEvent(name: "contact", value: "closed", descriptionText: "$device.displayName is closed", displayed: true)
> 				result << motionEvent(0)
> 				//result << createEvent(name: "tamper", value: "clear", displayed: false)
>                	result << createEvent(name: "acceleration", value: "inactive", descriptionText: "$device.displayName is inactive", displayed: true)
> 				break
> 			case 3:
>            		sendEvent(name: "contact", value: "open", descriptionText: "$device.displayName is open", displayed: true)
> 				//result << createEvent(name: "tamper", value: "detected", descriptionText: "$device.displayName was tampered")
>                 result << createEvent(name: "acceleration", value: "active", descriptionText: "$device.displayName is active", displayed: true)
> 				break
> 			case 7:
> 				result << motionEvent(1)
> 				break
> 		}
> 	} else {
> 		log.warn "Need to handle this cmd.notificationType: ${cmd.notificationType}"
> 		result << createEvent(descriptionText: cmd.toString(), isStateChange: false)
> 	}
> 	result
> }
> 
> def zwaveEvent(hubitat.zwave.commands.configurationv2.ConfigurationReport cmd) {
>  log.debug "---CONFIGURATION REPORT V2--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}"
> 
> def result = []
> 	def value
> 	if (cmd.parameterNumber == 9 && cmd.configurationValue[0] == 0) {
> 		value = "USB Cable"
> 		if (!isConfigured()) {
> 			log.debug("ConfigurationReport: configuring device")
> 			result << response(configure())
> 		}
> 		result << createEvent(name: "batteryStatus", value: value, displayed: false)
> 		result << createEvent(name: "powerSupply", value: value, displayed: false)
> 	}else if (cmd.parameterNumber == 9 && cmd.configurationValue[0] == 1) {
> 		value = "Battery"
> 		result << createEvent(name: "powerSupply", value: value, displayed: false)
> 	} else if (cmd.parameterNumber == 101){
> 		result << response(configure())
> 	}
> 	result
> }
> 
> def zwaveEvent(hubitat.zwave.Command cmd) {
> 	log.debug "General zwaveEvent cmd: ${cmd}"
> 	createEvent(descriptionText: cmd.toString(), isStateChange: false)
> }
> 
> def configure() {
> 	// This sensor joins as a secure device if you double-click the button to include it
> 	log.debug "${device.displayName} is configuring its settings"
> 
> if (settings.motionDelayTime == null)
>   settings.motionDelayTime = 60
> if (settings.reportInterval == null)
>   settings.reportInterval = 8*60
> if (settings.motionSensitivity == null)
>   settings.motionSensitivity = 3
> if (settings.TempOffset == null)
>   settings.TempOffset = 0
> if (settings.HumidOffset == null)
>   settings.HumidOffset = 0
> if (settings.tzOffset == null)
>   settings.tzOffset = -5
> if (settings.tempScale == null)
>   settings.tempScale = "F"
> if (settings.TempChangeAmount == null)
>   settings.TempChangeAmount = 2
>   
>   if (settings.motionSensitivity < 0)
>     {
>       log.debug "Illegal motion sensitivity ... resetting to 0!"
>       settings.motionSensitivity = 0
>     }
>     
>    if (settings.motionSensitivity > 5)
>     {
>       log.debug "Illegal motion sensitivity ... resetting to 5!"
>       settings.motionSensitivity = 5
>     }
>     
>    // fix tz offset
>  if (settings.tzOffset < -12)
>   {
>     settings.tzOffset = -12
>     log.debug "Timezone too low... resetting to -12"
>     }
>     
>  if (settings.tzOffset > 14)
>   {
>     settings.tzOffset = 14
>     log.debug "Timezone too high ... resetting to 14"
>     }
>     
>      // fix temp offset
>  if (settings.TempOffset < -10)
>   {
>     settings.TempOffset = -10
>     log.debug "Temperature Offset too low... resetting to -10"
>     }
>     
>  if (settings.TempOffset > 10)
>   {
>     settings.TempOffset = 10
>     log.debug "Temperature Adjusment too high ... resetting to 10"
>     }
> 
>      // fix temp offset
>  if (settings.HumidOffset < -10)
>   {
>     settings.HumidOffset = -10
>     log.debug "Humidity Offset too low... resetting to -10"
>     }
>     
>  if (settings.HumidOffset > 10)
>   {
>     settings.HumidOffset = 10
>     log.debug "Humidity Adjusment too high ... resetting to 10"
>     }
> 
>   
> log.debug "In configure report interval value = $reportInterval"
> log.debug "Motion Delay Time = $motionDelayTime"
> log.debug "Motion Sensitivity = $motionSensitivity"
> log.debug "Temperature adjust = $TempOffset"
> log.debug "Humidity adjust = $HumidOffset"
> log.debug "Tz Offset = $settings.tzOffset"
> log.debug "temp scale = $tempScale"
> log.debug "min temp change for reporting = $TempChangeAmount"
> 
> def now = new Date()
> def tf = new java.text.SimpleDateFormat("MM/dd/yyyy h:mm a")
> tf.setTimeZone(TimeZone.getTimeZone("GMT${settings.tzOffset}"))
> def newtime = "${tf.format(now)}" as String   
> sendEvent(name: "lastUpdate", value: newtime, descriptionText: "Configured: $newtime")
> 
> setConfigured("true")      
> def waketime
> 
> if (timeOptionValueMap[reportInterval] < 300)
>   waketime = timeOptionValueMap[reportInterval] 
>  else waketime = 300
>  
>  log.debug "wake time reset to $waketime send to $zwaveHubNodeId"
> 
> def request = [
> // set wakeup interval to report time otherwise it doesnt report in time
> 
> 		zwave.wakeUpV1.wakeUpIntervalSet(seconds:waketime, nodeid:zwaveHubNodeId),
> 		
>         zwave.versionV1.versionGet(),
>         zwave.firmwareUpdateMdV2.firmwareMdGet(),
>  
> 	//1. set association groups for hub
> 	zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId),
> 	zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId),
> 
> 	//2. automatic report flags
>     // lgk change ultraviolet is 16 not 2 
> 	// param 101 -103 [4 bytes] 128: light sensor, 64 humidity, 32 temperature sensor, 16 ultraviolet sensor, 1 battery sensor -> send command 241 to get all reports
> 	zwave.configurationV1.configurationSet(parameterNumber: 101, size: 4, scaledConfigurationValue: 241), //association group 1
> 	zwave.configurationV1.configurationSet(parameterNumber: 102, size: 4, scaledConfigurationValue: 1), //association group 2
> 
> 	//3. no-motion report x seconds after motion stops (default 60 secs)
> 	zwave.configurationV1.configurationSet(parameterNumber: 3, size: 2, scaledConfigurationValue: timeOptionValueMap[motionDelayTime] ?: 60),
> 
> 	//4. afSensitivity 3 levels: 64-normal (default), 127-maximum, 0-minimum
>     zwave.configurationV1.configurationSet(parameterNumber: 6, size: 1, scaledConfigurationValue: motionSensitivity),
>      
> 	//5. report every x minutes (threshold reports don't work on battery power, default 8 mins)
>  	zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue:  timeOptionValueMap[reportInterval]), //association group 1
>     zwave.configurationV1.configurationGet(parameterNumber: 0x6F),
>     	        
>     // battery report time.. too long at  every 6 hours change to 2 hours.
> 	zwave.configurationV1.configurationSet(parameterNumber: 112, size: 4, scaledConfigurationValue: 2*60*60),  //association group 2
> 
> 	//6. report automatically on threshold change
> 	zwave.configurationV1.configurationSet(parameterNumber: 40, size: 1, scaledConfigurationValue: 1),
> 
> 	// min change in temp to report
>     zwave.configurationV1.configurationSet(parameterNumber: 41, size: 1, scaledConfigurationValue: TempChangeAmount),
> 
> 
> 	// send binary sensor report for motion
> 		zwave.configurationV1.configurationSet(parameterNumber: 0x05, size: 1, scaledConfigurationValue: 2),
> 	// Enable the function of touch sensor
>         zwave.configurationV1.configurationSet(parameterNumber: 0x07, size: 1, scaledConfigurationValue: 1),
> 	
>      // configure temp offset
>      // these are done directly in the reporting
> 		//zwave.configurationV1.configurationSet(parameterNumber: 0xC9, size: 1, scaledConfigurationValue: 1),
> 		//zwave.configurationV1.configurationGet(parameterNumber: 0xC9),
> 		
>      // configure humidity offset
> 	//  zwave.configurationV1.configurationSet(parameterNumber: 0xCA, size: 1, scaledConfigurationValue: 01),
> 	//  zwave.configurationV1.configurationGet(parameterNumber: 0xCA),
> 	
> 	//7. query sensor data
>     zwave.batteryV1.batteryGet(),
> 	zwave.sensorBinaryV2.sensorBinaryGet(),
> 	zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 1), //temperature
> 	zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 3), //illuminance
> 	zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 5), //humidity
> 	zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 27) //ultravioletIndex
> 
>   ]
> 	commands(request) + ["delay 20000", zwave.wakeUpV1.wakeUpNoMoreInformation().format()]
> 
> }
> 
> def refresh() {
> // refresh not working for now.
> 	// This sensor joins as a secure device if you double-click the button to include it
> 	log.debug "in refresh"
> 
>  	delayBetween([
> 		zwave.versionV1.versionGet(),
>         zwave.firmwareUpdateMdV2.firmwareMdGet(),
>         zwave.configurationV1.configurationGet(parameterNumber: 6),
>         zwave.batteryV1.batteryGet().format(),
>         zwave.sensorBinaryV2.sensorBinaryGet(), //motion
> 		zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 1), //temperature
> 	    zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 3), //illuminance
> 		zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 5), //humidity
> 		zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 27) //ultravioletIndex
>  	], 1000)
> }
> 
> private def getTimeOptionValueMap() { [
> 		"20 seconds" : 20,
> 		"30 seconds" : 30,
> 		"1 minute"   : 60,
> 		"2 minutes"  : 2*60,
> 		"3 minutes"  : 3*60,
> 		"4 minutes"  : 4*60,
> 		"5 minutes"  : 5*60,
> 		"10 minutes" : 10*60,
> 		"15 minutes" : 15*60,
> 		"30 minutes" : 30*60,
> 		"1 hours"    : 1*60*60,
> 		"6 hours"    : 6*60*60,
> 		"12 hours"   : 12*60*60,
> 		"18 hours"   : 18*60*60,
> 		"24 hours"   : 24*60*60,
> ]}
> 
> private setConfigured(configure) {
> 	updateDataValue("configured", configure)
> }
> 
> private isConfigured() {
> 	getDataValue("configured") == "true"
> }
> 
> private command(hubitat.zwave.Command cmd) {
> 	if (state.sec) {
> 		zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
> //	} else {
> //    		logging("Unknown Z-Wave Command: ${cmd.toString()}")
> //		cmd.format()
> 	}
> }
> 
> private commands(commands, delay=1000) {
> 	log.info "sending commands: ${commands}"
> 	delayBetween(commands.collect{ command(it) }, delay)
> }
> 
> 
> def zwaveEvent(hubitat.zwave.commands.versionv1.VersionCommandClassReport cmd) {
>    log.debug "in version class report"
> 	//if (state.debug) 
>     log.debug "---COMMAND CLASS VERSION REPORT V1--- ${device.displayName} has command class version: ${cmd.commandClassVersion} - payload: ${cmd.payload}"
> }
> 
> def zwaveEvent(hubitat.zwave.commands.versionv1.VersionReport cmd) {
>     log.debug "in version report"
> 	def fw = "${cmd.applicationVersion}.${cmd.applicationSubVersion}"
> 	updateDataValue("fw", fw)
> 	//if (state.debug) 
>     log.debug "---VERSION REPORT V1--- ${device.displayName} is running firmware version: $fw, Z-Wave version: ${cmd.zWaveProtocolVersion}.${cmd.zWaveProtocolSubVersion}"
> }
> 
> 
> def zwaveEvent(hubitat.zwave.commands.configurationv1.ConfigurationReport cmd) {
>     //if (state.debug) 
>     log.debug "---CONFIGURATION REPORT V1--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}"
> }

I'm using it on all 12 of my Aeon Multisensor 6's. Debug seems to be on Automatically.

OK then we will need to see the logs I talked about before for the triggers. Also, look at the event logs for the multisensor for the time in question, when it turns off at 100%. You will have to have Logs running to get the trigger logs at the time of failure.

The parameters that you currently have set will carry over and be used by our stock driver so long as you do not hit configure in our driver ui after making the switch.
I would switch drivers and see what the results are.

Thanks Mike. This was on my list of things to do this morning, but I am having bigger problems now. Getting error 500 and backup won't restore. I started a service ticket. I'm not to surprised since I am constantly installing and uninstalling apps, and tweaking things.

This is exactly why I now have 2 Hubitat Elevation hubs - one for production, one for development/testing. My family is much happier now that I am not "breaking the house" any longer (at least not as frequently!)

HE hubs are on sale for $99 this weekend! :wink:

4 Likes

Just ordered a second one.

3 Likes

Me too! :grimacing:

A post was split to a new topic: Uvindex missing