Air Quality Sensor Z-Wave Plus

Hi guys. I bought the Air Quality Sensor Z-Wave Plus Eurotronic the other day. Unfortunately there is no suitable driver for it. I tried to write my own. But, unfortunately, I can not achieve an indication of air quality by VOC and dew point. The air indication should be interpreted in terms of the VOC value. The meaning itself is shown in the appendix, only the interpretation is not visible. Please, help. Don’t swear too much, I’m not a programmer. The driver is written by an amateur, so to speak.

metadata {
definition(name: “Luftgütesensor”, namespace: “Aelfot”, author: “aelfot”, mnmn: “SmartThingsCommunity”, vid: “generic-leak-5”, ocfDeviceType: “x.com.st.d.airqualitysensor”) {
capability “Dew Point”
capability “Carbon Dioxide Measurement”
capability “Tvoc Measurement”
capability “Temperature Measurement”
capability “Relative Humidity Measurement”
capability “Sensor”
capability “Configuration”
capability “Tvoc Health Concern”
capability “Carbon Dioxide Health Concern”

  fingerprint mfr:"0148", prod:"0005", model:"0001"	
    fingerprint mfr:"0000", prod:"0000", model:"0000"
    }

tiles(scale: 2) {
multiAttributeTile(name: “water”, type: “generic”, width: 6, height: 6) {
tileAttribute(“device.water”, key: “PRIMARY_CONTROL”) {
attributeState(“dry”, label:‘${name}’, icon: “st.alarm.water.dry”, backgroundColor: “#ffffff”)
attributeState(“wet”, label:‘${name}’, icon: “st.alarm.water.wet”, backgroundColor: “#00A0DC”)
}
}
valueTile(“humidity”, “device.humidity”, inactiveLabel: false, width: 2, height: 2) {
state “humidity”, label: ‘${currentValue}%’, unit: “”
}
valueTile(“temperature”, “device.temperature”, width: 2, height: 2) {
state(“temperature”, label: ‘${currentValue}°’,
backgroundColors: [
// Celsius
[value: 0, color: “#153591”],
[value: 7, color: “#1e9cbb”],
[value: 15, color: “#90d2a7”],
[value: 23, color: “#44b621”],
[value: 28, color: “#f1d801”],
[value: 35, color: “#d04e00”],
[value: 37, color: “#bc2323”],
// Fahrenheit
[value: 40, 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”]
])
}
valueTile(“carbonDioxide”, “device.co2Level”, inactiveLabel: false, width: 2, height: 2) {
state “carbonDioxide”, label: ‘${currentValue}’, unit: “”
}
valueTile(“dewPoint”, “device.dewPoint”, inactiveLabel: false, width: 2, height: 2) {
state “dewPoint”, label:‘${currentValue}°’, unit: “”
}
valueTile(“tvocLevel”, “device.tvocLevel”, inactiveLabel: false, width: 2, height: 2) {
state “tvocLevel”, label: ‘${currentValue}’, unit: “”
}
standardTile(“carbonDioxideHealthConcern”, “device.carbonDioxideHealthConcern”, inactiveLabel: false, width: 2, height: 2) {
state “good”, label:‘Hohe Raumluftqualität’, unit: “”
state “moderate”, label:‘Mittlere Raumluftqualität’, unit: “”
state “slightlyUnhealthy”, label:‘Mäßige Raumluftqualität’, unit: “”
state “unhealthy”, label:‘Niedrige Raumluftqualität’, unit: “”
state “veryUnhealthy”, label:‘Raumluftqualität unakzeptabel’, unit: “”
}
standardTile(“tvocHealthConcern”, “device.tvocHealthConcern”, inactiveLabel: false, width: 2, height: 2) {
state “good”, label:‘Luft frei von Verunreinigungen’, unit: “”
state “moderate”, label:‘Luft frei von Verunreinigungen’, unit: “”
state “slightlyUnhealthy”, label:‘Geringfügige Verunreinigung’, unit: “”
state “unhealthy”, label:‘Mittelmäßige Verunreinigung’, unit: “”
state “veryUnhealthy”, label:‘Raumluftqualität unakzeptabel’, unit: “”
}

    preferences {
    input "Temperaturdifferenz", "enum", title: "Temperaturdifferenz", options: ["0.1", "0.5", "1"], description: "Report, wenn Temperature geändert 0.1...5,0°C", defaultValue: "0.5" , displayDuringSetup: true
    input "Feuchtigkeitsdifferenz", "number", title: "Feuchtigkeitsdifferenz", description: "Report, wenn Feuchtigkeit geändert 1...100%", defaultValue: 5, range: "1..100", displayDuringSetup: false
    input "Temperatureeinheit", "enum", title: "Temperatureeinheit", options: ["°C", "°F"], defaultValue: "°C", required: false, displayDuringSetup: true
    input "TemperaturAufloesung", "enum", title: "Auflösung Temperatur", options: ["keine Nachkommastelle", "eine Nachkommastelle", "zwei Nachkommastellen"], defaultValue: "eine Nachkommastelle", required: false, displayDuringSetup: true
    input "FeuchtigkeitsAufloesung", "enum", title: "Auflösung Feuchte", options: ["keine Nachkommastelle", "eine Nachkommastelle", "zwei Nachkommastellen"], defaultValue: "keine Nachkommastelle", required: false, displayDuringSetup: true
    input "VOCChageReporting", "number", title: "VOC-on Change Reporting", description: "VOC-on Change Reporting 100...1000 ppb", range: "100..1000",  displayDuringSetup: false
    input "CO2ChangeReporting", "number", title: "CO2 Change Reporting", description: "CO2 Change Reporting 100...1000 ppb", range: "100..1000", displayDuringSetup: false
    input "LedIndikation", "enum", title: "Luftgüte per LED signalisieren", options: ["nein", "ja"], defaultValue: "ja", required: false, displayDuringSetup: true
	}   
  
  main "water"
  details(["water", "humidity", "temperature", "carbonDioxide", "dewPoint", "tvocLevel", "carbonDioxideHealthConcern", "tvocHealthConcern"])

}
}

def installed() {
sendEvent(name: “dewPoint”, value: 0, unit: “C”, linkText:“$device.displayName”, descriptionText: “$device.displayName Dew Point is $value”, isStateChange:true, displayed:true)
sendEvent(name: “carbonDioxideHealthConcern”, value: “good”, linkText:“$device.displayName”, descriptionText: “$device.displayName Hohe Raumluftqualität”, isStateChange:true, displayed:true)
sendEvent(name: “tvocHealthConcern”, value: “good”, linkText:“$device.displayName”, descriptionText: “$device.displayName Sauber”, isStateChange:true, displayed:true)
response([
secure(zwave.notificationV3.notificationGet(notificationType: 0x0D)), // Home Health
“delay 500”,
secure(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x01)), // temperature
“delay 500”,
secure(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x05)), // humidity
“delay 500”,
secure(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x0B)), // dewpoint
“delay 500”,
secure(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x11)), // CO2
“delay 500”,
secure(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x27)), // VOC
“delay 10000”,
secure(zwave.wakeUpV2.wakeUpNoMoreInformation())
])
}

def updated() {
configure()
}

def configure() {
sendEvent(name: “dewPoint”, value: 13, unit: “°”, linkText:‘$device.displayName’, descriptionText: “$device.displayName Dew Point is $value”, isStateChange:true, displayed:true)
sendEvent(name: “carbonDioxideHealthConcern”, value: “good”, linkText:‘$device.displayName’, descriptionText: “$device.displayName Hohe Raumluftqualität”, isStateChange:true, displayed:true)
sendEvent(name: “tvocHealthConcern”, value: “good”, linkText:‘$device.displayName’, descriptionText: “$device.displayName Sauber”, isStateChange:true, displayed:true)
sendEvent(name: “checkInterval”, value: 8 * 60 * 60 + 10 * 60, displayed: false, data: [protocol: “zwave”, hubHardwareId: device.hub.hardwareID])
secure(zwave.configurationV1.configurationSet(configurationValue: Temperaturdifferenz == “0.1” ? [0x01] : Temperaturdifferenz == “0.5” ? [0x05] : [0x0A] , parameterNumber:1, size:1, scaledConfigurationValue: Temperaturdifferenz == “0.1” ? 0x01 : Temperaturdifferenz == “0.5” ? 0x05 : 0x0A))//,
secure(zwave.configurationV1.configurationSet(configurationValue: Feuchtigkeitsdifferenz == null ? [0x05] : [Integer.toHexString(Feuchtigkeitsdifferenz).toUpperCase()], parameterNumber:2, size:1, scaledConfigurationValue: Feuchtigkeitsdifferenz == null ? 0x05 : Integer.toHexString(Feuchtigkeitsdifferenz).toUpperCase()))//,
secure(zwave.configurationV1.configurationSet(configurationValue: Temperatureeinheit == “°C” ? [0x00] : [0x01], parameterNumber:3, size:1, scaledConfigurationValue: Temperatureeinheit == “°C” ? 0x00 : 0x01))//,
secure(zwave.configurationV1.configurationSet(configurationValue: TemperaturAufloesung == “keine Nachkommastelle” ? [0x00] : TemperaturAufloesung == “eine Nachkommastelle” ? [0x01] : [0x02], parameterNumber:4, size:1, scaledConfigurationValue: TemperaturAufloesung == “keine Nachkommastelle” ? 0x00 : TemperaturAufloesung == “eine Nachkommastelle” ? 0x01 : 0x02))//,
secure(zwave.configurationV1.configurationSet(configurationValue: FeuchtigkeitsAufloesung == “keine Nachkommastelle” ? [0x00] : FeuchtigkeitsAufloesung == “eine Nachkommastelle” ? [0x01] : [0x02], parameterNumber:5, size:1, scaledConfigurationValue: FeuchtigkeitsAufloesung == “keine Nachkommastelle” ? 0x00 : FeuchtigkeitsAufloesung == “eine Nachkommastelle” ? 0x01 : 0x02))//,
secure(zwave.configurationV1.configurationSet(configurationValue: VOCChageReporting == null ? [0x05] : [Integer.toHexString(VOCChageReporting-100).toUpperCase()], parameterNumber:6, size:1, scaledConfigurationValue: VOCChageReporting == null ? 0x05 : VOCChageReporting-100))//,
secure(zwave.configurationV1.configurationSet(configurationValue: CO2ChangeReporting == null ? [0x05] : [Integer.toHexString(CO2ChangeReporting-100).toUpperCase()], parameterNumber:7, size:1, scaledConfigurationValue: CO2ChangeReporting == null ? 0x05 : CO2ChangeReporting-100))//,
secure(zwave.configurationV1.configurationSet(configurationValue: LedIndikation == “nein” ? [0x00] : [0x01], parameterNumber:8, size:1, scaledConfigurationValue: LedIndikation == “nein” ? 0x00 : 0x01))//,
}

def parse(String description) {
def results =
if (description.startsWith(“Err”)) {
results += createEvent(descriptionText: description, displayed: true)
} else {
def cmd = zwave.parse(description)
if (cmd) {
results += zwaveEvent(cmd)
}
}
log.debug “parse() result ${results.inspect()}”
return results
}

def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand()
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
} else {
log.warn “Unable to extract encapsulated cmd from $cmd”
createEvent(descriptionText: cmd.toString())
}
}

def zwaveEvent(physicalgraph.zwave.commands.notificationv3.EventSupportedReport cmd) {
switch (cmd.event) {
case 1:
createEvent(name:“tvocHealthConcern”, value:“good”, linkText:‘$device.displayName’, descriptionText:“$device.displayName Zielwert”, isStateChange:true, displayed:true)
sendPush(“Luftqualität ist super”)
break;
case 2:
createEvent(name:“tvocHealthConcern”, value:“moderate”, linkText:‘$device.displayName’, descriptionText:“$device.displayName Verstärktes Lüften wird empfohlen”, isStateChange:true, displayed:true)
sendPush(“Luftqualität ist nicht perfekt. Lüften empfohlen”)
break;
case 3:
createEvent(name:“tvocHealthConcern”, value:“slightlyUnhealthy”, linkText:‘$device.displayName’, descriptionText:“$device.displayName Verstärktes Lüften notwendig”, isStateChange:true, displayed:true)
sendPush(“Luftqualität ist schlecht. Verstärktes Lüften notwendig”)
break;
case 4:
createEvent(name:“tvocHealthConcern”, value:“unhealthy”, linkText:‘$device.displayName’, descriptionText:“$device.displayName Nur nutzen, wenn unvermeidbar”, isStateChange:true, displayed:true)
sendPush(“Luftqualität ist miserabel. Raum nutzen nur, wenn unvermeidbar. Lüften!!!”)
break;
case 5:
createEvent(name:“tvocHealthConcern”, value:“veryUnhealthy”, linkText:‘$device.displayName’, descriptionText:“$device.displayName Nur nutzen, wenn unvermeidbar”, isStateChange:true, displayed:true)
sendPush(“Luftqualität ist lebensgefährlich. Raum verlassen und lüften.”)
break;
}
}

def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) {
switch (cmd.event) {
case 1:
createEvent(name:“tvocHealthConcern”, value:“good”, linkText:‘$device.displayName’, descriptionText:“$device.displayName Zielwert”, isStateChange:true, displayed:true)
sendPush(“Luftqualität ist super”)
break;
case 2:
createEvent(name:“tvocHealthConcern”, value:“moderate”, linkText:‘$device.displayName’, descriptionText:“$device.displayName Verstärktes Lüften wird empfohlen”, isStateChange:true, displayed:true)
sendPush(“Luftqualität ist nicht perfekt. Lüften empfohlen”)
break;
case 3:
createEvent(name:“tvocHealthConcern”, value:“slightlyUnhealthy”, linkText:‘$device.displayName’, descriptionText:“$device.displayName Verstärktes Lüften notwendig”, isStateChange:true, displayed:true)
sendPush(“Luftqualität ist schlecht. Verstärktes Lüften notwendig”)
break;
case 4:
createEvent(name:“tvocHealthConcern”, value:“unhealthy”, linkText:‘$device.displayName’, descriptionText:“$device.displayName Nur nutzen, wenn unvermeidbar”, isStateChange:true, displayed:true)
sendPush(“Luftqualität ist miserabel. Raum nutzen nur, wenn unvermeidbar. Lüften!!!”)
break;
case 5:
createEvent(name:“tvocHealthConcern”, value:“veryUnhealthy”, linkText:‘$device.displayName’, descriptionText:“$device.displayName Nur nutzen, wenn unvermeidbar”, isStateChange:true, displayed:true)
sendPush(“Luftqualität ist lebensgefährlich. Raum verlassen und lüften.”)
break;
}
}

def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv5.SensorMultilevelReport cmd) {
def map = [:]
switch (cmd.sensorType) {
case 1:
map.name = “temperature”
map.unit = temperatureScale
map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmd.scale == 1 ? “F” : “C”, cmd.precision)
break;
case 5:
map.name = “humidity”
map.unit = cmd.scale == 0 ? “%” : “g/m^3”
map.value = cmd.scaledSensorValue.toFloat()
break;
case 0xB:
map.name = “dewPoint”
map.unit = cmd.scale == 1 ? “F” : “C”
map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmd.scale == 1 ? “F” : “C”, cmd.precision)
map.isStateChange = true
map.displayed = true
break;
case 0x11:
map.name = “carbonDioxide”
map.unit = cmd.scale == 0 ? “Parts/million” : “”
map.value = cmd.scaledSensorValue.toInteger()
sensorcarbonDioxideHealthConcernLevel (map.value)
break;
case 0x27:
map.name = “tvocLevel”
map.unit = cmd.scale == 1 ? “Parts/million” : “mol/m^3”
map.value = cmd.scaledSensorValue.toFloat()
sensortvocHealthConcernLevel (map.value)
break;
default:
map.descriptionText = cmd.toString()
}
createEvent(map)
}

def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd) {
def cmds =
def result = createEvent(descriptionText: “$device.displayName woke up”, isStateChange: false)
cmds += secure(physicalgraph.zwave.commands.notificationv3.NotificationGet(notificationType: 0x0D))
cmds += secure(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x27))
cmds += secure(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x11))
cmds += secure(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x0B))
cmds += secure(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x05))
cmds += secure(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x01))
cmds += secure(zwave.wakeUpV2.wakeUpNoMoreInformation())
[result, response(cmds)]
}

def zwaveEvent(physicalgraph.zwave.Command cmd) {
log.warn “Unhandled command: ${cmd}”
}

def sensortvocHealthConcernLevel (value) {
if (value < 0.065) {
sensortvocHealthConcern (1)
} else if (value < 0.22) {
sensortvocHealthConcern (2)
} else if (value < 0.66) {
sensortvocHealthConcern (3)
} else if (value < 2.2) {
sensortvocHealthConcern (4)
} else {
sensortvocHealthConcern (5)}
}

def sensorcarbonDioxideHealthConcernLevel (value) {
if (value < 800) {
sensorcarbonDioxideHealthConcern (1)
} else if (value < 1000) {
sensorcarbonDioxideHealthConcern (2)
} else if (value < 1400) {
sensorcarbonDioxideHealthConcern (3)
} else if (value < 2000) {
sensorcarbonDioxideHealthConcern (4)
} else {
sensorcarbonDioxideHealthConcern (5)}
}

def sensorcarbonDioxideHealthConcern (value) {
switch (value) {
case 1:
sendEvent(name:“carbonDioxideHealthConcernn”, value:“good”, linkText:‘$device.displayName’, descriptionText:“$device.displayName Zielwert”, isStateChange:true, displayed:true)
break;
case 2:
sendEvent(name:“carbonDioxideHealthConcernn”, value:“moderate”, linkText:‘$device.displayName’, descriptionText:“$device.displayName Verstärktes Lüften wird empfohlen”, isStateChange:true, displayed:true)
break;
case 3:
sendEvent(name:“carbonDioxideHealthConcernn”, value:“slightlyUnhealthy”, linkText:‘$device.displayName’, descriptionText:“$device.displayName Verstärktes Lüften notwendig”, isStateChange:true, displayed:true)
break;
case 4:
sendEvent(name:“carbonDioxideHealthConcernn”, value:“unhealthy”, linkText:‘$device.displayName’, descriptionText:“$device.displayName Nur nutzen, wenn unvermeidbar”, isStateChange:true, displayed:true)
break;
case 5:
sendEvent(nname:“carbonDioxideHealthConcernn”, value:“veryUnhealthy”, linkText:‘$device.displayName’, descriptionText:“$device.displayName Nur nutzen, wenn unvermeidbar”, isStateChange:true, displayed:true)
break;
}
}

def sensortvocHealthConcern (value){
switch (value) {
case 1:
sendEvent(name:“tvocHealthConcern”, value:“good”, linkText:‘$device.displayName’, descriptionText:“$device.displayName Zielwert”, isStateChange:true, displayed:true)
break;
case 2:
sendEvent(name:“tvocHealthConcern”, value:“moderate”, linkText:‘$device.displayName’, descriptionText:“$device.displayName Verstärktes Lüften wird empfohlen”, isStateChange:true, displayed:true)
break;
case 3:
sendEvent(name:“tvocHealthConcern”, value:“slightlyUnhealthy”, linkText:‘$device.displayName’, descriptionText:“$device.displayName Verstärktes Lüften notwendig”, isStateChange:true, displayed:true)
break;
case 4:
sendEvent(name:“tvocHealthConcern”, value:“unhealthy”, linkText:‘$device.displayName’, descriptionText:“$device.displayName Nur nutzen, wenn unvermeidbar”, isStateChange:true, displayed:true)
break;
case 5:
sendEvent(name:“tvocHealthConcern”, value:“veryUnhealthy”, linkText:‘$device.displayName’, descriptionText:“$device.displayName Nur nutzen, wenn unvermeidbar”, isStateChange:true, displayed:true)
break;
}
}

private secure(cmd) {
if (zwaveInfo.zw.contains(“s”)) {
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
} else {
cmd.format()
}
}

1 Like

Have you found out the issue?
I have also such a sensor and would like to try it :wink:

If you have working device handler - can you share it?

Thanks!
Michael

Hi, when i try to create a device handler with your code I get the error message:
"Org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed: script_dth_metadata_9b0355ee_33e9_4b50_8637_da73fef9edf6: 4: expecting ‘)’, found ‘”’ @ line 4, column 129. mmunity”, vid: “generic-leak-5”, ocfDevi ^ 1 error ".
What could be the cause of this?
Is this the most recent code available for the Eurotronic Air Quality Sensor Z-Wave Plus ?

