I have a rule that has not been turning on all the lights that should be turned.
The rule is triggered by an Ecolink tilt sensor on the garage door.
When triggered the rule:
- Requests a measurement of garage distance to see if a vehicle is in the garage. (device and driver is custom)
- If not and the time is such that it is dark outside turn on the Accent lights scene and Exterior lights.
Not all the lights come on. I would normally think it would be in the Accent lights scene but these work with a different rule.
Active Logs show nothing useful.
Looking and the details of the "G01 Safety GarageOpen_Vehicle_Dark__LightsOn" rule I see the "trigCustom" has distance many many times. Is this typical?
Garage distance measurement device driver code:
/**
* Garage Ultrasonic Sensor
*
* 2020-12-25 - v02b - "saves" in hubitat and can request measurement via device page button.
* v04a - distance was an integer
*
* todo - transfer initial configure to Hub instead of Arduino.
* - add ability to change "ping." in cc2430 and #OK. in Arduino.
* -
* - clean up some of the log commands etc
* Change vehicle present to enum present, not present, null
*
*/
import hubitat.device.HubAction
import hubitat.device.HubMultiAction
import hubitat.device.Protocol
metadata {
definition (name: "Garage Ultrasonic v04a", namespace: "johnrob", author: "various") {
capability "Actuator" // our device has commands...
capability "Sensor" // our device has attributes...
capability "PresenceSensor" // ENUM["present", "not present"]
capability "Configuration" // capability "Configuration" commands: configure()
command "requestMeasRM"
attribute "vehiclePresent", "enum", ["present", "not present","null"]
//attribute "someOtherName", "enum", ["light", "dark"]
attribute "lastActivity", "String"
attribute "distance", "number"
}
preferences { // see: Hubitat Notes (HTTP, driver and app).docx for more input options (there are lots of them)
input name: "threshold", type: "num", title: "Presence Threshold (cm)", defaultValue: 200, range: "50..250", required: false
input name: "logEnable", type: "bool", title: "Enable debug logging", defaultValue: true
input name: "txtEnable", type: "bool", title: "Enable descriptionecho logging", defaultValue: true
}
}
// Parse incoming device messages to generate events
def parse(String description) {
if (logEnable) log.debug " description is $description"
state.lastRan = now()
// runIn(300, clearOldData) //seconds, watchdogAlarm,[overwrite: true]) // [] because overwrite is a map
Map map = [:]
def event = zigbee.getEvent(description)
if (event) {
if (txtEnable) log.debug " parsed zigbee event = '${event}"
sendEvent(event)
}
else if (description?.startsWith("catchall:")) {
if (logEnable) log.debug " catchall is $description"
}
else if (description?.startsWith("read attr -")) { // our returned measurement is in this Map
def descMap = zigbee.parseDescriptionAsMap(description)
if (logEnable) log.debug " Desc Map: $descMap"
if (descMap.clusterInt == 0) {
def echo = descMap.value // def = define untyped variable
if (txtEnable) log.info " parsing '${echo}'"
echo = echo.replace(".","").trim()
if (echo.startsWith("!")) {
echo = echo.replace("!","")
sendEvent(name: "distance", value: echo, isStateChange: true, unit: "cm")
int echoValue = Integer.parseInt(echo)
int threshold = Integer.parseInt(threshold)
if (txtEnable) log.info "echo=${echoValue}"
if (echoValue > threshold) {
vehState = "not present"
log.info " > threshold}"
}
else{
vehState = "present"
if (txtEnable) log.info "${echo} < threshold}"
}
return sendEvent(name: "vehiclePresent", value: vehState, isStateChange: true)
}
if (echo.startsWith("ping")) return // trailing . removed above
else if (echo.startsWith("#OK")){
clearOldData() // by the time we get the next OK, the data will be obsolete.
return
}
else log.warn "Not an attribute we can decode"
}
} // --- 2nd else if ---
else {
log.warn "DID NOT PARSE MESSAGE for description : $description"
if (logEnable) log.debug zigbee.parseDescriptionAsMap(description)
}
} // --- parse ---
//def getecho(){ // read some attribute string from the device
// if (txtEnable) log.info "gettext"
// //zigbee.readAttribute(0x000, 0x0006) // gets the last thing the device tried to send to us
// zigbee.readAttribute(0x000, 0x0010) // gets the last command the device heard us send
//}
def requestMeasRM() {
sendHubCommand(new HubAction(sendtodevice("@."), Protocol.ZIGBEE))
}
def sendtodevice(String mystr){
if (txtEnable) log.info "sending '${mystr}'"
mystr=mystr.padRight(16,".") // mystr should be 16 bytes!
def packed = hubitat.helper.HexUtils.byteArrayToHexString(mystr.getBytes())
if (logEnable) log.info "sending '${mystr}', packed is ${packed}"
def commandtosend = "he wattr 0x${device.deviceNetworkId} 8 0x000 0x010 0x42 {10"+packed+"}" // SAMPLELIGHT_ENDPOINT is defined as 8 in device code // the 10 on the end means 16 bytes length
if (logEnable) log.debug "$commandtosend"
return commandtosend
}
def sendCommand(String msg) {
if (txtEnable) log.info "sendCommand - ${msg}"
sendHubCommand(new HubAction(sendtodevice(msg), Protocol.ZIGBEE)) // "new" Creates a new HubAction object
}
def configure() {
if (txtEnable) log.info "Configuring Reporting and Bindings."
zigbee.onOffRefresh() + zigbee.onOffConfig()
}
def installed() {
if (txtEnable) log.info "Executing 'installed()'"
updated()
}
def initialize() {
if (txtEnable) log.info "Executing 'initialize()'"
}
def updated() {
if (txtEnable) log.info "Executing 'updated()'"
if (logEnable) {
log.info "Enabling Debug Logging for 30 minutes"
runIn(1800,logsOff)
} else {
unschedule(logsoff)
}
}
def now() {
if(location.timeZone)
now = new Date().format("yyyy MMM dd EEE h:mm:ss a", location.timeZone)
else
now = new Date().format("yyyy MMM dd EEE h:mm:ss a")
sendEvent(name: "lastActivity", value: now, displayed:false)
result
}
def clearOldData() {
sendEvent(name: "distance", value: "null", isStateChange: true, unit: "cm")
sendEvent(name: "vehiclePresent", value: "null", isStateChange: true)
}
// --- code ---
// --- eof ---