Skip to content

Instantly share code, notes, and snippets.

@CosmicPuppy
Created May 23, 2016 20:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CosmicPuppy/c253f07e53e7792db07f89d6b8aac1c1 to your computer and use it in GitHub Desktop.
Save CosmicPuppy/c253f07e53e7792db07f89d6b8aac1c1 to your computer and use it in GitHub Desktop.
SmartPower Outlet configure reporting test...
/**
* Copyright 2015 SmartThings
*
* 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.
*
* SmartPower Outlet (CentraLite)
*
* Author: SmartThings
* Date: 2015-08-23
*/
/* Based on: https://community.smartthings.com/t/smart-power-outlet-configure-disable-energy-reporting/27137/18?u=tgauchat */
metadata {
// Automatically generated. Make future change here.
definition (name: "CP SmartPower Outlet", namespace: "CosmicPuppy", author: "SmartThings") {
capability "Actuator"
capability "Switch"
capability "Power Meter"
capability "Configuration"
capability "Refresh"
capability "Sensor"
// indicates that device keeps track of heartbeat (in state.heartbeat)
attribute "heartbeat", "string"
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0B04,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3200", deviceJoinName: "Outlet"
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0B04,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3200-Sgb", deviceJoinName: "Outlet"
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0B04,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "4257050-RZHAC", deviceJoinName: "Outlet"
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0B04,0B05", outClusters: "0019"
}
// simulator metadata
simulator {
// status messages
status "on": "on/off: 1"
status "off": "on/off: 0"
// reply messages
reply "zcl on-off on": "on/off: 1"
reply "zcl on-off off": "on/off: 0"
}
preferences {
section {
image(name: 'educationalcontent', multiple: true, images: [
"http://cdn.device-gse.smartthings.com/Outlet/US/OutletUS1.jpg",
"http://cdn.device-gse.smartthings.com/Outlet/US/OutletUS2.jpg"
])
}
}
// UI tile definitions
tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821", nextState: "turningOff"
attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "turningOn"
attributeState "turningOn", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821", nextState: "turningOff"
attributeState "turningOff", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "turningOn"
}
tileAttribute ("power", key: "SECONDARY_CONTROL") {
attributeState "power", label:'${currentValue} W'
}
}
standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
}
standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat") {
state "default", label:"", action:"configuration.configure", icon:"st.secondary.configure"
}
main "switch"
details(["switch","refresh","configure"])
}
}
// Parse incoming device messages to generate events
def parse(String description) {
log.debug "description is $description"
// save heartbeat (i.e. last time we got a message from device)
state.heartbeat = Calendar.getInstance().getTimeInMillis()
def finalResult = zigbee.getKnownDescription(description)
//TODO: Remove this after getKnownDescription can parse it automatically
if (!finalResult && description!="updated")
finalResult = getPowerDescription(zigbee.parseDescriptionAsMap(description))
if (finalResult) {
log.info finalResult
if (finalResult.type == "update") {
log.info "$device updates: ${finalResult.value}"
}
else if (finalResult.type == "power") {
def powerValue = (finalResult.value as Integer)/10
sendEvent(name: "power", value: powerValue)
/*
Dividing by 10 as the Divisor is 10000 and unit is kW for the device. AttrId: 0302 and 0300. Simplifying to 10
power level is an integer. The exact power level with correct units needs to be handled in the device type
to account for the different Divisor value (AttrId: 0302) and POWER Unit (AttrId: 0300). CLUSTER for simple metering is 0702
*/
}
else {
sendEvent(name: finalResult.type, value: finalResult.value)
}
}
else {
log.warn "DID NOT PARSE MESSAGE for description : $description"
log.debug zigbee.parseDescriptionAsMap(description)
}
}
def off() {
zigbee.off()
}
def on() {
zigbee.on()
}
def refresh() {
sendEvent(name: "heartbeat", value: "alive", displayed:false)
zigbee.onOffRefresh() + zigbee.refreshData("0x0B04", "0x050B")
}
def configure() {
/* Call configure using raw zdo bind and zcl clusters. */
//zigbee.onOffConfig() + powerConfig() + refresh()
/* Call zigbee.configureReporting() method. */
powerConfigST() + refresh()
}
//power config for devices with min reporting interval as 1 seconds and reporting interval if no activity as 10min (600s)
//min change in value is 01
def powerConfig() {
log.debug "powerConfig send..."
/* Per ZigBee Cluster Library Specification, Page ~26-27 of this or later doc:
https://people.ece.cornell.edu/land/courses/ece4760/FinalProjects/s2011/kjb79_ajm232/pmeter/ZigBee%20Cluster%20Library.pdf
Direction, Attribute identifier, Attribute data type, Minimum reporting interval, Maximum reporting interval, Reportable change
*/
[
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x0B04 {${device.zigbeeId}} {}", "delay 200",
/* From Forum post, 6400 / 6401 supposed to be 1 hour reporting -- but why not 2600? */
//"zcl global send-me-a-report 0x0B04 0x050B 0x29 6400 6401 {64 0000}", //The send-me-a-report is custom to the attribute type for CentraLite
/* Using 120 instead of 6400 results in 2 minutes, though isn't that the min instead of max? Gotta experiment with both min and max. */
//"zcl global send-me-a-report 0x0B04 0x050B 0x29 120 6401 {64 0000}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500"
]
}
def powerConfigST() {
log.debug "powerConfigST (zigbee.configureReporting) send..."
/* Attempting 3600 = 1 hour maximum reporting interval. 600 = Five minutes minimum reporting interval. 0 = minimum change. */
zigbee.configureReporting(0x0B04, 0x050B, 0x29, 3600, 600, 0)
}
private getEndpointId() {
new BigInteger(device.endpointId, 16).toString()
}
//TODO: Remove this after getKnownDescription can parse it automatically
def getPowerDescription(descMap) {
def powerValue = "undefined"
if (descMap.cluster == "0B04") {
if (descMap.attrId == "050b") {
if(descMap.value!="ffff")
powerValue = zigbee.convertHexToInt(descMap.value)
}
}
else if (descMap.clusterId == "0B04") {
if(descMap.command=="07"){
return [type: "update", value : "power (0B04) capability configured successfully"]
}
}
if (powerValue != "undefined"){
return [type: "power", value : powerValue]
}
else {
return [:]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment