-
Notifications
You must be signed in to change notification settings - Fork 0
/
SchluterDitraHeatChild.groovy
186 lines (154 loc) · 7.09 KB
/
SchluterDitraHeatChild.groovy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/*
* SchluterDitraHeatChild
*
* Description:
* This Hubitat driver is designed for use with a Schluter DITRA-HEAT Wifi thermostat. This is the child device per thermostat. It takes no direct configuration
*
* Preferences:
*
* Features List:
* Control Schluter DITRA-HEAT Wifi thermostats
*
* Licensing:
* Copyright 2023 Marc Reyhner
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
* Version Control:
* 0.1.0 - Initial version
*
* Thank you(s):
* I used the Tesla PowerWall driver fron snell as a sample and skeleton for creating a HTTP based driver
* https://community.hubitat.com/t/project-driver-for-connecting-to-your-tesla-devices/41375
* API details learned from py-schluter library - https://github.com/prairieapps/py-schluter/
*/
import groovy.json.*
metadata{
definition ( name: "SchluterDitraHeatChild", namespace: "marcre", author: "Marc Reyhner", importUrl: "tbd" ) {
capability "Sensor"
capability "TemperatureMeasurement"
capability "Thermostat"
capability "ThermostatHeatingSetpoint"
capability "ThermostatOperatingState"
capability "ThermostatSetpoint"
attribute "Group Name", "string"
attribute "Manual Temperature", "number"
attribute "Maximum Temperature", "number"
attribute "Minimum Temperature", "number"
attribute "Measured Load", "number"
attribute "Schedule Mode", "string"
attribute "Software Version", "string"
}
}
def installed() {
// Set static attributes at install time
sendEvent(name: 'supportedThermostatFanModes', value: JsonOutput.toJson(["auto"]) )
sendEvent(name: 'supportedThermostatModes', value: JsonOutput.toJson(["heat"]) )
sendEvent(name: "thermostatFanMode", value: "auto")
sendEvent(name: "thermostatMode", "heat")
}
def ProcessUpdate(thermostat) {
if (getParent().DebugLogsEnabled()) log.debug("Thermostat raw data ${thermostat}.toString()")
UpsertAttribute("temperature", thermostatToSystemUnits(thermostat.Temperature, 1), location.temperatureScale)
UpsertAttribute("thermostatOperatingState", thermostat.Heating ? "heating" : "idle")
UpsertAttribute("thermostatSetpoint", (int)thermostatToSystemUnits(thermostat.SetPointTemp, 0), location.temperatureScale)
UpsertAttribute("heatingSetpoint", (int)thermostatToSystemUnits(thermostat.SetPointTemp, 0), location.temperatureScale)
UpsertAttribute("Group Name", thermostat.GroupName)
UpsertAttribute("Manual Temperature", (int)thermostatToSystemUnits(thermostat.ManualTemperature, 0), location.temperatureScale)
UpsertAttribute("Maximum Temperature", (int)thermostatToSystemUnits(thermostat.MaxTemp, 0), location.temperatureScale)
UpsertAttribute("Minimum Temperature", (int)thermostatToSystemUnits(thermostat.MinTemp, 0), location.temperatureScale)
UpsertAttribute("Measured Load", thermostat.LoadMeasuredWatt, "W")
UpsertAttribute("Schedule Mode", ResolveScheduleMode(thermostat.RegulationMode))
UpsertAttribute("Software Version", thermostat.SWVersion)
}
def cool() {
log.warn("cool() is not supported and takes no action.")
}
def emergencyHeat() {
log.warn("emergencyHeat() is not supported and takes no action.")
}
def setCoolingSetpoint(requestedTemperator) {
log.warn("setCoolingSetpoint() is not supported and takes no action.")
}
def fanAuto() {
log.warn("fanAuto() is not supported and takes no action.")
}
def fanCirculate() {
log.warn("fanCirculate() is not supported and takes no action.")
}
def fanOn() {
log.warn("fanOn() is not supported and takes no action.")
}
def setSchedule(schedule) {
log.warn("setSchedule() is not supported and takes no action.")
}
def setThermostatFanMode(fanmode) {
log.warn("setThermostatFanMode() is not supported and takes no action.")
}
def auto() {
log.warn("auto() is not supported and takes no action.")
}
def heat() {
log.warn("heat() is not supported and takes no action.")
}
def off() {
log.warn("off() is not supported and takes no action.")
}
def setThermostatMode(thermostatMode) {
log.warn("setThermostatMode() is not supported and takes no action.")
}
def setHeatingSetpoint(temperature) {
log.info("setHeatingSetpoint(${temperature}) on ${device.getDisplayName()} invoked.")
minimumTemperature = device.currentValue("Minimum Temperature")
if (temperature < minimumTemperature) {
log.warn("setHeatingSetpoint(${temperature}) on ${device.getDisplayName()} is less than minimum temperature ${minimumTemperature}. Will set to minimum temperature.")
temperature = minimumTemperature;
}
maximumTemperature = device.currentValue("Maximum Temperature")
if (temperature > maximumTemperature) {
log.warn("setHeatingSetpoint(${temperature}) on ${device.getDisplayName()} is greater than maximum temperature ${maximumTemperature}. Will set to maximum temperature.")
temperature = maximumTemperature;
}
getParent().SetThermostatTemperature(device.deviceNetworkId, (int)(systemUnitsToCelsius(temperature)*100))
}
def UpsertAttribute( Variable, Value, Unit = null ){
if( device.currentValue(Variable) != Value ){
if( Unit != null ){
log.info( "Event: ${ Variable } = ${ Value }${ Unit }" )
sendEvent( name: "${ Variable }", value: Value, unit: Unit )
} else {
log.info( "Event: ${ Variable } = ${ Value }" )
sendEvent( name: "${ Variable }", value: Value )
}
}
}
// Convert thermostat temperature (celsius * 100) to the system temperature
def thermostatToSystemUnits(thermostatTemperature, precision) {
return celsiusToSystemUnits(thermostatTemperature / 100).doubleValue().round(precision)
}
// Convert celsius to the system temperature
def celsiusToSystemUnits(celsiusTemperature) {
return (location.temperatureScale == "F") ? celsiusToFahrenheit(celsiusTemperature) : celsiusTemperature
}
// Convert system units to celsius
def systemUnitsToCelsius(temperature) {
return (location.temperatureScale == "F") ? fahrenheitToCelsius(temperature) : temperature
}
// Translate the schedule mode enumeration from the thermostat to a friendly string
def ResolveScheduleMode(regulationMode) {
switch (regulationMode) {
case 1:
return "Follow Schedule"
case 2:
return "Temporary Hold"
case 3:
return "Permanently Hold"
case 4:
return "Vacation"
default:
return regulationMode.toString()
}
}