Advertisement
erocm123

Environment Sensor EX - Extra Logging

Dec 19th, 2018
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 25.60 KB | None | 0 0
  1. import physicalgraph.zigbee.zcl.DataType
  2. metadata {
  3. definition (name: "Environment Sensor EX", namespace: "iharyadi", author: "iharyadi", ocfDeviceType: "oic.r.temperature", runLocally: false, minHubCoreVersion: "000.019.00012", executeCommandsLocally: true, vid: "generic-motion-6") {
  4. capability "Configuration"
  5. capability "Refresh"
  6. capability "Temperature Measurement"
  7. capability "RelativeHumidityMeasurement"
  8. capability "Illuminance Measurement"
  9. capability "Switch"
  10. capability "Battery"
  11. capability "Sensor"
  12.  
  13. MapDiagAttributes().each{ k, v -> attribute "$v", "number" }
  14.  
  15. attribute "pressure", "number"
  16. attribute "binaryinput", "string"
  17. attribute "binaryoutput", "string"
  18. attribute "analoginput", "number"
  19.  
  20. command "binaryoutputOn"
  21. command "binaryoutputOff"
  22.  
  23.  
  24. fingerprint profileId: "0104", inClusters: "0000, 0003, 0006, 0402, 0403, 0405, 0400, 0B05, 000F, 000C, 0010, 1001", manufacturer: "KMPCIL", model: "RES001", deviceJoinName: "Environment Sensor"
  25. fingerprint profileId: "0104", inClusters: "0000, 0001, 0003, 0006, 0402, 0403, 0405, 0400, 0B05, 000F, 000C, 0010", manufacturer: "KMPCIL", model: "RES001", deviceJoinName: "Environment Sensor"
  26. fingerprint profileId: "0104", inClusters: "0000, 0003, 0006, 0402, 0403, 0405, 0B05, 000F, 000C, 0010, 1001", manufacturer: "KMPCIL", model: "RES002", deviceJoinName: "Environment Sensor"
  27. fingerprint profileId: "0104", inClusters: "0000, 0003, 0006, 0400, 0B05, 000F, 000C, 0010, 1001", manufacturer: "KMPCIL", model: "RES003", deviceJoinName: "Environment Sensor"
  28. fingerprint profileId: "0104", inClusters: "0000, 0003, 0006, 0B05, 000F, 000C, 0010, 1001", manufacturer: "KMPCIL", model: "RES004", deviceJoinName: "Environment Sensor"
  29. }
  30.  
  31. // simulator metadata
  32. simulator {
  33. }
  34.  
  35. tiles(scale: 2) {
  36. multiAttributeTile(name: "temperature", type: "generic", width: 6, height: 4, canChangeIcon: true) {
  37. tileAttribute("device.temperature", key: "PRIMARY_CONTROL") {
  38. attributeState "temperature", label: '${currentValue}°',
  39. backgroundColors: [
  40. [value: 31, color: "#153591"],
  41. [value: 44, color: "#1e9cbb"],
  42. [value: 59, color: "#90d2a7"],
  43. [value: 74, color: "#44b621"],
  44. [value: 84, color: "#f1d801"],
  45. [value: 95, color: "#d04e00"],
  46. [value: 96, color: "#bc2323"]
  47. ]
  48. }
  49. }
  50. valueTile("humidity", "device.humidity", inactiveLabel: false, width: 3, height: 2, wordWrap: true) {
  51. state "humidity", label: 'Humidity ${currentValue}${unit}', unit:"%", defaultState: true
  52. }
  53. valueTile("pressure", "device.pressure", inactiveLabel: false, width: 3, height: 2, wordWrap: true) {
  54. state "pressure", label: 'Pressure ${currentValue}${unit}', unit:"kPa", defaultState: true
  55. }
  56.  
  57. valueTile("illuminance", "device.illuminance", width:3, height: 2) {
  58. state "illuminance", label: 'illuminance ${currentValue}${unit}', unit:"Lux", defaultState: true
  59. }
  60.  
  61. valueTile("battery", "device.battery", width:3, height: 2) {
  62. state "battery", label: 'battery ${currentValue}${unit}', unit:"%", defaultState: true
  63. }
  64.  
  65. standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
  66. state "default", label:"Refresh", action:"refresh.refresh", icon:"st.secondary.refresh"
  67. }
  68.  
  69. standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
  70. state "default", label:"Configure", action:"configure", icon:"st.secondary.refresh"
  71. }
  72.  
  73. def tiles_detail = [];
  74.  
  75. tiles_detail.add("temperature")
  76. tiles_detail.add("humidity")
  77. tiles_detail.add("pressure")
  78.  
  79. tiles_detail.add("illuminance")
  80. tiles_detail.add("battery")
  81.  
  82. MapDiagAttributes().each{ k, v -> valueTile("$v", "device.$v", width: 2, height: 2, wordWrap: true) {
  83. state "val", label: "$v \n"+'${currentValue}', defaultState: true
  84. };
  85. tiles_detail.add(v);
  86. }
  87. tiles_detail.add("refresh")
  88. tiles_detail.add("configure")
  89.  
  90. main "temperature"
  91. details(tiles_detail)
  92. }
  93.  
  94. preferences {
  95. section("Environment Sensor")
  96. {
  97. input name:"tempOffset", type:"decimal", title: "Degrees", description: "Adjust temperature by this many degrees in Celcius",
  98. range: "*..*", displayDuringSetup: false
  99. input name:"tempFilter", type:"decimal", title: "Coeficient", description: "Temperature filter between 0.0 and 1.0",
  100. range: "0..1", displayDuringSetup: false
  101. input name:"humOffset", type:"decimal", title: "Percent", description: "Adjust humidity by this many percent",
  102. range: "*..*", displayDuringSetup: false
  103. input name:"illumAdj", type:"decimal", title: "Factor", description: "Adjust illuminace base on formula illum / Factor",
  104. range: "1..*", displayDuringSetup: false
  105. }
  106.  
  107. section("Expansion Sensor")
  108. {
  109. input name:"enableAnalogInput", type: "bool", title: "Analog Input", description: "Enable Analog Input",
  110. defaultValue: "false", displayDuringSetup: false
  111.  
  112. input name:"childAnalogInput", type:"text", title: "Analog Input Handler", description: "Analog Input Child Handler",
  113. displayDuringSetup: false
  114.  
  115. input name:"enableBinaryInput", type: "bool", title: "Binary Input", description: "Enable Binary Input",
  116. defaultValue: "false", displayDuringSetup: false
  117.  
  118. input name:"childBinaryInput", type:"string", title: "Binary Input Handler", description: "Binary Input Device Handler",
  119. displayDuringSetup: false
  120.  
  121. input name:"enableBinaryOutput", type: "bool", title: "Binary Output", description: "Enable Binary Output",
  122. defaultValue: "false", displayDuringSetup: false
  123.  
  124. input name:"childBinaryOutput", type:"text", title: "Binary Output Handler", description: "Binary Output Child Handler",
  125. displayDuringSetup: false
  126. }
  127.  
  128. section("Debug Messages")
  129. {
  130. input name: "logEnabled", defaultValue: "true", type: "bool", title: "Enable info message logging", description: "",
  131. displayDuringSetup: false
  132. }
  133. }
  134. }
  135.  
  136. private def Log(message) {
  137. if (logEnabled)
  138. log.info "${message}"
  139. }
  140.  
  141. private def BATT_REMINING_ID()
  142. {
  143. return 0x0021;
  144. }
  145.  
  146. private def NUMBER_OF_RESETS_ID()
  147. {
  148. return 0x0000;
  149. }
  150.  
  151. private def MAC_TX_UCAST_RETRY_ID()
  152. {
  153. return 0x0104;
  154. }
  155.  
  156. private def MAC_TX_UCAST_FAIL_ID()
  157. {
  158. return 0x0105;
  159. }
  160.  
  161. private def NWK_DECRYPT_FAILURES_ID()
  162. {
  163. return 0x0115;
  164. }
  165.  
  166. private def PACKET_VALIDATE_DROP_COUNT_ID()
  167. {
  168. return 0x011A;
  169. }
  170.  
  171. private def PARENT_COUNT_ID()
  172. {
  173. return 0x011D+1;
  174. }
  175.  
  176. private def CHILD_COUNT_ID()
  177. {
  178. return 0x011D+2;
  179. }
  180.  
  181. private def NEIGHBOR_COUNT_ID()
  182. {
  183. return 0x011D+3;
  184. }
  185.  
  186. private def LAST_RSSI_ID()
  187. {
  188. return 0x011D;
  189. }
  190.  
  191. private def DIAG_CLUSTER_ID()
  192. {
  193. return 0x0B05;
  194. }
  195.  
  196. private def TEMPERATURE_CLUSTER_ID()
  197. {
  198. return 0x0402;
  199. }
  200.  
  201. private def PRESSURE_CLUSTER_ID()
  202. {
  203. return 0x0403;
  204. }
  205.  
  206. private def HUMIDITY_CLUSTER_ID()
  207. {
  208. return 0x0405;
  209. }
  210.  
  211. private def ILLUMINANCE_CLUSTER_ID()
  212. {
  213. return 0x0400;
  214. }
  215.  
  216. private def POWER_CLUSTER_ID()
  217. {
  218. return 0x0001;
  219. }
  220.  
  221. private def SENSOR_VALUE_ATTRIBUTE()
  222. {
  223. return 0x0000;
  224. }
  225.  
  226. private def MapDiagAttributes()
  227. {
  228. def result = [(CHILD_COUNT_ID()):'Children',
  229. (NEIGHBOR_COUNT_ID()):'Neighbor',
  230. (NUMBER_OF_RESETS_ID()):'ResetCount',
  231. (MAC_TX_UCAST_RETRY_ID()):'TXRetry',
  232. (MAC_TX_UCAST_FAIL_ID()):'TXFail',
  233. (LAST_RSSI_ID()):'RSSI',
  234. (NWK_DECRYPT_FAILURES_ID()):'DecryptFailure',
  235. (PACKET_VALIDATE_DROP_COUNT_ID()):'PacketDrop']
  236.  
  237. return result;
  238. }
  239.  
  240. private def createDiagnosticEvent( String attr_name, type, value )
  241. {
  242. def result = [:]
  243. result.name = attr_name
  244. result.translatable = true
  245.  
  246. def converter = [(DataType.INT8):{int val -> return (byte) val},
  247. (DataType.INT16):{int val -> return val},
  248. (DataType.UINT16):{int val -> return (long)val}]
  249.  
  250. result.value = converter[zigbee.convertHexToInt(type)]( zigbee.convertHexToInt(value));
  251.  
  252. result.descriptionText = "{{ device.displayName }} $attr_name was $result.value"
  253.  
  254. return createEvent(result)
  255. }
  256.  
  257. private def parseDiagnosticEvent(def descMap)
  258. {
  259. def attr_name = MapDiagAttributes()[descMap.attrInt];
  260. if(!attr_name)
  261. {
  262. return null;
  263. }
  264.  
  265. return createDiagnosticEvent(attr_name, descMap.encoding, descMap.value)
  266. }
  267.  
  268. private def createPressureEvent(float pressure)
  269. {
  270. def result = [:]
  271. result.name = "pressure"
  272. result.translatable = true
  273. result.unit = "kPa"
  274. result.value = pressure.round(1)
  275. result.descriptionText = "{{ device.displayName }} pressure was $result.value"
  276. return result
  277. }
  278.  
  279. private def parsePressureEvent(def descMap)
  280. {
  281. if(zigbee.convertHexToInt(descMap.attrId) != SENSOR_VALUE_ATTRIBUTE())
  282. {
  283. return null
  284. }
  285. float pressure = (float)zigbee.convertHexToInt(descMap.value) / 10.0
  286. return createPressureEvent(pressure)
  287. }
  288.  
  289. private def createIlluminanceEvent(int illum)
  290. {
  291. def result = [:]
  292. result.name = "illuminance"
  293. result.translatable = true
  294. result.unit = "Lux"
  295.  
  296. if(!illumAdj || illumAdj < 1.0)
  297. {
  298. if(ilumm == 0)
  299. {
  300. result.value = 0.0
  301. }
  302. else
  303. {
  304. result.value = 10.0 ** (((double) illum / 10000.0) -1.0)
  305. }
  306.  
  307. result.value = result.value.round(2)
  308. }
  309. else
  310. {
  311. result.value = ((double)illum / illumAdj).toInteger()
  312. }
  313.  
  314. result.descriptionText = "{{ device.displayName }} illuminance was $result.value"
  315. return result
  316. }
  317. private String ilummStringPrefix()
  318. {
  319. return "illuminance: "
  320. }
  321.  
  322. private def parseIlluminanceEventFromString(String description)
  323. {
  324. if(!description.startsWith(ilummStringPrefix()))
  325. {
  326. return null
  327. }
  328. int ilumm = Integer.parseInt(description.substring(ilummStringPrefix().length()))
  329.  
  330. return createIlluminanceEvent(ilumm)
  331. }
  332.  
  333. private def parseIlluminanceEvent(def descMap)
  334. {
  335. if(zigbee.convertHexToInt(descMap.attrId) != SENSOR_VALUE_ATTRIBUTE())
  336. {
  337. return null
  338. }
  339.  
  340. int res = zigbee.convertHexToInt(descMap.value)
  341.  
  342. return createIlluminanceEvent(res)
  343. }
  344.  
  345. private def createBinaryOutputEvent(boolean val)
  346. {
  347. def result = [:]
  348. result.name = "binaryoutput"
  349. result.translatable = true
  350. result.value = val ? "true" : "false"
  351. result.descriptionText = "{{ device.displayName }} BinaryOutput was $result.value"
  352. return result
  353. }
  354.  
  355. private def parseBinaryOutputEvent(def descMap)
  356. {
  357. def present_value = descMap.attrInt?.equals(0x0055)?
  358. descMap.value:
  359. descMap.additionalAttrs?.find { item -> item.attrInt?.equals(0x0055)}?.value
  360.  
  361. if(!present_value)
  362. {
  363. return null
  364. }
  365.  
  366. return createBinaryOutputEvent(zigbee.convertHexToInt(present_value) > 0)
  367. }
  368.  
  369. private def createAnalogInputEvent(float value)
  370. {
  371. def result = [:]
  372. result.name = "analoginput"
  373. result.translatable = true
  374. result.value = value.round(2)
  375. result.unit = "Volt"
  376. result.descriptionText = "{{ device.displayName }} AnalogInput was $result.value"
  377. return result
  378. }
  379.  
  380. private def parseAnalogInputEvent(def descMap)
  381. {
  382. def adc;
  383. def vdd;
  384.  
  385. if(descMap.attrInt?.equals(0x0103))
  386. {
  387. adc = descMap.value
  388. }
  389. else if (descMap.attrInt?.equals(0x0104))
  390. {
  391. vdd = descMap.value
  392. }
  393. else
  394. {
  395. adc = descMap.additionalAttrs?.find { item -> item.attrInt?.equals(0x0103)}?.value
  396. vdd = descMap.additionalAttrs?.find { item -> item.attrInt?.equals(0x0104)}?.value
  397. }
  398.  
  399. if(vdd)
  400. {
  401. state.lastVdd = (((float)zigbee.convertHexToInt(vdd)*3.45)/0x1FFF)
  402. }
  403.  
  404. if(!adc)
  405. {
  406. return null
  407. }
  408.  
  409. float volt = 0;
  410. if(state.lastVdd)
  411. {
  412. volt = (zigbee.convertHexToInt(adc) * state.lastVdd)/0x1FFF
  413. }
  414.  
  415. return createAnalogInputEvent(volt)
  416. }
  417.  
  418. private def createBinaryInputEvent(boolean val)
  419. {
  420. def result = [:]
  421. result.name = "binaryinput"
  422. result.translatable = true
  423. result.value = val ? "true" : "false"
  424. result.descriptionText = "{{ device.displayName }} BinaryInput was $result.value"
  425. return result
  426. }
  427.  
  428. private def parseBinaryInputEvent(def descMap)
  429. {
  430. def value = descMap.attrInt?.equals(0x0055) ?
  431. descMap.value :
  432. descMap.additionalAttrs?.find { item -> item.attrInt?.equals(0x0055)}?.value
  433.  
  434. if(!value)
  435. {
  436. return null
  437. }
  438.  
  439. return createBinaryInputEvent(zigbee.convertHexToInt(value)>0)
  440. }
  441.  
  442. private def reflectToChild(String childtype, String description)
  443. {
  444. if(!childtype)
  445. {
  446. return
  447. }
  448.  
  449. def childDevice = childDevices?.find{item->
  450. return item.deviceNetworkId == "${device.deviceNetworkId}-$childtype"
  451. }
  452.  
  453. if(!childDevice)
  454. {
  455. return
  456. }
  457.  
  458. def childEvent = childDevice.parse(description)
  459. if(!childEvent)
  460. {
  461. return
  462. }
  463.  
  464. childDevice.sendEvent(childEvent)
  465. }
  466.  
  467. private def createBattEvent(int val)
  468. {
  469. def result = [:]
  470. result.name = "battery"
  471. result.translatable = true
  472. result.value = val/2
  473. result.unit = "%"
  474. result.descriptionText = "${device.displayName} ${result.name} was ${result.value}"
  475. return result
  476. }
  477.  
  478. def parseBattEvent(def descMap)
  479. {
  480. def value = descMap.attrInt?.equals(BATT_REMINING_ID()) ?
  481. descMap.value :
  482. null
  483.  
  484. if(!value)
  485. {
  486. return null
  487. }
  488.  
  489. return createBattEvent(zigbee.convertHexToInt(value))
  490. }
  491.  
  492. private def parseCustomEvent(String description)
  493. {
  494. def event = null
  495. def descMap = zigbee.parseDescriptionAsMap(description)
  496. if(description?.startsWith("read attr - raw:"))
  497. {
  498. if(descMap?.clusterInt == DIAG_CLUSTER_ID())
  499. {
  500. event = parseDiagnosticEvent(descMap);
  501. }
  502. else if(descMap?.clusterInt == PRESSURE_CLUSTER_ID())
  503. {
  504. event = parsePressureEvent(descMap);
  505. }
  506. else if(descMap?.clusterInt == 0x000F)
  507. {
  508. event = parseBinaryInputEvent(descMap);
  509. reflectToChild(childBinaryInput,description)
  510. }
  511. else if(descMap?.clusterInt == 0x000C)
  512. {
  513. event = parseAnalogInputEvent(descMap)
  514. reflectToChild(childAnalogInput,description)
  515. }
  516. else if(descMap?.clusterInt == 0x0010)
  517. {
  518. event = parseBinaryOutputEvent(descMap)
  519. reflectToChild(childBinaryOutput,description)
  520. }
  521. else if(descMap?.clusterInt == POWER_CLUSTER_ID())
  522. {
  523. event = parseBattEvent(descMap)
  524. }
  525. }
  526. else if (description?.startsWith("catchall:"))
  527. {
  528. if(descMap?.clusterInt == ILLUMINANCE_CLUSTER_ID() &&
  529. descMap.messageType == "00" &&
  530. descMap.command == "01")
  531. {
  532. event = parseIlluminanceEvent(descMap);
  533. }
  534. }
  535. return event
  536. }
  537.  
  538. private String tempStringPrefix()
  539. {
  540. return "temperature:"
  541. }
  542.  
  543. private String humidityStringPrefix()
  544. {
  545. return "humidity:"
  546. }
  547.  
  548. private def createAdjustedTempString(double val)
  549. {
  550. log.debug "createAdjustedTempString: $val | tempOffset: $tempOffset"
  551. if (tempOffset) {
  552. val = val + tempOffset
  553. }
  554.  
  555. if(tempFilter)
  556. {
  557. if(state.tempCelcius)
  558. {
  559. log.debug "val: $val | tempFilter: $tempFilter | state.tempCelcius: $state.tempCelcius"
  560. val = tempFilter*val + (1.0-tempFilter)*state.tempCelcius
  561. }
  562. log.debug "val: $val"
  563. state.tempCelcius = val
  564. }
  565.  
  566. return tempStringPrefix() + " " +val.toString()
  567. }
  568.  
  569. private def createAdjustedHumString(double val)
  570. {
  571. double adj = 0.0
  572. if (humOffset) {
  573. adj = humOffset
  574. }
  575.  
  576. return humidityStringPrefix() + " " +(val + adj).toString() + "%"
  577. }
  578.  
  579. private def adjustTempHumValue(String description)
  580. {
  581.  
  582. if(description.startsWith(tempStringPrefix()))
  583. {
  584. double d = Double.parseDouble(description.substring(tempStringPrefix().length()))
  585. log.debug "adjustTempHumValue: $d"
  586. return createAdjustedTempString(d)
  587. }
  588.  
  589. if(description.startsWith(humidityStringPrefix()))
  590. {
  591. double d = Double.parseDouble(description.substring(humidityStringPrefix().length()).replaceAll("[^\\d.]", ""))
  592. return createAdjustedHumString(d)
  593. }
  594.  
  595. if(!description.startsWith("catchall:"))
  596. {
  597. return description
  598. }
  599.  
  600. def descMap = zigbee.parseDescriptionAsMap(description)
  601.  
  602. if(descMap.attrInt != SENSOR_VALUE_ATTRIBUTE())
  603. {
  604. return description
  605. }
  606.  
  607. if( descMap.clusterInt == TEMPERATURE_CLUSTER_ID() )
  608. {
  609. return createAdjustedTempString((double) zigbee.convertHexToInt(descMap.value) / 100.00)
  610. }
  611. else if(descMap.clusterInt == HUMIDITY_CLUSTER_ID())
  612. {
  613. return createAdjustedHumString((double) zigbee.convertHexToInt(descMap.value) / 100.00)
  614. }
  615.  
  616. return description
  617. }
  618.  
  619. // Parse incoming device messages to generate events
  620. def parse(String description) {
  621.  
  622. description = adjustTempHumValue(description)
  623. Log("description is $description")
  624.  
  625. def event = zigbee.getEvent(description)
  626. if(event)
  627. {
  628. sendEvent(event)
  629. return
  630. }
  631.  
  632. event = parseIlluminanceEventFromString(description)
  633. if(event)
  634. {
  635. sendEvent(event)
  636. return
  637. }
  638.  
  639. event = parseCustomEvent(description)
  640. if(event)
  641. {
  642. sendEvent(event)
  643. return
  644. }
  645.  
  646. Log("DID NOT PARSE MESSAGE : $description")
  647. }
  648.  
  649. def off() {
  650. zigbee.off()
  651. }
  652.  
  653. def on() {
  654. zigbee.on()
  655. }
  656.  
  657. def sendCommandP(def cmd)
  658. {
  659. if(cmd)
  660. {
  661. sendHubCommand(cmd.collect { new physicalgraph.device.HubAction(it) }, 0)
  662. }
  663. }
  664.  
  665. def command(Integer Cluster, Integer Command, String payload)
  666. {
  667. return zigbee.command(Cluster,Command,payload)
  668. }
  669.  
  670. def command(Integer Cluster, Integer Command)
  671. {
  672. return zigbee.command(Cluster,Command)
  673. }
  674.  
  675. def readAttribute(Integer Cluster, Integer attributeId, Map additionalParams)
  676. {
  677. return zigbee.readAttribute(Cluster, attributeId, additionalParams)
  678. }
  679.  
  680. def readAttribute(Integer Cluster, Integer attributeId)
  681. {
  682. return zigbee.readAttribute(Cluster, attributeId)
  683. }
  684.  
  685. def writeAttribute(Integer Cluster, Integer attributeId,
  686. Integer dataType, Integer value,
  687. Map additionalParams)
  688. {
  689. return zigbee.writeAttribute(Cluster, attributeId,
  690. dataType, value,
  691. additionalParams)
  692. }
  693.  
  694. def writeAttribute(Integer Cluster, Integer attributeId,
  695. Integer dataType, Integer value)
  696. {
  697. return zigbee.writeAttribute(Cluster, attributeId,
  698. dataType, value)
  699. }
  700.  
  701. def configureReporting(Integer Cluster,
  702. Integer attributeId, Integer dataType,
  703. Integer minReportTime, Integer MaxReportTime,
  704. Integer reportableChange,
  705. Map additionalParams)
  706. {
  707. return zigbee.configureReporting( Cluster,
  708. attributeId, dataType,
  709. minReportTime, MaxReportTime,
  710. reportableChange,
  711. aditionalParams)
  712. }
  713.  
  714. def configureReporting(Integer Cluster,
  715. Integer attributeId, Integer dataType,
  716. Integer minReportTime, Integer MaxReportTime,
  717. Integer reportableChange)
  718. {
  719. return zigbee.configureReporting( Cluster,
  720. attributeId, dataType,
  721. minReportTime, MaxReportTime,
  722. reportableChange)
  723. }
  724.  
  725. def configureReporting(Integer Cluster,
  726. Integer attributeId, Integer dataType,
  727. Integer minReportTime, Integer MaxReportTime)
  728. {
  729. return zigbee.configureReporting( Cluster,
  730. attributeId, dataType,
  731. minReportTime, MaxReportTime)
  732. }
  733.  
  734. def binaryoutputOff()
  735. {
  736. return zigbee.writeAttribute(0x0010, 0x0055, DataType.BOOLEAN, 0)
  737. }
  738.  
  739. def binaryoutputOn()
  740. {
  741. return zigbee.writeAttribute(0x0010, 0x0055, DataType.BOOLEAN, 1)
  742. }
  743.  
  744. private def refreshExpansionSensor()
  745. {
  746. def cmds = []
  747.  
  748. def mapExpansionRefresh = [[0x0010,enableBinaryOutput,0x0055],
  749. [0x000F,enableBinaryInput,0x0055],
  750. [0x000C, enableAnalogInput,0x00104],
  751. [0x000C, enableAnalogInput,0x00103]]
  752.  
  753. mapExpansionRefresh.findAll { return it[1] }.each{
  754. cmds = cmds + zigbee.readAttribute(it[0],it[2])
  755. }
  756.  
  757. return cmds
  758. }
  759.  
  760. private def refreshOnBoardSensor()
  761. {
  762. def model = device.getDataValue("model")
  763.  
  764. def cmds = [];
  765.  
  766. def mapRefresh = ["RES001":[TEMPERATURE_CLUSTER_ID(), HUMIDITY_CLUSTER_ID(), PRESSURE_CLUSTER_ID(),ILLUMINANCE_CLUSTER_ID()],
  767. "RES002":[TEMPERATURE_CLUSTER_ID(), HUMIDITY_CLUSTER_ID(), PRESSURE_CLUSTER_ID()],
  768. "RES003":[ILLUMINANCE_CLUSTER_ID()]]
  769.  
  770. mapRefresh[model]?.each{
  771. cmds = cmds + zigbee.readAttribute(it,SENSOR_VALUE_ATTRIBUTE());
  772. }
  773.  
  774. return cmds
  775. }
  776.  
  777. private def refreshDiagnostic()
  778. {
  779. def cmds = [];
  780. MapDiagAttributes().each{ k, v -> cmds += zigbee.readAttribute(DIAG_CLUSTER_ID(), k) }
  781. return cmds
  782. }
  783.  
  784. private def refreshBatt()
  785. {
  786. return zigbee.readAttribute(POWER_CLUSTER_ID(), BATT_REMINING_ID())
  787. }
  788.  
  789. def refresh() {
  790. Log("Refresh")
  791. state.lastRefreshAt = new Date(now()).format("yyyy-MM-dd HH:mm:ss", location.timeZone)
  792.  
  793. return refreshOnBoardSensor() +
  794. refreshExpansionSensor() +
  795. refreshDiagnostic()+
  796. refreshBatt()
  797. }
  798.  
  799. private def reportBME280Parameters()
  800. {
  801. def reportParameters = [];
  802. reportParameters = reportParameters + [[TEMPERATURE_CLUSTER_ID(),DataType.INT16, 5, 300, 10]]
  803. reportParameters = reportParameters + [[HUMIDITY_CLUSTER_ID(),DataType.UINT16, 5, 301, 100]]
  804. reportParameters = reportParameters + [[PRESSURE_CLUSTER_ID(),DataType.UINT16, 5, 302, 2]]
  805. return reportParameters
  806. }
  807.  
  808. private def reportTEMT6000Parameters()
  809. {
  810. def reportParameters = [];
  811. reportParameters = reportParameters + [[ILLUMINANCE_CLUSTER_ID(),DataType.UINT16, 5, 303, 500]]
  812. return reportParameters
  813. }
  814.  
  815. def configure() {
  816.  
  817. Log("Configuring Reporting and Bindings.")
  818. state.remove("tempCelcius")
  819.  
  820. def mapConfigure = ["RES001":reportBME280Parameters()+reportTEMT6000Parameters(),
  821. "RES002":reportBME280Parameters(),
  822. "RES003":reportTEMT6000Parameters()]
  823.  
  824. def model = device.getDataValue("model")
  825.  
  826. def cmds = [];
  827. mapConfigure[model]?.each{
  828. cmds = cmds + zigbee.configureReporting(it[0], SENSOR_VALUE_ATTRIBUTE(), it[1],it[2],it[3],it[4])
  829. }
  830.  
  831. cmds += zigbee.configureReporting(POWER_CLUSTER_ID(), BATT_REMINING_ID(), DataType.UINT8,5,307,2)
  832. cmds = cmds + refresh();
  833.  
  834. return cmds
  835. }
  836.  
  837. private def createChild(String childDH, String componentName)
  838. {
  839. if(!childDH)
  840. {
  841. return null
  842. }
  843.  
  844. def childDevice = childDevices.find{item-> return item.deviceNetworkId == "${device.deviceNetworkId}-$childDH"}
  845. if(!childDevice)
  846. {
  847. childDevice = addChildDevice("iharyadi",
  848. "$childDH",
  849. "${device.deviceNetworkId}-$childDH", null,
  850. [completedSetup: true,
  851. label: "${device.displayName} $childDH",
  852. isComponent: false,
  853. componentName: componentName,
  854. componentLabel: "${device.displayName} $childDH"])
  855.  
  856. }
  857.  
  858. return childDevice?.configure_child()
  859. }
  860.  
  861. private updateExpansionSensorSetting()
  862. {
  863. def cmds = []
  864.  
  865. def mapExpansionEnable = [[0x0010,enableBinaryOutput,DataType.BOOLEAN,0x0055],
  866. [0x000F,enableBinaryInput,DataType.BOOLEAN,0x0055],
  867. [0x000C, enableAnalogInput,DataType.UINT16,0x0103]]
  868.  
  869. mapExpansionEnable.each{
  870. cmds = cmds + zigbee.writeAttribute(it[0], 0x0051, DataType.BOOLEAN, it[1]?1:0)
  871. if(!it[1])
  872. {
  873. cmds = cmds + zigbee.configureReporting(it[0], it[3], it[2], 0xFFFF, 0xFFFF,1)
  874. }
  875. }
  876.  
  877. def mapExpansionChildrenCreate = [[enableBinaryOutput,childBinaryOutput,"BinaryOutput"],
  878. [enableBinaryInput,childBinaryInput,"BinaryInput"],
  879. [enableAnalogInput,childAnalogInput,"AnalogInput"]]
  880.  
  881. mapExpansionChildrenCreate.findAll{return (it[0] && it[1])}.each{
  882. cmds = cmds + createChild(it[1],it[2])
  883. }
  884.  
  885. return cmds
  886. }
  887.  
  888. def updated() {
  889. Log("updated():")
  890.  
  891. if (!state.updatedLastRanAt || now() >= state.updatedLastRanAt + 2000) {
  892. state.updatedLastRanAt = now()
  893. state.remove("tempCelcius")
  894. return response(updateExpansionSensorSetting() + refresh())
  895. }
  896. else {
  897. Log("updated(): Ran within last 2 seconds so aborting.")
  898. }
  899. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement