Compare commits

..

2 Commits

Author SHA1 Message Date
YANG JR-SHENG
a68e64fb2c Modifying 'SmartApps for Switch' 2017-04-16 23:05:33 -07:00
YANG JR-SHENG
bcb92426ff MSA-1897: Bling's SmartApps for discovery switch 2017-04-16 23:04:19 -07:00
12 changed files with 174 additions and 2916 deletions

View File

@@ -1,426 +0,0 @@
// Express Controls EZMultiPli Multi-sensor
// Motion Sensor - Temperature - Light level - 8 Color Indicator LED - Z-Wave Range Extender - Wall Powered
// driver for SmartThings
// The EZMultiPli is also known as the HSM200 from HomeSeer.com
//
// 2017-04-10 - DrZwave (with help from Don Kirker) - changed fingerprint to the new format, lowered the OnTime
// and other parameters to be "more in line with ST user expectations", get the luminance in LUX so it reports in lux all the time.
// 2016-10-06 - erocm1231 - Added "updated" method to run when configuration options are changed. Depending on model of unit, luminance is being
// reported as a relative percentace or as a lux value. Added the option to configure this in the handler.
// 2016-01-28 - erocm1231 - Changed the configuration method to use scaledConfiguration so that it properly formatted negative numbers.
// Also, added configurationGet and a configurationReport method so that config values can be verified.
// 2015-12-04 - erocm1231 - added range value to preferences as suggested by @Dela-Rick.
// 2015-11-26 - erocm1231 - Fixed null condition error when adding as a new device.
// 2015-11-24 - erocm1231 - Added refresh command. Made a few changes to how the handler maps colors to the LEDs. Fixed
// the device not having its on/off status updated when colors are changed.
// 2015-11-23 - erocm1231 - Changed the look to match SmartThings v2 devices.
// 2015-11-21 - erocm1231 - Made code much more efficient. Also made it compatible when setColor is passed a hex value.
// Mapping of special colors: Soft White - Default - Yellow, White - Concentrate - White,
// Daylight - Energize - Teal, Warm White - Relax - Yellow
// 2015-11-19 - erocm1231 - Fixed a couple incorrect colors, changed setColor to be more compatible with other apps
// 2015-11-18 - erocm1231 - Added to setColor for compatibility with Smart Lighting
// v0.1.0 - DrZWave - chose better icons, Got color LED to work - first fully functional version
// v0.0.9 - jrs - got the temp and luminance to work. Motion works. Debugging the color wheel.
// v0.0.8 - DrZWave 2/25/2015 - change the color control to be tiles since there are only 8 colors.
// v0.0.7 - jrs - 02/23/2015 - Jim Sulin
metadata {
definition (name: "EZmultiPli", namespace: "DrZWave", author: "Eric Ryherd", oauth: true) {
capability "Actuator"
capability "Sensor"
capability "Motion Sensor"
capability "Temperature Measurement"
capability "Illuminance Measurement"
capability "Switch"
capability "Color Control"
capability "Configuration"
capability "Refresh"
fingerprint mfr: "001E", prod: "0004", model: "0001" // new format for Fingerprint which is unique for every certified Z-Wave product
} // end definition
simulator {
// messages the device returns in response to commands it receives
status "motion" : "command: 7105000000FF07, payload: 07"
status "no motion" : "command: 7105000000FF07, payload: 00"
for (int i = 0; i <= 100; i += 20) {
status "temperature ${i}F": new physicalgraph.zwave.Zwave().sensorMultilevelV5.sensorMultilevelReport(
scaledSensorValue: i, precision: 1, sensorType: 1, scale: 1).incomingMessage()
}
for (int i = 0; i <= 100; i += 20) {
status "luminance ${i} %": new physicalgraph.zwave.Zwave().sensorMultilevelV5.sensorMultilevelReport(
scaledSensorValue: i, precision: 0, sensorType: 3).incomingMessage()
}
} //end simulator
tiles (scale: 2){
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL", icon: "st.Lighting.light18") {
attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn"
attributeState "turningOn", label:'${name}', icon:"st.switches.light.on", backgroundColor:"#79b821"
attributeState "turningOff", label:'${name}', icon:"st.switches.light.off", backgroundColor:"#ffffff"
}
tileAttribute ("device.color", key: "COLOR_CONTROL") {
attributeState "color", action:"setColor"
}
tileAttribute ("statusText", key: "SECONDARY_CONTROL") {
attributeState "statusText", label:'${currentValue}'
}
}
standardTile("motion", "device.motion", width: 2, height: 2, canChangeIcon: true, canChangeBackground: true) {
state "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0"
state "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff"
}
valueTile("temperature", "device.temperature", width: 2, height: 2) {
state "temperature", label:'${currentValue}°', unit:"F", icon:"", // would be better if the units would switch to the desired units of the system (imperial or metric)
backgroundColors:[
[value: 0, color: "#1010ff"], // blue=cold
[value: 65, color: "#a0a0f0"],
[value: 70, color: "#e0e050"],
[value: 75, color: "#f0d030"], // yellow
[value: 80, color: "#fbf020"],
[value: 85, color: "#fbdc01"],
[value: 90, color: "#fb3a01"],
[value: 95, color: "#fb0801"] // red=hot
]
}
// icons to use would be st.Weather.weather2 or st.alarm.temperature.normal - see http://scripts.3dgo.net/smartthings/icons/ for a list of icons
valueTile("illuminance", "device.illuminance", width: 2, height: 2, inactiveLabel: false) {
// jrs 4/7/2015 - Null on display
//state "luminosity", label:'${currentValue} ${unit}'
state "luminosity", label:'${currentValue}', unit:'${currentValue}', icon:"",
backgroundColors:[
[value: 25, color: "#404040"],
[value: 50, color: "#808080"],
[value: 75, color: "#a0a0a0"],
[value: 90, color: "#e0e0e0"],
//lux measurement values
[value: 150, color: "#404040"],
[value: 300, color: "#808080"],
[value: 600, color: "#a0a0a0"],
[value: 900, color: "#e0e0e0"]
]
}
standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
}
standardTile("configure", "device.configure", inactiveLabel: false, width: 2, height: 2, decoration: "flat") {
state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
}
main (["temperature","motion", "switch"])
details(["switch", "motion", "temperature", "illuminance", "refresh", "configure"])
} // end tiles
preferences {
input "OnTime", "number", title: "No Motion Interval", description: "N minutes lights stay on after no motion detected [0, 1-127]", range: "0..127", defaultValue: 2, displayDuringSetup: true, required: false
input "OnLevel", "number", title: "Dimmer Onlevel", description: "Dimmer OnLevel for associated node 2 lights [-1, 0, 1-99]", range: "-1..99", defaultValue: -1, displayDuringSetup: true, required: false
input "LiteMin", "number", title: "Luminance Report Frequency", description: "Luminance report sent every N minutes [0-127]", range: "0..127", defaultValue: 6, displayDuringSetup: true, required: false
input "TempMin", "number", title: "Temperature Report Frequency", description: "Temperature report sent every N minutes [0-127]", range: "0..127", defaultValue: 6, displayDuringSetup: true, required: false
input "TempAdj", "number", title: "Temperature Calibration", description: "Adjust temperature up/down N tenths of a degree F [(-127)-(+128)]", range: "-127..128", defaultValue: 0, displayDuringSetup: true, required: false
input("lum", "enum", title:"Illuminance Measurement", description: "Percent or Lux", defaultValue: 2 ,required: false, displayDuringSetup: true, options:
[1:"Percent",
2:"Lux"])
}
} // end metadata
// Parse incoming device messages from device to generate events
def parse(String description){
//log.debug "==> New Zwave Event: ${description}"
def result = []
def cmd = zwave.parse(description, [0x31: 5]) // 0x31=SensorMultilevel which we force to be version 5
if (cmd) {
def cmdData = zwaveEvent(cmd)
if (cmdData != [:])
result << createEvent(cmdData)
}
def statusTextmsg = ""
if (device.currentState('temperature') != null && device.currentState('illuminance') != null) {
statusTextmsg = "${device.currentState('temperature').value} ° - ${device.currentState('illuminance').value} ${(lum == "" || lum == null || lum == 1) ? "%" : "LUX"}"
sendEvent("name":"statusText", "value":statusTextmsg, displayed:false)
}
if (result != [null] && result != []) log.debug "Parse returned ${result}"
return result
}
// Event Generation
def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv5.SensorMultilevelReport cmd){
def map = [:]
switch (cmd.sensorType) {
case 0x01: // SENSOR_TYPE_TEMPERATURE_VERSION_1
def cmdScale = cmd.scale == 1 ? "F" : "C"
map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision)
map.unit = getTemperatureScale()
map.name = "temperature"
log.debug "Temperature report"
break;
case 0x03 : // SENSOR_TYPE_LUMINANCE_VERSION_1
map.value = cmd.scaledSensorValue.toInteger().toString()
if(lum == "" || lum == null || lum == 1) map.unit = "%"
else map.unit = "lux"
map.name = "illuminance"
log.debug "Luminance report"
break;
}
return map
}
def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) {
log.debug "${device.displayName} parameter '${cmd.parameterNumber}' with a byte size of '${cmd.size}' is set to '${cmd.configurationValue}'"
}
def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) {
def map = [:]
if (cmd.notificationType==0x07) { // NOTIFICATION_TYPE_BURGLAR
if (cmd.event==0x07 || cmd.event==0x08) {
map.name = "motion"
map.value = "active"
map.descriptionText = "$device.displayName motion detected"
log.debug "motion recognized"
} else if (cmd.event==0) {
map.name = "motion"
map.value = "inactive"
map.descriptionText = "$device.displayName no motion detected"
log.debug "No motion recognized"
}
}
if (map.name != "motion") {
log.debug "unmatched parameters for cmd: ${cmd.toString()}}"
}
return map
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
if (cmd.value == 0 && device.latestState("color").value != "#ffffff") {
sendEvent(name: "color", value: "#ffffff", displayed: true)
}
[name: "switch", value: cmd.value ? "on" : "off", type: "digital"]
}
def updated()
{
log.debug "updated() is being called"
def cmds = configure()
if (cmds != []) response(cmds)
}
def on() {
log.debug "Turning Light 'on'"
delayBetween([
zwave.basicV1.basicSet(value: 0xFF).format(),
zwave.basicV1.basicGet().format()
], 500)
}
def off() {
log.debug "Turning Light 'off'"
delayBetween([
zwave.basicV1.basicSet(value: 0x00).format(),
zwave.basicV1.basicGet().format()
], 500)
}
def setColor(value) {
log.debug "setColor() : ${value}"
def myred
def mygreen
def myblue
def hexValue
def cmds = []
if ( value.level == 1 && value.saturation > 20) {
def rgb = huesatToRGB(value.hue as Integer, 100)
myred = rgb[0] >=128 ? 255 : 0
mygreen = rgb[1] >=128 ? 255 : 0
myblue = rgb[2] >=128 ? 255 : 0
}
else if ( value.level > 1 ) {
def rgb = huesatToRGB(value.hue as Integer, value.saturation as Integer)
myred = rgb[0] >=128 ? 255 : 0
mygreen = rgb[1] >=128 ? 255 : 0
myblue = rgb[2] >=128 ? 255 : 0
}
else if (value.hex) {
def rgb = value.hex.findAll(/[0-9a-fA-F]{2}/).collect { Integer.parseInt(it, 16) }
myred = rgb[0] >=128 ? 255 : 0
mygreen = rgb[1] >=128 ? 255 : 0
myblue = rgb[2] >=128 ? 255 : 0
}
else {
myred=value.red >=128 ? 255 : 0 // the EZMultiPli has just on/off for each of the 3 channels RGB so convert the 0-255 value into 0 or 255.
mygreen=value.green >=128 ? 255 : 0
myblue=value.blue>=128 ? 255 : 0
}
//log.debug "Red: ${myred} Green: ${mygreen} Blue: ${myblue}"
//cmds << zwave.colorControlV1.stateSet(stateDataLength: 3, VariantGroup1: [0x02, myred], VariantGroup2:[ 0x03, mygreen], VariantGroup3:[0x04,myblue]).format() // ST support for this command as of 2015/02/23 does not support the color IDs so this command cannot be used.
// So instead we'll use these commands to hack around the lack of support of the above command
cmds << zwave.basicV1.basicSet(value: 0x00).format() // As of 2015/02/23 ST is not supporting stateSet properly but found this hack that works.
if (myred!=0) {
cmds << zwave.colorControlV1.startCapabilityLevelChange(capabilityId: 0x02, startState: myred, ignoreStartState: True, updown: True).format()
cmds << zwave.colorControlV1.stopStateChange(capabilityId: 0x02).format()
}
if (mygreen!=0) {
cmds << zwave.colorControlV1.startCapabilityLevelChange(capabilityId: 0x03, startState: mygreen, ignoreStartState: True, updown: True).format()
cmds << zwave.colorControlV1.stopStateChange(capabilityId: 0x03).format()
}
if (myblue!=0) {
cmds << zwave.colorControlV1.startCapabilityLevelChange(capabilityId: 0x04, startState: myblue, ignoreStartState: True, updown: True).format()
cmds << zwave.colorControlV1.stopStateChange(capabilityId: 0x04).format()
}
cmds << zwave.basicV1.basicGet().format()
hexValue = rgbToHex([r:myred, g:mygreen, b:myblue])
if(hexValue) sendEvent(name: "color", value: hexValue, displayed: true)
delayBetween(cmds, 100)
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
// Handles all Z-Wave commands we aren't interested in
[:]
}
// ensure we are passing acceptable param values for LiteMin & TempMin configs
def checkLiteTempInput(value) {
if (value == null) {
value=60
}
def liteTempVal = value.toInteger()
switch (liteTempVal) {
case { it < 0 }:
return 60 // bad value, set to default
break
case { it > 127 }:
return 127 // bad value, greater then MAX, set to MAX
break
default:
return liteTempVal // acceptable value
}
}
// ensure we are passing acceptable param value for OnTime config
def checkOnTimeInput(value) {
if (value == null) {
value=10
}
def onTimeVal = value.toInteger()
switch (onTimeVal) {
case { it < 0 }:
return 10 // bad value set to default
break
case { it > 127 }:
return 127 // bad value, greater then MAX, set to MAX
break
default:
return onTimeVal // acceptable value
}
}
// ensure we are passing acceptable param value for OnLevel config
def checkOnLevelInput(value) {
if (value == null) {
value=99
}
def onLevelVal = value.toInteger()
switch (onLevelVal) {
case { it < -1 }:
return -1 // bad value set to default
break
case { it > 99 }:
return 99 // bad value, greater then MAX, set to MAX
break
default:
return onLevelVal // acceptable value
}
}
// ensure we are passing an acceptable param value for TempAdj configs
def checkTempAdjInput(value) {
if (value == null) {
value=0
}
def tempAdjVal = value.toInteger()
switch (tempAdjVal) {
case { it < -127 }:
return 0 // bad value, set to default
break
case { it > 128 }:
return 128 // bad value, greater then MAX, set to MAX
break
default:
return tempAdjVal // acceptable value
}
}
def refresh() {
def cmd = []
cmd << zwave.switchColorV3.switchColorGet().format()
cmd << zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType:1, scale:1).format()
cmd << zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType:3, scale:1).format()
cmd << zwave.basicV1.basicGet().format()
delayBetween(cmd, 1000)
}
def configure() {
log.debug "OnTime=${settings.OnTime} OnLevel=${settings.OnLevel} TempAdj=${settings.TempAdj}"
def cmd = delayBetween([
zwave.configurationV1.configurationSet(parameterNumber: 1, size: 1, scaledConfigurationValue: checkOnTimeInput(settings.OnTime)).format(),
zwave.configurationV1.configurationSet(parameterNumber: 2, size: 1, scaledConfigurationValue: checkOnLevelInput(settings.OnLevel)).format(),
zwave.configurationV1.configurationSet(parameterNumber: 3, size: 1, scaledConfigurationValue: checkLiteTempInput(settings.LiteMin)).format(),
zwave.configurationV1.configurationSet(parameterNumber: 4, size: 1, scaledConfigurationValue: checkLiteTempInput(settings.TempMin)).format(),
zwave.configurationV1.configurationSet(parameterNumber: 5, size: 1, scaledConfigurationValue: checkTempAdjInput(settings.TempAdj)).format(),
zwave.configurationV1.configurationGet(parameterNumber: 1).format(),
zwave.configurationV1.configurationGet(parameterNumber: 2).format(),
zwave.configurationV1.configurationGet(parameterNumber: 3).format(),
zwave.configurationV1.configurationGet(parameterNumber: 4).format(),
zwave.configurationV1.configurationGet(parameterNumber: 5).format()
], 100)
//log.debug cmd
cmd + refresh()
}
def huesatToRGB(float hue, float sat) {
while(hue >= 100) hue -= 100
int h = (int)(hue / 100 * 6)
float f = hue / 100 * 6 - h
int p = Math.round(255 * (1 - (sat / 100)))
int q = Math.round(255 * (1 - (sat / 100) * f))
int t = Math.round(255 * (1 - (sat / 100) * (1 - f)))
switch (h) {
case 0: return [255, t, p]
case 1: return [q, 255, p]
case 2: return [p, 255, t]
case 3: return [p, q, 255]
case 4: return [t, p, 255]
case 5: return [255, p, q]
}
}
def rgbToHex(rgb) {
def r = hex(rgb.r)
def g = hex(rgb.g)
def b = hex(rgb.b)
def hexColor = "#${r}${g}${b}"
hexColor
}
private hex(value, width=2) {
def s = new BigInteger(Math.round(value).toString()).toString(16)
while (s.size() < width) {
s = "0" + s
}
s
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2017 SmartThings
* 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:
@@ -59,7 +59,7 @@ def updated() {
}
def configure() {
def cmds = zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020) + zigbee.batteryConfig(20, 20, 0x01)
def cmds = zigbee.batteryConfig(20, 20, 0x01)
log.debug "configure -- cmds: ${cmds}"
return cmds
}
@@ -166,4 +166,4 @@ def checkPresenceCallback() {
if (timeSinceLastCheckin >= theCheckInterval) {
handlePresenceEvent(false)
}
}
}

View File

@@ -23,9 +23,9 @@ metadata {
capability "Health Check"
capability "Light"
fingerprint mfr:"0063", prod:"4457", deviceJoinName: "GE In-Wall Smart Dimmer"
fingerprint mfr:"0063", prod:"4944", deviceJoinName: "GE In-Wall Smart Dimmer"
fingerprint mfr:"0063", prod:"5044", deviceJoinName: "GE Plug-In Smart Dimmer"
fingerprint mfr:"0063", prod:"4457", deviceJoinName: "GE In-Wall Smart Dimmer "
fingerprint mfr:"0063", prod:"4944", deviceJoinName: "GE In-Wall Smart Dimmer "
fingerprint mfr:"0063", prod:"5044", deviceJoinName: "GE Plug-In Smart Dimmer "
fingerprint mfr:"0063", prod:"4944", model:"3034", deviceJoinName: "GE In-Wall Smart Fan Control"
}

View File

@@ -114,17 +114,9 @@ def refresh() {
def configure() {
log.debug "Configuring Reporting and Bindings."
def cmds = []
if (device.getDataValue("manufacturer") == "sengled") {
def startLevel = 0xFE
if ((device.currentState("level")?.value != null)) {
startLevel = Math.round(Integer.parseInt(device.currentState("level").value) * 0xFE / 100)
}
// Level Control Cluster, command Move to Level, level start level, transition time 0
cmds << zigbee.command(zigbee.LEVEL_CONTROL_CLUSTER, 0x00, sprintf("%02X0000", startLevel))
}
// 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 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
cmds + refresh()
refresh()
}

View File

@@ -30,9 +30,6 @@ metadata {
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x86,0x72,0x98", outClusters: "0x5A,0x82"
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x80,0x71,0x85,0x70,0x72,0x86,0x30,0x31,0x84,0x59,0x73,0x5A,0x8F,0x98,0x7A", outClusters:"0x20" // Philio multi+
fingerprint mfr:"0086", prod:"0002", model:"001D", deviceJoinName: "Aeon Labs Door/Window Sensor (Gen 5)"
fingerprint mfr:"014A", prod:"0001", model:"0002", deviceJoinName: "Ecolink Door/Window Sensor"
fingerprint mfr:"0086", prod:"0102", model:"0070", deviceJoinName: "Aeon Labs Door/Window Sensor 6"
fingerprint mfr:"011A", prod:"0601", model:"0903", deviceJoinName: "Enerwave Magnetic Door/Window Sensor"
}
// simulator metadata

View File

@@ -22,9 +22,9 @@ metadata {
capability "Health Check"
capability "Light"
fingerprint mfr:"0063", prod:"4952", deviceJoinName: "GE Wall Switch"
fingerprint mfr:"0063", prod:"5257", deviceJoinName: "GE Wall Switch"
fingerprint mfr:"0063", prod:"5052", deviceJoinName: "GE Plug-In Switch"
fingerprint mfr:"0063", prod:"4952", deviceJoinName: "Z-Wave Wall Switch"
fingerprint mfr:"0063", prod:"5257", deviceJoinName: "Z-Wave Wall Switch"
fingerprint mfr:"0063", prod:"5052", deviceJoinName: "Z-Wave Plug-In Switch"
fingerprint mfr:"0113", prod:"5257", deviceJoinName: "Z-Wave Wall Switch"
}

View File

@@ -1,711 +0,0 @@
definition(
name: "app.home.ai",
namespace: "app.home.ai",
author: "Eric Greer",
description: "SmartThings SmartApp for app.home.ai.",
category: "Fun & Social",
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"
)
// These are preferences displayed in the smart phone app
preferences {
// we need a settings section to enable subscriptions
section("Pick which devices home.ai will help you automate:"){
input "motion", "capability.motionSensor", title: "Choose motion sensors", required: false, multiple: true
input "contact", "capability.contactSensor", title: "Choose contact sensors", required: false, multiple: true
input "lightswitch", "capability.switch", title: "Choose normal power switches", required: false, multiple: true
input "lightswitchlevel", "capability.switchLevel", title: "Choose dimmer power switches", required: false, multiple: true
input "presence", "capability.presenceSensor", title: "Choose presence sensors", required: false, multiple: true
// removed in prod until dual-signal devices are supported
//input "tempSensor", "capability.temperatureMeasurement", title: "Choose temperature sensors", required: false, multiple: true
//input "humidity", "capability.relativeHumidityMeasurement", title: "Choose humidity sensors", required: false, multiple: true
input "waterSensor", "capability.waterSensor", title: "Choose water sensors", required: false, multiple: true
input "lock", "capability.lock", title: "Pick Door Locks", required: false, multiple: true
input "garagedoor", "capability.garageDoorControl", title: "Pick garage doors", required: false, multiple: true
input "touchsensor", "capability.touchSensor", title: "Pick touch sensors", required: false, multiple: true
input "speechparser", "capability.speechRecognition", title: "Pick speech recognizers", required: false, multiple: true
input "soundsensor", "capability.soundSensor", title: "Pick sound sensors", required: false, multiple: true
input "smokedetector", "capability.smokeDetector", title: "Pick smoke detectors", required: false, multiple: true
input "sleepsensor", "capability.sleepSensor", title: "Pick sleep sensors", required: false, multiple: true
input "carbonsensor", "capability.carbonMonoxideDetector", title: "Pick carbon monoxide detectors", required: false, multiple: true
input "button", "capability.button", title: "Pick buttons", required: false, multiple: true
input "beacon", "capability.beacon", title: "Pick beacons", required: false, multiple: true
input "alarm", "capability.alarm", title: "Pick alarms", required: false, multiple: true
input "thermostat", "capability.thermostat", title: "Pick thermostats", required: false, multiple: true
input "voltage", "capability.voltageMeasurement", title: "Pick voltage sensors", required: false, multiple: true
input "windowshade", "capability.windowShade", title: "Pick window shades", required: false, multiple: true
input "powermeter", "capability.powerMeter", title: "Pick power meters", required: false, multiple: true
}
}
// vlaues for security system are 'away', 'stay', or 'off'
// off security
def offSecurity() {
sendLocationEvent(
name: "alarmSystemStatus",
value: "off",
displayed: false,
isStateChange: true)
}
// stay security
def staySecurity() {
sendLocationEvent(
name: "alarmSystemStatus",
value: "stay",
displayed: false,
isStateChange: true)
}
// away security
def awaySecurity() {
sendLocationEvent(
name: "alarmSystemStatus",
value: "away",
displayed: false,
isStateChange: true)
}
// sets window shade open temperature
def setWindowShadeOpen() {
def deviceID = params.deviceID
log.debug("setWindowShadeOpen command recieved ${deviceID}")
windowshade.each {
if (it.id == deviceID) {
log.debug("Operating window shade because it is the one specified: ${deviceID}");
it.open()
} else {
log.debug("NOT operting window shade because it is not the one specified: ${deviceID}");
}
}
}
// sets window shade close temperature
def setWindowShadeClosed() {
def deviceID = params.deviceID
log.debug("setWindowShadeClosed command recieved ${deviceID}")
windowshade.each {
if (it.id == deviceID) {
log.debug("Operating window shade because it is the one specified: ${deviceID}");
it.close()
} else {
log.debug("NOT operting window shade because it is not the one specified: ${deviceID}");
}
}
}
// sets thermostat heating temperature
def setThermostatHeatTemp() {
def deviceID = params.deviceID
log.debug("setThermostatHeat command recieved ${deviceID}")
thermostat.each {
if (it.id == deviceID) {
log.debug("Operating thermostat because it is the one specified: ${deviceID}");
it.setHeatingSetpoint(params.temp)
} else {
log.debug("NOT operting thermostat because it is not the one specified: ${deviceID}");
}
}
}
// sets thermostat cooling temperature
def setThermostatCoolTemp() {
def deviceID = params.deviceID
log.debug("setThermostatCool command recieved ${deviceID}")
thermostat.each {
if (it.id == deviceID) {
log.debug("Operating thermostat because it is the one specified: ${deviceID}");
it.setCoolingSetpoint(params.temp)
} else {
log.debug("NOT operting thermostat because it is not the one specified: ${deviceID}");
}
}
}
// sets thermostat off
def setThermostatOff() {
def deviceID = params.deviceID
log.debug("setThermostatOff command recieved ${deviceID}")
thermostat.each {
if (it.id == deviceID) {
log.debug("Operating thermostat because it is the one specified: ${deviceID}");
it.off()
} else {
log.debug("NOT operting thermostat because it is not the one specified: ${deviceID}");
}
}
}
// sets thermostat to heat
def setThermostatHeat() {
def deviceID = params.deviceID
log.debug("setThermostatHeat command recieved ${deviceID}")
thermostat.each {
if (it.id == deviceID) {
log.debug("Operating thermostat because it is the one specified: ${deviceID}");
it.heat()
} else {
log.debug("NOT operting thermostat because it is not the one specified: ${deviceID}");
}
}
}
// sets thermostat to cool
def setThermostatCool() {
def deviceID = params.deviceID
log.debug("setThermostatCool command recieved ${deviceID}")
thermostat.each {
if (it.id == deviceID) {
log.debug("Operating thermostat because it is the one specified: ${deviceID}");
it.cool()
} else {
log.debug("NOT operting thermostat because it is not the one specified: ${deviceID}");
}
}
}
// sets thermostat mode
def setThermostatMode() {
def deviceID = params.deviceID
log.debug("setThermostatMode command recieved ${deviceID}")
thermostat.each {
if (it.id == deviceID) {
log.debug("Operating thermostat because it is the one specified: ${deviceID}");
it.setThermostatMode(params.mode)
} else {
log.debug("NOT operting thermostat because it is not the one specified: ${deviceID}");
}
}
}
// sets thermostat fan mode
def setThermostatFanMode() {
def deviceID = params.deviceID
log.debug("setThermostatFanMode command recieved ${deviceID}")
thermostat.each {
if (it.id == deviceID) {
log.debug("Operating thermostat because it is the one specified: ${deviceID}");
it.setThermostatFanMode(params.mode)
} else {
log.debug("NOT operting thermostat because it is not the one specified: ${deviceID}");
}
}
}
// sends an alarm strobe
def strobeAlarm() {
def deviceID = params.deviceID
log.debug("Alarm strobe command recieved ${deviceID}")
alarm.each {
if (it.id == deviceID) {
log.debug("Operating alarm because it is the one specified: ${deviceID}");
it.strobe()
} else {
log.debug("NOT operting alarm because it is not the one specified: ${deviceID}");
}
}
}
// sends an alarm siren
def sirenAlarm() {
def deviceID = params.deviceID
log.debug("Alarm siren command recieved ${deviceID}")
alarm.each {
if (it.id == deviceID) {
log.debug("Operating alarm because it is the one specified: ${deviceID}");
it.siren()
} else {
log.debug("NOT operting alarm because it is not the one specified: ${deviceID}");
}
}
}
// disables an alarm siren
def silenceAlarm() {
def deviceID = params.deviceID
log.debug("Alarm silence command recieved ${deviceID}")
alarm.each {
if (it.id == deviceID) {
log.debug("Operating alarm because it is the one specified: ${deviceID}");
it.off()
} else {
log.debug("NOT operting alarm because it is not the one specified: ${deviceID}");
}
}
}
// opens a garage door
def openGarage() {
def deviceID = params.deviceID
log.debug("Open Garage command recieved ${deviceID}")
garagedoor.each {
if (it.id == deviceID) {
log.debug("Operating garage door because it is the one specified: ${deviceID}");
it.open()
} else {
log.debug("NOT operting garage door device because it is not the one specified: ${deviceID}");
}
}
}
// closes a garage door
def closeGarage() {
def deviceID = params.deviceID
log.debug("Close Garage command recieved ${deviceID}")
garagedoor.each {
if (it.id == deviceID) {
log.debug("Operating garage door because it is the one specified: ${deviceID}");
it.close()
} else {
log.debug("NOT operting garage door device because it is not the one specified: ${deviceID}");
}
}
}
// lock locks a door lock
def lockDoor() {
def deviceID = params.deviceID
log.debug("Lock command recieved ${deviceID}")
lock.each {
if (it.id == deviceID) {
log.debug("Operating lock device because it is the one specified: ${deviceID}");
it.lock()
} else {
log.debug("NOT operting lock device because it is not the one specified: ${deviceID}");
}
}
}
// unlock unlocks a door lock
def unlockDoor() {
def deviceID = params.deviceID
log.debug("Unlock command recieved ${deviceID}")
lock.each {
if (it.id == deviceID) {
log.debug("Operating lock device because it is the one specified: ${deviceID}");
it.unlock()
} else {
log.debug("NOT operting lock device because it is not the one specified: ${deviceID}");
}
}
}
// turns on a wall switch as instructed from the homeai webservice
def switchOn() {
def deviceID = params.deviceID
log.debug("Switch on command recieved ${deviceID}")
lightswitch.each {
if (it.id == deviceID) {
log.debug("Operating switch device because it is the one specified: ${deviceID}");
it.on()
} else {
log.debug("Skipping switch device because it is not the one specified: ${deviceID}");
}
}
}
// turns off a wall switch as instructed from the homeai webservice
def switchOff() {
def deviceID = params.deviceID
log.debug("Switch off desired for ${deviceID}")
lightswitch.each {
if (it.id == deviceID) {
log.debug("Operating switch device because it is the one specified: ${deviceID}");
it.off()
} else {
log.debug("Skipping switch device because it is not the one specified: ${deviceID}");
}
}
}
// fetch the id of this smartthings hub
def hubId() {
log.debug("hub id requested.")
def response = [hubId: location.hubs.id[0]]
}
// This handles requests for device inventories
def inventory() {
def response = []
lightswitch.each {
response << [name: it.displayName, value: it.currentValue("switch"), deviceId: it.id, type: "lightSwitch"]
}
contact.each {
response << [name: it.displayName, value: it.currentValue("contact"), deviceId: it.id, type: "contact"]
}
motion.each {
response << [name: it.displayName, value: it.currentValue("motion"), deviceId: it.id, type: "motion"]
}
presence.each {
response << [name: it.displayName, value: it.currentValue("presence"), deviceId: it.id, type: "presence"]
}
// removed until dual device functions are supported on the backend
//tempSensor.each {
// response << [name: it.displayName, value: it.currentValue("temperature"), deviceId: it.id, type: "tempSensor"]
//}
//humidity.each {
// response << [name: it.displayName, value: it.currentValue("humidity"), deviceId: it.id, type: "humiditySensor"]
//}
waterSensor.each {
response << [name: it.displayName, value: it.currentValue("water"), deviceId: it.id, type: "waterSensor"]
}
lock.each {
response << [name: it.displayName, value: it.currentValue("lock"), deviceId: it.id, type: "lock"]
}
garagedoor.each {
response << [name: it.displayName, value: it.currentValue("door"), deviceId: it.id, type: "garagedoor"]
}
touchsensor.each {
response << [name: it.displayName, value: it.currentValue("touch"), deviceId: it.id, type: "touchsensor"]
}
speechparser.each {
response << [name: it.displayName, value: it.currentValue("phraseSpoken"), deviceId: it.id, type: "speechparser"]
}
soundsensor.each {
response << [name: it.displayName, value: it.currentValue("sound"), deviceId: it.id, type: "sound"]
}
smokedetector.each {
response << [name: it.displayName, value: it.currentValue("smoke"), deviceId: it.id, type: "smoke"]
}
sleepsensor.each {
response << [name: it.displayName, value: it.currentValue("sleeping"), deviceId: it.id, type: "sleepsensor"]
}
carbonsensor.each {
response << [name: it.displayName, value: it.currentValue("carbonMonoxide"), deviceId: it.id, type: "carbonsensor"]
}
button.each {
response << [name: it.displayName, value: it.currentValue("button"), deviceId: it.id, type: "button"]
}
beacon.each {
response << [name: it.displayName, value: it.currentValue("presence"), deviceId: it.id, type: "beacon"]
}
alarm.each {
response << [name: it.displayName, value: it.currentValue("alarm"), deviceId: it.id, type: "alarm"]
}
thermostat.each {
response << [name: it.displayName, value: it.currentValue("thermostatMode"), deviceId: it.id, type: "thermostat"]
}
voltage.each {
response << [name: it.displayName, value: it.currentValue("voltage"), deviceId: it.id, type: "voltage"]
}
windowshade.each {
response << [name: it.displayName, value: it.currentValue("windowShade"), deviceId: it.id, type: "windowshade"]
}
powermeter.each {
response << [name: it.displayName, value: it.currentValue("power"), deviceId: it.id, type: "powermeter"]
}
lightswitchlevel.each {
response << [name: it.displayName, value: it.currentValue("level"), deviceId: it.id, type: "lightswitchlevel"]
}
log.debug("Inventory request processed. Response: " + response)
return response
}
// After the user hits the 'install' button in the mobile app
def installed() {
initialize()
}
// After app settings are changed. All subscriptions are wiped before this is invoked by smartthings.
def updated() {
unsubscribe()
initialize()
}
// This appears to be what the tutorials meant to use in the examples
def initialize() {
// SHM subscription
// evt.value will be "off", "stay", or "away"
subscribe(location, "alarmSystemStatus", eventForwarder)
// motion sensor subscription
subscribe(motion, "motion", eventForwarder)
// Contact sensor subscription
subscribe(contact, "contact", eventForwarder)
// power plug subscription
subscribe(lightswitch, "switch", eventForwarder)
// presence sensor subscription
subscribe(presence, "presence", eventForwarder)
// temperature sensor subscription
subscribe(tempSensor, "temperature", eventForwarder)
// water sensor subscription
subscribe(waterSensor, "water", eventForwarder)
// humidity sensor subscription
subscribe(humidity, "humidity", eventForwarder)
// lock subscription
subscribe(lock, "lock", eventForwarder)
// garage door subscription
subscribe(garagedoor, "garagedoor", eventForwarder)
// touch sensor subscription
subscribe(touchsensor, "touchsensor", eventForwarder)
// speech parser subscription
subscribe(speechparser, "phraseSpoken", eventForwarder)
// sound sensor subscription
subscribe(soundsensor, "sound", eventForwarder)
// smoke detector subscription
subscribe(smokedetector, "smoke", eventForwarder)
// sleep sensor subscription
subscribe(sleepsensor, "sleeping", eventForwarder)
// carbon monoxide sensor subscription
subscribe(carbonsensor, "carbonMonoxide", eventForwarder)
// button subscription
subscribe(button, "button", eventForwarder)
// beacon subscription
subscribe(beacon, "presence", eventForwarder)
// alarm subscription
subscribe(alarm, "alarm", eventForwarder)
// thermostat subscriptions
subscribe(thermostat, "temperature", eventForwarder)
subscribe(thermostat, "heatingSetpoint", eventForwarder)
subscribe(thermostat, "coolingSetpoint", eventForwarder)
subscribe(thermostat, "thermostatSetpoint", eventForwarder)
subscribe(thermostat, "thermostatMode", eventForwarder)
subscribe(thermostat, "thermostatFanMode", eventForwarder)
subscribe(thermostat, "thermostatOperatingState", eventForwarder)
// voltage subscription
subscribe(voltage, "voltage", eventForwarder)
// window shade subscription
subscribe(windowshade, "windowShade", eventForwarder)
// shm events
subscribe(location, "alarmSystemStatus", shmEventForwarder)
// power meter subscription
subscribe(powermeter, "power", eventForwarder)
// level switch (dimmer switch)
subscribe(lightswitchlevel, "level", eventForwarder)
}
def shmEventForwarder(evt) {
// evt.value will be "off", "stay", or "away"
log.debug("FORWARDING SHM CHANGE" + evt.value + " " + evt.hub.id)
def deviceState = evt.value
def deviceId = "smarthomemonitor"
def hubId = hubId()
def params = [
uri: "https://app.home.ai",
path: "/smartThingsPostback/shmStateChange/${hubId}/${deviceId}/${deviceState}"
]
log.info(params)
httpGet(params)
}
// This is used to forward events to the home.ai webservice
def eventForwarder(evt) {
def hubId = location.hubs.id[0]
log.debug(params.uri + " " + params.path)
log.debug("FORWARDING EVENT" + evt.deviceId + " " + evt.value + " " + hubId)
def deviceId = evt.deviceId
def deviceState = evt.value
def params = [
uri: "https://app.home.ai",
path: "/smartThingsPostback/stateChange/${hubId}/${deviceId}/${deviceState}"
]
log.info(params)
httpGet(params)
}
// Mappings that serve web requests against our smart app
mappings {
path("/inventory") {
action: [
GET: "inventory"
]
}
path("/hubId") {
action: [
GET: "hubId"
]
}
path("/switchOn/:deviceID") {
action: [
GET: "switchOn"
]
}
path("/switchOff/:deviceID") {
action: [
GET: "switchOff"
]
}
path("/lock/:deviceID") {
action: [
GET: "lockDoor"
]
}
path("/unlock/:deviceID") {
action: [
GET: "unlockDoor"
]
}
path("/opengarage/:deviceID") {
action: [
GET: "openGarage"
]
}
path("/closegarage/:deviceID") {
action: [
GET: "closeGarage"
]
}
path("/strobeAlarm/:deviceID") {
action: [
GET: "strobeAlarm"
]
}
path("/sirenAlarm/:deviceID") {
action: [
GET: "sirenAlarm"
]
}
path("/silenceAlarm/:deviceID") {
action: [
GET: "silenceAlarm"
]
}
path("/setThermostatHeatTemp/:deviceID/:temp") {
action: [
GET: "setThermostatHeatTemp"
]
}
path("/setThermostatCoolTemp/:deviceID/:temp") {
action: [
GET: "setThermostatCoolTemp"
]
}
path("/setThermostatHeat/:deviceID") {
action: [
GET: "setThermostatHeat"
]
}
path("/setThermostatCool/:deviceID") {
action: [
GET: "setThermostatCool"
]
}
path("/setThermostatMode/:deviceID/:mode") {
action: [
GET: "setThermostatMode"
]
}
path("/setThermostatFanMode/:deviceID/:mode") {
action: [
GET: "setThermostatFanMode"
]
}
path("/closeWindowShade/:deviceID") {
action: [
GET: "setWindowShadeClosed"
]
}
path("/openWindowShade/:deviceID") {
action: [
GET: "setWindowShadeOpen"
]
}
path("/awaySecurity") {
action: [
GET: "awaySecurity"
]
}
path("/staySecurity") {
action: [
GET: "staySecurity"
]
}
path("/offSecurity") {
action: [
GET: "offSecurity"
]
}
}

View File

@@ -0,0 +1,64 @@
import grails.converters.JSON
/**
* JSON API Access App
*/
definition(
name: "Bling_SmartApps",
namespace: "BlingSmartApps",
author: "Bling",
description: "Return things as JSON",
category: "My Apps",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
oauth: [displayName: "JSON API", displayLink: ""]
)
preferences {
section("Allow these things to be exposed via JSON...") {
input "switches", "capability.switch", title: "Switches", multiple: true, required: true, hideWhenEmpty: true
//input "temperatures", "capability.temperatureMeasurement", title: "Temp Measurements", multiple: true, required: false
//input "contacts", "capability.contactSensor", title: "Open/Closed Devices", multiple: true, required: false
//input "presences", "capability.presenceSensor", title: "Presence Sensors", multiple: true, required: false
//input "motions", "capability.motionSensor", title: "Motion Sensors", multiple: true, required: false
}
}
mappings {
path("/things") {
action: [
GET: "listThings"
]
}
}
def listThings() {
[
switches: switches.collect{device(it,"switch")}
/*
switches: switches.collect{device(it,"switch")},
temperatures: temperatures.collect{device(it,"temperature")},
contacts: contacts.collect{device(it,"contact")},
presences: presences.collect{device(it,"presence")},
motions: motions.collect{device(it,"motion")}
*/
]
}
private device(it, type) {
def device_state = [label:it.label, type:type, id:it.id, devtest:it]
for (attribute in it.supportedAttributes) {
device_state."${attribute}" = it.currentValue("${attribute}")
}
device_state ? device_state : null
}
def installed() {}
def updated() {}

View File

@@ -1,829 +0,0 @@
definition(
name: "demo.home.ai",
namespace: "demo.home.ai",
author: "Eric Greer",
description: "SmartThings demo SmartApp for home.ai.",
category: "Fun & Social",
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"
)
// These are preferences displayed in the smart phone app
preferences {
// we need a settings section to enable subscriptions
section("Pick which devices home.ai will help you automate:"){
input "motion", "capability.motionSensor", title: "Choose motion sensors", required: false, multiple: true
input "contact", "capability.contactSensor", title: "Choose contact sensors", required: false, multiple: true
input "lightswitch", "capability.switch", title: "Choose normal power switches", required: false, multiple: true
input "lightswitchlevel", "capability.switchLevel", title: "Choose dimmer power switches", required: false, multiple: true
input "presence", "capability.presenceSensor", title: "Choose presence sensors", required: false, multiple: true
input "tempSensor", "capability.temperatureMeasurement", title: "Choose temperature sensors", required: false, multiple: true
input "humidity", "capability.relativeHumidityMeasurement", title: "Choose humidity sensors", required: false, multiple: true
input "waterSensor", "capability.waterSensor", title: "Choose water sensors", required: false, multiple: true
input "lock", "capability.lock", title: "Pick Door Locks", required: false, multiple: true
input "garagedoor", "capability.garageDoorControl", title: "Pick garage doors", required: false, multiple: true
input "touchsensor", "capability.touchSensor", title: "Pick touch sensors", required: false, multiple: true
input "speechparser", "capability.speechRecognition", title: "Pick speech recognizers", required: false, multiple: true
input "soundsensor", "capability.soundSensor", title: "Pick sound sensors", required: false, multiple: true
input "smokedetector", "capability.smokeDetector", title: "Pick smoke detectors", required: false, multiple: true
input "sleepsensor", "capability.sleepSensor", title: "Pick sleep sensors", required: false, multiple: true
input "carbonsensor", "capability.carbonMonoxideDetector", title: "Pick carbon monoxide detectors", required: false, multiple: true
input "button", "capability.button", title: "Pick buttons", required: false, multiple: true
input "beacon", "capability.beacon", title: "Pick beacons", required: false, multiple: true
input "alarm", "capability.alarm", title: "Pick alarms", required: false, multiple: true
input "thermostat", "capability.thermostat", title: "Pick thermostats", required: false, multiple: true
input "voltage", "capability.voltageMeasurement", title: "Pick voltage sensors", required: false, multiple: true
input "windowshade", "capability.windowShade", title: "Pick window shades", required: false, multiple: true
input "powermeter", "capability.powerMeter", title: "Pick power meters", required: false, multiple: true
}
}
// vlaues for security system are 'away', 'stay', or 'off'
// off security
def offSecurity() {
sendLocationEvent(
name: "alarmSystemStatus",
value: "off",
displayed: false,
isStateChange: true)
}
// stay security
def staySecurity() {
sendLocationEvent(
name: "alarmSystemStatus",
value: "stay",
displayed: false,
isStateChange: true)
}
// away security
def awaySecurity() {
sendLocationEvent(
name: "alarmSystemStatus",
value: "away",
displayed: false,
isStateChange: true)
}
// sets window shade open temperature
def setWindowShadeOpen() {
def deviceID = params.deviceID
log.debug("setWindowShadeOpen command recieved ${deviceID}")
windowshade.each {
if (it.id == deviceID) {
log.debug("Operating window shade because it is the one specified: ${deviceID}");
it.open()
} else {
log.debug("NOT operting window shade because it is not the one specified: ${deviceID}");
}
}
}
// sets window shade close temperature
def setWindowShadeClosed() {
def deviceID = params.deviceID
log.debug("setWindowShadeClosed command recieved ${deviceID}")
windowshade.each {
if (it.id == deviceID) {
log.debug("Operating window shade because it is the one specified: ${deviceID}");
it.close()
} else {
log.debug("NOT operting window shade because it is not the one specified: ${deviceID}");
}
}
}
// sets thermostat heating temperature
def setThermostatHeatTemp() {
def deviceID = params.deviceID
log.debug("setThermostatHeat command recieved ${deviceID}")
thermostat.each {
if (it.id == deviceID) {
log.debug("Operating thermostat because it is the one specified: ${deviceID}");
it.setHeatingSetpoint(params.temp)
} else {
log.debug("NOT operting thermostat because it is not the one specified: ${deviceID}");
}
}
}
// sets thermostat cooling temperature
def setThermostatCoolTemp() {
def deviceID = params.deviceID
log.debug("setThermostatCool command recieved ${deviceID}")
thermostat.each {
if (it.id == deviceID) {
log.debug("Operating thermostat because it is the one specified: ${deviceID}");
it.setCoolingSetpoint(params.temp)
} else {
log.debug("NOT operting thermostat because it is not the one specified: ${deviceID}");
}
}
}
// sets thermostat off
def setThermostatOff() {
def deviceID = params.deviceID
log.debug("setThermostatOff command recieved ${deviceID}")
thermostat.each {
if (it.id == deviceID) {
log.debug("Operating thermostat because it is the one specified: ${deviceID}");
it.off()
} else {
log.debug("NOT operting thermostat because it is not the one specified: ${deviceID}");
}
}
}
// sets thermostat to heat
def setThermostatHeat() {
def deviceID = params.deviceID
log.debug("setThermostatHeat command recieved ${deviceID}")
thermostat.each {
if (it.id == deviceID) {
log.debug("Operating thermostat because it is the one specified: ${deviceID}");
it.heat()
} else {
log.debug("NOT operting thermostat because it is not the one specified: ${deviceID}");
}
}
}
// sets thermostat to cool
def setThermostatCool() {
def deviceID = params.deviceID
log.debug("setThermostatCool command recieved ${deviceID}")
thermostat.each {
if (it.id == deviceID) {
log.debug("Operating thermostat because it is the one specified: ${deviceID}");
it.cool()
} else {
log.debug("NOT operting thermostat because it is not the one specified: ${deviceID}");
}
}
}
// sets thermostat mode
def setThermostatMode() {
def deviceID = params.deviceID
log.debug("setThermostatMode command recieved ${deviceID}")
thermostat.each {
if (it.id == deviceID) {
log.debug("Operating thermostat because it is the one specified: ${deviceID}");
it.setThermostatMode(params.mode)
} else {
log.debug("NOT operting thermostat because it is not the one specified: ${deviceID}");
}
}
}
// sets thermostat fan mode
def setThermostatFanMode() {
def deviceID = params.deviceID
log.debug("setThermostatFanMode command recieved ${deviceID}")
thermostat.each {
if (it.id == deviceID) {
log.debug("Operating thermostat because it is the one specified: ${deviceID}");
it.setThermostatFanMode(params.mode)
} else {
log.debug("NOT operting thermostat because it is not the one specified: ${deviceID}");
}
}
}
// sends an alarm strobe
def strobeAlarm() {
def deviceID = params.deviceID
log.debug("Alarm strobe command recieved ${deviceID}")
alarm.each {
if (it.id == deviceID) {
log.debug("Operating alarm because it is the one specified: ${deviceID}");
it.strobe()
} else {
log.debug("NOT operting alarm because it is not the one specified: ${deviceID}");
}
}
}
// sends an alarm siren
def sirenAlarm() {
def deviceID = params.deviceID
log.debug("Alarm siren command recieved ${deviceID}")
alarm.each {
if (it.id == deviceID) {
log.debug("Operating alarm because it is the one specified: ${deviceID}");
it.siren()
} else {
log.debug("NOT operting alarm because it is not the one specified: ${deviceID}");
}
}
}
// disables an alarm siren
def silenceAlarm() {
def deviceID = params.deviceID
log.debug("Alarm silence command recieved ${deviceID}")
alarm.each {
if (it.id == deviceID) {
log.debug("Operating alarm because it is the one specified: ${deviceID}");
it.off()
} else {
log.debug("NOT operting alarm because it is not the one specified: ${deviceID}");
}
}
}
// opens a garage door
def openGarage() {
def deviceID = params.deviceID
log.debug("Open Garage command recieved ${deviceID}")
garagedoor.each {
if (it.id == deviceID) {
log.debug("Operating garage door because it is the one specified: ${deviceID}");
it.open()
} else {
log.debug("NOT operting garage door device because it is not the one specified: ${deviceID}");
}
}
}
// closes a garage door
def closeGarage() {
def deviceID = params.deviceID
log.debug("Close Garage command recieved ${deviceID}")
garagedoor.each {
if (it.id == deviceID) {
log.debug("Operating garage door because it is the one specified: ${deviceID}");
it.close()
} else {
log.debug("NOT operting garage door device because it is not the one specified: ${deviceID}");
}
}
}
// lock locks a door lock
def lockDoor() {
def deviceID = params.deviceID
log.debug("Lock command recieved ${deviceID}")
lock.each {
if (it.id == deviceID) {
log.debug("Operating lock device because it is the one specified: ${deviceID}");
it.lock()
} else {
log.debug("NOT operting lock device because it is not the one specified: ${deviceID}");
}
}
}
// unlock unlocks a door lock
def unlockDoor() {
def deviceID = params.deviceID
log.debug("Unlock command recieved ${deviceID}")
lock.each {
if (it.id == deviceID) {
log.debug("Operating lock device because it is the one specified: ${deviceID}");
it.unlock()
} else {
log.debug("NOT operting lock device because it is not the one specified: ${deviceID}");
}
}
}
// turns on a wall switch as instructed from the homeai webservice
def switchOn() {
def deviceID = params.deviceID
log.debug("Switch on command recieved ${deviceID}")
lightswitch.each {
if (it.id == deviceID) {
log.debug("Operating switch device because it is the one specified: ${deviceID}");
it.on()
} else {
log.debug("Skipping switch device because it is not the one specified: ${deviceID}");
}
}
}
// turns off a wall switch as instructed from the homeai webservice
def switchOff() {
def deviceID = params.deviceID
log.debug("Switch off desired for ${deviceID}")
lightswitch.each {
if (it.id == deviceID) {
log.debug("Operating switch device because it is the one specified: ${deviceID}");
it.off()
} else {
log.debug("Skipping switch device because it is not the one specified: ${deviceID}");
}
}
}
// sets a level switch to off
def setLevelSwitch0() {
def deviceID = params.deviceID
log.debug("Level switch off desired for ${deviceID}")
lightswitchlevel.each {
if (it.id == deviceID) {
log.debug("Operating level switch device because it is the one specified: ${deviceID}");
it.setLevel(0)
} else {
log.debug("Skipping level switch device because it is not the one specified: ${deviceID}");
}
}
}
// sets a level switch to 25%
def setLevelSwitch25() {
def deviceID = params.deviceID
log.debug("Level switch 25 desired for ${deviceID}")
lightswitchlevel.each {
if (it.id == deviceID) {
log.debug("Operating level switch device because it is the one specified: ${deviceID}");
it.setLevel(25)
} else {
log.debug("Skipping level switch device because it is not the one specified: ${deviceID}");
}
}
}
// sets a level switch to 50%
def setLevelSwitch50() {
def deviceID = params.deviceID
log.debug("Level switch 50 desired for ${deviceID}")
lightswitchlevel.each {
if (it.id == deviceID) {
log.debug("Operating level switch device because it is the one specified: ${deviceID}");
it.setLevel(50)
} else {
log.debug("Skipping level switch device because it is not the one specified: ${deviceID}");
}
}
}
// sets a level switch to 75%
def setLevelSwitch75() {
def deviceID = params.deviceID
log.debug("Level switch 75 desired for ${deviceID}")
lightswitchlevel.each {
if (it.id == deviceID) {
log.debug("Operating level switch device because it is the one specified: ${deviceID}");
it.setLevel(75)
} else {
log.debug("Skipping level switch device because it is not the one specified: ${deviceID}");
}
}
}
// sets a level switch to 100%
def setLevelSwitch100() {
def deviceID = params.deviceID
log.debug("Level switch 100 desired for ${deviceID}")
lightswitchlevel.each {
if (it.id == deviceID) {
log.debug("Operating level switch device because it is the one specified: ${deviceID}");
it.setLevel(100)
} else {
log.debug("Skipping level switch device because it is not the one specified: ${deviceID}");
}
}
}
// fetch the id of this smartthings hub
def hubId() {
log.debug("hub id requested.")
def response = [hubId: location.hubs.id[0]]
}
// This handles requests for device inventories
def inventory() {
def response = []
lightswitch.each {
response << [name: it.displayName, value: it.currentValue("switch"), deviceId: it.id, type: "lightSwitch"]
}
contact.each {
response << [name: it.displayName, value: it.currentValue("contact"), deviceId: it.id, type: "contact"]
}
motion.each {
response << [name: it.displayName, value: it.currentValue("motion"), deviceId: it.id, type: "motion"]
}
presence.each {
response << [name: it.displayName, value: it.currentValue("presence"), deviceId: it.id, type: "presence"]
}
tempSensor.each {
response << [name: it.displayName, value: it.currentValue("temperature"), deviceId: it.id, type: "tempSensor"]
}
waterSensor.each {
response << [name: it.displayName, value: it.currentValue("water"), deviceId: it.id, type: "waterSensor"]
}
humidity.each {
response << [name: it.displayName, value: it.currentValue("humidity"), deviceId: it.id, type: "humiditySensor"]
}
lock.each {
response << [name: it.displayName, value: it.currentValue("lock"), deviceId: it.id, type: "lock"]
}
garagedoor.each {
response << [name: it.displayName, value: it.currentValue("door"), deviceId: it.id, type: "garagedoor"]
}
touchsensor.each {
response << [name: it.displayName, value: it.currentValue("touch"), deviceId: it.id, type: "touchsensor"]
}
speechparser.each {
response << [name: it.displayName, value: it.currentValue("phraseSpoken"), deviceId: it.id, type: "speechparser"]
}
soundsensor.each {
response << [name: it.displayName, value: it.currentValue("sound"), deviceId: it.id, type: "sound"]
}
smokedetector.each {
response << [name: it.displayName, value: it.currentValue("smoke"), deviceId: it.id, type: "smoke"]
}
sleepsensor.each {
response << [name: it.displayName, value: it.currentValue("sleeping"), deviceId: it.id, type: "sleepsensor"]
}
carbonsensor.each {
response << [name: it.displayName, value: it.currentValue("carbonMonoxide"), deviceId: it.id, type: "carbonsensor"]
}
button.each {
response << [name: it.displayName, value: it.currentValue("button"), deviceId: it.id, type: "button"]
}
beacon.each {
response << [name: it.displayName, value: it.currentValue("presence"), deviceId: it.id, type: "beacon"]
}
alarm.each {
response << [name: it.displayName, value: it.currentValue("alarm"), deviceId: it.id, type: "alarm"]
}
thermostat.each {
response << [name: it.displayName, value: it.currentValue("thermostatMode"), deviceId: it.id, type: "thermostat"]
}
voltage.each {
response << [name: it.displayName, value: it.currentValue("voltage"), deviceId: it.id, type: "voltage"]
}
windowshade.each {
response << [name: it.displayName, value: it.currentValue("windowShade"), deviceId: it.id, type: "windowshade"]
}
powermeter.each {
response << [name: it.displayName, value: it.currentValue("power"), deviceId: it.id, type: "powermeter"]
}
lightswitchlevel.each {
response << [name: it.displayName, value: it.currentValue("level"), deviceId: it.id, type: "lightswitchlevel"]
}
log.debug("Inventory request processed. Response: " + response)
return response
}
// After the user hits the 'install' button in the mobile app
def installed() {
initialize()
}
// After app settings are changed. All subscriptions are wiped before this is invoked by smartthings.
def updated() {
unsubscribe()
initialize()
}
// This appears to be what the tutorials meant to use in the examples
def initialize() {
// motion sensor subscription
subscribe(motion, "motion", eventForwarder)
// Contact sensor subscription
subscribe(contact, "contact", eventForwarder)
// power plug subscription
subscribe(lightswitch, "switch", eventForwarder)
// presence sensor subscription
subscribe(presence, "presence", eventForwarder)
// temperature sensor subscription
subscribe(tempSensor, "temperature", eventForwarder)
// water sensor subscription
subscribe(waterSensor, "water", eventForwarder)
// humidity sensor subscription
subscribe(humidity, "humidity", eventForwarder)
// lock subscription
subscribe(lock, "lock", eventForwarder)
// garage door subscription
subscribe(garagedoor, "garagedoor", eventForwarder)
// touch sensor subscription
subscribe(touchsensor, "touchsensor", eventForwarder)
// speech parser subscription
subscribe(speechparser, "phraseSpoken", eventForwarder)
// sound sensor subscription
subscribe(soundsensor, "sound", eventForwarder)
// smoke detector subscription
subscribe(smokedetector, "smoke", eventForwarder)
// sleep sensor subscription
subscribe(sleepsensor, "sleeping", eventForwarder)
// carbon monoxide sensor subscription
subscribe(carbonsensor, "carbonMonoxide", eventForwarder)
// button subscription
subscribe(button, "button", eventForwarder)
// beacon subscription
subscribe(beacon, "presence", eventForwarder)
// alarm subscription
subscribe(alarm, "alarm", eventForwarder)
// thermostat subscriptions
subscribe(thermostat, "temperature", eventForwarder)
subscribe(thermostat, "heatingSetpoint", eventForwarder)
subscribe(thermostat, "coolingSetpoint", eventForwarder)
subscribe(thermostat, "thermostatSetpoint", eventForwarder)
subscribe(thermostat, "thermostatMode", eventForwarder)
subscribe(thermostat, "thermostatFanMode", eventForwarder)
subscribe(thermostat, "thermostatOperatingState", eventForwarder)
// voltage subscription
subscribe(voltage, "voltage", eventForwarder)
// window shade subscription
subscribe(windowshade, "windowShade", eventForwarder)
// shm events
subscribe(location, "alarmSystemStatus", shmEventForwarder)
// power meter subscription
subscribe(powermeter, "power", eventForwarder)
// level switch (dimmer switch)
subscribe(lightswitchlevel, "level", eventForwarder)
}
// This is used to forward events to the home.ai webservice
def eventForwarder(evt) {
log.debug(params.uri + " " + params.path)
log.debug("FORWARDING EVENT" + evt.deviceId + " " + evt.value + " " + evt.hub.id)
def deviceId = evt.deviceId
def deviceState = evt.value
def hubId = evt.hub.id
def params = [
uri: "https://demo.home.ai",
path: "/smartThingsPostback/stateChange/${hubId}/${deviceId}/${deviceState}"
]
log.info(params)
httpGet(params)
}
// Mappings that serve web requests against our smart app
mappings {
path("/inventory") {
action: [
GET: "inventory"
]
}
path("/hubId") {
action: [
GET: "hubId"
]
}
path("/switchOn/:deviceID") {
action: [
GET: "switchOn"
]
}
path("/switchOff/:deviceID") {
action: [
GET: "switchOff"
]
}
path("/lock/:deviceID") {
action: [
GET: "lockDoor"
]
}
path("/unlock/:deviceID") {
action: [
GET: "unlockDoor"
]
}
path("/opengarage/:deviceID") {
action: [
GET: "openGarage"
]
}
path("/closegarage/:deviceID") {
action: [
GET: "closeGarage"
]
}
path("/strobeAlarm/:deviceID") {
action: [
GET: "strobeAlarm"
]
}
path("/sirenAlarm/:deviceID") {
action: [
GET: "sirenAlarm"
]
}
path("/silenceAlarm/:deviceID") {
action: [
GET: "silenceAlarm"
]
}
path("/setThermostatHeatTemp/:deviceID/:temp") {
action: [
GET: "setThermostatHeatTemp"
]
}
path("/setThermostatCoolTemp/:deviceID/:temp") {
action: [
GET: "setThermostatCoolTemp"
]
}
path("/setThermostatHeat/:deviceID") {
action: [
GET: "setThermostatHeat"
]
}
path("/setThermostatCool/:deviceID") {
action: [
GET: "setThermostatCool"
]
}
path("/setThermostatMode/:deviceID/:mode") {
action: [
GET: "setThermostatMode"
]
}
path("/setThermostatFanMode/:deviceID/:mode") {
action: [
GET: "setThermostatFanMode"
]
}
path("/closeWindowShade/:deviceID") {
action: [
GET: "setWindowShadeClosed"
]
}
path("/openWindowShade/:deviceID") {
action: [
GET: "setWindowShadeOpen"
]
}
// level switch setting endpoints
path("/levelSwitch0/:deviceID") {
action: [
GET: "setLevelSwitch0"
]
}
path("/levelSwitch25/:deviceID") {
action: [
GET: "setLevelSwitch25"
]
}
path("/levelSwitch50/:deviceID") {
action: [
GET: "setLevelSwitch50"
]
}
path("/levelSwitch75/:deviceID") {
action: [
GET: "setLevelSwitch75"
]
}
path("/levelSwitch100/:deviceID") {
action: [
GET: "setLevelSwitch100"
]
}
// Smart home monitor controls
path("/awaySecurity") {
action: [
GET: "awaySecurity"
]
}
path("/staySecurity") {
action: [
GET: "staySecurity"
]
}
path("/offSecurity") {
action: [
GET: "offSecurity"
]
}
}

View File

@@ -52,15 +52,15 @@ definition(
//Device Inputs
preferences {
section("Allow OpenT2T to control these things...") {
input "contactSensors", "capability.contactSensor", title: "Which Contact Sensors", multiple: true, required: false, hideWhenEmpty: true
input "garageDoors", "capability.garageDoorControl", title: "Which Garage Doors?", multiple: true, required: false, hideWhenEmpty: true
input "locks", "capability.lock", title: "Which Locks?", multiple: true, required: false, hideWhenEmpty: true
input "cameras", "capability.videoCapture", title: "Which Cameras?", multiple: true, required: false, hideWhenEmpty: true
input "motionSensors", "capability.motionSensor", title: "Which Motion Sensors?", multiple: true, required: false, hideWhenEmpty: true
input "presenceSensors", "capability.presenceSensor", title: "Which Presence Sensors", multiple: true, required: false, hideWhenEmpty: true
input "switches", "capability.switch", title: "Which Switches and Lights?", multiple: true, required: false, hideWhenEmpty: true
input "thermostats", "capability.thermostat", title: "Which Thermostat?", multiple: true, required: false, hideWhenEmpty: true
input "waterSensors", "capability.waterSensor", title: "Which Water Leak Sensors?", multiple: true, required: false, hideWhenEmpty: true
input "contactSensors", "capability.contactSensor", title: "Which Contact Sensors", multiple: true, required: false
input "garageDoors", "capability.garageDoorControl", title: "Which Garage Doors?", multiple: true, required: false
input "locks", "capability.lock", title: "Which Locks?", multiple: true, required: false
input "cameras", "capability.videoCapture", title: "Which Cameras?", multiple: true, required: false
input "motionSensors", "capability.motionSensor", title: "Which Motion Sensors?", multiple: true, required: false
input "presenceSensors", "capability.presenceSensor", title: "Which Presence Sensors", multiple: true, required: false
input "switches", "capability.switch", title: "Which Switches and Lights?", multiple: true, required: false
input "thermostats", "capability.thermostat", title: "Which Thermostat?", multiple: true, required: false
input "waterSensors", "capability.waterSensor", title: "Which Water Leak Sensors?", multiple: true, required: false
}
}
@@ -80,6 +80,16 @@ def getInputs() {
//API external Endpoints
mappings {
path("/subscriptionURL/:url") {
action: [
PUT: "updateEndpointURL"
]
}
path("/connectionId/:connId") {
action: [
PUT: "updateConnectionId"
]
}
path("/devices") {
action: [
GET: "getDevices"
@@ -95,52 +105,33 @@ mappings {
PUT: "updateDevice"
]
}
path("/deviceSubscription") {
path("/subscription/:id") {
action: [
POST: "registerDeviceChange",
DELETE: "unregisterDeviceChange"
]
}
path("/locationSubscription") {
action: [
POST: "registerDeviceGraph",
DELETE: "unregisterDeviceGraph"
]
}
}
def installed() {
log.debug "Installing with settings: ${settings}"
log.debug "Installed with settings: ${settings}"
initialize()
}
def updated() {
log.debug "Updating with settings: ${settings}"
if(state.deviceSubscriptionMap == null){
state.deviceSubscriptionMap = [:]
log.debug "deviceSubscriptionMap created."
}
if( state.locationSubscriptionMap == null){
state.locationSubscriptionMap = [:]
log.debug "locationSubscriptionMap created."
}
log.debug "Updated with settings: ${settings}"
unsubscribe()
registerAllDeviceSubscriptions()
registerSubscriptions()
}
def initialize() {
log.debug "Initializing with settings: ${settings}"
state.deviceSubscriptionMap = [:]
log.debug "deviceSubscriptionMap created."
registerAllDeviceSubscriptions()
state.locationSubscriptionMap = [:]
log.debug "locationSubscriptionMap created."
state.connectionId = ""
state.endpointURL = "https://ifs.windows-int.com/v1/cb/81C7E77B-EABC-488A-B2BF-FEC42F0DABD2/notify"
registerSubscriptions()
}
/*** Subscription Functions ***/
//Subscribe events for all devices
def registerAllDeviceSubscriptions() {
def registerSubscriptions() {
registerChangeHandler(inputs)
}
@@ -149,195 +140,101 @@ def registerChangeHandler(myList) {
myList.each { myDevice ->
def theAtts = myDevice.supportedAttributes
theAtts.each {att ->
subscribe(myDevice, att.name, deviceEventHandler)
log.info "Registering for ${myDevice.displayName}.${att.name}"
subscribe(myDevice, att.name, eventHandler)
log.info "Registering ${myDevice.displayName}.${att.name}"
}
}
}
//Endpoints function: Subscribe to events from a specific device
def registerDeviceChange() {
def subscriptionEndpt = params.subscriptionURL
def deviceId = params.deviceId
def myDevice = findDevice(deviceId)
if( myDevice == null ){
httpError(404, "Cannot find device with device ID ${deviceId}.")
}
def myDevice = findDevice(params.id)
def theAtts = myDevice.supportedAttributes
try {
theAtts.each {att ->
subscribe(myDevice, att.name, deviceEventHandler)
}
log.info "Subscribing for ${myDevice.displayName}"
if(subscriptionEndpt != null){
if(state.deviceSubscriptionMap[deviceId] == null){
state.deviceSubscriptionMap.put(deviceId, [subscriptionEndpt])
log.info "Added subscription URL: ${subscriptionEndpt} for ${myDevice.displayName}"
} else if (!state.deviceSubscriptionMap[deviceId].contains(subscriptionEndpt)){
state.deviceSubscriptionMap[deviceId] << subscriptionEndpt
log.info "Added subscription URL: ${subscriptionEndpt} for ${myDevice.displayName}"
}
subscribe(myDevice, att.name, eventHandler)
log.info "Registering ${myDevice.displayName}.${att.name}"
}
return ["succeed"]
} catch (e) {
httpError(500, "something went wrong: $e")
}
log.info "Current subscription map is ${state.deviceSubscriptionMap}"
return ["succeed"]
}
//Endpoints function: Unsubscribe to events from a specific device
def unregisterDeviceChange() {
def subscriptionEndpt = params.subscriptionURL
def deviceId = params.deviceId
def myDevice = findDevice(deviceId)
if( myDevice == null ){
httpError(404, "Cannot find device with device ID ${deviceId}.")
}
def myDevice = findDevice(params.id)
try {
if(subscriptionEndpt != null && subscriptionEndpt != "undefined"){
if (state.deviceSubscriptionMap[deviceId]?.contains(subscriptionEndpt)){
if(state.deviceSubscriptionMap[deviceId].size() == 1){
state.deviceSubscriptionMap.remove(deviceId)
} else {
state.deviceSubscriptionMap[deviceId].remove(subscriptionEndpt)
}
log.info "Removed subscription URL: ${subscriptionEndpt} for ${myDevice.displayName}"
}
} else {
state.deviceSubscriptionMap.remove(deviceId)
log.info "Unsubscriping for ${myDevice.displayName}"
}
} catch (e) {
httpError(500, "something went wrong: $e")
}
log.info "Current subscription map is ${state.deviceSubscriptionMap}"
}
//Endpoints function: Subscribe to device additiona/removal updated in a location
def registerDeviceGraph() {
def subscriptionEndpt = params.subscriptionURL
if (subscriptionEndpt != null && subscriptionEndpt != "undefined"){
subscribe(location, "DeviceCreated", locationEventHandler, [filterEvents: false])
subscribe(location, "DeviceUpdated", locationEventHandler, [filterEvents: false])
subscribe(location, "DeviceDeleted", locationEventHandler, [filterEvents: false])
if(state.locationSubscriptionMap[location.id] == null){
state.locationSubscriptionMap.put(location.id, [subscriptionEndpt])
log.info "Added subscription URL: ${subscriptionEndpt} for Location ${location.name}"
} else if (!state.locationSubscriptionMap[location.id].contains(subscriptionEndpt)){
state.locationSubscriptionMap[location.id] << subscriptionEndpt
log.info "Added subscription URL: ${subscriptionEndpt} for Location ${location.name}"
}
log.info "Current location subscription map is ${state.locationSubscriptionMap}"
unsubscribe(myDevice)
log.info "Unregistering ${myDevice.displayName}"
return ["succeed"]
} else {
httpError(400, "missing input parameter: subscriptionURL")
}
}
//Endpoints function: Unsubscribe to events from a specific device
def unregisterDeviceGraph() {
def subscriptionEndpt = params.subscriptionURL
try {
if(subscriptionEndpt != null && subscriptionEndpt != "undefined"){
if (state.locationSubscriptionMap[location.id]?.contains(subscriptionEndpt)){
if(state.locationSubscriptionMap[location.id].size() == 1){
state.locationSubscriptionMap.remove(location.id)
} else {
state.locationSubscriptionMap[location.id].remove(subscriptionEndpt)
}
log.info "Removed subscription URL: ${subscriptionEndpt} for Location ${location.name}"
}
}else{
httpError(400, "missing input parameter: subscriptionURL")
}
} catch (e) {
httpError(500, "something went wrong: $e")
}
log.info "Current location subscription map is ${state.locationSubscriptionMap}"
}
//When events are triggered, send HTTP post to web socket servers
def deviceEventHandler(evt) {
def eventHandler(evt) {
def evt_device_id = evt.deviceId
def evt_device_value = evt.value
def evt_name = evt.name
def evt_device = evt.device
def evt_deviceType = getDeviceType(evt_device)
def evt_deviceType = getDeviceType(evt_device);
def deviceInfo
def params = [ body: [deviceName: evt_device.displayName, deviceId: evt_device.id, locationId: location.id] ]
if(evt.data != null){
def evtData = parseJson(evt.data)
log.info "Received event for ${evt_device.displayName}, data: ${evtData}, description: ${evt.descriptionText}"
if(evt_deviceType == "thermostat")
{
deviceInfo = [name: evt_device.displayName, id: evt_device.id, status:evt_device.getStatus(), deviceType:evt_deviceType, manufacturer:evt_device.getManufacturerName(), model:evt_device.getModelName(), attributes: deviceAttributeList(evt_device), locationMode: getLocationModeInfo()]
}
else
{
deviceInfo = [name: evt_device.displayName, id: evt_device.id, status:evt_device.getStatus(), deviceType:evt_deviceType, manufacturer:evt_device.getManufacturerName(), model:evt_device.getModelName(), attributes: deviceAttributeList(evt_device)]
}
//send event to all subscriptions urls
log.debug "Current subscription urls for ${evt_device.displayName} is ${state.deviceSubscriptionMap[evt_device.id]}"
state.deviceSubscriptionMap[evt_device.id].each {
params.uri = "${it}"
def params = [
uri: "${state.endpointURL}/${state.connectionId}",
body: [ deviceInfo ]
]
try {
log.trace "POST URI: ${params.uri}"
log.trace "Payload: ${params.body}"
try{
httpPostJson(params) { resp ->
log.trace "response status code: ${resp.status}"
log.trace "response data: ${resp.data}"
httpPostJson(params) { resp ->
resp.headers.each {
log.debug "${it.name} : ${it.value}"
}
} catch (e) {
log.error "something went wrong: $e"
log.trace "response status code: ${resp.status}"
log.trace "response data: ${resp.data}"
}
} catch (e) {
log.debug "something went wrong: $e"
}
}
def locationEventHandler(evt) {
log.info "Received event for location ${location.name}/${location.id}, Event: ${evt.name}, description: ${evt.descriptionText}, apiServerUrl: ${apiServerUrl("")}"
switch(evt.name){
case "DeviceCreated":
case "DeviceDeleted":
def evt_device = evt.device
def evt_deviceType = getDeviceType(evt_device)
log.info "DeviceName: ${evt_device.displayName}, DeviceID: ${evt_device.id}, deviceType: ${evt_deviceType}"
def params = [ body: [ eventType:evt.name, deviceId: evt_device.id, locationId: location.id ] ]
state.locationSubscriptionMap[location.id].each {
params.uri = "${it}"
log.trace "POST URI: ${params.uri}"
log.trace "Payload: ${params.body}"
try{
httpPostJson(params) { resp ->
log.trace "response status code: ${resp.status}"
log.trace "response data: ${resp.data}"
}
} catch (e) {
log.error "something went wrong: $e"
}
}
case "DeviceUpdated":
default:
break
}
//Endpoints function: update subcription endpoint url [state.endpoint]
void updateEndpointURL() {
state.endpointURL = params.url
log.info "Updated EndpointURL to ${state.endpointURL}"
}
/*** Device Query/Update Functions ***/
//Endpoints function: update global variable [state.connectionId]
void updateConnectionId() {
def connId = params.connId
state.connectionId = connId
log.info "Updated ConnectionID to ${state.connectionId}"
}
//Endpoints function: return all device data in json format
def getDevices() {
def deviceData = []
inputs?.each {
def deviceType = getDeviceType(it)
if(deviceType == "thermostat") {
deviceData << [name: it.displayName, id: it.id, status:it.status, deviceType:deviceType, manufacturer:it.manufacturerName, model:it.modelName, attributes: deviceAttributeList(it, deviceType), locationMode: getLocationModeInfo()]
} else {
deviceData << [name: it.displayName, id: it.id, status:it.status, deviceType:deviceType, manufacturer:it.manufacturerName, model:it.modelName, attributes: deviceAttributeList(it, deviceType)]
if(deviceType == "thermostat")
{
deviceData << [name: it.displayName, id: it.id, status:it.getStatus(), deviceType:deviceType, manufacturer:it.getManufacturerName(), model:it.getModelName(), attributes: deviceAttributeList(it), locationMode: getLocationModeInfo()]
}
else
{
deviceData << [name: it.displayName, id: it.id, status:it.getStatus(), deviceType:deviceType, manufacturer:it.getManufacturerName(), model:it.getModelName(), attributes: deviceAttributeList(it)]
}
}
@@ -350,12 +247,14 @@ def getDevice() {
def it = findDevice(params.id)
def deviceType = getDeviceType(it)
def device
if(deviceType == "thermostat") {
device = [name: it.displayName, id: it.id, status:it.status, deviceType:deviceType, manufacturer:it.manufacturerName, model:it.modelName, attributes: deviceAttributeList(it,deviceType), locationMode: getLocationModeInfo()]
} else {
device = [name: it.displayName, id: it.id, status:it.status, deviceType:deviceType, manufacturer:it.manufacturerName, model:it.modelName, attributes: deviceAttributeList(it, deviceType)]
if(deviceType == "thermostat")
{
device = [name: it.displayName, id: it.id, status:it.getStatus(), deviceType:deviceType, manufacturer:it.getManufacturerName(), model:it.getModelName(), attributes: deviceAttributeList(it), locationMode: getLocationModeInfo()]
}
else
{
device = [name: it.displayName, id: it.id, status:it.getStatus(), deviceType:deviceType, manufacturer:it.getManufacturerName(), model:it.getModelName(), attributes: deviceAttributeList(it)]
}
log.debug "getDevice, return: ${device}"
return device
}
@@ -451,6 +350,9 @@ private getDeviceType(device) {
}
}
break
case "contact sensor":
deviceType = "contactSensor"
return deviceType
case "garageDoorControl":
deviceType = "garageDoor"
return deviceType
@@ -460,15 +362,17 @@ private getDeviceType(device) {
case "video camera":
deviceType = "camera"
return deviceType
case "motion sensor":
deviceType = "motionSensor"
return deviceType
case "presence sensor":
deviceType = "presenceSensor"
return deviceType
case "thermostat":
deviceType = "thermostat"
return deviceType
case "acceleration sensor":
case "contact sensor":
case "motion sensor":
case "presence sensor":
case "water sensor":
deviceType = "genericSensor"
deviceType = "waterSensor"
return deviceType
default:
break
@@ -483,33 +387,14 @@ private findDevice(deviceId) {
}
//Return a list of device attributes
private deviceAttributeList(device, deviceType) {
def attributeList = [:]
def allAttributes = device.supportedAttributes
allAttributes.each { attribute ->
private deviceAttributeList(device) {
device.supportedAttributes.collectEntries { attribute->
try {
def currentState = device.currentState(attribute.name)
if(currentState != null ){
switch(attribute.name){
case 'temperature':
attributeList.putAll([ (attribute.name): currentState.value, 'temperatureScale':location.temperatureScale ])
break;
default:
attributeList.putAll([(attribute.name): currentState.value ])
break;
}
if( deviceType == "genericSensor" ){
def key = attribute.name + "_lastUpdated"
attributeList.putAll([ (key): currentState.isoDate ])
}
} else {
attributeList.putAll([ (attribute.name): null ]);
}
[ (attribute.name): device.currentValue(attribute.name) ]
} catch(e) {
attributeList.putAll([ (attribute.name): null ]);
[ (attribute.name): null ]
}
}
return attributeList
}
//Map device command and value.

View File

@@ -73,7 +73,7 @@ def bridgeDiscovery(params = [:]) {
}
ssdpSubscribe()
log.trace "bridgeRefreshCount: $bridgeRefreshCount"
//bridge discovery request every 15 //25 seconds
if ((bridgeRefreshCount % 5) == 0) {
discoverBridges()
@@ -207,7 +207,6 @@ def bulbDiscovery() {
}
private discoverBridges() {
log.trace "Sending Hue Discovery message to the hub"
sendHubCommand(new physicalgraph.device.HubAction("lan discovery urn:schemas-upnp-org:device:basic:1", physicalgraph.device.Protocol.LAN))
}

View File

@@ -1,713 +0,0 @@
definition(
name: "stage.app.home.ai",
namespace: "stage.app.home.ai",
author: "Eric Greer",
description: "SmartThings SmartApp for stage.app.home.ai.",
category: "Fun & Social",
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"
)
// These are preferences displayed in the smart phone app
preferences {
// we need a settings section to enable subscriptions
section("Pick which devices home.ai will help you automate:"){
input "motion", "capability.motionSensor", title: "Choose motion sensors", required: false, multiple: true
input "contact", "capability.contactSensor", title: "Choose contact sensors", required: false, multiple: true
input "lightswitch", "capability.switch", title: "Choose normal power switches", required: false, multiple: true
input "lightswitchlevel", "capability.switchLevel", title: "Choose dimmer power switches", required: false, multiple: true
input "presence", "capability.presenceSensor", title: "Choose presence sensors", required: false, multiple: true
input "tempSensor", "capability.temperatureMeasurement", title: "Choose temperature sensors", required: false, multiple: true
input "humidity", "capability.relativeHumidityMeasurement", title: "Choose humidity sensors", required: false, multiple: true
input "waterSensor", "capability.waterSensor", title: "Choose water sensors", required: false, multiple: true
input "lock", "capability.lock", title: "Pick Door Locks", required: false, multiple: true
input "garagedoor", "capability.garageDoorControl", title: "Pick garage doors", required: false, multiple: true
input "touchsensor", "capability.touchSensor", title: "Pick touch sensors", required: false, multiple: true
input "speechparser", "capability.speechRecognition", title: "Pick speech recognizers", required: false, multiple: true
input "soundsensor", "capability.soundSensor", title: "Pick sound sensors", required: false, multiple: true
input "smokedetector", "capability.smokeDetector", title: "Pick smoke detectors", required: false, multiple: true
input "sleepsensor", "capability.sleepSensor", title: "Pick sleep sensors", required: false, multiple: true
input "carbonsensor", "capability.carbonMonoxideDetector", title: "Pick carbon monoxide detectors", required: false, multiple: true
input "button", "capability.button", title: "Pick buttons", required: false, multiple: true
input "beacon", "capability.beacon", title: "Pick beacons", required: false, multiple: true
input "alarm", "capability.alarm", title: "Pick alarms", required: false, multiple: true
input "thermostat", "capability.thermostat", title: "Pick thermostats", required: false, multiple: true
input "voltage", "capability.voltageMeasurement", title: "Pick voltage sensors", required: false, multiple: true
input "windowshade", "capability.windowShade", title: "Pick window shades", required: false, multiple: true
input "powermeter", "capability.powerMeter", title: "Pick power meters", required: false, multiple: true
}
}
// vlaues for security system are 'away', 'stay', or 'off'
// off security
def offSecurity() {
sendLocationEvent(
name: "alarmSystemStatus",
value: "off",
displayed: false,
isStateChange: true
)
}
// stay security
def staySecurity() {
sendLocationEvent(
name: "alarmSystemStatus",
value: "stay",
displayed: false,
isStateChange: true
)
}
// away security
def awaySecurity() {
sendLocationEvent(
name: "alarmSystemStatus",
value: "away",
displayed: false,
isStateChange: true
)
}
// sets window shade open temperature
def setWindowShadeOpen() {
def deviceID = params.deviceID
log.debug("setWindowShadeOpen command recieved ${deviceID}")
windowshade.each {
if (it.id == deviceID) {
log.debug("Operating window shade because it is the one specified: ${deviceID}");
it.open()
} else {
log.debug("NOT operting window shade because it is not the one specified: ${deviceID}");
}
}
}
// sets window shade close temperature
def setWindowShadeClosed() {
def deviceID = params.deviceID
log.debug("setWindowShadeClosed command recieved ${deviceID}")
windowshade.each {
if (it.id == deviceID) {
log.debug("Operating window shade because it is the one specified: ${deviceID}");
it.close()
} else {
log.debug("NOT operting window shade because it is not the one specified: ${deviceID}");
}
}
}
// sets thermostat heating temperature
def setThermostatHeatTemp() {
def deviceID = params.deviceID
log.debug("setThermostatHeat command recieved ${deviceID}")
thermostat.each {
if (it.id == deviceID) {
log.debug("Operating thermostat because it is the one specified: ${deviceID}");
it.setHeatingSetpoint(params.temp)
} else {
log.debug("NOT operting thermostat because it is not the one specified: ${deviceID}");
}
}
}
// sets thermostat cooling temperature
def setThermostatCoolTemp() {
def deviceID = params.deviceID
log.debug("setThermostatCool command recieved ${deviceID}")
thermostat.each {
if (it.id == deviceID) {
log.debug("Operating thermostat because it is the one specified: ${deviceID}");
it.setCoolingSetpoint(params.temp)
} else {
log.debug("NOT operting thermostat because it is not the one specified: ${deviceID}");
}
}
}
// sets thermostat off
def setThermostatOff() {
def deviceID = params.deviceID
log.debug("setThermostatOff command recieved ${deviceID}")
thermostat.each {
if (it.id == deviceID) {
log.debug("Operating thermostat because it is the one specified: ${deviceID}");
it.off()
} else {
log.debug("NOT operting thermostat because it is not the one specified: ${deviceID}");
}
}
}
// sets thermostat to heat
def setThermostatHeat() {
def deviceID = params.deviceID
log.debug("setThermostatHeat command recieved ${deviceID}")
thermostat.each {
if (it.id == deviceID) {
log.debug("Operating thermostat because it is the one specified: ${deviceID}");
it.heat()
} else {
log.debug("NOT operting thermostat because it is not the one specified: ${deviceID}");
}
}
}
// sets thermostat to cool
def setThermostatCool() {
def deviceID = params.deviceID
log.debug("setThermostatCool command recieved ${deviceID}")
thermostat.each {
if (it.id == deviceID) {
log.debug("Operating thermostat because it is the one specified: ${deviceID}");
it.cool()
} else {
log.debug("NOT operting thermostat because it is not the one specified: ${deviceID}");
}
}
}
// sets thermostat mode
def setThermostatMode() {
def deviceID = params.deviceID
log.debug("setThermostatMode command recieved ${deviceID}")
thermostat.each {
if (it.id == deviceID) {
log.debug("Operating thermostat because it is the one specified: ${deviceID}");
it.setThermostatMode(params.mode)
} else {
log.debug("NOT operting thermostat because it is not the one specified: ${deviceID}");
}
}
}
// sets thermostat fan mode
def setThermostatFanMode() {
def deviceID = params.deviceID
log.debug("setThermostatFanMode command recieved ${deviceID}")
thermostat.each {
if (it.id == deviceID) {
log.debug("Operating thermostat because it is the one specified: ${deviceID}");
it.setThermostatFanMode(params.mode)
} else {
log.debug("NOT operting thermostat because it is not the one specified: ${deviceID}");
}
}
}
// sends an alarm strobe
def strobeAlarm() {
def deviceID = params.deviceID
log.debug("Alarm strobe command recieved ${deviceID}")
alarm.each {
if (it.id == deviceID) {
log.debug("Operating alarm because it is the one specified: ${deviceID}");
it.strobe()
} else {
log.debug("NOT operting alarm because it is not the one specified: ${deviceID}");
}
}
}
// sends an alarm siren
def sirenAlarm() {
def deviceID = params.deviceID
log.debug("Alarm siren command recieved ${deviceID}")
alarm.each {
if (it.id == deviceID) {
log.debug("Operating alarm because it is the one specified: ${deviceID}");
it.siren()
} else {
log.debug("NOT operting alarm because it is not the one specified: ${deviceID}");
}
}
}
// disables an alarm siren
def silenceAlarm() {
def deviceID = params.deviceID
log.debug("Alarm silence command recieved ${deviceID}")
alarm.each {
if (it.id == deviceID) {
log.debug("Operating alarm because it is the one specified: ${deviceID}");
it.off()
} else {
log.debug("NOT operting alarm because it is not the one specified: ${deviceID}");
}
}
}
// opens a garage door
def openGarage() {
def deviceID = params.deviceID
log.debug("Open Garage command recieved ${deviceID}")
garagedoor.each {
if (it.id == deviceID) {
log.debug("Operating garage door because it is the one specified: ${deviceID}");
it.open()
} else {
log.debug("NOT operting garage door device because it is not the one specified: ${deviceID}");
}
}
}
// closes a garage door
def closeGarage() {
def deviceID = params.deviceID
log.debug("Close Garage command recieved ${deviceID}")
garagedoor.each {
if (it.id == deviceID) {
log.debug("Operating garage door because it is the one specified: ${deviceID}");
it.close()
} else {
log.debug("NOT operting garage door device because it is not the one specified: ${deviceID}");
}
}
}
// lock locks a door lock
def lockDoor() {
def deviceID = params.deviceID
log.debug("Lock command recieved ${deviceID}")
lock.each {
if (it.id == deviceID) {
log.debug("Operating lock device because it is the one specified: ${deviceID}");
it.lock()
} else {
log.debug("NOT operting lock device because it is not the one specified: ${deviceID}");
}
}
}
// unlock unlocks a door lock
def unlockDoor() {
def deviceID = params.deviceID
log.debug("Unlock command recieved ${deviceID}")
lock.each {
if (it.id == deviceID) {
log.debug("Operating lock device because it is the one specified: ${deviceID}");
it.unlock()
} else {
log.debug("NOT operting lock device because it is not the one specified: ${deviceID}");
}
}
}
// turns on a wall switch as instructed from the homeai webservice
def switchOn() {
def deviceID = params.deviceID
log.debug("Switch on command recieved ${deviceID}")
lightswitch.each {
if (it.id == deviceID) {
log.debug("Operating switch device because it is the one specified: ${deviceID}");
it.on()
} else {
log.debug("Skipping switch device because it is not the one specified: ${deviceID}");
}
}
}
// turns off a wall switch as instructed from the homeai webservice
def switchOff() {
def deviceID = params.deviceID
log.debug("Switch off desired for ${deviceID}")
lightswitch.each {
if (it.id == deviceID) {
log.debug("Operating switch device because it is the one specified: ${deviceID}");
it.off()
} else {
log.debug("Skipping switch device because it is not the one specified: ${deviceID}");
}
}
}
// fetch the id of this smartthings hub
def hubId() {
log.debug("hub id requested.")
def response = [hubId: location.hubs.id[0]]
}
// This handles requests for device inventories
def inventory() {
def response = []
lightswitch.each {
response << [name: it.displayName, value: it.currentValue("switch"), deviceId: it.id, type: "lightSwitch"]
}
contact.each {
response << [name: it.displayName, value: it.currentValue("contact"), deviceId: it.id, type: "contact"]
}
motion.each {
response << [name: it.displayName, value: it.currentValue("motion"), deviceId: it.id, type: "motion"]
}
presence.each {
response << [name: it.displayName, value: it.currentValue("presence"), deviceId: it.id, type: "presence"]
}
// removed until dual device functions are supported on the backend
//tempSensor.each {
// response << [name: it.displayName, value: it.currentValue("temperature"), deviceId: it.id, type: "tempSensor"]
//}
//humidity.each {
// response << [name: it.displayName, value: it.currentValue("humidity"), deviceId: it.id, type: "humiditySensor"]
//}
waterSensor.each {
response << [name: it.displayName, value: it.currentValue("water"), deviceId: it.id, type: "waterSensor"]
}
lock.each {
response << [name: it.displayName, value: it.currentValue("lock"), deviceId: it.id, type: "lock"]
}
garagedoor.each {
response << [name: it.displayName, value: it.currentValue("door"), deviceId: it.id, type: "garagedoor"]
}
touchsensor.each {
response << [name: it.displayName, value: it.currentValue("touch"), deviceId: it.id, type: "touchsensor"]
}
speechparser.each {
response << [name: it.displayName, value: it.currentValue("phraseSpoken"), deviceId: it.id, type: "speechparser"]
}
soundsensor.each {
response << [name: it.displayName, value: it.currentValue("sound"), deviceId: it.id, type: "sound"]
}
smokedetector.each {
response << [name: it.displayName, value: it.currentValue("smoke"), deviceId: it.id, type: "smoke"]
}
sleepsensor.each {
response << [name: it.displayName, value: it.currentValue("sleeping"), deviceId: it.id, type: "sleepsensor"]
}
carbonsensor.each {
response << [name: it.displayName, value: it.currentValue("carbonMonoxide"), deviceId: it.id, type: "carbonsensor"]
}
button.each {
response << [name: it.displayName, value: it.currentValue("button"), deviceId: it.id, type: "button"]
}
beacon.each {
response << [name: it.displayName, value: it.currentValue("presence"), deviceId: it.id, type: "beacon"]
}
alarm.each {
response << [name: it.displayName, value: it.currentValue("alarm"), deviceId: it.id, type: "alarm"]
}
thermostat.each {
response << [name: it.displayName, value: it.currentValue("thermostatMode"), deviceId: it.id, type: "thermostat"]
}
voltage.each {
response << [name: it.displayName, value: it.currentValue("voltage"), deviceId: it.id, type: "voltage"]
}
windowshade.each {
response << [name: it.displayName, value: it.currentValue("windowShade"), deviceId: it.id, type: "windowshade"]
}
powermeter.each {
response << [name: it.displayName, value: it.currentValue("power"), deviceId: it.id, type: "powermeter"]
}
lightswitchlevel.each {
response << [name: it.displayName, value: it.currentValue("level"), deviceId: it.id, type: "lightswitchlevel"]
}
log.debug("Inventory request processed. Response: " + response)
return response
}
// After the user hits the 'install' button in the mobile app
def installed() {
initialize()
}
// After app settings are changed. All subscriptions are wiped before this is invoked by smartthings.
def updated() {
unsubscribe()
initialize()
}
// This appears to be what the tutorials meant to use in the examples
def initialize() {
// SHM subscription
// evt.value will be "off", "stay", or "away"
subscribe(location, "alarmSystemStatus", eventForwarder)
// motion sensor subscription
subscribe(motion, "motion", eventForwarder)
// Contact sensor subscription
subscribe(contact, "contact", eventForwarder)
// power plug subscription
subscribe(lightswitch, "switch", eventForwarder)
// presence sensor subscription
subscribe(presence, "presence", eventForwarder)
// temperature sensor subscription
subscribe(tempSensor, "temperature", eventForwarder)
// water sensor subscription
subscribe(waterSensor, "water", eventForwarder)
// humidity sensor subscription
subscribe(humidity, "humidity", eventForwarder)
// lock subscription
subscribe(lock, "lock", eventForwarder)
// garage door subscription
subscribe(garagedoor, "garagedoor", eventForwarder)
// touch sensor subscription
subscribe(touchsensor, "touchsensor", eventForwarder)
// speech parser subscription
subscribe(speechparser, "phraseSpoken", eventForwarder)
// sound sensor subscription
subscribe(soundsensor, "sound", eventForwarder)
// smoke detector subscription
subscribe(smokedetector, "smoke", eventForwarder)
// sleep sensor subscription
subscribe(sleepsensor, "sleeping", eventForwarder)
// carbon monoxide sensor subscription
subscribe(carbonsensor, "carbonMonoxide", eventForwarder)
// button subscription
subscribe(button, "button", eventForwarder)
// beacon subscription
subscribe(beacon, "presence", eventForwarder)
// alarm subscription
subscribe(alarm, "alarm", eventForwarder)
// thermostat subscriptions
subscribe(thermostat, "temperature", eventForwarder)
subscribe(thermostat, "heatingSetpoint", eventForwarder)
subscribe(thermostat, "coolingSetpoint", eventForwarder)
subscribe(thermostat, "thermostatSetpoint", eventForwarder)
subscribe(thermostat, "thermostatMode", eventForwarder)
subscribe(thermostat, "thermostatFanMode", eventForwarder)
subscribe(thermostat, "thermostatOperatingState", eventForwarder)
// voltage subscription
subscribe(voltage, "voltage", eventForwarder)
// window shade subscription
subscribe(windowshade, "windowShade", eventForwarder)
// shm events
subscribe(location, "alarmSystemStatus", shmEventForwarder)
// power meter subscription
subscribe(powermeter, "power", eventForwarder)
// level switch (dimmer switch)
subscribe(lightswitchlevel, "level", eventForwarder)
}
def shmEventForwarder(evt) {
// evt.value will be "off", "stay", or "away"
log.debug("FORWARDING SHM CHANGE" + evt.value + " " + evt.hub.id)
def deviceState = evt.value
def deviceId = "smarthomemonitor"
def hubId = hubId()
def params = [
uri: "https://stage.app.home.ai",
path: "/smartThingsPostback/shmStateChange/${hubId}/${deviceId}/${deviceState}"
]
log.info(params)
httpGet(params)
}
// This is used to forward events to the home.ai webservice
def eventForwarder(evt) {
def hubId = location.hubs.id[0]
log.debug(params.uri + " " + params.path)
log.debug("FORWARDING EVENT" + evt.deviceId + " " + evt.value + " " + hubId)
def deviceId = evt.deviceId
def deviceState = evt.value
def params = [
uri: "https://stage.app.home.ai",
path: "/smartThingsPostback/stateChange/${hubId}/${deviceId}/${deviceState}"
]
log.info(params)
httpGet(params)
}
// Mappings that serve web requests against our smart app
mappings {
path("/inventory") {
action: [
GET: "inventory"
]
}
path("/hubId") {
action: [
GET: "hubId"
]
}
path("/switchOn/:deviceID") {
action: [
GET: "switchOn"
]
}
path("/switchOff/:deviceID") {
action: [
GET: "switchOff"
]
}
path("/lock/:deviceID") {
action: [
GET: "lockDoor"
]
}
path("/unlock/:deviceID") {
action: [
GET: "unlockDoor"
]
}
path("/opengarage/:deviceID") {
action: [
GET: "openGarage"
]
}
path("/closegarage/:deviceID") {
action: [
GET: "closeGarage"
]
}
path("/strobeAlarm/:deviceID") {
action: [
GET: "strobeAlarm"
]
}
path("/sirenAlarm/:deviceID") {
action: [
GET: "sirenAlarm"
]
}
path("/silenceAlarm/:deviceID") {
action: [
GET: "silenceAlarm"
]
}
path("/setThermostatHeatTemp/:deviceID/:temp") {
action: [
GET: "setThermostatHeatTemp"
]
}
path("/setThermostatCoolTemp/:deviceID/:temp") {
action: [
GET: "setThermostatCoolTemp"
]
}
path("/setThermostatHeat/:deviceID") {
action: [
GET: "setThermostatHeat"
]
}
path("/setThermostatCool/:deviceID") {
action: [
GET: "setThermostatCool"
]
}
path("/setThermostatMode/:deviceID/:mode") {
action: [
GET: "setThermostatMode"
]
}
path("/setThermostatFanMode/:deviceID/:mode") {
action: [
GET: "setThermostatFanMode"
]
}
path("/closeWindowShade/:deviceID") {
action: [
GET: "setWindowShadeClosed"
]
}
path("/openWindowShade/:deviceID") {
action: [
GET: "setWindowShadeOpen"
]
}
path("/awaySecurity") {
action: [
GET: "awaySecurity"
]
}
path("/staySecurity") {
action: [
GET: "staySecurity"
]
}
path("/offSecurity") {
action: [
GET: "offSecurity"
]
}
}