mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-10 21:03:04 +00:00
Compare commits
1 Commits
staging
...
MSA-2154-1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d14468800 |
427
devicetypes/smartthings/aeon-hemv2.src/aeon-hemv2.groovy
Normal file
427
devicetypes/smartthings/aeon-hemv2.src/aeon-hemv2.groovy
Normal file
@@ -0,0 +1,427 @@
|
||||
/**
|
||||
* Aeon HEMv2
|
||||
*
|
||||
* Copyright 2014 Barry A. Burke
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
* Aeon Home Energy Meter v2 (US)
|
||||
*
|
||||
* Author: Barry A. Burke
|
||||
* Contributors: Brock Haymond: UI updates
|
||||
*
|
||||
* Genesys: Based off of Aeon Smart Meter Code sample provided by SmartThings (2013-05-30). Built on US model
|
||||
* may also work on international versions (currently reports total values only)
|
||||
*
|
||||
* History:
|
||||
*
|
||||
* 2014-06-13: Massive OverHaul
|
||||
* - Fixed Configuration (original had byte order of bitstrings backwards
|
||||
* - Increased reporting frequency to 10s - note that values won't report unless they change
|
||||
* (they will also report if they exceed limits defined in the settings - currently just using
|
||||
* the defaults).
|
||||
* - Added support for Volts & Amps monitoring (was only Power and Energy)
|
||||
* - Added flexible tile display. Currently only used to show High and Low values since last
|
||||
* reset (with time stamps).
|
||||
* - All tiles are attributes, so that their values are preserved when you're not 'watching' the
|
||||
* meter display
|
||||
* - Values are formatted to Strings in zwaveEvent parser so that we don't lose decimal values
|
||||
* in the tile label display conversion
|
||||
* - Updated fingerprint to match Aeon Home Energy Monitor v2 deviceId & clusters
|
||||
* - Added colors for Watts and Amps display
|
||||
* - Changed time format to 24 hour
|
||||
* 2014-06-17: Tile Tweaks
|
||||
* - Reworked "decorations:" - current values are no longer "flat"
|
||||
* - Added colors to current Watts (0-18000) & Amps (0-150)
|
||||
* - Changed all colors to use same blue-green-orange-red as standard ST temperature guages
|
||||
* 2014-06-18: Cost calculations
|
||||
* - Added $/kWh preference
|
||||
* 2014-09-07: Bug fix & Cleanup
|
||||
* - Fixed "Unexpected Error" on Refresh tile - (added Refresh Capability)
|
||||
* - Cleaned up low values - reset to ridiculously high value instead of null
|
||||
* - Added poll() command/capability (just does a refresh)
|
||||
*
|
||||
* 2014-09-19 GUI Tweaks, HEM v1 alterations (from Brock Haymond)
|
||||
* - Reworked all tiles for look, color, text formatting, & readability
|
||||
*/
|
||||
metadata {
|
||||
// Automatically generated. Make future change here.
|
||||
definition (
|
||||
name: "Aeon HEMv2",
|
||||
namespace: "smartthings",
|
||||
category: "Green Living",
|
||||
author: "Barry A. Burke"
|
||||
)
|
||||
{
|
||||
capability "Energy Meter"
|
||||
capability "Power Meter"
|
||||
capability "Configuration"
|
||||
capability "Sensor"
|
||||
capability "Refresh"
|
||||
capability "Polling"
|
||||
capability "Battery"
|
||||
|
||||
attribute "energy", "string"
|
||||
attribute "power", "string"
|
||||
attribute "volts", "string"
|
||||
attribute "amps", "string"
|
||||
|
||||
attribute "energyDisp", "string"
|
||||
attribute "energyOne", "string"
|
||||
attribute "energyTwo", "string"
|
||||
|
||||
attribute "powerDisp", "string"
|
||||
attribute "powerOne", "string"
|
||||
attribute "powerTwo", "string"
|
||||
|
||||
attribute "voltsDisp", "string"
|
||||
attribute "voltsOne", "string"
|
||||
attribute "voltsTwo", "string"
|
||||
|
||||
attribute "ampsDisp", "string"
|
||||
attribute "ampsOne", "string"
|
||||
attribute "ampsTwo", "string"
|
||||
|
||||
command "reset"
|
||||
command "configure"
|
||||
|
||||
// v1 fingerprint deviceId: "0x2101", inClusters: " 0x70,0x31,0x72,0x86,0x32,0x80,0x85,0x60"
|
||||
|
||||
fingerprint deviceId: "0x3101", inClusters: "0x70,0x32,0x60,0x85,0x56,0x72,0x86"
|
||||
}
|
||||
|
||||
// simulator metadata
|
||||
simulator {
|
||||
for (int i = 0; i <= 10000; i += 1000) {
|
||||
status "power ${i} W": new physicalgraph.zwave.Zwave().meterV1.meterReport(
|
||||
scaledMeterValue: i, precision: 3, meterType: 33, scale: 2, size: 4).incomingMessage()
|
||||
}
|
||||
for (int i = 0; i <= 100; i += 10) {
|
||||
status "energy ${i} kWh": new physicalgraph.zwave.Zwave().meterV1.meterReport(
|
||||
scaledMeterValue: i, precision: 3, meterType: 33, scale: 0, size: 4).incomingMessage()
|
||||
}
|
||||
// TODO: Add data feeds for Volts and Amps
|
||||
}
|
||||
|
||||
// tile definitions
|
||||
tiles {
|
||||
|
||||
// Watts row
|
||||
|
||||
valueTile("powerDisp", "device.powerDisp") {
|
||||
state (
|
||||
"default",
|
||||
label:'${currentValue}',
|
||||
foregroundColors:[
|
||||
[value: 1, color: "#000000"],
|
||||
[value: 10000, color: "#ffffff"]
|
||||
],
|
||||
foregroundColor: "#000000",
|
||||
backgroundColors:[
|
||||
[value: "0 Watts", color: "#153591"],
|
||||
[value: "500 Watts", color: "#1e9cbb"],
|
||||
[value: "1000 Watts", color: "#90d2a7"],
|
||||
[value: "1500 Watts", color: "#44b621"],
|
||||
[value: "2000 Watts", color: "#f1d801"],
|
||||
[value: "2500 Watts", color: "#d04e00"],
|
||||
[value: "3000 Watts", color: "#bc2323"]
|
||||
/*
|
||||
[value: "0 Watts", color: "#153591"],
|
||||
[value: "3000 Watts", color: "#1e9cbb"],
|
||||
[value: "6000 Watts", color: "#90d2a7"],
|
||||
[value: "9000 Watts", color: "#44b621"],
|
||||
[value: "12000 Watts", color: "#f1d801"],
|
||||
[value: "15000 Watts", color: "#d04e00"],
|
||||
[value: "18000 Watts", color: "#bc2323"]
|
||||
*/
|
||||
]
|
||||
)
|
||||
}
|
||||
valueTile("powerOne", "device.powerOne", decoration: "flat") {
|
||||
state("default", label:'${currentValue}')
|
||||
}
|
||||
valueTile("powerTwo", "device.powerTwo", decoration: "flat") {
|
||||
state("default", label:'${currentValue}')
|
||||
}
|
||||
|
||||
// Power row
|
||||
|
||||
valueTile("energyDisp", "device.energyDisp") {
|
||||
state("default", label: '${currentValue}', backgroundColor:"#ffffff")
|
||||
}
|
||||
valueTile("energyOne", "device.energyOne") {
|
||||
state("default", label: '${currentValue}', backgroundColor:"#ffffff")
|
||||
}
|
||||
valueTile("energyTwo", "device.energyTwo") {
|
||||
state("default", label: '${currentValue}', backgroundColor:"#ffffff")
|
||||
}
|
||||
|
||||
|
||||
// Volts row
|
||||
|
||||
valueTile("voltsDisp", "device.voltsDisp") {
|
||||
state "default", label: '${currentValue}', backgroundColors:[
|
||||
[value: "115.6 Volts", color: "#bc2323"],
|
||||
[value: "117.8 Volts", color: "#D04E00"],
|
||||
[value: "120.0 Volts", color: "#44B621"],
|
||||
[value: "122.2 Volts", color: "#D04E00"],
|
||||
[value: "124.4 Volts", color: "#bc2323"]
|
||||
]
|
||||
}
|
||||
valueTile("voltsOne", "device.voltsOne", decoration: "flat") {
|
||||
state "default", label:'${currentValue}'
|
||||
}
|
||||
valueTile("voltsTwo", "device.voltsTwo", decoration: "flat") {
|
||||
state "default", label:'${currentValue}'
|
||||
}
|
||||
|
||||
// Amps row
|
||||
|
||||
valueTile("ampsDisp", "device.ampsDisp") {
|
||||
state "default", label: '${currentValue}' , foregroundColor: "#000000", color: "#000000", backgroundColors:[
|
||||
[value: "0 Amps", color: "#153591"],
|
||||
[value: "25 Amps", color: "#1e9cbb"],
|
||||
[value: "50 Amps", color: "#90d2a7"],
|
||||
[value: "75 Amps", color: "#44b621"],
|
||||
[value: "100 Amps", color: "#f1d801"],
|
||||
[value: "125 Amps", color: "#d04e00"],
|
||||
[value: "150 Amps", color: "#bc2323"]
|
||||
]
|
||||
}
|
||||
valueTile("ampsOne", "device.ampsOne", decoration: "flat") {
|
||||
state "default", label:'${currentValue}'
|
||||
}
|
||||
valueTile("ampsTwo", "device.ampsTwo", decoration: "flat") {
|
||||
state "default", label:'${currentValue}'
|
||||
}
|
||||
|
||||
// Controls row
|
||||
|
||||
standardTile("reset", "device.energy", inactiveLabel: false) {
|
||||
state "default", label:'reset', action:"reset", icon: "st.Health & Wellness.health7"
|
||||
}
|
||||
standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat" ) {
|
||||
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
|
||||
}
|
||||
standardTile("configure", "device.power", inactiveLabel: false, decoration: "flat") {
|
||||
state "configure", label:'', action:"configure", icon:"st.secondary.configure"
|
||||
}
|
||||
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
|
||||
state "battery", label:'${currentValue}% battery', unit:""
|
||||
}
|
||||
|
||||
|
||||
// TODO: Add configurable delay button - Cycle through 10s, 30s, 1m, 5m, 60m, off?
|
||||
|
||||
main (["powerDisp","energyDisp","ampsDisp","voltsDisp"])
|
||||
details([
|
||||
"energyOne","energyDisp","energyTwo",
|
||||
"powerOne","powerDisp","powerTwo",
|
||||
//"ampsOne","ampsDisp","ampsTwo", // Comment out these two lines for HEMv!
|
||||
//"voltsOne","voltsDisp","voltsTwo", // Comment out these two lines for HEMv1
|
||||
"reset","refresh", "battery", "configure"
|
||||
])
|
||||
}
|
||||
preferences {
|
||||
input "kWhCost", "string", title: "\$/kWh (0.16)", defaultValue: "0.16" as String
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def parse(String description) {
|
||||
// log.debug "Parse received ${description}"
|
||||
def result = null
|
||||
def cmd = zwave.parse(description, [0x31: 1, 0x32: 1, 0x60: 3])
|
||||
if (cmd) {
|
||||
result = createEvent(zwaveEvent(cmd))
|
||||
}
|
||||
if (result) log.debug "Parse returned ${result}"
|
||||
return result
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.meterv1.MeterReport cmd) {
|
||||
// log.debug "zwaveEvent received ${cmd}"
|
||||
|
||||
def dispValue
|
||||
def newValue
|
||||
def timeString = new Date().format("h:mm a", location.timeZone)
|
||||
|
||||
if (cmd.meterType == 33) {
|
||||
if (cmd.scale == 0) {
|
||||
newValue = cmd.scaledMeterValue
|
||||
if (newValue != state.energyValue) {
|
||||
dispValue = String.format("%5.2f",newValue)+"\nkWh"
|
||||
sendEvent(name: "energyDisp", value: dispValue as String, unit: "")
|
||||
state.energyValue = newValue
|
||||
BigDecimal costDecimal = newValue * ( kWhCost as BigDecimal)
|
||||
def costDisplay = String.format("%3.2f",costDecimal)
|
||||
sendEvent(name: "energyTwo", value: "Cost\n\$${costDisplay}", unit: "")
|
||||
[name: "energy", value: newValue, unit: "kWh"]
|
||||
}
|
||||
} else if (cmd.scale == 1) {
|
||||
newValue = cmd.scaledMeterValue
|
||||
if (newValue != state.energyValue) {
|
||||
dispValue = String.format("%5.2f",newValue)+"\nkVAh"
|
||||
sendEvent(name: "energyDisp", value: dispValue as String, unit: "")
|
||||
state.energyValue = newValue
|
||||
[name: "energy", value: newValue, unit: "kVAh"]
|
||||
}
|
||||
}
|
||||
else if (cmd.scale==2) {
|
||||
newValue = Math.round( cmd.scaledMeterValue ) // really not worth the hassle to show decimals for Watts
|
||||
if (newValue != state.powerValue) {
|
||||
dispValue = newValue+"\nWatts"
|
||||
sendEvent(name: "powerDisp", value: dispValue as String, unit: "")
|
||||
|
||||
if (newValue < state.powerLow) {
|
||||
dispValue = "Low\n"+newValue+" W\n"+timeString
|
||||
sendEvent(name: "powerOne", value: dispValue as String, unit: "")
|
||||
state.powerLow = newValue
|
||||
}
|
||||
if (newValue > state.powerHigh) {
|
||||
dispValue = "High\n"+newValue+" W\n"+timeString
|
||||
sendEvent(name: "powerTwo", value: dispValue as String, unit: "")
|
||||
state.powerHigh = newValue
|
||||
}
|
||||
state.powerValue = newValue
|
||||
[name: "power", value: newValue, unit: "W"]
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (cmd.meterType == 161) {
|
||||
if (cmd.scale == 0) {
|
||||
newValue = cmd.scaledMeterValue
|
||||
if (newValue != state.voltsValue) {
|
||||
dispValue = String.format("%5.2f", newValue)+"\nVolts"
|
||||
sendEvent(name: "voltsDisp", value: dispValue as String, unit: "")
|
||||
|
||||
if (newValue < state.voltsLow) {
|
||||
dispValue = "Low\n"+String.format("%5.2f", newValue)+" V\n"+timeString
|
||||
sendEvent(name: "voltsOne", value: dispValue as String, unit: "")
|
||||
state.voltsLow = newValue
|
||||
}
|
||||
if (newValue > state.voltsHigh) {
|
||||
dispValue = "High\n"+String.format("%5.2f", newValue)+" V\n"+timeString
|
||||
sendEvent(name: "voltsTwo", value: dispValue as String, unit: "")
|
||||
state.voltsHigh = newValue
|
||||
}
|
||||
state.voltsValue = newValue
|
||||
[name: "volts", value: newValue, unit: "V"]
|
||||
}
|
||||
}
|
||||
else if (cmd.scale==1) {
|
||||
newValue = cmd.scaledMeterValue
|
||||
if (newValue != state.ampsValue) {
|
||||
dispValue = String.format("%5.2f", newValue)+"\nAmps"
|
||||
sendEvent(name: "ampsDisp", value: dispValue as String, unit: "")
|
||||
|
||||
if (newValue < state.ampsLow) {
|
||||
dispValue = "Low\n"+String.format("%5.2f", newValue)+" A\n"+timeString
|
||||
sendEvent(name: "ampsOne", value: dispValue as String, unit: "")
|
||||
state.ampsLow = newValue
|
||||
}
|
||||
if (newValue > state.ampsHigh) {
|
||||
dispValue = "High\n"+String.format("%5.2f", newValue)+" A\n"+timeString
|
||||
sendEvent(name: "ampsTwo", value: dispValue as String, unit: "")
|
||||
state.ampsHigh = newValue
|
||||
}
|
||||
state.ampsValue = newValue
|
||||
[name: "amps", value: newValue, unit: "A"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
|
||||
def map = [:]
|
||||
map.name = "battery"
|
||||
map.unit = "%"
|
||||
if (cmd.batteryLevel == 0xFF) {
|
||||
map.value = 1
|
||||
map.descriptionText = "${device.displayName} has a low battery"
|
||||
map.isStateChange = true
|
||||
} else {
|
||||
map.value = cmd.batteryLevel
|
||||
}
|
||||
log.debug map
|
||||
return map
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.Command cmd) {
|
||||
// Handles all Z-Wave commands we aren't interested in
|
||||
log.debug "Unhandled event ${cmd}"
|
||||
[:]
|
||||
}
|
||||
|
||||
def refresh() {
|
||||
delayBetween([
|
||||
zwave.meterV2.meterGet(scale: 0).format(),
|
||||
zwave.meterV2.meterGet(scale: 2).format()
|
||||
])
|
||||
}
|
||||
|
||||
def poll() {
|
||||
refresh()
|
||||
}
|
||||
|
||||
def reset() {
|
||||
log.debug "${device.name} reset"
|
||||
|
||||
state.powerHigh = 0
|
||||
state.powerLow = 99999
|
||||
state.ampsHigh = 0
|
||||
state.ampsLow = 999
|
||||
state.voltsHigh = 0
|
||||
state.voltsLow = 999
|
||||
|
||||
def dateString = new Date().format("m/d/YY", location.timeZone)
|
||||
def timeString = new Date().format("h:mm a", location.timeZone)
|
||||
sendEvent(name: "energyOne", value: "Since\n"+dateString+"\n"+timeString, unit: "")
|
||||
sendEvent(name: "powerOne", value: "", unit: "")
|
||||
sendEvent(name: "voltsOne", value: "", unit: "")
|
||||
sendEvent(name: "ampsOne", value: "", unit: "")
|
||||
sendEvent(name: "ampsDisp", value: "", unit: "")
|
||||
sendEvent(name: "voltsDisp", value: "", unit: "")
|
||||
sendEvent(name: "powerDisp", value: "", unit: "")
|
||||
sendEvent(name: "energyDisp", value: "", unit: "")
|
||||
sendEvent(name: "energyTwo", value: "Cost\n--", unit: "")
|
||||
sendEvent(name: "powerTwo", value: "", unit: "")
|
||||
sendEvent(name: "voltsTwo", value: "", unit: "")
|
||||
sendEvent(name: "ampsTwo", value: "", unit: "")
|
||||
|
||||
// No V1 available
|
||||
def cmd = delayBetween( [
|
||||
zwave.meterV2.meterReset().format(),
|
||||
zwave.meterV2.meterGet(scale: 0).format()
|
||||
])
|
||||
|
||||
cmd
|
||||
}
|
||||
|
||||
def configure() {
|
||||
// TODO: Turn on reporting for each leg of power - display as alternate view (Currently those values are
|
||||
// returned as zwaveEvents...they probably aren't implemented in the core Meter device yet.
|
||||
|
||||
def cmd = delayBetween([
|
||||
zwave.configurationV1.configurationSet(parameterNumber: 3, size: 1, scaledConfigurationValue: 1).format(), // Enable selective reporting
|
||||
zwave.configurationV1.configurationSet(parameterNumber: 4, size: 2, scaledConfigurationValue: 50).format(), // Don't send unless watts have increased by 50
|
||||
zwave.configurationV1.configurationSet(parameterNumber: 8, size: 2, scaledConfigurationValue: 10).format(), // Or by 10% (these 3 are the default values
|
||||
zwave.configurationV1.configurationSet(parameterNumber: 101, size: 4, scaledConfigurationValue: 10).format(), // Average Watts & Amps
|
||||
zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: 30).format(), // Every 30 Seconds
|
||||
zwave.configurationV1.configurationSet(parameterNumber: 102, size: 4, scaledConfigurationValue: 4).format(), // Average Voltage
|
||||
zwave.configurationV1.configurationSet(parameterNumber: 112, size: 4, scaledConfigurationValue: 150).format(), // every 2.5 minute
|
||||
zwave.configurationV1.configurationSet(parameterNumber: 103, size: 4, scaledConfigurationValue: 1).format(), // Total kWh (cumulative)
|
||||
zwave.configurationV1.configurationSet(parameterNumber: 113, size: 4, scaledConfigurationValue: 300).format() // every 5 minutes
|
||||
])
|
||||
log.debug cmd
|
||||
|
||||
cmd
|
||||
}
|
||||
@@ -18,7 +18,6 @@ metadata {
|
||||
command "raiseHeatingSetpoint"
|
||||
command "lowerCoolSetpoint"
|
||||
command "raiseCoolSetpoint"
|
||||
command "poll"
|
||||
|
||||
fingerprint deviceId: "0x08", inClusters: "0x43,0x40,0x44,0x31,0x80,0x85,0x60"
|
||||
fingerprint mfr:"0098", prod:"6401", model:"0107", deviceJoinName: "2Gig CT100 Programmable Thermostat"
|
||||
@@ -102,8 +101,9 @@ metadata {
|
||||
|
||||
def installed() {
|
||||
// Configure device
|
||||
def cmds = [new physicalgraph.device.HubAction(zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:[zwaveHubNodeId]).format()),
|
||||
new physicalgraph.device.HubAction(zwave.manufacturerSpecificV2.manufacturerSpecificGet().format())]
|
||||
def cmds = []
|
||||
cmds << new physicalgraph.device.HubAction(zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:[zwaveHubNodeId]).format())
|
||||
cmds << new physicalgraph.device.HubAction(zwave.manufacturerSpecificV2.manufacturerSpecificGet().format())
|
||||
sendHubCommand(cmds)
|
||||
runIn(3, "initialize", [overwrite: true]) // Allow configure command to be sent and acknowledged before proceeding
|
||||
}
|
||||
@@ -123,7 +123,7 @@ def initialize() {
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
// Poll device for additional data that will be updated by refresh tile
|
||||
pollDevice()
|
||||
poll()
|
||||
}
|
||||
|
||||
def parse(String description)
|
||||
@@ -150,6 +150,7 @@ def parse(String description)
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.multichannelv3.MultiInstanceCmdEncap cmd) {
|
||||
def encapsulatedCommand = cmd.encapsulatedCommand([0x31: 3])
|
||||
log.debug ("multiinstancev1.MultiInstanceCmdEncap: command from instance ${cmd.instance}: ${encapsulatedCommand}")
|
||||
if (encapsulatedCommand) {
|
||||
zwaveEvent(encapsulatedCommand)
|
||||
}
|
||||
@@ -340,7 +341,7 @@ def zwaveEvent(physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeSuppo
|
||||
if(cmd.auxiliaryemergencyHeat) { supportedModes << "emergency heat" }
|
||||
|
||||
state.supportedModes = supportedModes
|
||||
sendEvent(name: "supportedThermostatModes", value: supportedModes, displayed: false)
|
||||
sendEvent(name: "supportedThermostatModes", value: supportedModes, isStateChange: true, displayed: false)
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanModeSupportedReport cmd) {
|
||||
@@ -350,7 +351,7 @@ def zwaveEvent(physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanMod
|
||||
if(cmd.circulation) { supportedFanModes << "circulate" }
|
||||
|
||||
state.supportedFanModes = supportedFanModes
|
||||
sendEvent(name: "supportedThermostatFanModes", value: supportedFanModes, displayed: false)
|
||||
sendEvent(name: "supportedThermostatFanModes", value: supportedFanModes, isStateChange: true, displayed: false)
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
|
||||
@@ -376,6 +377,7 @@ def zwaveEvent(physicalgraph.zwave.Command cmd) {
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
|
||||
log.debug "ManufacturerSpecificReport ${cmd}: value:${cmd}"
|
||||
if (cmd.manufacturerName) {
|
||||
updateDataValue("manufacturer", cmd.manufacturerName)
|
||||
}
|
||||
@@ -387,11 +389,6 @@ def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerS
|
||||
}
|
||||
}
|
||||
|
||||
def poll() {
|
||||
// Call refresh which will cap the polling to once every 2 minutes
|
||||
refresh()
|
||||
}
|
||||
|
||||
def refresh() {
|
||||
// Only allow refresh every 2 minutes to prevent flooding the Zwave network
|
||||
def timeNow = now()
|
||||
@@ -400,11 +397,11 @@ def refresh() {
|
||||
// refresh will request battery, prevent multiple request by setting lastbatt now
|
||||
state.lastbatt = timeNow
|
||||
// use runIn with overwrite to prevent multiple DTH instances run before state.refreshTriggeredAt has been saved
|
||||
runIn(2, "pollDevice", [overwrite: true])
|
||||
runIn(2, "poll", [overwrite: true])
|
||||
}
|
||||
}
|
||||
|
||||
def pollDevice() {
|
||||
def poll() {
|
||||
def cmds = []
|
||||
cmds << new physicalgraph.device.HubAction(zwave.thermostatModeV2.thermostatModeSupportedGet().format())
|
||||
cmds << new physicalgraph.device.HubAction(zwave.thermostatFanModeV3.thermostatFanModeSupportedGet().format())
|
||||
@@ -617,7 +614,7 @@ def updateThermostatSetpoint(setpoint, value) {
|
||||
* */
|
||||
def ping() {
|
||||
log.debug "ping() called"
|
||||
// Just get Operating State as it is not reported when it changes and there's no need to flood more commands
|
||||
// Just get Operating State as it is not reported when it chnages and there's no need to flood more commands
|
||||
sendHubCommand(new physicalgraph.device.HubAction(zwave.thermostatOperatingStateV1.thermostatOperatingStateGet().format()))
|
||||
}
|
||||
|
||||
@@ -627,7 +624,7 @@ def switchMode() {
|
||||
if (supportedModes) {
|
||||
def next = { supportedModes[supportedModes.indexOf(it) + 1] ?: supportedModes[0] }
|
||||
def nextMode = next(currentMode)
|
||||
runIn(2, "setGetThermostatMode", [data: [nextMode: nextMode], overwrite: true])
|
||||
runIn(2, "setThermostatMode", [data: [nextMode: nextMode], overwrite: true])
|
||||
} else {
|
||||
log.warn "supportedModes not defined"
|
||||
getSupportedModes()
|
||||
@@ -638,7 +635,7 @@ def switchToMode(nextMode) {
|
||||
def supportedModes = state.supportedModes
|
||||
if (supportedModes) {
|
||||
if (supportedModes.contains(nextMode)) {
|
||||
runIn(2, "setGetThermostatMode", [data: [nextMode: nextMode], overwrite: true])
|
||||
runIn(2, "setThermostatMode", [data: [nextMode: nextMode], overwrite: true])
|
||||
} else {
|
||||
log.debug("ThermostatMode $nextMode is not supported by ${device.displayName}")
|
||||
}
|
||||
@@ -660,7 +657,7 @@ def switchFanMode() {
|
||||
if (supportedFanModes) {
|
||||
def next = { supportedFanModes[supportedFanModes.indexOf(it) + 1] ?: supportedFanModes[0] }
|
||||
def nextMode = next(currentMode)
|
||||
runIn(2, "setGetThermostatFanMode", [data: [nextMode: nextMode], overwrite: true])
|
||||
runIn(2, "setThermostatFanMode", [data: [nextMode: nextMode], overwrite: true])
|
||||
} else {
|
||||
log.warn "supportedFanModes not defined"
|
||||
getSupportedFanModes()
|
||||
@@ -671,7 +668,7 @@ def switchToFanMode(nextMode) {
|
||||
def supportedFanModes = state.supportedFanModes
|
||||
if (supportedFanModes) {
|
||||
if (supportedFanModes.contains(nextMode)) {
|
||||
runIn(2, "setGetThermostatFanMode", [data: [nextMode: nextMode], overwrite: true])
|
||||
runIn(2, "setThermostatFanMode", [data: [nextMode: nextMode], overwrite: true])
|
||||
} else {
|
||||
log.debug("FanMode $nextMode is not supported by ${device.displayName}")
|
||||
}
|
||||
@@ -682,7 +679,8 @@ def switchToFanMode(nextMode) {
|
||||
}
|
||||
|
||||
def getSupportedFanModes() {
|
||||
def cmds = [new physicalgraph.device.HubAction(zwave.thermostatFanModeV3.thermostatFanModeSupportedGet().format())]
|
||||
def cmds = []
|
||||
cmds << new physicalgraph.device.HubAction(zwave.thermostatFanModeV3.thermostatFanModeSupportedGet().format())
|
||||
sendHubCommand(cmds)
|
||||
}
|
||||
|
||||
@@ -698,9 +696,10 @@ def setThermostatMode(String value) {
|
||||
switchToMode(value)
|
||||
}
|
||||
|
||||
def setGetThermostatMode(data) {
|
||||
def cmds = [new physicalgraph.device.HubAction(zwave.thermostatModeV2.thermostatModeSet(mode: modeMap[data.nextMode]).format()),
|
||||
new physicalgraph.device.HubAction(zwave.thermostatModeV2.thermostatModeGet().format())]
|
||||
def setThermostatMode(data) {
|
||||
def cmds = []
|
||||
cmds << new physicalgraph.device.HubAction(zwave.thermostatModeV2.thermostatModeSet(mode: modeMap[data.nextMode]).format())
|
||||
cmds << new physicalgraph.device.HubAction(zwave.thermostatModeV2.thermostatModeGet().format())
|
||||
sendHubCommand(cmds)
|
||||
}
|
||||
|
||||
@@ -714,9 +713,10 @@ def setThermostatFanMode(String value) {
|
||||
switchToFanMode(value)
|
||||
}
|
||||
|
||||
def setGetThermostatFanMode(data) {
|
||||
def cmds = [new physicalgraph.device.HubAction(zwave.thermostatFanModeV3.thermostatFanModeSet(fanMode: fanModeMap[data.nextMode]).format()),
|
||||
new physicalgraph.device.HubAction(zwave.thermostatFanModeV3.thermostatFanModeGet().format())]
|
||||
def setThermostatFanMode(data) {
|
||||
def cmds = []
|
||||
cmds << new physicalgraph.device.HubAction(zwave.thermostatFanModeV3.thermostatFanModeSet(fanMode: fanModeMap[data.nextMode]).format())
|
||||
cmds << new physicalgraph.device.HubAction(zwave.thermostatFanModeV3.thermostatFanModeGet().format())
|
||||
sendHubCommand(cmds)
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ metadata {
|
||||
command "raiseHeatingSetpoint"
|
||||
command "lowerCoolSetpoint"
|
||||
command "raiseCoolSetpoint"
|
||||
command "poll"
|
||||
|
||||
fingerprint deviceId: "0x08"
|
||||
fingerprint inClusters: "0x43,0x40,0x44,0x31"
|
||||
@@ -92,7 +91,7 @@ metadata {
|
||||
standardTile("raiseCoolSetpoint", "device.heatingSetpoint", width:2, height:1, inactiveLabel: false, decoration: "flat") {
|
||||
state "heatingSetpoint", action:"raiseCoolSetpoint", icon:"st.thermostat.thermostat-right"
|
||||
}
|
||||
standardTile("thermostatOperatingState", "device.thermostatOperatingState", width: 2, height:1, decoration: "flat") {
|
||||
valueTile("thermostatOperatingState", "device.thermostatOperatingState", width: 2, height:1, decoration: "flat") {
|
||||
state "thermostatOperatingState", label:'${currentValue}', backgroundColor:"#ffffff"
|
||||
}
|
||||
standardTile("refresh", "device.thermostatMode", width:2, height:1, inactiveLabel: false, decoration: "flat") {
|
||||
@@ -106,8 +105,9 @@ metadata {
|
||||
|
||||
def installed() {
|
||||
// Configure device
|
||||
def cmds = [new physicalgraph.device.HubAction(zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:[zwaveHubNodeId]).format()),
|
||||
new physicalgraph.device.HubAction(zwave.manufacturerSpecificV2.manufacturerSpecificGet().format())]
|
||||
def cmds = []
|
||||
cmds << new physicalgraph.device.HubAction(zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:[zwaveHubNodeId]).format())
|
||||
cmds << new physicalgraph.device.HubAction(zwave.manufacturerSpecificV2.manufacturerSpecificGet().format())
|
||||
sendHubCommand(cmds)
|
||||
runIn(3, "initialize", [overwrite: true]) // Allow configure command to be sent and acknowledged before proceeding
|
||||
}
|
||||
@@ -129,7 +129,7 @@ def initialize() {
|
||||
if (getDataValue("manufacturer") != "Honeywell") {
|
||||
runEvery5Minutes("poll") // This is not necessary for Honeywell Z-wave, but could be for other Z-wave thermostats
|
||||
}
|
||||
pollDevice()
|
||||
poll()
|
||||
}
|
||||
|
||||
def parse(String description)
|
||||
@@ -319,22 +319,17 @@ def zwaveEvent(physicalgraph.zwave.Command cmd) {
|
||||
}
|
||||
|
||||
// Command Implementations
|
||||
def poll() {
|
||||
// Call refresh which will cap the polling to once every 2 minutes
|
||||
refresh()
|
||||
}
|
||||
|
||||
def refresh() {
|
||||
// Only allow refresh every 2 minutes to prevent flooding the Zwave network
|
||||
def timeNow = now()
|
||||
if (!state.refreshTriggeredAt || (2 * 60 * 1000 < (timeNow - state.refreshTriggeredAt))) {
|
||||
state.refreshTriggeredAt = timeNow
|
||||
// use runIn with overwrite to prevent multiple DTH instances run before state.refreshTriggeredAt has been saved
|
||||
runIn(2, "pollDevice", [overwrite: true])
|
||||
runIn(2, "poll", [overwrite: true])
|
||||
}
|
||||
}
|
||||
|
||||
def pollDevice() {
|
||||
def poll() {
|
||||
def cmds = []
|
||||
cmds << new physicalgraph.device.HubAction(zwave.thermostatModeV2.thermostatModeSupportedGet().format())
|
||||
cmds << new physicalgraph.device.HubAction(zwave.thermostatFanModeV3.thermostatFanModeSupportedGet().format())
|
||||
@@ -510,7 +505,7 @@ def switchMode() {
|
||||
if (supportedModes) {
|
||||
def next = { supportedModes[supportedModes.indexOf(it) + 1] ?: supportedModes[0] }
|
||||
def nextMode = next(currentMode)
|
||||
runIn(2, "setGetThermostatMode", [data: [nextMode: nextMode], overwrite: true])
|
||||
runIn(2, "setThermostatMode", [data: [nextMode: nextMode], overwrite: true])
|
||||
} else {
|
||||
log.warn "supportedModes not defined"
|
||||
getSupportedModes()
|
||||
@@ -521,7 +516,7 @@ def switchToMode(nextMode) {
|
||||
def supportedModes = state.supportedModes
|
||||
if (supportedModes) {
|
||||
if (supportedModes.contains(nextMode)) {
|
||||
runIn(2, "setGetThermostatMode", [data: [nextMode: nextMode], overwrite: true])
|
||||
runIn(2, "setThermostatMode", [data: [nextMode: nextMode], overwrite: true])
|
||||
} else {
|
||||
log.debug("ThermostatMode $nextMode is not supported by ${device.displayName}")
|
||||
}
|
||||
@@ -543,7 +538,7 @@ def switchFanMode() {
|
||||
if (supportedFanModes) {
|
||||
def next = { supportedFanModes[supportedFanModes.indexOf(it) + 1] ?: supportedFanModes[0] }
|
||||
def nextMode = next(currentMode)
|
||||
runIn(2, "setGetThermostatFanMode", [data: [nextMode: nextMode], overwrite: true])
|
||||
runIn(2, "setThermostatFanMode", [data: [nextMode: nextMode], overwrite: true])
|
||||
} else {
|
||||
log.warn "supportedFanModes not defined"
|
||||
getSupportedFanModes()
|
||||
@@ -554,7 +549,7 @@ def switchToFanMode(nextMode) {
|
||||
def supportedFanModes = state.supportedFanModes
|
||||
if (supportedFanModes) {
|
||||
if (supportedFanModes.contains(nextMode)) {
|
||||
runIn(2, "setGetThermostatFanMode", [data: [nextMode: nextMode], overwrite: true])
|
||||
runIn(2, "setThermostatFanMode", [data: [nextMode: nextMode], overwrite: true])
|
||||
} else {
|
||||
log.debug("FanMode $nextMode is not supported by ${device.displayName}")
|
||||
}
|
||||
@@ -565,7 +560,8 @@ def switchToFanMode(nextMode) {
|
||||
}
|
||||
|
||||
def getSupportedFanModes() {
|
||||
def cmds = [new physicalgraph.device.HubAction(zwave.thermostatFanModeV3.thermostatFanModeSupportedGet().format())]
|
||||
def cmds = []
|
||||
cmds << new physicalgraph.device.HubAction(zwave.thermostatFanModeV3.thermostatFanModeSupportedGet().format())
|
||||
sendHubCommand(cmds)
|
||||
}
|
||||
|
||||
@@ -581,9 +577,10 @@ def setThermostatMode(String value) {
|
||||
switchToMode(value)
|
||||
}
|
||||
|
||||
def setGetThermostatMode(data) {
|
||||
def cmds = [new physicalgraph.device.HubAction(zwave.thermostatModeV2.thermostatModeSet(mode: modeMap[data.nextMode]).format()),
|
||||
new physicalgraph.device.HubAction(zwave.thermostatModeV2.thermostatModeGet().format())]
|
||||
def setThermostatMode(data) {
|
||||
def cmds = []
|
||||
cmds << new physicalgraph.device.HubAction(zwave.thermostatModeV2.thermostatModeSet(mode: modeMap[data.nextMode]).format())
|
||||
cmds << new physicalgraph.device.HubAction(zwave.thermostatModeV2.thermostatModeGet().format())
|
||||
sendHubCommand(cmds)
|
||||
}
|
||||
|
||||
@@ -597,9 +594,10 @@ def setThermostatFanMode(String value) {
|
||||
switchToFanMode(value)
|
||||
}
|
||||
|
||||
def setGetThermostatFanMode(data) {
|
||||
def cmds = [new physicalgraph.device.HubAction(zwave.thermostatFanModeV3.thermostatFanModeSet(fanMode: fanModeMap[data.nextMode]).format()),
|
||||
new physicalgraph.device.HubAction(zwave.thermostatFanModeV3.thermostatFanModeGet().format())]
|
||||
def setThermostatFanMode(data) {
|
||||
def cmds = []
|
||||
cmds << new physicalgraph.device.HubAction(zwave.thermostatFanModeV3.thermostatFanModeSet(fanMode: fanModeMap[data.nextMode]).format())
|
||||
cmds << new physicalgraph.device.HubAction(zwave.thermostatFanModeV3.thermostatFanModeGet().format())
|
||||
sendHubCommand(cmds)
|
||||
}
|
||||
|
||||
@@ -665,7 +663,7 @@ def getTempInDeviceScale(temp, scale) {
|
||||
if (temp && scale) {
|
||||
def deviceScale = (state.scale == 1) ? "F" : "C"
|
||||
return (deviceScale == scale) ? temp :
|
||||
(deviceScale == "F" ? celsiusToFahrenheit(temp).toDouble().round(0).toInteger() : roundC(fahrenheitToCelsius(temp)))
|
||||
(deviceScale == "F" ? celsiusToFahrenheit(temp) : roundC(fahrenheitToCelsius(temp)))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user