Advertisement
erocm123

Stelpro Ki ZigBee Thermostat

Dec 18th, 2018
116
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.82 KB | None | 0 0
  1. /**
  2. * Copyright 2017 - 2018 Stelpro
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
  5. * in compliance with the License. You may obtain a copy of the License at:
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
  10. * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing permissions and limitations under the License.
  12. *
  13. * Stelpro Ki ZigBee Thermostat
  14. *
  15. * Author: Stelpro
  16. *
  17. * Date: 2018-04-04
  18. */
  19.  
  20. import com.hubitat.zigbee.DataType
  21.  
  22. metadata {
  23. definition (name: "Stelpro Ki ZigBee Thermostat", namespace: "stelpro", author: "Stelpro", ocfDeviceType: "oic.d.thermostat") {
  24. capability "Actuator"
  25. capability "Temperature Measurement"
  26. //capability "Temperature Alarm"
  27. capability "Thermostat"
  28. capability "Thermostat Mode"
  29. capability "Thermostat Operating State"
  30. capability "Thermostat Heating Setpoint"
  31. capability "Configuration"
  32. capability "Sensor"
  33. capability "Refresh"
  34. capability "Health Check"
  35.  
  36. attribute "outsideTemp", "number"
  37.  
  38. command "setOutdoorTemperature"
  39. command "quickSetOutTemp" // Maintain backward compatibility with self published versions of the "Stelpro Get Remote Temperature" SmartApp
  40. command "increaseHeatSetpoint"
  41. command "decreaseHeatSetpoint"
  42. command "parameterSetting"
  43. command "eco" // Command does not exist in "Thermostat Mode"
  44. command "updateWeather"
  45.  
  46. fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0201, 0204", outClusters: "0402", manufacturer: "Stelpro", model: "STZB402+", deviceJoinName: "Stelpro Ki ZigBee Thermostat"
  47. fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0201, 0204", outClusters: "0402", manufacturer: "Stelpro", model: "ST218", deviceJoinName: "Stelpro ORLÉANS Convector"
  48. }
  49.  
  50. // simulator metadata
  51. simulator { }
  52.  
  53. preferences {
  54. input("lock", "enum", title: "Do you want to lock your thermostat's physical keypad?", options: ["No", "Yes"], defaultValue: "No", required: false, displayDuringSetup: false)
  55. input("heatdetails", "enum", title: "Do you want a detailed operating state notification?", options: ["No", "Yes"], defaultValue: "No", required: false, displayDuringSetup: true)
  56. input("zipcode", "text", title: "ZipCode (Outdoor Temperature)", description: "[Do not use space](Blank = No Forecast)")
  57. }
  58.  
  59. tiles(scale : 2) {
  60. multiAttributeTile(name:"thermostatMulti", type:"thermostat", width:6, height:4, canChangeIcon: true) {
  61. tileAttribute("device.temperature", key: "PRIMARY_CONTROL") {
  62. attributeState("temperature", label:'${currentValue}°', icon: "st.alarm.temperature.normal")
  63. }
  64. tileAttribute("device.heatingSetpoint", key: "VALUE_CONTROL") {
  65. attributeState("VALUE_UP", action: "increaseHeatSetpoint")
  66. attributeState("VALUE_DOWN", action: "decreaseHeatSetpoint")
  67. }
  68. tileAttribute("device.thermostatOperatingState", key: "OPERATING_STATE") {
  69. attributeState("idle", backgroundColor:"#44b621")
  70. attributeState("heating", backgroundColor:"#ffa81e")
  71. }
  72. tileAttribute("device.thermostatMode", key: "THERMOSTAT_MODE") {
  73. attributeState("off", label:'${name}')
  74. attributeState("heat", label:'${name}')
  75. attributeState("eco", label:'${name}')
  76. }
  77. tileAttribute("device.heatingSetpoint", key: "HEATING_SETPOINT") {
  78. attributeState("heatingSetpoint", label:'${currentValue}°')
  79. }
  80. }
  81. standardTile("mode", "device.thermostatMode", width: 2, height: 2) {
  82. state "off", label:'${name}', action:"heat", nextState:"heat", icon:"st.Home.home29"
  83. state "heat", label:'${name}', action:"eco", nextState:"eco", icon:"st.Outdoor.outdoor3"
  84. state "eco", label:'${name}', action:"off", nextState:"off", icon:"st.Outdoor.outdoor3"
  85. }
  86. valueTile("heatingSetpoint", "device.heatingSetpoint", width: 2, height: 2) {
  87. state "heatingSetpoint", label:'Setpoint ${currentValue}°', backgroundColors:[
  88. // Celsius
  89. [value: 0, color: "#153591"],
  90. [value: 7, color: "#1e9cbb"],
  91. [value: 15, color: "#90d2a7"],
  92. [value: 23, color: "#44b621"],
  93. [value: 28, color: "#f1d801"],
  94. [value: 35, color: "#d04e00"],
  95. [value: 37, color: "#bc2323"],
  96. // Fahrenheit
  97. [value: 40, color: "#153591"],
  98. [value: 44, color: "#1e9cbb"],
  99. [value: 59, color: "#90d2a7"],
  100. [value: 74, color: "#44b621"],
  101. [value: 84, color: "#f1d801"],
  102. [value: 95, color: "#d04e00"],
  103. [value: 96, color: "#bc2323"]
  104. ]
  105. }
  106. standardTile("temperatureAlarm", "device.temperatureAlarm", decoration: "flat", width: 2, height: 2) {
  107. state "default", label: 'No Alarm', icon: "st.alarm.temperature.normal", backgroundColor: "#ffffff"
  108. state "cleared", label: 'No Alarm', icon: "st.alarm.temperature.normal", backgroundColor: "#ffffff"
  109. state "freeze", label: 'Freeze', icon: "st.alarm.temperature.freeze", backgroundColor: "#bc2323"
  110. state "heat", label: 'Overheat', icon: "st.alarm.temperature.overheat", backgroundColor: "#bc2323"
  111. }
  112. standardTile("refresh", "device.refresh", decoration: "flat", width: 2, height: 2) {
  113. state "default", action:"refresh.refresh", icon:"st.secondary.refresh"
  114. }
  115. standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
  116. state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
  117. }
  118.  
  119. main ("thermostatMulti")
  120. details(["thermostatMulti", "mode", "heatingSetpoint", "temperatureAlarm", "refresh", "configure"])
  121. }
  122. }
  123.  
  124. def getTHERMOSTAT_CLUSTER() { 0x0201 }
  125. def getATTRIBUTE_LOCAL_TEMP() { 0x0000 }
  126. def getATTRIBUTE_PI_HEATING_STATE() { 0x0008 }
  127. def getATTRIBUTE_HEAT_SETPOINT() { 0x0012 }
  128. def getATTRIBUTE_SYSTEM_MODE() { 0x001C }
  129. def getATTRIBUTE_MFR_SPEC_SETPOINT_MODE() { 0x401C }
  130. def getATTRIBUTE_MFR_SPEC_OUT_TEMP() { 0x4001 }
  131.  
  132. def getTHERMOSTAT_UI_CONFIG_CLUSTER() { 0x0204 }
  133. def getATTRIBUTE_TEMP_DISP_MODE() { 0x0000 }
  134. def getATTRIBUTE_KEYPAD_LOCKOUT() { 0x0001 }
  135.  
  136.  
  137. def getSupportedThermostatModes() {
  138. ["heat", "eco", "off"]
  139. }
  140.  
  141. def getMinSetpointIndex() {
  142. 0
  143. }
  144. def getMaxSetpointIndex() {
  145. 1
  146. }
  147.  
  148. def getThermostatSetpointRange() {
  149. (getTemperatureScale() == "C") ? [5, 30] : [41, 86]
  150. }
  151.  
  152. def getHeatingSetpointRange() {
  153. thermostatSetpointRange
  154. }
  155.  
  156. def getSetpointStep() {
  157. (getTemperatureScale() == "C") ? 0.5 : 1.0
  158. }
  159.  
  160. def getModeMap() {[
  161. "00":"off",
  162. "04":"heat",
  163. "05":"eco"
  164. ]}
  165.  
  166. def setupHealthCheck() {
  167. // Device-Watch simply pings if no device events received for 32min(checkInterval)
  168. sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
  169. }
  170.  
  171. def configureSupportedRanges() {
  172. sendEvent(name: "supportedThermostatModes", value: supportedThermostatModes, displayed: false)
  173. sendEvent(name: "thermostatSetpointRange", value: thermostatSetpointRange, displayed: false)
  174. sendEvent(name: "heatingSetpointRange", value: heatingSetpointRange, displayed: false)
  175. }
  176.  
  177. def installed() {
  178. sendEvent(name: "temperatureAlarm", value: "cleared", displayed: false)
  179.  
  180. setupHealthCheck()
  181.  
  182. configureSupportedRanges()
  183. }
  184.  
  185. def updated() {
  186. def requests = []
  187. setupHealthCheck()
  188.  
  189. configureSupportedRanges()
  190.  
  191. unschedule(scheduledUpdateWeather)
  192. if (settings.zipcode) {
  193. requests += updateWeather()
  194. runEvery1Hour(scheduledUpdateWeather)
  195. }
  196.  
  197. requests += parameterSetting()
  198. response(requests)
  199. }
  200.  
  201. def parameterSetting() {
  202. def lockmode = null
  203. def valid_lock = false
  204.  
  205. log.debug "lock : $settings.lock"
  206. if (settings.lock == "Yes") {
  207. lockmode = 0x01
  208. valid_lock = true
  209. } else if (settings.lock == "No") {
  210. lockmode = 0x00
  211. valid_lock = true
  212. }
  213.  
  214. if (valid_lock) {
  215. log.debug "lock valid"
  216. zigbee.writeAttribute(THERMOSTAT_UI_CONFIG_CLUSTER, ATTRIBUTE_KEYPAD_LOCKOUT, DataType.ENUM8, lockmode) +
  217. poll()
  218. } else {
  219. log.debug "nothing valid"
  220. }
  221. }
  222.  
  223. def parse(String description) {
  224. log.debug "Parse description $description"
  225. def map = [:]
  226.  
  227. // If the user installed with an old DTH version, update so that the new mobile client will work
  228. if (!device.currentValue("supportedThermostatModes")) {
  229. configureSupportedRanges()
  230. }
  231. // Existing installations need the temperatureAlarm state initialized
  232. if (device.currentValue("temperatureAlarm") == null) {
  233. sendEvent(name: "temperatureAlarm", value: "cleared", displayed: false)
  234. }
  235.  
  236. if (description?.startsWith("read attr -")) {
  237. def descMap = zigbee.parseDescriptionAsMap(description)
  238. log.debug "Desc Map: $descMap"
  239. if (descMap.clusterInt == THERMOSTAT_CLUSTER) {
  240. if (descMap.attrInt == ATTRIBUTE_LOCAL_TEMP) {
  241. def intVal = Integer.parseInt(descMap.value, 16)
  242. map.name = "temperature"
  243. map.unit = getTemperatureScale()
  244. map.value = getTemperature(descMap.value)
  245.  
  246. if (intVal == 0x7ffd) { // 0x7FFD
  247. map.name = "temperatureAlarm"
  248. map.value = "freeze"
  249. map.unit = ""
  250. } else if (intVal == 0x7fff) { // 0x7FFF
  251. map.name = "temperatureAlarm"
  252. map.value = "heat"
  253. map.unit = ""
  254. } else if (intVal == 0x8000) { // 0x8000
  255. map.name = null
  256. map.value = null
  257. map.descriptionText = "Received a temperature error"
  258. } else if (intVal > 0x8000) {
  259. map.value = -(Math.round(2*(655.36 - map.value))/2)
  260. }
  261.  
  262. if (device.currentValue("temperatureAlarm") != "cleared" && map.name == "temperature") {
  263. sendEvent(name: "temperatureAlarm", value: "cleared")
  264. }
  265. } else if (descMap.attrInt == ATTRIBUTE_HEAT_SETPOINT) {
  266. def intVal = Integer.parseInt(descMap.value, 16)
  267. if (intVal != 0x8000) { // 0x8000
  268. log.debug "HEATING SETPOINT"
  269. map.name = "heatingSetpoint"
  270. map.value = getTemperature(descMap.value)
  271. map.data = [heatingSetpointRange: heatingSetpointRange]
  272. }
  273. } else if (descMap.attrInt == ATTRIBUTE_SYSTEM_MODE) {
  274. log.debug "MODE - ${descMap.value}"
  275. def value = modeMap[descMap.value]
  276.  
  277. // If we receive an off here then we are off
  278. // Else we will determine the real mode in the mfg specific packet so store this
  279. if (value == "off") {
  280. map.name = "thermostatMode"
  281. map.value = value
  282. map.data = [supportedThermostatModes: supportedThermostatModes]
  283. } else {
  284. state.storedSystemMode = value
  285. }
  286. // Right now this doesn't seem to happen -- regardless of the size field the value seems to be two bytes
  287. /*if (descMap.size == "08") {
  288. log.debug "MODE"
  289. map.name = "thermostatMode"
  290. map.value = modeMap[descMap.value]
  291. map.data = [supportedThermostatModes: supportedThermostatModes]
  292. } else if (descMap.size == "0A") {
  293. log.debug "MODE & SETPOINT MODE"
  294. def twoModesAttributes = descMap.value[0..-9]
  295. map.name = "thermostatMode"
  296. map.value = modeMap[twoModesAttributes]
  297. map.data = [supportedThermostatModes: supportedThermostatModes]
  298. }*/
  299. } else if (descMap.attrInt == ATTRIBUTE_MFR_SPEC_SETPOINT_MODE) {
  300. log.debug "SETPOINT MODE - ${descMap.value}"
  301. // If the storedSystemMode is heat, then we set the real mode here
  302. // Otherwise, we just ignore this
  303. if (!state.storedSystemMode || state.storedSystemMode == "heat") {
  304. log.debug "USING SETPOINT MODE - ${descMap.value}"
  305. map.name = "thermostatMode"
  306. map.value = modeMap[descMap.value]
  307. map.data = [supportedThermostatModes: supportedThermostatModes]
  308. }
  309. } else if (descMap.attrInt == ATTRIBUTE_PI_HEATING_STATE) {
  310. def intVal = Integer.parseInt(descMap.value, 16)
  311. log.debug "HEAT DEMAND"
  312. map.name = "thermostatOperatingState"
  313. if (intVal < 10) {
  314. map.value = "idle"
  315. } else {
  316. map.value = "heating"
  317. }
  318.  
  319. if (settings.heatdetails == "No") {
  320. map.displayed = false
  321. }
  322. }
  323. }
  324. }
  325.  
  326. def result = null
  327. if (map) {
  328. result = createEvent(map)
  329. }
  330. log.debug "Parse returned $map"
  331. return result
  332. }
  333.  
  334. def updateWeather() {
  335. log.debug "updating weather"
  336. def weather
  337. // If there is a zipcode defined, weather forecast will be sent. Otherwise, no weather forecast.
  338. if (settings.zipcode) {
  339. log.debug "ZipCode: ${settings.zipcode}"
  340. weather = getWeatherFeature("conditions", settings.zipcode)
  341.  
  342. // Check if the variable is populated, otherwise return.
  343. if (!weather) {
  344. log.debug("Something went wrong, no data found.")
  345. return false
  346. }
  347.  
  348. def locationScale = getTemperatureScale()
  349. def tempToSend = (locationScale == "C") ? weather.current_observation.temp_c : weather.current_observation.temp_f
  350. log.debug("Outdoor Temperature: ${tempToSend} ${locationScale}")
  351. // Right now this can disrupt device health if the device is
  352. // currently offline -- it would be erroneously marked online.
  353. //sendEvent( name: 'outsideTemp', value: tempToSend )
  354. setOutdoorTemperature(tempToSend)
  355. }
  356. }
  357.  
  358. def scheduledUpdateWeather() {
  359. def actions = updateWeather()
  360.  
  361. if (actions) {
  362. sendHubCommand(actions)
  363. }
  364. }
  365.  
  366. /**
  367. * PING is used by Device-Watch in attempt to reach the Device
  368. **/
  369. def ping() {
  370. log.debug "ping()"
  371. zigbee.readAttribute(THERMOSTAT_CLUSTER, ATTRIBUTE_LOCAL_TEMP)
  372. }
  373.  
  374. def poll() {
  375. def requests = []
  376. log.debug "poll()"
  377.  
  378. requests += updateWeather()
  379. requests += zigbee.readAttribute(THERMOSTAT_CLUSTER, ATTRIBUTE_LOCAL_TEMP)
  380. requests += zigbee.readAttribute(THERMOSTAT_CLUSTER, ATTRIBUTE_PI_HEATING_STATE)
  381. requests += zigbee.readAttribute(THERMOSTAT_CLUSTER, ATTRIBUTE_HEAT_SETPOINT)
  382. requests += zigbee.readAttribute(THERMOSTAT_CLUSTER, ATTRIBUTE_SYSTEM_MODE)
  383. requests += zigbee.readAttribute(THERMOSTAT_CLUSTER, ATTRIBUTE_MFR_SPEC_SETPOINT_MODE, ["mfgCode": "0x1185"])
  384. requests += zigbee.readAttribute(THERMOSTAT_UI_CONFIG_CLUSTER, ATTRIBUTE_TEMP_DISP_MODE)
  385. requests += zigbee.readAttribute(THERMOSTAT_UI_CONFIG_CLUSTER, ATTRIBUTE_KEYPAD_LOCKOUT)
  386.  
  387. requests
  388. }
  389.  
  390. def getTemperature(value) {
  391. if (value != null) {
  392. log.debug("value $value")
  393. def celsius = Integer.parseInt(value, 16) / 100
  394. if (getTemperatureScale() == "C") {
  395. return celsius
  396. } else {
  397. return Math.round(celsiusToFahrenheit(celsius))
  398. }
  399. }
  400. }
  401.  
  402. def refresh() {
  403. poll()
  404. }
  405.  
  406. def setHeatingSetpoint(preciseDegrees) {
  407. if (preciseDegrees != null) {
  408. def temperatureScale = getTemperatureScale()
  409. float minSetpoint = thermostatSetpointRange[minSetpointIndex]
  410. float maxSetpoint = thermostatSetpointRange[maxSetpointIndex]
  411.  
  412. if (preciseDegrees >= minSetpoint && preciseDegrees <= maxSetpoint) {
  413. def degrees = new BigDecimal(preciseDegrees).setScale(1, BigDecimal.ROUND_HALF_UP)
  414. def celsius = (getTemperatureScale() == "C") ? degrees : (fahrenheitToCelsius(degrees) as Float).round(2)
  415.  
  416. log.debug "setHeatingSetpoint({$degrees} ${temperatureScale})"
  417.  
  418. zigbee.writeAttribute(THERMOSTAT_CLUSTER, ATTRIBUTE_HEAT_SETPOINT, DataType.INT16, zigbee.convertToHexString((celsius * 100 as Integer), 4)) +
  419. zigbee.readAttribute(THERMOSTAT_CLUSTER, ATTRIBUTE_HEAT_SETPOINT) +
  420. zigbee.readAttribute(THERMOSTAT_CLUSTER, ATTRIBUTE_PI_HEATING_STATE)
  421. } else {
  422. log.debug "heatingSetpoint $preciseDegrees out of range! (supported: $minSetpoint - $maxSetpoint ${getTemperatureScale()})"
  423. }
  424. }
  425. }
  426.  
  427. // Maintain backward compatibility with self published versions of the "Stelpro Get Remote Temperature" SmartApp
  428. def quickSetOutTemp(outsideTemp) {
  429. setOutdoorTemperature(outsideTemp)
  430. }
  431.  
  432. def setOutdoorTemperature(outsideTemp) {
  433. def degrees = outsideTemp as Double
  434. Integer tempToSend
  435. def celsius = (getTemperatureScale() == "C") ? degrees : (fahrenheitToCelsius(degrees) as Float).round(2)
  436.  
  437. if (celsius < 0) {
  438. tempToSend = (celsius*100) + 65536
  439. } else {
  440. tempToSend = (celsius*100)
  441. }
  442. // The thermostat expects the byte order to be a little different than we send usually
  443. zigbee.writeAttribute(THERMOSTAT_CLUSTER, ATTRIBUTE_MFR_SPEC_OUT_TEMP, DataType.INT16, zigbee.swapEndianHex(zigbee.convertToHexString(tempToSend, 4)), ["mfgCode": "0x1185"])
  444. }
  445.  
  446. def increaseHeatSetpoint() {
  447. def currentMode = device.currentState("thermostatMode")?.value
  448. if (currentMode != "off") {
  449. float currentSetpoint = device.currentValue("heatingSetpoint")
  450.  
  451. currentSetpoint = currentSetpoint + setpointStep
  452. setHeatingSetpoint(currentSetpoint)
  453. }
  454. }
  455.  
  456. def decreaseHeatSetpoint() {
  457. def currentMode = device.currentState("thermostatMode")?.value
  458. if (currentMode != "off") {
  459. float currentSetpoint = device.currentValue("heatingSetpoint")
  460.  
  461. currentSetpoint = currentSetpoint - setpointStep
  462. setHeatingSetpoint(currentSetpoint)
  463. }
  464. }
  465.  
  466. def setThermostatMode(value) {
  467. log.debug "setThermostatMode({$value})"
  468. if (supportedThermostatModes.contains(value)) {
  469. def currentMode = device.currentState("thermostatMode")?.value
  470. def modeNumber;
  471. Integer setpointModeNumber;
  472. if (value == "heat") {
  473. modeNumber = 04
  474. setpointModeNumber = 04
  475. } else if (value == "eco") {
  476. modeNumber = 04
  477. setpointModeNumber = 05
  478. } else {
  479. modeNumber = 00
  480. setpointModeNumber = 00
  481. }
  482.  
  483. zigbee.writeAttribute(THERMOSTAT_CLUSTER, ATTRIBUTE_SYSTEM_MODE, DataType.ENUM8, modeNumber) +
  484. zigbee.writeAttribute(THERMOSTAT_CLUSTER, ATTRIBUTE_MFR_SPEC_SETPOINT_MODE, DataType.ENUM8, setpointModeNumber, ["mfgCode": "0x1185"]) +
  485. poll()
  486. } else {
  487. log.debug "Invalid thermostat mode $value"
  488. }
  489. }
  490.  
  491. def off() {
  492. log.debug "off"
  493. setThermostatMode("off")
  494. }
  495.  
  496. def heat() {
  497. log.debug "heat"
  498. setThermostatMode("heat")
  499. }
  500.  
  501. def eco() {
  502. log.debug "eco"
  503. setThermostatMode("eco")
  504. }
  505.  
  506. def configure() {
  507. def requests = []
  508. log.debug "binding to Thermostat cluster"
  509.  
  510. unschedule(scheduledUpdateWeather)
  511. if (settings.zipcode) {
  512. requests += updateWeather()
  513. runEvery1Hour(scheduledUpdateWeather)
  514. }
  515.  
  516. requests += zigbee.addBinding(THERMOSTAT_CLUSTER)
  517. // Configure Thermostat Cluster
  518. requests += zigbee.configureReporting(THERMOSTAT_CLUSTER, ATTRIBUTE_LOCAL_TEMP, DataType.INT16, 10, 60, 50)
  519. requests += zigbee.configureReporting(THERMOSTAT_CLUSTER, ATTRIBUTE_HEAT_SETPOINT, DataType.INT16, 1, 0, 50)
  520. requests += zigbee.configureReporting(THERMOSTAT_CLUSTER, ATTRIBUTE_SYSTEM_MODE, DataType.ENUM8, 1, 0, 1)
  521. requests += zigbee.configureReporting(THERMOSTAT_CLUSTER, ATTRIBUTE_MFR_SPEC_SETPOINT_MODE, DataType.ENUM8, 1, 0, 1)
  522. requests += zigbee.configureReporting(THERMOSTAT_CLUSTER, ATTRIBUTE_PI_HEATING_STATE, DataType.UINT8, 300, 900, 5)
  523.  
  524. // Configure Thermostat Ui Conf Cluster
  525. requests += zigbee.configureReporting(THERMOSTAT_UI_CONFIG_CLUSTER, ATTRIBUTE_TEMP_DISP_MODE, DataType.ENUM8, 1, 0, 1)
  526. requests += zigbee.configureReporting(THERMOSTAT_UI_CONFIG_CLUSTER, ATTRIBUTE_KEYPAD_LOCKOUT, DataType.ENUM8, 1, 0, 1)
  527.  
  528. // Read the configured variables
  529. requests += zigbee.readAttribute(THERMOSTAT_CLUSTER, ATTRIBUTE_LOCAL_TEMP)
  530. requests += zigbee.readAttribute(THERMOSTAT_CLUSTER, ATTRIBUTE_HEAT_SETPOINT)
  531. requests += zigbee.readAttribute(THERMOSTAT_CLUSTER, ATTRIBUTE_SYSTEM_MODE)
  532. requests += zigbee.readAttribute(THERMOSTAT_CLUSTER, ATTRIBUTE_MFR_SPEC_SETPOINT_MODE, ["mfgCode": "0x1185"])
  533. requests += zigbee.readAttribute(THERMOSTAT_CLUSTER, ATTRIBUTE_PI_HEATING_STATE)
  534. requests += zigbee.readAttribute(THERMOSTAT_UI_CONFIG_CLUSTER, ATTRIBUTE_TEMP_DISP_MODE)
  535. requests += zigbee.readAttribute(THERMOSTAT_UI_CONFIG_CLUSTER, ATTRIBUTE_KEYPAD_LOCKOUT)
  536.  
  537. requests
  538. }
  539.  
  540. // Unused Thermostat Capability commands
  541. def emergencyHeat() {
  542. log.debug "${device.displayName} does not support emergency heat mode"
  543. }
  544.  
  545. def cool() {
  546. log.debug "${device.displayName} does not support cool mode"
  547. }
  548.  
  549. def setCoolingSetpoint(degrees) {
  550. log.debug "${device.displayName} does not support cool setpoint"
  551. }
  552.  
  553. def on() {
  554. heat()
  555. }
  556.  
  557. def setThermostatFanMode(value) {
  558. log.debug "${device.displayName} does not support $value"
  559. }
  560.  
  561. def fanOn() {
  562. log.debug "${device.displayName} does not support fan on"
  563. }
  564.  
  565. def auto() {
  566. fanAuto()
  567. }
  568.  
  569. def fanAuto() {
  570. log.debug "${device.displayName} does not support fan auto"
  571. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement