Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rolling up staging to acceptance #39562

Merged
merged 8 commits into from
Aug 4, 2020
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ private onOffCmd(value, endpoint = 1) {
delayBetween([
encap(zwave.basicV1.basicSet(value: value), endpoint),
encap(zwave.basicV1.basicGet(), endpoint)
])
], 1000)
}

private refreshAll(includeMeterGet = true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,13 +207,27 @@ private def parseAttributeResponse(String description) {
responseMap.value = "unknown"
responseMap.descriptionText = "Unknown state"
}
if (responseMap.value) {
/* delay this event for a second in the hopes that we get the operation event (which has more info).
If we don't get one, then it's okay to send. If we send the event with more info first, the event
with less info will be marked as not displayed
*/
log.debug "Lock attribute report received: ${responseMap.value}. Delaying event."
runIn(1, "delayLockEvent", [data : [map : responseMap]])
return [:]
}
} else {
return null
}
result << createEvent(responseMap)
return result
}

def delayLockEvent(data) {
log.debug "Sending cached lock operation: ${data.map}"
sendEvent(data.map)
}

private def parseIasMessage(String description) {
ZoneStatus zs = zigbee.parseZoneStatus(description)
def responseMap = [ name: "battery", value: zs.isBatterySet() ? 5 : 55]
Expand Down
14 changes: 14 additions & 0 deletions devicetypes/smartthings/zigbee-lock.src/zigbee-lock.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,15 @@ private def parseAttributeResponse(String description) {
responseMap.value = "unknown"
responseMap.descriptionText = "Unknown state"
}
if (responseMap.value) {
/* delay this event for a second in the hopes that we get the operation event (which has more info).
If we don't get one, then it's okay to send. If we send the event with more info first, the event
with less info will be marked as not displayed
*/
log.debug "Lock attribute report received: ${responseMap.value}. Delaying event."
runIn(1, "delayLockEvent", [data : [map : responseMap]])
return [:]
}
} else if (clusterInt == CLUSTER_DOORLOCK && attrInt == DOORLOCK_ATTR_MIN_PIN_LENGTH && descMap.value) {
def minCodeLength = Integer.parseInt(descMap.value, 16)
responseMap = [name: "minCodeLength", value: minCodeLength, descriptionText: "Minimum PIN length is ${minCodeLength}", displayed: false]
Expand All @@ -517,6 +526,11 @@ private def parseAttributeResponse(String description) {
return result
}

def delayLockEvent(data) {
log.debug "Sending cached lock operation: ${data.map}"
sendEvent(data.map)
}

/**
* Responsible for handling command responses
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,17 @@ def parse(String description) {
log.debug "description is $description"
def event = zigbee.getEvent(description)
def descMap = zigbee.parseDescriptionAsMap(description)
def powerDiv = 1
def energyDiv = 100

if (event) {
log.info "event enter:$event"
if (event.name == "switch" && !descMap.isClusterSpecific && descMap.commandInt == 0x0B) {
log.info "Ignoring default response with desc map: $descMap"
return [:]
} else if (event.name== "power") {
event.value = event.value/powerDiv
event.value = event.value/getPowerDiv()
event.unit = "W"
} else if (event.name== "energy") {
event.value = event.value/energyDiv
event.value = event.value/getEnergyDiv()
event.unit = "kWh"
}
log.info "event outer:$event"
Expand All @@ -98,13 +96,13 @@ def parse(String description) {
if (it.value && it.clusterInt == zigbee.SIMPLE_METERING_CLUSTER && it.attrInt == ATTRIBUTE_HISTORICAL_CONSUMPTION) {
log.debug "power"
map.name = "power"
map.value = zigbee.convertHexToInt(it.value)/powerDiv
map.value = zigbee.convertHexToInt(it.value)/getPowerDiv()
map.unit = "W"
}
else if (it.value && it.clusterInt == zigbee.SIMPLE_METERING_CLUSTER && it.attrInt == ATTRIBUTE_READING_INFO_SET) {
log.debug "energy"
map.name = "energy"
map.value = zigbee.convertHexToInt(it.value)/energyDiv
map.value = zigbee.convertHexToInt(it.value)/getEnergyDiv()
map.unit = "kWh"
}

Expand Down Expand Up @@ -155,5 +153,18 @@ def configure() {
return refresh() +
zigbee.onOffConfig() +
zigbee.configureReporting(zigbee.SIMPLE_METERING_CLUSTER, ATTRIBUTE_READING_INFO_SET, DataType.UINT48, 1, 600, 1) +
zigbee.electricMeasurementPowerConfig(1, 600, 1)
zigbee.electricMeasurementPowerConfig(1, 600, 1) +
zigbee.simpleMeteringPowerConfig()
}

private int getPowerDiv() {
isSengledOutlet() ? 10 : 1
}

private int getEnergyDiv() {
isSengledOutlet() ? 10000 : 100
}

private boolean isSengledOutlet() {
device.getDataValue("model") == "E1C-NB7"
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ metadata {
//this DTH is sending temperature setpoint commands using Celsius scale and assumes that they'll be handled correctly by device
//if new device added to this DTH won't be able to do that, make sure to you'll handle conversion in a right way
fingerprint mfr: "0002", prod: "0115", model: "A010", deviceJoinName: "POPP Thermostat", mnmn: "SmartThings", vid: "generic-radiator-thermostat-2" //POPP Radiator Thermostat Valve
fingerprint mfr: "0371", prod: "0002", model: "0015", deviceJoinName: "Aeotec Thermostat", mnmn: "SmartThings", vid: "aeotec-radiator-thermostat" //Aeotec Radiator Thermostat ZWA021
}

tiles(scale: 2) {
Expand Down Expand Up @@ -168,6 +169,7 @@ def zwaveEvent(physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeRepor
map.value = "heat"
break
case 11:
case 15:
map.value = "emergency heat"
break
case 0:
Expand Down Expand Up @@ -213,7 +215,11 @@ def setThermostatMode(String mode) {
modeValue = 1
break
case "emergency heat":
modeValue = 11
if (isAeotecRadiatorThermostat()) {
modeValue = 15
} else {
modeValue = 11
}
break
case "off":
modeValue = 0
Expand Down Expand Up @@ -295,7 +301,7 @@ def multiEncap(cmds) {
private getMaxHeatingSetpointTemperature() {
if (isEverspringRadiatorThermostat()) {
temperatureScale == 'C' ? 35 : 95
} else if (isPoppRadiatorThermostat()) {
} else if (isPoppRadiatorThermostat() || isAeotecRadiatorThermostat()) {
temperatureScale == 'C' ? 28 : 82
} else {
temperatureScale == 'C' ? 30 : 86
Expand All @@ -307,13 +313,15 @@ private getMinHeatingSetpointTemperature() {
temperatureScale == 'C' ? 15 : 59
} else if (isPoppRadiatorThermostat()) {
temperatureScale == 'C' ? 4 : 39
} else if (isAeotecRadiatorThermostat()) {
temperatureScale == 'C' ? 8 : 47
} else {
temperatureScale == 'C' ? 10 : 50
}
}

private getThermostatSupportedModes() {
if (isEverspringRadiatorThermostat()) {
if (isEverspringRadiatorThermostat() || isAeotecRadiatorThermostat()) {
["off", "heat", "emergency heat"]
} else if (isPoppRadiatorThermostat()) { //that's just for looking fine in Classic
["heat"]
Expand All @@ -336,4 +344,8 @@ private isEverspringRadiatorThermostat() {

private isPoppRadiatorThermostat() {
zwaveInfo.mfr == "0002" && zwaveInfo.prod == "0115"
}

private isAeotecRadiatorThermostat() {
zwaveInfo.mfr == "0371" && zwaveInfo.prod == "0002"
}