Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ metadata {
fingerprint mfr: "0060", prod: "0015", model: "0001", deviceJoinName: "Everspring Thermostatic Radiator Valve", mnmn: "SmartThings", vid: "generic-radiator-thermostat"
//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 Radiator Thermostat Valve", mnmn: "SmartThings", vid: "generic-radiator-thermostat-2"
}

tiles(scale: 2) {
Expand Down Expand Up @@ -85,7 +86,7 @@ metadata {
}

def initialize() {
sendEvent(name: "checkInterval", value: 4 * 60 * 60 + 24 * 60 , displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"])
sendEvent(name: "checkInterval", value: checkInterval , displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
sendEvent(name: "supportedThermostatModes", value: thermostatSupportedModes.encodeAsJson(), displayed: false)
sendEvent(name: "heatingSetpointRange", value: [minHeatingSetpointTemperature, maxHeatingSetpointTemperature], displayed: false)
response(refresh())
Expand All @@ -103,6 +104,8 @@ def configure() {
def cmds = []
if (isEverspringRadiatorThermostat()) {
cmds += secure(zwave.configurationV1.configurationSet(parameterNumber: 1, size: 2, scaledConfigurationValue: 15)) //automatic temperature reports every 15 minutes
} else if (isPoppRadiatorThermostat()) {
cmds += secure(zwave.wakeUpV2.wakeUpIntervalSet(seconds: 600, nodeid: zwaveHubNodeId))
}
return cmds
}
Expand Down Expand Up @@ -130,6 +133,25 @@ def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulat
}
}

def zwaveEvent(physicalgraph.zwave.commands.multicmdv1.MultiCmdEncap cmd) {
cmd.encapsulatedCommands().collect { encapsulatedCommand ->
zwaveEvent(encapsulatedCommand)
}.flatten()
}

def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd) {
def cmds = []
if (!isPoppRadiatorThermostat()) {
cmds += zwave.batteryV1.batteryGet() // POPP sends battery report automatically every wake up by itself, there's no need to duplicate it
}
cmds += [
zwave.thermostatSetpointV2.thermostatSetpointSet([precision: 1, scale: 0, scaledValue: state.cachedSetpoint, setpointType: 1, size: 2]),
zwave.thermostatSetpointV2.thermostatSetpointGet(setpointType: 1),
zwave.wakeUpV2.wakeUpNoMoreInformation()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kianooshST here's some command caching for wakeup like we had talked about. Maybe a more generic implementation in the future?

]
[response(multiEncap(cmds))]
}

def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
def value = cmd.batteryLevel == 255 ? 1 : cmd.batteryLevel
def map = [name: "battery", value: value, unit: "%"]
Expand Down Expand Up @@ -205,8 +227,12 @@ def off() {
}

def setHeatingSetpoint(setpoint) {
if (isPoppRadiatorThermostat()) {
sendEvent(name: "heatingSetpoint", value: setpoint, unit: temperatureScale)
Copy link
Contributor

@greens greens Nov 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand why you did this, since I bet the app will just spin forever unless you do, but I'm just going to note that it seems wrong to do this when we know that it won't actually be set for up to 5 minutes.

Copy link
Contributor Author

@PKacprowiczS PKacprowiczS Nov 7, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I know, but since we don't have any 'pending' indicator in OneApp or something else that would inform user that it still hasn't been changed I think it's lesser evil.

}
setpoint = temperatureScale == 'C' ? setpoint : fahrenheitToCelsius(setpoint)
setpoint = Math.max(Math.min(setpoint, maxHeatingSetpointTemperature), minHeatingSetpointTemperature)
state.cachedSetpoint = setpoint
[
secure(zwave.thermostatSetpointV2.thermostatSetpointSet([precision: 1, scale: 0, scaledValue: setpoint, setpointType: 1, size: 2])),
"delay 2000",
Expand Down Expand Up @@ -237,9 +263,23 @@ private secure(cmd) {
}
}

def multiEncap(cmds) {
if (zwaveInfo.cc.contains("8F")) {
secure(zwave.multiCmdV1.multiCmdEncap().encapsulate(cmds.collect {
cmd -> cmd.format()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have we used multiencap anywhere else before this? Any problems?

Copy link
Contributor Author

@PKacprowiczS PKacprowiczS Nov 7, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we haven't, at least I haven't found any example. In this particular case it works like a charm. I haven't really noticed that such CC existed until I got this device. Manufacturer stated in manual that using this would extend battery life, so I figured out it's worth trying. I don't know whether it is commonly used in other devices.

}))
} else {
delayBetween(cmds.collect {
cmd -> secure(cmd)
}, 2500)
}
}

private getMaxHeatingSetpointTemperature() {
if (isEverspringRadiatorThermostat()) {
temperatureScale == 'C' ? 35 : 95
} else if (isPoppRadiatorThermostat()) {
temperatureScale == 'C' ? 28 : 82
} else {
temperatureScale == 'C' ? 30 : 86
}
Expand All @@ -248,6 +288,8 @@ private getMaxHeatingSetpointTemperature() {
private getMinHeatingSetpointTemperature() {
if (isEverspringRadiatorThermostat()) {
temperatureScale == 'C' ? 15 : 59
} else if (isPoppRadiatorThermostat()) {
temperatureScale == 'C' ? 4 : 39
} else {
temperatureScale == 'C' ? 10 : 50
}
Expand All @@ -256,11 +298,25 @@ private getMinHeatingSetpointTemperature() {
private getThermostatSupportedModes() {
if (isEverspringRadiatorThermostat()) {
["off", "heat", "emergency heat"]
} else if (isPoppRadiatorThermostat()) { //that's just for looking fine in Classic
["heat"]
} else {
["off","heat"]
}
}

def getCheckInterval() {
if (isPoppRadiatorThermostat()) {
2 * 60 * 10 + 2 * 60
} else {
4 * 60 * 60 + 24 * 60
}
}

private isEverspringRadiatorThermostat() {
zwaveInfo.mfr == "0060" && zwaveInfo.prod == "0015"
}

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