From 246847fc3abab9ce47dc6aefb6d20844350377d7 Mon Sep 17 00:00:00 2001 From: PJ <120332908+iamtrep@users.noreply.github.com> Date: Thu, 22 Dec 2022 17:01:49 -0500 Subject: [PATCH 1/7] Integrated functionality from veeceeoh's driver for Aqara Temperature and Humidity sensor WSDCGQ11LM The new code will look for sensor values in the check-in message that arrives every 50-60 minutes and includes the battery level. --- ...perature_humidity_sensor_wsdcgq11lm.groovy | 220 +++++++++++++----- .../BirdsLikeWires.xiaomi.groovy | 41 ++-- 2 files changed, 179 insertions(+), 82 deletions(-) diff --git a/xiaomi/drivers/xiaomi_aqara_temperature_humidity_sensor_wsdcgq11lm.groovy b/xiaomi/drivers/xiaomi_aqara_temperature_humidity_sensor_wsdcgq11lm.groovy index be8a547..56e2737 100644 --- a/xiaomi/drivers/xiaomi_aqara_temperature_humidity_sensor_wsdcgq11lm.groovy +++ b/xiaomi/drivers/xiaomi_aqara_temperature_humidity_sensor_wsdcgq11lm.groovy @@ -25,11 +25,11 @@ metadata { capability "Configuration" capability "PresenceSensor" capability "PressureMeasurement" - capability "PushableButton" capability "RelativeHumidityMeasurement" capability "Sensor" capability "TemperatureMeasurement" capability "VoltageMeasurement" + capability "PushableButton" attribute "absoluteHumidity", "number" attribute "pressureDirection", "string" @@ -73,102 +73,120 @@ void configureSpecifics() { } -void processMap(Map map) { +void processTemperature(temperatureFlippedHex) { - logging("${device} : processMap() : ${map}", "trace") + BigDecimal temperature = hexStrToSignedInt(temperatureFlippedHex) + temperature = temperature.setScale(2, BigDecimal.ROUND_HALF_UP) / 100 - String[] receivedValue = map.value + logging("${device} : temperature : ${temperature} from hex value ${temperatureFlippedHex}", "trace") - if (map.cluster == "0402") { + String temperatureScale = location.temperatureScale + if (temperatureScale == "F") { + temperature = (temperature * 1.8) + 32 + } - // Received temperature data. + if (temperature > 200 || temperature < -200) { - String[] temperatureHex = receivedValue[2..3] + receivedValue[0..1] - String temperatureFlippedHex = temperatureHex.join() - BigDecimal temperature = hexStrToSignedInt(temperatureFlippedHex) - temperature = temperature.setScale(2, BigDecimal.ROUND_HALF_UP) / 100 + logging("${device} : Temperature : Value of ${temperature}°${temperatureScale} is unusual. Watch out for batteries failing on this device.", "warn") - logging("${device} : temperature : ${temperature} from hex value ${temperatureFlippedHex} flipped from ${map.value}", "trace") + } else { - String temperatureScale = location.temperatureScale - if (temperatureScale == "F") { - temperature = (temperature * 1.8) + 32 - } + logging("${device} : Temperature : ${temperature} °${temperatureScale}", "info") + sendEvent(name: "temperature", value: temperature, unit: "${temperatureScale}") - if (temperature > 200 || temperature < -200) { + } +} - logging("${device} : Temperature : Value of ${temperature}°${temperatureScale} is unusual. Watch out for batteries failing on this device.", "warn") - } else { +void processPressure(pressureFlippedHex) { - logging("${device} : Temperature : ${temperature} °${temperatureScale}", "info") - sendEvent(name: "temperature", value: temperature, unit: "${temperatureScale}") + BigDecimal pressure = hexStrToSignedInt(pressureFlippedHex) + pressure = pressure.setScale(1, BigDecimal.ROUND_HALF_UP) / 10 - } + BigDecimal lastPressure = device.currentState("pressure") ? device.currentState("pressure").value.toBigDecimal() : 0 - } else if (map.cluster == "0403") { + ////////// WORK TO DO - RECORD PREVIOUS PRESSURE AS LASTPRESSURE IF PRESSURE HAS CHANGED OR SOMETHING - TOO TIRED! - // Received pressure data. + // BigDecimal pressurePrevious = device.currentState("pressurePrevious").value.toBigDecimal() + // if (pressurePrevious != null && pressure != lastPressure) { + // endEvent(name: "pressurePrevious", value: lastPressure, unit: "kPa") + // } else if - String[] pressureHex = receivedValue[2..3] + receivedValue[0..1] - String pressureFlippedHex = pressureHex.join() - BigDecimal pressure = hexStrToSignedInt(pressureFlippedHex) - pressure = pressure.setScale(1, BigDecimal.ROUND_HALF_UP) / 10 + String pressureDirection = pressure > lastPressure ? "rising" : "falling" - BigDecimal lastPressure = device.currentState("pressure") ? device.currentState("pressure").value.toBigDecimal() : 0 + logging("${device} : pressure : ${pressure} from hex value ${pressureFlippedHex}", "trace") + logging("${device} : Pressure : ${pressure} kPa", "info") + sendEvent(name: "pressure", value: pressure, unit: "kPa") + sendEvent(name: "pressureDirection", value: "${pressureDirection}") +} - ////////// WORK TO DO - RECORD PREVIOUS PRESSURE AS LASTPRESSURE IF PRESSURE HAS CHANGED OR SOMETHING - TOO TIRED! - // BigDecimal pressurePrevious = device.currentState("pressurePrevious").value.toBigDecimal() - // if (pressurePrevious != null && pressure != lastPressure) { - // endEvent(name: "pressurePrevious", value: lastPressure, unit: "kPa") - // } else if +void processHumidity(humidityFlippedHex) { - String pressureDirection = pressure > lastPressure ? "rising" : "falling" + BigDecimal humidity = hexStrToSignedInt(humidityFlippedHex) + humidity = humidity.setScale(2, BigDecimal.ROUND_HALF_UP) / 100 - logging("${device} : pressure : ${pressure} from hex value ${pressureFlippedHex} flipped from ${map.value}", "trace") - logging("${device} : Pressure : ${pressure} kPa", "info") - sendEvent(name: "pressure", value: pressure, unit: "kPa") - sendEvent(name: "pressureDirection", value: "${pressureDirection}") + logging("${device} : humidity : ${humidity} from hex value ${humidityFlippedHex}", "trace") - } else if (map.cluster == "0405") { + BigDecimal lastTemperature = device.currentState("temperature") ? device.currentState("temperature").value.toBigDecimal() : 0 - // Received humidity data. + String temperatureScale = location.temperatureScale + if (temperatureScale == "F") { + lastTemperature = (lastTemperature - 32) / 1.8 + } - String[] humidityHex = receivedValue[2..3] + receivedValue[0..1] - String humidityFlippedHex = humidityHex.join() - BigDecimal humidity = hexStrToSignedInt(humidityFlippedHex) - humidity = humidity.setScale(2, BigDecimal.ROUND_HALF_UP) / 100 + BigDecimal numerator = (6.112 * Math.exp((17.67 * lastTemperature) / (lastTemperature + 243.5)) * humidity * 2.1674) + BigDecimal denominator = lastTemperature + 273.15 + BigDecimal absoluteHumidity = numerator / denominator + absoluteHumidity = absoluteHumidity.setScale(1, BigDecimal.ROUND_HALF_UP) - logging("${device} : humidity : ${humidity} from hex value ${humidityFlippedHex} flipped from ${map.value}", "trace") + String cubedChar = String.valueOf((char)(179)) - BigDecimal lastTemperature = device.currentState("temperature") ? device.currentState("temperature").value.toBigDecimal() : 0 + if (humidity > 100 || humidity < 0) { - String temperatureScale = location.temperatureScale - if (temperatureScale == "F") { - lastTemperature = (lastTemperature - 32) / 1.8 - } + logging("${device} : Humidity : Value of ${humidity} is out of bounds. Watch out for batteries failing on this device.", "warn") - BigDecimal numerator = (6.112 * Math.exp((17.67 * lastTemperature) / (lastTemperature + 243.5)) * humidity * 2.1674) - BigDecimal denominator = lastTemperature + 273.15 - BigDecimal absoluteHumidity = numerator / denominator - absoluteHumidity = absoluteHumidity.setScale(1, BigDecimal.ROUND_HALF_UP) + } else { - String cubedChar = String.valueOf((char)(179)) + logging("${device} : Humidity (Relative) : ${humidity} %", "info") + logging("${device} : Humidity (Absolute) : ${absoluteHumidity} g/m${cubedChar}", "info") + sendEvent(name: "humidity", value: humidity, unit: "%") + sendEvent(name: "absoluteHumidity", value: absoluteHumidity, unit: "g/m${cubedChar}") - if (humidity > 100 || humidity < 0) { + } +} - logging("${device} : Humidity : Value of ${humidity} is out of bounds. Watch out for batteries failing on this device.", "warn") - } else { +void processMap(Map map) { - logging("${device} : Humidity (Relative) : ${humidity} %", "info") - logging("${device} : Humidity (Absolute) : ${absoluteHumidity} g/m${cubedChar}", "info") - sendEvent(name: "humidity", value: humidity, unit: "%") - sendEvent(name: "absoluteHumidity", value: absoluteHumidity, unit: "g/m${cubedChar}") + logging("${device} : processMap() : ${map}", "trace") - } + String[] receivedValue = map.value + + if (map.cluster == "0402") { + + // Received temperature data. + String[] temperatureHex = receivedValue[2..3] + receivedValue[0..1] + String temperatureFlippedHex = temperatureHex.join() + logging("${device} : processMap() : temperature ${temperatureFlippedHex}", "trace") + processTemperature(temperatureFlippedHex) + + } else if (map.cluster == "0403") { + + // Received pressure data. + String[] pressureHex = receivedValue[2..3] + receivedValue[0..1] + String pressureFlippedHex = pressureHex.join() + logging("${device} : processMap() : pressure ${pressureFlippedHex}", "trace") + processPressure(pressureFlippedHex) + + } else if (map.cluster == "0405") { + // Received humidity data. + String[] humidityHex = receivedValue[2..3] + receivedValue[0..1] + String humidityFlippedHex = humidityHex.join() + logging("${device} : processMap() : humidity ${humidityFlippedHex}", "trace") + processHumidity(humidityFlippedHex) + } else if (map.cluster == "0000") { if (map.attrId == "0005") { @@ -192,3 +210,79 @@ void processMap(Map map) { } + +// TODO attribution to veeceeoh's driver + github ref +// Reverses order of bytes in hex string +def reverseHexString(hexString) { + def reversed = "" + for (int i = hexString.length(); i > 0; i -= 2) { + reversed += hexString.substring(i - 2, i ) + } + return reversed +} + + +// TODO attribution to veeceeoh's driver + github ref +// Parse checkin message from lumi.weather device (WSDCGQ11LM) which contains +// a full set of sensor readings. +def parseCheckinMessageSpecifics(hexString) { + logging("Received check-in message","debug") + def result + // First byte of hexString is UINT8 of payload length in bytes, so it is skipped + def strPosition = 2 + def strLength = hexString.size() - 2 + while (strPosition < strLength) { + def dataTag = Integer.parseInt(hexString[strPosition++..strPosition++], 16) // Each attribute of the check-in message payload is preceded by a unique 1-byte tag value + def dataType = Integer.parseInt(hexString[strPosition++..strPosition++], 16) // After each attribute tag, the following byte gives the data type of the attribute data + def dataLength = DataType.getLength(dataType) // This looks up the length of data for the determined data type + def dataPayload // This is used to collect the payload data of each check-in message attribute + if (dataLength == null || dataLength == -1 || dataLength == 0) { // A length of null or -1 means the data type is probably variable-length, and 0 length is invalid + logging("Check-in message contains unsupported dataType 0x${Integer.toHexString(dataType)} for dataTag 0x${Integer.toHexString(dataTag)} with dataLength $dataLength","debug") + return + } else { + if (strPosition > (strLength - dataLength)) { + logging("Ran out of data before finishing parse of check-in message","debug") + return + } + dataPayload = hexString[strPosition++..(strPosition+=(dataLength * 2) - 1)-1] // Collect attribute tag payload according to data length of its data type + dataPayload = reverseHexString(dataPayload) // Reverse order of bytes for big endian payload + def dataDebug1 = "Check-in message: Found dataTag 0x${Integer.toHexString(dataTag)}" + def dataDebug2 = "dataType 0x${Integer.toHexString(dataType)}, dataLength $dataLength, dataPayload $dataPayload" + switch (dataTag) { + case 0x01: // Battery voltage + logging("$dataDebug1 (battery), $dataDebug2","debug") + //reportBattery(dataPayload, 1000, 2.8, 3.0) // already done in parent call xiaomiDeviceStatus() + break + case 0x05: // RSSI dB + def convertedPayload = Integer.parseInt(dataPayload,16) + logging("$dataDebug1 (RSSI dB), $dataDebug2 ($convertedPayload)","debug") + state.RSSI = convertedPayload + break + case 0x06: // LQI + def convertedPayload = Integer.parseInt(dataPayload,16) + logging("$dataDebug1 (LQI), $dataDebug2 ($convertedPayload)","debug") + state.LQI = convertedPayload + break + case 0x64: // Temperature in Celcius + logging("$dataDebug1 (temperature), $dataDebug2","debug") + processTemperature(dataPayload) + break + case 0x65: // Relative humidity + logging("$dataDebug1 (humidity), $dataDebug2","debug") + processHumidity(dataPayload) + break + case 0x66: // Atmospheric pressure + logging("$dataDebug1 (pressure), $dataDebug2","debug") + processPressure(dataPayload) + break + case 0x0A: // ZigBee parent DNI (device network identifier) + logging("$dataDebug1 (ZigBee parent DNI), $dataDebug2","debug") + state.zigbeeParentDNI = dataPayload + break + default: + logging("$dataDebug1 (unknown), $dataDebug2","debug") + } + } + } +} + diff --git a/xiaomi/libraries/BirdsLikeWires.xiaomi/BirdsLikeWires.xiaomi.groovy b/xiaomi/libraries/BirdsLikeWires.xiaomi/BirdsLikeWires.xiaomi.groovy index 10f75e1..a939d1a 100644 --- a/xiaomi/libraries/BirdsLikeWires.xiaomi/BirdsLikeWires.xiaomi.groovy +++ b/xiaomi/libraries/BirdsLikeWires.xiaomi/BirdsLikeWires.xiaomi.groovy @@ -61,8 +61,8 @@ void updated() { unschedule(traceLogOff) if (!debugMode) { - runIn(2400,debugLogOff) - runIn(1200,traceLogOff) +// runIn(2400,debugLogOff) +// runIn(1200,traceLogOff) } logging("${device} : Preferences Updated", "info") @@ -182,26 +182,29 @@ void xiaomiDeviceStatus(Map map) { reportBattery(batteryVoltageHex, batteryDivisor, 2.8, 3.0) - // On some devices (buttons for one) there's a wildly inaccurate temperature sensor. - // We may as well throw this out in the log for comedy value as it's rarely reported. - // Who knows. We may learn something. + try { - try { + if (modelCheck == "lumi.weather") { + // decode sensor values, which are part of the checkin message + parseCheckinMessageSpecifics(map.value) + } else { + // On some devices (buttons for one) there's a wildly inaccurate temperature sensor. + // We may as well throw this out in the log for comedy value as it's rarely reported. + // Who knows. We may learn something. - String temperatureValue = "undefined" + String temperatureValue = "undefined" + temperatureValue = map.value[14..15] + BigDecimal temperatureCelsius = hexToBigDecimal(temperatureValue) + + logging("${device} : temperatureValue : ${temperatureValue}", "trace") + logging("${device} : temperatureCelsius sensor value : ${temperatureCelsius}", "trace") - temperatureValue = map.value[14..15] - logging("${device} : temperatureValue : ${temperatureValue}", "trace") + logging("${device} : Inaccurate Temperature : $temperatureCelsius °C", "info") + // sendEvent(name: "temperature", value: temperatureCelsius, unit: "C") // No, don't do that. That would be silly. + } + } catch (Exception e) { - BigDecimal temperatureCelsius = hexToBigDecimal(temperatureValue) - logging("${device} : temperatureCelsius sensor value : ${temperatureCelsius}", "trace") - logging("${device} : Inaccurate Temperature : $temperatureCelsius °C", "info") - // sendEvent(name: "temperature", value: temperatureCelsius, unit: "C") // No, don't do that. That would be silly. - - } catch (Exception e) { - - return - - } + return + } } From 0908fea7f4d491494901f11362f8f74b1fe55edc Mon Sep 17 00:00:00 2001 From: PJ <120332908+iamtrep@users.noreply.github.com> Date: Thu, 22 Dec 2022 17:12:22 -0500 Subject: [PATCH 2/7] Fixed tabs + code attributions --- ...mi_aqara_temperature_humidity_sensor_wsdcgq11lm.groovy | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/xiaomi/drivers/xiaomi_aqara_temperature_humidity_sensor_wsdcgq11lm.groovy b/xiaomi/drivers/xiaomi_aqara_temperature_humidity_sensor_wsdcgq11lm.groovy index 56e2737..f46beb6 100644 --- a/xiaomi/drivers/xiaomi_aqara_temperature_humidity_sensor_wsdcgq11lm.groovy +++ b/xiaomi/drivers/xiaomi_aqara_temperature_humidity_sensor_wsdcgq11lm.groovy @@ -211,7 +211,8 @@ void processMap(Map map) { } -// TODO attribution to veeceeoh's driver + github ref +// Adapted from WSDCGQ11LM driver from veeceeoh (https://raw.githubusercontent.com/veeceeoh/xiaomi-hubitat/master/devicedrivers/xiaomi-temperature-humidity-sensor-hubitat.src/xiaomi-temperature-humidity-sensor-hubitat.groovy) +// // Reverses order of bytes in hex string def reverseHexString(hexString) { def reversed = "" @@ -222,7 +223,8 @@ def reverseHexString(hexString) { } -// TODO attribution to veeceeoh's driver + github ref +// Adapted from WSDCGQ11LM driver from veeceeoh (https://raw.githubusercontent.com/veeceeoh/xiaomi-hubitat/master/devicedrivers/xiaomi-temperature-humidity-sensor-hubitat.src/xiaomi-temperature-humidity-sensor-hubitat.groovy) +// // Parse checkin message from lumi.weather device (WSDCGQ11LM) which contains // a full set of sensor readings. def parseCheckinMessageSpecifics(hexString) { @@ -251,7 +253,7 @@ def parseCheckinMessageSpecifics(hexString) { switch (dataTag) { case 0x01: // Battery voltage logging("$dataDebug1 (battery), $dataDebug2","debug") - //reportBattery(dataPayload, 1000, 2.8, 3.0) // already done in parent call xiaomiDeviceStatus() + //reportBattery(dataPayload, 1000, 2.8, 3.0) // already done in parent call xiaomiDeviceStatus() break case 0x05: // RSSI dB def convertedPayload = Integer.parseInt(dataPayload,16) From 50421003cb9c519e4970c03cf9d18b3fb5a76e3b Mon Sep 17 00:00:00 2001 From: PJ <120332908+iamtrep@users.noreply.github.com> Date: Thu, 22 Dec 2022 17:20:10 -0500 Subject: [PATCH 3/7] reverted temporary commenting out of debug log disabling schedule --- .../BirdsLikeWires.xiaomi/BirdsLikeWires.xiaomi.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xiaomi/libraries/BirdsLikeWires.xiaomi/BirdsLikeWires.xiaomi.groovy b/xiaomi/libraries/BirdsLikeWires.xiaomi/BirdsLikeWires.xiaomi.groovy index a939d1a..10d718f 100644 --- a/xiaomi/libraries/BirdsLikeWires.xiaomi/BirdsLikeWires.xiaomi.groovy +++ b/xiaomi/libraries/BirdsLikeWires.xiaomi/BirdsLikeWires.xiaomi.groovy @@ -61,8 +61,8 @@ void updated() { unschedule(traceLogOff) if (!debugMode) { -// runIn(2400,debugLogOff) -// runIn(1200,traceLogOff) + runIn(2400,debugLogOff) + runIn(1200,traceLogOff) } logging("${device} : Preferences Updated", "info") From 46905b17e63315135abe8f3eca3cb1353f72d711 Mon Sep 17 00:00:00 2001 From: PJ <120332908+iamtrep@users.noreply.github.com> Date: Thu, 22 Dec 2022 18:19:33 -0500 Subject: [PATCH 4/7] moved some debugging logs to trace level --- ...temperature_humidity_sensor_wsdcgq11lm.groovy | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/xiaomi/drivers/xiaomi_aqara_temperature_humidity_sensor_wsdcgq11lm.groovy b/xiaomi/drivers/xiaomi_aqara_temperature_humidity_sensor_wsdcgq11lm.groovy index f46beb6..cf10eec 100644 --- a/xiaomi/drivers/xiaomi_aqara_temperature_humidity_sensor_wsdcgq11lm.groovy +++ b/xiaomi/drivers/xiaomi_aqara_temperature_humidity_sensor_wsdcgq11lm.groovy @@ -252,37 +252,37 @@ def parseCheckinMessageSpecifics(hexString) { def dataDebug2 = "dataType 0x${Integer.toHexString(dataType)}, dataLength $dataLength, dataPayload $dataPayload" switch (dataTag) { case 0x01: // Battery voltage - logging("$dataDebug1 (battery), $dataDebug2","debug") + logging("$dataDebug1 (battery), $dataDebug2","trace") //reportBattery(dataPayload, 1000, 2.8, 3.0) // already done in parent call xiaomiDeviceStatus() break case 0x05: // RSSI dB def convertedPayload = Integer.parseInt(dataPayload,16) - logging("$dataDebug1 (RSSI dB), $dataDebug2 ($convertedPayload)","debug") + logging("$dataDebug1 (RSSI dB), $dataDebug2 ($convertedPayload)","trace") state.RSSI = convertedPayload break case 0x06: // LQI def convertedPayload = Integer.parseInt(dataPayload,16) - logging("$dataDebug1 (LQI), $dataDebug2 ($convertedPayload)","debug") + logging("$dataDebug1 (LQI), $dataDebug2 ($convertedPayload)","trace") state.LQI = convertedPayload break case 0x64: // Temperature in Celcius - logging("$dataDebug1 (temperature), $dataDebug2","debug") + logging("$dataDebug1 (temperature), $dataDebug2","trace") processTemperature(dataPayload) break case 0x65: // Relative humidity - logging("$dataDebug1 (humidity), $dataDebug2","debug") + logging("$dataDebug1 (humidity), $dataDebug2","trace") processHumidity(dataPayload) break case 0x66: // Atmospheric pressure - logging("$dataDebug1 (pressure), $dataDebug2","debug") + logging("$dataDebug1 (pressure), $dataDebug2","trace") processPressure(dataPayload) break case 0x0A: // ZigBee parent DNI (device network identifier) - logging("$dataDebug1 (ZigBee parent DNI), $dataDebug2","debug") + logging("$dataDebug1 (ZigBee parent DNI), $dataDebug2","trace") state.zigbeeParentDNI = dataPayload break default: - logging("$dataDebug1 (unknown), $dataDebug2","debug") + logging("$dataDebug1 (unknown), $dataDebug2","trace") } } } From b890ed60fcd4833bca2e8173cc93e61d8b8bd5ea Mon Sep 17 00:00:00 2001 From: PJ <120332908+iamtrep@users.noreply.github.com> Date: Thu, 22 Dec 2022 19:23:50 -0500 Subject: [PATCH 5/7] Fixed a bug due to checkin message containing more precision on pressure value than other messages --- ...qara_temperature_humidity_sensor_wsdcgq11lm.groovy | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/xiaomi/drivers/xiaomi_aqara_temperature_humidity_sensor_wsdcgq11lm.groovy b/xiaomi/drivers/xiaomi_aqara_temperature_humidity_sensor_wsdcgq11lm.groovy index cf10eec..7351b8a 100644 --- a/xiaomi/drivers/xiaomi_aqara_temperature_humidity_sensor_wsdcgq11lm.groovy +++ b/xiaomi/drivers/xiaomi_aqara_temperature_humidity_sensor_wsdcgq11lm.groovy @@ -98,11 +98,13 @@ void processTemperature(temperatureFlippedHex) { } -void processPressure(pressureFlippedHex) { +void processPressure(pressureFlippedHex,checkin=false) { BigDecimal pressure = hexStrToSignedInt(pressureFlippedHex) + if (checkin) { + pressure = pressure / 100 + } pressure = pressure.setScale(1, BigDecimal.ROUND_HALF_UP) / 10 - BigDecimal lastPressure = device.currentState("pressure") ? device.currentState("pressure").value.toBigDecimal() : 0 ////////// WORK TO DO - RECORD PREVIOUS PRESSURE AS LASTPRESSURE IF PRESSURE HAS CHANGED OR SOMETHING - TOO TIRED! @@ -253,7 +255,7 @@ def parseCheckinMessageSpecifics(hexString) { switch (dataTag) { case 0x01: // Battery voltage logging("$dataDebug1 (battery), $dataDebug2","trace") - //reportBattery(dataPayload, 1000, 2.8, 3.0) // already done in parent call xiaomiDeviceStatus() + //reportBattery(dataPayload, 1000, 2.8, 3.0) // already done in parent call xiaomiDeviceStatus() break case 0x05: // RSSI dB def convertedPayload = Integer.parseInt(dataPayload,16) @@ -275,7 +277,7 @@ def parseCheckinMessageSpecifics(hexString) { break case 0x66: // Atmospheric pressure logging("$dataDebug1 (pressure), $dataDebug2","trace") - processPressure(dataPayload) + processPressure(dataPayload,true) break case 0x0A: // ZigBee parent DNI (device network identifier) logging("$dataDebug1 (ZigBee parent DNI), $dataDebug2","trace") @@ -287,4 +289,3 @@ def parseCheckinMessageSpecifics(hexString) { } } } - From 2eead7d7a3a31b6d638e73472e74a78db0c3427c Mon Sep 17 00:00:00 2001 From: PJ <120332908+iamtrep@users.noreply.github.com> Date: Fri, 23 Dec 2022 12:33:20 -0500 Subject: [PATCH 6/7] Update BirdsLikeWires.xiaomi.groovy Log check-in message arrival at "info" level. --- .../libraries/BirdsLikeWires.xiaomi/BirdsLikeWires.xiaomi.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/xiaomi/libraries/BirdsLikeWires.xiaomi/BirdsLikeWires.xiaomi.groovy b/xiaomi/libraries/BirdsLikeWires.xiaomi/BirdsLikeWires.xiaomi.groovy index 10d718f..4305928 100644 --- a/xiaomi/libraries/BirdsLikeWires.xiaomi/BirdsLikeWires.xiaomi.groovy +++ b/xiaomi/libraries/BirdsLikeWires.xiaomi/BirdsLikeWires.xiaomi.groovy @@ -155,6 +155,7 @@ void xiaomiDeviceStatus(Map map) { String modelCheck = "${getDeviceDataByName('model')}" def dataSize = map.value.size() + logging("${device} check-in message.", "info") logging("${device} : xiaomiDeviceStatus : Received $dataSize character message.", "debug") if (modelCheck == "lumi.sen_ill.mgl01") { From 8f84e8e44133fcb63d467647e8bc768ba3bb6ac9 Mon Sep 17 00:00:00 2001 From: PJ <120332908+iamtrep@users.noreply.github.com> Date: Sun, 5 Mar 2023 09:44:16 -0500 Subject: [PATCH 7/7] make future merges easier --- ...perature_humidity_sensor_wsdcgq11lm.groovy | 119 +++++++++--------- 1 file changed, 61 insertions(+), 58 deletions(-) diff --git a/xiaomi/drivers/xiaomi_aqara_temperature_humidity_sensor_wsdcgq11lm.groovy b/xiaomi/drivers/xiaomi_aqara_temperature_humidity_sensor_wsdcgq11lm.groovy index 2b6ec1a..937ccd9 100644 --- a/xiaomi/drivers/xiaomi_aqara_temperature_humidity_sensor_wsdcgq11lm.groovy +++ b/xiaomi/drivers/xiaomi_aqara_temperature_humidity_sensor_wsdcgq11lm.groovy @@ -80,7 +80,61 @@ void updateSpecifics() { } -void processTemperature(temperatureFlippedHex) { +void processMap(Map map) { + + logging("${device} : processMap() : ${map}", "trace") + + String[] receivedValue = map.value + + if (map.cluster == "0402") { + + // Received temperature data. + String[] temperatureHex = receivedValue[2..3] + receivedValue[0..1] + String temperatureFlippedHex = temperatureHex.join() + logging("${device} : processMap() : temperature ${temperatureFlippedHex}", "trace") + processTemperature(temperatureFlippedHex) + + } else if (map.cluster == "0403") { + + // Received pressure data. + String[] pressureHex = receivedValue[2..3] + receivedValue[0..1] + String pressureFlippedHex = pressureHex.join() + logging("${device} : processMap() : pressure ${pressureFlippedHex}", "trace") + processPressure(pressureFlippedHex) + + } else if (map.cluster == "0405") { + + // Received humidity data. + String[] humidityHex = receivedValue[2..3] + receivedValue[0..1] + String humidityFlippedHex = humidityHex.join() + logging("${device} : processMap() : humidity ${humidityFlippedHex}", "trace") + processHumidity(humidityFlippedHex) + + } else if (map.cluster == "0000") { + + if (map.attrId == "0005") { + + // Scrounge more value! We can capture a short press of the reset button and make it useful. + logging("${device} : Trigger : Button Pressed", "info") + sendEvent(name: "pushed", value: 1, isStateChange: true) + + } else { + + // processBasic(map) + filterThis(map) + + } + + } else { + + filterThis(map) + + } + +} + + +private void processTemperature(temperatureFlippedHex) { BigDecimal temperature = hexStrToSignedInt(temperatureFlippedHex) temperature = temperature.setScale(2, BigDecimal.ROUND_HALF_UP) / 100 @@ -105,7 +159,7 @@ void processTemperature(temperatureFlippedHex) { } -void processPressure(pressureFlippedHex,checkin=false) { +private void processPressure(pressureFlippedHex,checkin=false) { BigDecimal pressure = hexStrToSignedInt(pressureFlippedHex) if (checkin) { @@ -130,7 +184,7 @@ void processPressure(pressureFlippedHex,checkin=false) { } -void processHumidity(humidityFlippedHex) { +private void processHumidity(humidityFlippedHex) { BigDecimal humidity = hexStrToSignedInt(humidityFlippedHex) humidity = humidity.setScale(2, BigDecimal.ROUND_HALF_UP) / 100 @@ -166,64 +220,10 @@ void processHumidity(humidityFlippedHex) { } -void processMap(Map map) { - - logging("${device} : processMap() : ${map}", "trace") - - String[] receivedValue = map.value - - if (map.cluster == "0402") { - - // Received temperature data. - String[] temperatureHex = receivedValue[2..3] + receivedValue[0..1] - String temperatureFlippedHex = temperatureHex.join() - logging("${device} : processMap() : temperature ${temperatureFlippedHex}", "trace") - processTemperature(temperatureFlippedHex) - - } else if (map.cluster == "0403") { - - // Received pressure data. - String[] pressureHex = receivedValue[2..3] + receivedValue[0..1] - String pressureFlippedHex = pressureHex.join() - logging("${device} : processMap() : pressure ${pressureFlippedHex}", "trace") - processPressure(pressureFlippedHex) - - } else if (map.cluster == "0405") { - - // Received humidity data. - String[] humidityHex = receivedValue[2..3] + receivedValue[0..1] - String humidityFlippedHex = humidityHex.join() - logging("${device} : processMap() : humidity ${humidityFlippedHex}", "trace") - processHumidity(humidityFlippedHex) - - } else if (map.cluster == "0000") { - - if (map.attrId == "0005") { - - // Scrounge more value! We can capture a short press of the reset button and make it useful. - logging("${device} : Trigger : Button Pressed", "info") - sendEvent(name: "pushed", value: 1, isStateChange: true) - - } else { - - // processBasic(map) - filterThis(map) - - } - - } else { - - filterThis(map) - - } - -} - - // Adapted from WSDCGQ11LM driver from veeceeoh (https://raw.githubusercontent.com/veeceeoh/xiaomi-hubitat/master/devicedrivers/xiaomi-temperature-humidity-sensor-hubitat.src/xiaomi-temperature-humidity-sensor-hubitat.groovy) // // Reverses order of bytes in hex string -def reverseHexString(hexString) { +private def reverseHexString(hexString) { def reversed = "" for (int i = hexString.length(); i > 0; i -= 2) { reversed += hexString.substring(i - 2, i ) @@ -236,6 +236,9 @@ def reverseHexString(hexString) { // // Parse checkin message from lumi.weather device (WSDCGQ11LM) which contains // a full set of sensor readings. +// +// called from xiaomiDeviceStatus in xiaomi library +// def parseCheckinMessageSpecifics(hexString) { logging("Received check-in message","debug") def result