Compare commits

..

1 Commits

14 changed files with 180 additions and 268 deletions

View File

@@ -1,241 +0,0 @@
/**
* 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
*/
metadata {
// Automatically generated. Make future change here.
definition (name: "Iris Smart Plug", namespace: "blebson", author: "SmartThings") {
capability "Actuator"
capability "Switch"
capability "Power Meter"
capability "Energy Meter"
capability "Configuration"
capability "Refresh"
capability "Sensor"
// indicates that device keeps track of heartbeat (in state.heartbeat)
attribute "heartbeat", "string"
attribute "timerStart", "number"
attribute "energyDisplay", "string"
attribute "elapsedTimeDisplay", "string"
command "resetEnergyUsage"
fingerprint profileId: "0104", inClusters: "0000 0003 0004 0005 0006 0B04 0B05 FC03", outClusters: "0019", manufacturer: "CentraLite", model: "3210-L", deviceJoinName: "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"
}
// 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"
])
}
section("Reporting Intervals") {
input "intervalMin", "number", title: "Minimum interval between reports [s]", defaultValue: 5, range: "1..600"
input "intervalMax", "number", title: "Maximum interval between reports [s]", defaultValue: 600, range: "1..600"
}
}
// 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'
}
}
valueTile("energyDisplay", "device.energyDisplay", width: 5, height: 1, decoration: "flat") {
state "default", label:'Energy used: ${currentValue}', unit: "kWh"
}
standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat", width: 1, height: 1) {
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
}
standardTile("resetUsage", "command.resetEnergyUsage", decoration: "flat", width: 1, height: 1){
state "default", action: "resetEnergyUsage", label:'Reset kWh', icon:"st.Health & Wellness.health7"
}
valueTile("elapsedTimeDisplay", "device.elapsedTimeDisplay", decoration: "flat", width: 5, height: 1){
state "default", label: 'Time: ${currentValue}', unit: "h"
}
standardTile("configure", "device.switch", inactiveLabel: false, decoration: "flat", width: 1, height: 1) {
state "default", label:"", action:"configure", icon:"st.secondary.configure"
}
main "switch"
details(["switch","energyDisplay","resetUsage","power","elapsedTimeDisplay","refresh"])
}
}
// 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()
if (state.timerStart == null)
{
state.timerStart = Calendar.getInstance().getTimeInMillis()
state.energy = 0.0
}
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, isStateChange: true, displayed: false) // note: stateChange = true added so the energy calculation can work properly
/*
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
*/
calculateAndShowEnergy()
}
else {
sendEvent(name: finalResult.type, value: finalResult.value)
}
}
else {
log.warn "DID NOT PARSE MESSAGE for description : $description"
log.debug zigbee.parseDescriptionAsMap(description)
}
}
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)
def currentTime = Calendar.getInstance().getTimeInMillis()
def timeDifference = ((long)currentTime - state.timerStart)/1000; // in seconds
int h = (int) (timeDifference / (3600));
int m = (int) ((timeDifference - (h * 3600)) / 60);
int s = (int) (timeDifference - (h * 3600) - m * 60);
int d = (int) h >= 24 ? h / 24 : 0
h = d > 0 ? h % 24 : h
sendEvent(name: "elapsedTimeDisplay", value: String.format("%dd %02d:%02d:%02d", d, h, m, s), displayed: false)
}
def off() {
zigbee.off()
}
def on() {
zigbee.on()
}
def resetEnergyUsage() {
sendEvent(name: "energy", value: 0.0, displayed: false)
state.timerStart = Calendar.getInstance().getTimeInMillis()
sendEvent(name: "energyDisplay", value: String.format("%6.3f kWh",0.0), displayed: false)
sendEvent(name: "elapsedTimeDisplay", value: String.format("%dd %02d:%02d:%02d", 0, 0, 0, 0), displayed: false)
}
def refresh() {
sendEvent(name: "heartbeat", value: "alive", displayed:false)
return zigbee.onOffRefresh() + zigbee.refreshData("0x0B04", "0x050B")
}
def configure() {
log.debug "Configuring..."
return zigbee.onOffConfig() + powerConfig() + refresh()
}
def updated() {
response(configure())
}
//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() {
[
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x0B04 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 0x0B04 0x050B 0x29 ${intervalMin ?: 5} ${intervalMax ?: 600} {05 00}", //The send-me-a-report is custom to the attribute type for CentraLite
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500"
]
}
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 [:]
}
}

View File

@@ -14,7 +14,6 @@ metadata {
capability "Refresh"
capability "Sensor"
capability "Health Check"
capability "Light"
}
simulator {

View File

@@ -13,7 +13,6 @@ metadata {
capability "Refresh"
capability "Sensor"
capability "Health Check"
capability "Light"
}
simulator {

View File

@@ -36,7 +36,6 @@ metadata {
capability "Switch"
capability "Refresh"
capability "Contact Sensor"
capability "Light"
attribute "powered", "string"

View File

@@ -23,7 +23,6 @@ Works with:
* **Switch** - can detect state (possible values: on/off)
* **Switch Level** - represents current light level, usually 0-100 in percent
* **Health Check** - indicates ability to get device health notifications
* **Light** - indicates that the device belongs to Light category.
## Device Health

View File

@@ -22,7 +22,6 @@ metadata {
capability "Switch"
capability "Switch Level"
capability "Health Check"
capability "Light"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B04"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702"

View File

@@ -21,7 +21,6 @@ metadata {
capability "Sensor"
capability "Switch"
capability "Health Check"
capability "Light"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0B04"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0702"

View File

@@ -6,12 +6,6 @@ Works with:
* [Leviton Plug-in Lamp Dimmer Module (DZPD3-1LW)](https://www.smartthings.com/works-with-smartthings/outlets/leviton-plug-in-lamp-dimmer-module)
* [Leviton Universal Dimmer (DZMX1-LZ)](https://www.smartthings.com/works-with-smartthings/switches-and-dimmers/leviton-universal-dimmer)
* [Leviton 1000W Incandescent Dimmer](https://www.smartthings.com/works-with-smartthings/leviton/leviton-1000w-incandescent-dimmer)
* [Leviton 600W Incandescent Dimmer](https://www.smartthings.com/works-with-smartthings/leviton/leviton-600w-incandescent-dimmer)
* [Enerwave In-Wall Dimmer](https://www.smartthings.com/works-with-smartthings/enerwave/enerwave-in-wall-dimmer-zw500d)
* [Leviton 3-Speed Fan Controller](https://www.smartthings.com/works-with-smartthings/leviton/leviton-3-speed-fan-controller)
* [Leviton Magnetic Low Voltage Dimmer](https://www.smartthings.com/works-with-smartthings/leviton/leviton-magnetic-low-voltage-dimmer)
* [Remotec Technology Plug-In Dimmer](https://www.smartthings.com/works-with-smartthings/remotec-technology/remotec-technology-plug-in-dimmer)
## Table of contents
@@ -46,9 +40,4 @@ If the device doesn't pair when trying from the SmartThings mobile app, it is po
Pairing needs to be tried again by placing the device closer to the hub.
Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link:
* [Leviton Plug-in Lamp Dimmer Module (DZPD3-1LW) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices)
* [Leviton Universal Dimmer (DZMX1-LZ) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices)
* [Leviton 1000W Incandescent Dimmer Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices)
* [Leviton 600W Incandescent Dimmer Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices)
* [Leviton 3-Speed Fan Controller Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices)
* [Enerwave In-Wall Dimmer Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/204854176-How-to-connect-Enerwave-switches-and-dimmers)
* [Remotec Technology Plug-In Dimmer Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/202295150-Remotec-Technology-Plug-In-Dimmer-ZDS-100-)
* [Leviton Universal Dimmer (DZMX1-LZ) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices)

View File

@@ -20,7 +20,6 @@ metadata {
capability "Polling"
capability "Refresh"
capability "Sensor"
capability "Light"
fingerprint inClusters: "0x26", deviceJoinName: "Z-Wave Dimmer"
fingerprint mfr:"001D", prod:"1902", deviceJoinName: "Z-Wave Dimmer"
@@ -29,8 +28,6 @@ metadata {
fingerprint mfr:"001D", prod:"1001", model:"0334", deviceJoinName: "Leviton 3-Speed Fan Controller"
fingerprint mfr:"001D", prod:"0602", model:"0334", deviceJoinName: "Leviton Magnetic Low Voltage Dimmer"
fingerprint mfr:"001D", prod:"0401", model:"0334", deviceJoinName: "Leviton 600W Incandescent Dimmer"
fingerprint mfr:"0111", prod:"8200", model:"0200", deviceJoinName: "Remotec Technology Plug-In Dimmer"
fingerprint mfr:"1104", prod:"001D", model:"0501", deviceJoinName: "Leviton 1000W Incandescant Dimmer"
}
simulator {

View File

@@ -25,7 +25,6 @@ metadata {
capability "Switch Level"
capability "Sensor"
capability "Actuator"
capability "Light"
command "reset"

View File

@@ -21,7 +21,6 @@ metadata {
capability "Refresh"
capability "Configuration"
capability "Sensor"
capability "Light"
command "reset"

View File

@@ -19,7 +19,6 @@ metadata {
capability "Polling"
capability "Refresh"
capability "Sensor"
capability "Light"
fingerprint inClusters: "0x25", deviceJoinName: "Z-Wave Switch"
fingerprint mfr:"001D", prod:"1A02", model:"0334", deviceJoinName: "Leviton Appliance Module"
@@ -27,8 +26,6 @@ metadata {
fingerprint mfr:"001D", prod:"1D04", model:"0334", deviceJoinName: "Leviton Outlet"
fingerprint mfr:"001D", prod:"1C02", model:"0334", deviceJoinName: "Leviton Switch"
fingerprint mfr:"001D", prod:"0301", model:"0334", deviceJoinName: "Leviton 15A Switch"
fingerprint mfr:"001D", prod:"0F01", model:"0334", deviceJoinName: "Leviton 5A Incandescent Switch"
fingerprint mfr:"001D", prod:"1603", model:"0334", deviceJoinName: "Leviton 15A Split Duplex Receptacle"
fingerprint mfr:"011A", prod:"0101", model:"0102", deviceJoinName: "Enerwave On/Off Switch"
fingerprint mfr:"011A", prod:"0101", model:"0603", deviceJoinName: "Enerwave Duplex Receptacle"
}

View File

@@ -20,7 +20,6 @@ metadata {
capability "Refresh"
capability "Sensor"
capability "Health Check"
capability "Light"
fingerprint mfr:"0063", prod:"4952", deviceJoinName: "Z-Wave Wall Switch"
fingerprint mfr:"0063", prod:"5257", deviceJoinName: "Z-Wave Wall Switch"

View File

@@ -0,0 +1,179 @@
/**
* Switch control based on motion/door sensors
*
* Copyright 2017 narges noori
*
* 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.
*
*/
definition(
name: "Switch control based on motion/door sensors",
namespace: "nnoori0527",
author: "narges noori",
description: "This application turns on the outlet if the entrace door opens (multipurpose sensor) and there is motion in front of the motion sensor for a user defined amount of time (say 5 minutes). If there is no activity in front of the motion sensor for a user defined amount of time (say 10 minutes) the outlet is turned off.",
category: "Convenience",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
oauth: [displayName: "Switch/outlet control", displayLink: ""])
preferences {
section ("Allow external service to control these things...") {
input "switches", "capability.switch", multiple: true, required: true
}
section("Turn on when motion detected after someone opens the door:") {
input "motionSensor", "capability.motionSensor", required: true, title: "Where?"
}
section("Turn on when there's movement for:") {
input "minutes", "number", required: true, title: "Minutes to turn on TV?"
}
section("Turn on when there's movement for:") {
input "minutesInactive", "number", required: true, title: "Minutes to wait before turning off TV?"
}
section("Turn on when door open:") {
input "doorOpenCloseDetector", "capability.contactSensor", required: true, title: "Where?"
}
section("Turn on this outlet") {
input "tvOutlet", "capability.switch", required: true
}
}
def installed() {
initialize()
}
def updated() {
unsubscribe()
initialize()
}
def initialize() {
subscribe(doorOpenCloseDetector, "contact.open", doorOpenedHandler)
subscribe(motionSensor, "motion.inactive", motionStoppedHandler)
}
def doorOpenedHandler(evt){
log.debug "doorOpenedHandler called: $evt"
runIn(60 * minutes, checkMotion)
//tvOutlet.on()
}
def checkMotion() {
log.debug "In checkMotion scheduled method"
def motionState = motionSensor.currentState("motion")
if (motionState.value == "active") {
// get the time elapsed between now and when the motion reported inactive
def elapsed = now() - motionState.date.time
// elapsed time is in milliseconds, so the threshold must be converted to milliseconds too
def threshold = 1000 * 60 * minutes
if (elapsed <= threshold) {
log.debug "Motion has stayed active long enough since last check ($elapsed ms): turning outlet on"
//myswitch.on()
tvOutlet.on()
} else {
log.debug "Motion has not stayed active long enough since last check ($elapsed ms): doing nothing"
}
} else {
// Motion active; just log it and do nothing
log.debug "Motion is inactive, do nothing and wait for active"
}
}
def motionStoppedHandler(evt) {
log.debug "motionStoppedHandler called: $evt"
runIn(60 * (minutesInactive+1), checkMotionTurnOff)
}
def checkMotionTurnOff() {
log.debug "In checkMotionTurnOff scheduled method"
def motionState = motionSensor.currentState("motion")
if (motionState.value == "inactive") {
// get the time elapsed between now and when the motion reported inactive
def elapsed = now() - motionState.date.time
// elapsed time is in milliseconds, so the threshold must be converted to milliseconds too
def threshold = 1000 * 60 * minutesInactive
if (elapsed >= threshold) {
log.debug "Motion has stayed inactive long enough since last check ($elapsed ms): turning switch off"
tvOutlet.off()
} else {
log.debug "Motion has not stayed inactive long enough since last check ($elapsed ms): doing nothing"
}
} else {
// Motion active; just log it and do nothing
log.debug "Motion is active, do nothing and wait for inactive"
}
}
mappings {
path("/switches") {
action: [
GET: "listSwitches"
]
}
path("/switches/:command") {
action: [
PUT: "updateSwitches"
]
}
}
// returns a list like
// [[name: "kitchen lamp", value: "off"], [name: "bathroom", value: "on"]]
def listSwitches() {
def resp = []
switches.each {
resp << [name: it.displayName, value: it.currentValue("switch")]
}
return resp
}
void updateSwitches() {
// use the built-in request object to get the command parameter
def command = params.command
// all switches have the comand
// execute the command on all switches
// (note we can do this on the array - the command will be invoked on every element
switch(command) {
case "on":
switches.on()
break
case "off":
switches.off()
break
default:
httpError(400, "$command is not a valid command for all switches specified")
}
}