Hi, I was wondering if you have completed your device handler for the Eurotronic Air Quality Sensor Z-Wave Plus? I am very interested

is this work now?

Hey everybody, no worries. Ravil has done a great job and his device handler works like a charm. It just needed some restoration, which I did. The code placed above doesn’t work because of some auto-formatting, which must have appeared due to copy-and-paste operations. Please see the restored version below. And, Ravil, thank you once again for your effort!

metadata {
definition(name: "Luftgütesensor", namespace: "Aelfot", author: "aelfot", mnmn: "SmartThingsCommunity", vid: "generic-leak-5", ocfDeviceType: "x.com.st.d.airqualitysensor") {
capability "Dew Point"
capability "Carbon Dioxide Measurement"
capability "Tvoc Measurement"
capability "Temperature Measurement"
capability "Relative Humidity Measurement"
capability "Sensor"
capability "Configuration"
capability "Tvoc Health Concern"
capability "Carbon Dioxide Health Concern"
 fingerprint mfr:"0148", prod:"0005", model:"0001"	
   fingerprint mfr:"0000", prod:"0000", model:"0000"
   }
tiles(scale: 2) {
multiAttributeTile(name: "water", type: "generic", width: 6, height: 6) {
tileAttribute("device.water", key: "PRIMARY_CONTROL") {
attributeState("dry", label:'${name}', icon: "st.alarm.water.dry", backgroundColor: "#ffffff")
attributeState("wet", label:'${name}', icon: "st.alarm.water.wet", backgroundColor: "#00A0DC")
}
}
valueTile("humidity", "device.humidity", inactiveLabel: false, width: 2, height: 2) {
state "humidity", label: '${currentValue}%', unit: ""
}
valueTile("temperature", "device.temperature", width: 2, height: 2) {
state("temperature", label: '${currentValue}°',
backgroundColors: [
// Celsius
[value: 0, color: "#153591"],
[value: 7, color: "#1e9cbb"],
[value: 15, color: "#90d2a7"],
[value: 23, color: "#44b621"],
[value: 28, color: "#f1d801"],
[value: 35, color: "#d04e00"],
[value: 37, color: "#bc2323"],
// Fahrenheit
[value: 40, 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"]
])
}
valueTile("carbonDioxide", "device.co2Level", inactiveLabel: false, width: 2, height: 2) {
state "carbonDioxide", label: '${currentValue}', unit: ""
}
valueTile("dewPoint", "device.dewPoint", inactiveLabel: false, width: 2, height: 2) {
state "dewPoint", label:'${currentValue}°', unit: ""
}
valueTile("tvocLevel", "device.tvocLevel", inactiveLabel: false, width: 2, height: 2) {
state "tvocLevel", label: '${currentValue}', unit: ""
}
standardTile("carbonDioxideHealthConcern", "device.carbonDioxideHealthConcern", inactiveLabel: false, width: 2, height: 2) {
state "good", label:'Hohe Raumluftqualität', unit: ""
state "moderate", label:'Mittlere Raumluftqualität', unit: ""
state "slightlyUnhealthy", label:'Mäßige Raumluftqualität', unit: ""
state "unhealthy", label:'Niedrige Raumluftqualität', unit: ""
state "veryUnhealthy", label:'Raumluftqualität unakzeptabel', unit: ""
}
standardTile("tvocHealthConcern", "device.tvocHealthConcern", inactiveLabel: false, width: 2, height: 2) {
state "good", label:'Luft frei von Verunreinigungen', unit: ""
state "moderate", label:'Luft frei von Verunreinigungen', unit: ""
state "slightlyUnhealthy", label:'Geringfügige Verunreinigung', unit: ""
state "unhealthy", label:'Mittelmäßige Verunreinigung', unit: ""
state "veryUnhealthy", label:'Raumluftqualität unakzeptabel', unit: ""
}
   preferences {
   input "Temperaturdifferenz", "enum", title: "Temperaturdifferenz", options: ["0.1", "0.5", "1"], description: "Report, wenn Temperature geändert 0.1...5,0°C", defaultValue: "0.5" , displayDuringSetup: true
   input "Feuchtigkeitsdifferenz", "number", title: "Feuchtigkeitsdifferenz", description: "Report, wenn Feuchtigkeit geändert 1...100%", defaultValue: 5, range: "1..100", displayDuringSetup: false
   input "Temperatureeinheit", "enum", title: "Temperatureeinheit", options: ["°C", "°F"], defaultValue: "°C", required: false, displayDuringSetup: true
   input "TemperaturAufloesung", "enum", title: "Auflösung Temperatur", options: ["keine Nachkommastelle", "eine Nachkommastelle", "zwei Nachkommastellen"], defaultValue: "eine Nachkommastelle", required: false, displayDuringSetup: true
   input "FeuchtigkeitsAufloesung", "enum", title: "Auflösung Feuchte", options: ["keine Nachkommastelle", "eine Nachkommastelle", "zwei Nachkommastellen"], defaultValue: "keine Nachkommastelle", required: false, displayDuringSetup: true
   input "VOCChageReporting", "number", title: "VOC-on Change Reporting", description: "VOC-on Change Reporting 100...1000 ppb", range: "100..1000",  displayDuringSetup: false
   input "CO2ChangeReporting", "number", title: "CO2 Change Reporting", description: "CO2 Change Reporting 100...1000 ppb", range: "100..1000", displayDuringSetup: false
   input "LedIndikation", "enum", title: "Luftgüte per LED signalisieren", options: ["nein", "ja"], defaultValue: "ja", required: false, displayDuringSetup: true
   }   
 
 main "water"
 details(["water", "humidity", "temperature", "carbonDioxide", "dewPoint", "tvocLevel", "carbonDioxideHealthConcern", "tvocHealthConcern"])
}
}
def installed() {
sendEvent(name: "dewPoint", value: 0, unit: "C", linkText:"$device.displayName", descriptionText: "$device.displayName Dew Point is $value", isStateChange:true, displayed:true)
sendEvent(name: "carbonDioxideHealthConcern", value: "good", linkText:"$device.displayName", descriptionText: "$device.displayName Hohe Raumluftqualität", isStateChange:true, displayed:true)
sendEvent(name: "tvocHealthConcern", value: "good", linkText:"$device.displayName", descriptionText: "$device.displayName Sauber", isStateChange:true, displayed:true)
response([
secure(zwave.notificationV3.notificationGet(notificationType: 0x0D)), // Home Health
"delay 500",
secure(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x01)), // temperature
"delay 500",
secure(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x05)), // humidity
"delay 500",
secure(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x0B)), // dewpoint
"delay 500",
secure(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x11)), // CO2
"delay 500",
secure(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x27)), // VOC
"delay 10000",
secure(zwave.wakeUpV2.wakeUpNoMoreInformation())
])
}
def updated() {
configure()
}
def configure() {
sendEvent(name: "dewPoint", value: 13, unit: "°", linkText:'$device.displayName', descriptionText: "$device.displayName Dew Point is $value", isStateChange:true, displayed:true)
sendEvent(name: "carbonDioxideHealthConcern", value: "good", linkText:'$device.displayName', descriptionText: "$device.displayName Hohe Raumluftqualität", isStateChange:true, displayed:true)
sendEvent(name: "tvocHealthConcern", value: "good", linkText:'$device.displayName', descriptionText: "$device.displayName Sauber", isStateChange:true, displayed:true)
sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 10 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
secure(zwave.configurationV1.configurationSet(configurationValue: Temperaturdifferenz == "0.1" ? [0x01] : Temperaturdifferenz == "0.5" ? [0x05] : [0x0A] , parameterNumber:1, size:1, scaledConfigurationValue: Temperaturdifferenz == "0.1" ? 0x01 : Temperaturdifferenz == "0.5" ? 0x05 : 0x0A))//,
secure(zwave.configurationV1.configurationSet(configurationValue: Feuchtigkeitsdifferenz == null ? [0x05] : [Integer.toHexString(Feuchtigkeitsdifferenz).toUpperCase()], parameterNumber:2, size:1, scaledConfigurationValue: Feuchtigkeitsdifferenz == null ? 0x05 : Integer.toHexString(Feuchtigkeitsdifferenz).toUpperCase()))//,
secure(zwave.configurationV1.configurationSet(configurationValue: Temperatureeinheit == "°C" ? [0x00] : [0x01], parameterNumber:3, size:1, scaledConfigurationValue: Temperatureeinheit == "°C" ? 0x00 : 0x01))//,
secure(zwave.configurationV1.configurationSet(configurationValue: TemperaturAufloesung == "keine Nachkommastelle" ? [0x00] : TemperaturAufloesung == "eine Nachkommastelle" ? [0x01] : [0x02], parameterNumber:4, size:1, scaledConfigurationValue: TemperaturAufloesung == "keine Nachkommastelle" ? 0x00 : TemperaturAufloesung == "eine Nachkommastelle" ? 0x01 : 0x02))//,
secure(zwave.configurationV1.configurationSet(configurationValue: FeuchtigkeitsAufloesung == "keine Nachkommastelle" ? [0x00] : FeuchtigkeitsAufloesung == "eine Nachkommastelle" ? [0x01] : [0x02], parameterNumber:5, size:1, scaledConfigurationValue: FeuchtigkeitsAufloesung == "keine Nachkommastelle" ? 0x00 : FeuchtigkeitsAufloesung == "eine Nachkommastelle" ? 0x01 : 0x02))//,
secure(zwave.configurationV1.configurationSet(configurationValue: VOCChageReporting == null ? [0x05] : [Integer.toHexString(VOCChageReporting-100).toUpperCase()], parameterNumber:6, size:1, scaledConfigurationValue: VOCChageReporting == null ? 0x05 : VOCChageReporting-100))//,
secure(zwave.configurationV1.configurationSet(configurationValue: CO2ChangeReporting == null ? [0x05] : [Integer.toHexString(CO2ChangeReporting-100).toUpperCase()], parameterNumber:7, size:1, scaledConfigurationValue: CO2ChangeReporting == null ? 0x05 : CO2ChangeReporting-100))//,
secure(zwave.configurationV1.configurationSet(configurationValue: LedIndikation == "nein" ? [0x00] : [0x01], parameterNumber:8, size:1, scaledConfigurationValue: LedIndikation == "nein" ? 0x00 : 0x01))//,
}
def parse(String description) {
def results = []
if (description.startsWith("Err")) {
results += createEvent(descriptionText: description, displayed: true)
} else {
def cmd = zwave.parse(description)
if (cmd) {
results += zwaveEvent(cmd)
}
}
log.debug "parse() result ${results.inspect()}"
return results
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand()
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
} else {
log.warn "Unable to extract encapsulated cmd from $cmd"
createEvent(descriptionText: cmd.toString())
}
}
def zwaveEvent(physicalgraph.zwave.commands.notificationv3.EventSupportedReport cmd) {
switch (cmd.event) {
case 1:
createEvent(name:"tvocHealthConcern", value:"good", linkText:'$device.displayName', descriptionText:"$device.displayName Zielwert", isStateChange:true, displayed:true)
sendPush("Luftqualität ist super")
break;
case 2:
createEvent(name:"tvocHealthConcern", value:"moderate", linkText:'$device.displayName', descriptionText:"$device.displayName Verstärktes Lüften wird empfohlen", isStateChange:true, displayed:true)
sendPush("Luftqualität ist nicht perfekt. Lüften empfohlen")
break;
case 3:
createEvent(name:"tvocHealthConcern", value:"slightlyUnhealthy", linkText:'$device.displayName', descriptionText:"$device.displayName Verstärktes Lüften notwendig", isStateChange:true, displayed:true)
sendPush("Luftqualität ist schlecht. Verstärktes Lüften notwendig")
break;
case 4:
createEvent(name:"tvocHealthConcern", value:"unhealthy", linkText:'$device.displayName', descriptionText:"$device.displayName Nur nutzen, wenn unvermeidbar", isStateChange:true, displayed:true)
sendPush("Luftqualität ist miserabel. Raum nutzen nur, wenn unvermeidbar. Lüften!!!")
break;
case 5:
createEvent(name:"tvocHealthConcern", value:"veryUnhealthy", linkText:'$device.displayName', descriptionText:"$device.displayName Nur nutzen, wenn unvermeidbar", isStateChange:true, displayed:true)
sendPush("Luftqualität ist lebensgefährlich. Raum verlassen und lüften.")
break;
}
}
def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) {
switch (cmd.event) {
case 1:
createEvent(name:"tvocHealthConcern", value:"good", linkText:'$device.displayName', descriptionText:"$device.displayName Zielwert", isStateChange:true, displayed:true)
sendPush("Luftqualität ist super")
break;
case 2:
createEvent(name:"tvocHealthConcern", value:"moderate", linkText:'$device.displayName', descriptionText:"$device.displayName Verstärktes Lüften wird empfohlen", isStateChange:true, displayed:true)
sendPush("Luftqualität ist nicht perfekt. Lüften empfohlen")
break;
case 3:
createEvent(name:"tvocHealthConcern", value:"slightlyUnhealthy", linkText:'$device.displayName', descriptionText:"$device.displayName Verstärktes Lüften notwendig", isStateChange:true, displayed:true)
sendPush("Luftqualität ist schlecht. Verstärktes Lüften notwendig")
break;
case 4:
createEvent(name:"tvocHealthConcern", value:"unhealthy", linkText:'$device.displayName', descriptionText:"$device.displayName Nur nutzen, wenn unvermeidbar", isStateChange:true, displayed:true)
sendPush("Luftqualität ist miserabel. Raum nutzen nur, wenn unvermeidbar. Lüften!!!")
break;
case 5:
createEvent(name:"tvocHealthConcern", value:"veryUnhealthy", linkText:'$device.displayName', descriptionText:"$device.displayName Nur nutzen, wenn unvermeidbar", isStateChange:true, displayed:true)
sendPush("Luftqualität ist lebensgefährlich. Raum verlassen und lüften.")
break;
}
}
def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv5.SensorMultilevelReport cmd) {
def map = [:]
switch (cmd.sensorType) {
case 1:
map.name = "temperature"
map.unit = temperatureScale
map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmd.scale == 1 ? "F" : "C", cmd.precision)
break;
case 5:
map.name = "humidity"
map.unit = cmd.scale == 0 ? "%" : "g/m^3"
map.value = cmd.scaledSensorValue.toFloat()
break;
case 0xB:
map.name = "dewPoint"
map.unit = cmd.scale == 1 ? "F" : "C"
map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmd.scale == 1 ? "F" : "C", cmd.precision)
map.isStateChange = true
map.displayed = true
break;
case 0x11:
map.name = "carbonDioxide"
map.unit = cmd.scale == 0 ? "Parts/million" : ""
map.value = cmd.scaledSensorValue.toInteger()
sensorcarbonDioxideHealthConcernLevel (map.value)
break;
case 0x27:
map.name = "tvocLevel"
map.unit = cmd.scale == 1 ? "Parts/million" : "mol/m^3"
map.value = cmd.scaledSensorValue.toFloat()
sensortvocHealthConcernLevel (map.value)
break;
default:
map.descriptionText = cmd.toString()
}
createEvent(map)
}
def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd) {
def cmds = []
def result = createEvent(descriptionText: "$device.displayName woke up", isStateChange: false)
cmds += secure(physicalgraph.zwave.commands.notificationv3.NotificationGet(notificationType: 0x0D))
cmds += secure(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x27))
cmds += secure(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x11))
cmds += secure(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x0B))
cmds += secure(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x05))
cmds += secure(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x01))
cmds += secure(zwave.wakeUpV2.wakeUpNoMoreInformation())
[result, response(cmds)]
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
log.warn "Unhandled command: ${cmd}"
}
def sensortvocHealthConcernLevel (value) {
if (value < 0.065) {
sensortvocHealthConcern (1)
} else if (value < 0.22) {
sensortvocHealthConcern (2)
} else if (value < 0.66) {
sensortvocHealthConcern (3)
} else if (value < 2.2) {
sensortvocHealthConcern (4)
} else {
sensortvocHealthConcern (5)}
}
def sensorcarbonDioxideHealthConcernLevel (value) {
if (value < 800) {
sensorcarbonDioxideHealthConcern (1)
} else if (value < 1000) {
sensorcarbonDioxideHealthConcern (2)
} else if (value < 1400) {
sensorcarbonDioxideHealthConcern (3)
} else if (value < 2000) {
sensorcarbonDioxideHealthConcern (4)
} else {
sensorcarbonDioxideHealthConcern (5)}
}
def sensorcarbonDioxideHealthConcern (value) {
switch (value) {
case 1:
sendEvent(name:"carbonDioxideHealthConcernn", value:"good", linkText:'$device.displayName', descriptionText:"$device.displayName Zielwert", isStateChange:true, displayed:true)
break;
case 2:
sendEvent(name:"carbonDioxideHealthConcernn", value:"moderate", linkText:'$device.displayName', descriptionText:"$device.displayName Verstärktes Lüften wird empfohlen", isStateChange:true, displayed:true)
break;
case 3:
sendEvent(name:"carbonDioxideHealthConcernn", value:"slightlyUnhealthy", linkText:'$device.displayName', descriptionText:"$device.displayName Verstärktes Lüften notwendig", isStateChange:true, displayed:true)
break;
case 4:
sendEvent(name:"carbonDioxideHealthConcernn", value:"unhealthy", linkText:'$device.displayName', descriptionText:"$device.displayName Nur nutzen, wenn unvermeidbar", isStateChange:true, displayed:true)
break;
case 5:
sendEvent(nname:"carbonDioxideHealthConcernn", value:"veryUnhealthy", linkText:'$device.displayName', descriptionText:"$device.displayName Nur nutzen, wenn unvermeidbar", isStateChange:true, displayed:true)
break;
}
}
def sensortvocHealthConcern (value){
switch (value) {
case 1:
sendEvent(name:"tvocHealthConcern", value:"good", linkText:'$device.displayName', descriptionText:"$device.displayName Zielwert", isStateChange:true, displayed:true)
break;
case 2:
sendEvent(name:"tvocHealthConcern", value:"moderate", linkText:'$device.displayName', descriptionText:"$device.displayName Verstärktes Lüften wird empfohlen", isStateChange:true, displayed:true)
break;
case 3:
sendEvent(name:"tvocHealthConcern", value:"slightlyUnhealthy", linkText:'$device.displayName', descriptionText:"$device.displayName Verstärktes Lüften notwendig", isStateChange:true, displayed:true)
break;
case 4:
sendEvent(name:"tvocHealthConcern", value:"unhealthy", linkText:'$device.displayName', descriptionText:"$device.displayName Nur nutzen, wenn unvermeidbar", isStateChange:true, displayed:true)
break;
case 5:
sendEvent(name:"tvocHealthConcern", value:"veryUnhealthy", linkText:'$device.displayName', descriptionText:"$device.displayName Nur nutzen, wenn unvermeidbar", isStateChange:true, displayed:true)
break;
}
}
private secure(cmd) {
if (zwaveInfo.zw.contains("s")) {
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
} else {
cmd.format()
}
}

