/* * Copyright 2016 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. * * Updates: * ------- * 03-24-2017 : Initial commit. * 03-25-2017 : Added features from @blebson's DTH (Energy in kWh), as well as from my Aeon DSC06 gen 1 DTH * */ metadata { // Automatically generated. Make future change here. definition(name: "My SmartPower Outlet", namespace: "jscgs350", author: "SmartThings") { capability "Actuator" capability "Switch" capability "Power Meter" capability "Energy Meter" capability "Configuration" capability "Refresh" capability "Sensor" capability "Health Check" capability "Light" capability "Outlet" 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" } 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" ]) } section("Device customizations") { input "disableOnOff", "boolean", title: "Disable On/Off switch?", defaultValue: false, displayDuringSetup: true input "debugOutput", "boolean", title: "Enable debug logging?", defaultValue: false, displayDuringSetup: true input "displayEvents", "boolean", title: "Display Power (watts) events in the Recently tab and the device's event log?", defaultValue: false, required: false, displayDuringSetup: true input "kWhCost", "string", title: "Enter your cost per kWh (or just use the default, or use 0 to not calculate):", defaultValue: 0.16, required: false, displayDuringSetup: true } } // 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: 'On', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC" attributeState "off", label: 'Off', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" } tileAttribute("power", key: "SECONDARY_CONTROL") { attributeState "power", label: 'Currently using ${currentValue}W', icon: "st.secondary.activity" } } standardTile("power", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { state "power", label: '${currentValue} W', icon: "st.secondary.activity" } standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat", width: 6, height: 2) { state "default", label: '', action: "refresh.refresh", icon: "st.secondary.refresh" } main "power" details(["switch", "energyDisplay", "energyCost", "refresh"]) } } def updated() { state.onOffDisabled = ("true" == disableOnOff) state.debug = ("true" == debugOutput) state.displayDisabled = ("true" == displayEvents) log.debug "updated(disableOnOff: ${disableOnOff}(${state.onOffDisabled}), debugOutput: ${debugOutput}(${state.debug})" response(configure()) } // Parse incoming device messages to generate events def parse(String description) { if (state.debug) log.debug "description is $description" def event = zigbee.getEvent(description) if (event) { if (event.name == "power") { def value = (event.value as Integer) / 10 if (state.displayDisabled) { event = createEvent(name: event.name, value: value, descriptionText: '{{ device.displayName }} power is {{ value }} Watts', translatable: true, displayed: true) } else { event = createEvent(name: event.name, value: value, descriptionText: '{{ device.displayName }} power is {{ value }} Watts', translatable: true, displayed: false) } // return calculateAndShowEnergy() } else if (event.name == "switch") { def descriptionText = event.value == "on" ? '{{ device.displayName }} is On' : '{{ device.displayName }} is Off' event = createEvent(name: event.name, value: event.value, descriptionText: descriptionText, translatable: true) } } else { def cluster = zigbee.parse(description) if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07) { if (cluster.data[0] == 0x00) { if (state.debug) log.debug "ON/OFF REPORTING CONFIG RESPONSE: " + cluster event = createEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) } else { if (state.debug) log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}" event = null } } else { if (state.debug) log.warn "DID NOT PARSE MESSAGE for description : $description" if (state.debug) log.debug "${cluster}" } } return event ? createEvent(event) : event } def off() { if (state.onOffDisabled) { if (state.debug) log.debug "On/Off disabled..." refresh() } else { zigbee.off() } } def on() { if (state.onOffDisabled) { if (state.debug) log.debug "On/Off disabled..." refresh() } else { zigbee.on() } } def calculateAndShowEnergy() { def recentEvents = device.statesSince("power", new Date()-1, [max: 2]).collect {[value: it.value as float, date: it.date]} def deltaT = (recentEvents[0].date.getTime() - recentEvents[1].date.getTime()) // time since last "power" event in milliseconds deltaT = deltaT / 3600000 // convert to hours def energyValue = device.currentValue("energy") if(energyValue != null) { energyValue += (recentEvents[1].value * deltaT) / 1000 // energy used since last "power" event in kWh } sendEvent(name: "energy", value: energyValue, displayed: false) sendEvent(name: "energyDisplay", value: String.format("%6.3f kWh",energyValue), displayed: false) } /** * PING is used by Device-Watch in attempt to reach the Device * */ def ping() { return zigbee.onOffRefresh() } def refresh() { zigbee.onOffRefresh() + zigbee.electricMeasurementPowerRefresh() } def configure() { log.debug "Configuring..." // Device-Watch allows 2 check-in misses from device + ping (plus 1 min lag time) // enrolls with default periodic reporting until newer 5 min interval is confirmed sendEvent(name: "checkInterval", value: 2 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) // OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity refresh() + zigbee.onOffConfig(0, 300) + zigbee.electricMeasurementPowerConfig() }