Hello to everyone ,

Are there any plans to make an Edge driver for that sensor ? The normal Z-Wave driver don’t work

Thank you

No one here that use this sensor and need an Edge Driver ?

I bought this device and can’t get it to work. I assume because it doesn’t have a proper edge driver for it.

There is no driver in the moment. So this device do not work with Smartthings anymore. There was an old Device Handler, but nothing for Edge

Hello,
Did you find a functional Edge driver for Eurotronic air quality sensor? With the generic z-wave driver it shows only the temperature and humidity.

Hello oyibo,

I looked a long time for a Driver, but Eurotonic didn’t make one. So that device do not work with Smartthings anymore

Best wishes

Meine Freunde, seit Langem bin ich auf andere Smart Home Systeme umgestiegen, dementsprechend unterstütze ich die Weiterentwicklung vom Driver nicht mehr. Es ist sicherlich möglich ihn zur Funktion zu bringen, ich habe dafür, aber, kein Smartthing Hub und keine Zeit.
Viele Grüße

Hello Daniel,
Many thanks for your answer, although it is not a positive one… :disappointed:
With the generic SmartThings driver this air quality sensor only shows temperature and humidity, missing CO2, VOC and dew point.
I still hope that an enthusiast and less busy developer will make a compatible driver in the near future.
Best regards

I also hope. But I think that is not easy to do