mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-20 13:20:53 +00:00
Compare commits
16 Commits
MSA-1794-1
...
PROD_2017.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2151e2dd3e | ||
|
|
ccb7b6e49d | ||
|
|
34f77a2989 | ||
|
|
318cdedaec | ||
|
|
649ed033d0 | ||
|
|
843d8800ac | ||
|
|
bcc680ee5d | ||
|
|
245e85f850 | ||
|
|
af16720528 | ||
|
|
c6d6ba85f5 | ||
|
|
81550ee25c | ||
|
|
1cc9d8a90b | ||
|
|
bfd2b6c0fa | ||
|
|
9b6e7d3be8 | ||
|
|
fc312286a2 | ||
|
|
0846b6f34c |
@@ -7,6 +7,7 @@
|
|||||||
metadata {
|
metadata {
|
||||||
// Automatically generated. Make future change here.
|
// Automatically generated. Make future change here.
|
||||||
definition (name: "Hue Bridge", namespace: "smartthings", author: "SmartThings") {
|
definition (name: "Hue Bridge", namespace: "smartthings", author: "SmartThings") {
|
||||||
|
capability "Bridge"
|
||||||
capability "Health Check"
|
capability "Health Check"
|
||||||
|
|
||||||
attribute "networkAddress", "string"
|
attribute "networkAddress", "string"
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ metadata {
|
|||||||
capability "Refresh"
|
capability "Refresh"
|
||||||
capability "Actuator"
|
capability "Actuator"
|
||||||
capability "Sensor"
|
capability "Sensor"
|
||||||
|
capability "Outlet"
|
||||||
|
|
||||||
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0B04,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "4257050-ZHAC"
|
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0B04,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "4257050-ZHAC"
|
||||||
|
|
||||||
@@ -79,7 +80,8 @@ def parse(String description) {
|
|||||||
*/
|
*/
|
||||||
event.value = event.value / 10
|
event.value = event.value / 10
|
||||||
}
|
}
|
||||||
return event
|
|
||||||
|
return event ? createEvent(event) : event
|
||||||
}
|
}
|
||||||
|
|
||||||
def setLevel(value) {
|
def setLevel(value) {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ metadata {
|
|||||||
capability "Actuator"
|
capability "Actuator"
|
||||||
capability "Switch"
|
capability "Switch"
|
||||||
capability "Sensor"
|
capability "Sensor"
|
||||||
|
capability "Outlet"
|
||||||
|
|
||||||
fingerprint profileId: "0104", inClusters: "0006, 0004, 0003, 0000, 0005", outClusters: "0019", manufacturer: "Compacta International, Ltd", model: "ZBMPlug15", deviceJoinName: "SmartPower Outlet V1"
|
fingerprint profileId: "0104", inClusters: "0006, 0004, 0003, 0000, 0005", outClusters: "0019", manufacturer: "Compacta International, Ltd", model: "ZBMPlug15", deviceJoinName: "SmartPower Outlet V1"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,9 +83,8 @@ def parse(String description) {
|
|||||||
|
|
||||||
if (event) {
|
if (event) {
|
||||||
if (event.name == "power") {
|
if (event.name == "power") {
|
||||||
event.value = event.value / 10
|
def value = (event.value as Integer) / 10
|
||||||
event.descriptionText = '{{ device.displayName }} power is {{ value }} Watts'
|
event = createEvent(name: event.name, value: value, descriptionText: '{{ device.displayName }} power is {{ value }} Watts', translatable: true)
|
||||||
event.translatable = true
|
|
||||||
} else if (event.name == "switch") {
|
} else if (event.name == "switch") {
|
||||||
def descriptionText = event.value == "on" ? '{{ device.displayName }} is On' : '{{ device.displayName }} is Off'
|
def descriptionText = event.value == "on" ? '{{ device.displayName }} is On' : '{{ device.displayName }} is Off'
|
||||||
event = createEvent(name: event.name, value: event.value, descriptionText: descriptionText, translatable: true)
|
event = createEvent(name: event.name, value: event.value, descriptionText: descriptionText, translatable: true)
|
||||||
@@ -106,7 +105,7 @@ def parse(String description) {
|
|||||||
log.debug "${cluster}"
|
log.debug "${cluster}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return event
|
return event ? createEvent(event) : event
|
||||||
}
|
}
|
||||||
|
|
||||||
def off() {
|
def off() {
|
||||||
|
|||||||
@@ -17,14 +17,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
definition(
|
definition(
|
||||||
name: "Hue (Connect)",
|
name: "Hue (Connect)",
|
||||||
namespace: "smartthings",
|
namespace: "smartthings",
|
||||||
author: "SmartThings",
|
author: "SmartThings",
|
||||||
description: "Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Adjust colors by going to the Thing detail screen for your Hue lights (tap the gear on Hue tiles).\n\nPlease update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.",
|
description: "Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Adjust colors by going to the Thing detail screen for your Hue lights (tap the gear on Hue tiles).\n\nPlease update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.",
|
||||||
category: "SmartThings Labs",
|
category: "SmartThings Labs",
|
||||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/hue.png",
|
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/hue.png",
|
||||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/hue@2x.png",
|
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/hue@2x.png",
|
||||||
singleInstance: true
|
singleInstance: true
|
||||||
)
|
)
|
||||||
|
|
||||||
preferences {
|
preferences {
|
||||||
@@ -85,7 +85,8 @@ def bridgeDiscovery(params=[:])
|
|||||||
}
|
}
|
||||||
|
|
||||||
return dynamicPage(name:"bridgeDiscovery", title:"Discovery Started!", nextPage:"bridgeBtnPush", refreshInterval:refreshInterval, uninstall: true) {
|
return dynamicPage(name:"bridgeDiscovery", title:"Discovery Started!", nextPage:"bridgeBtnPush", refreshInterval:refreshInterval, uninstall: true) {
|
||||||
section("Please wait while we discover your Hue Bridge. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.") {
|
section("Please wait while we discover your Hue Bridge. Kindly note that you must first configure your Hue Bridge and Lights using the Philips Hue application. " +
|
||||||
|
"Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.") {
|
||||||
input "selectedHue", "enum", required:false, title:"Select Hue Bridge (${numFound} found)", multiple:false, options:options, submitOnChange: true
|
input "selectedHue", "enum", required:false, title:"Select Hue Bridge (${numFound} found)", multiple:false, options:options, submitOnChange: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -178,7 +179,7 @@ def bulbDiscovery() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bulbRefreshCount > 200 && numFound == 0) {
|
if (bulbRefreshCount > 200 && numFound == 0) {
|
||||||
// Time out to avoid endless discovery
|
// Time out after 10 minutes
|
||||||
state.inBulbDiscovery = false
|
state.inBulbDiscovery = false
|
||||||
bulbRefreshCount = 0
|
bulbRefreshCount = 0
|
||||||
return dynamicPage(name:"bulbDiscovery", title:"Light Discovery Failed!", nextPage:"", refreshInterval:0, install:true, uninstall: true) {
|
return dynamicPage(name:"bulbDiscovery", title:"Light Discovery Failed!", nextPage:"", refreshInterval:0, install:true, uninstall: true) {
|
||||||
@@ -216,32 +217,32 @@ private sendDeveloperReq() {
|
|||||||
def token = app.id
|
def token = app.id
|
||||||
def host = getBridgeIP()
|
def host = getBridgeIP()
|
||||||
sendHubCommand(new physicalgraph.device.HubAction([
|
sendHubCommand(new physicalgraph.device.HubAction([
|
||||||
method: "POST",
|
method: "POST",
|
||||||
path: "/api",
|
path: "/api",
|
||||||
headers: [
|
headers: [
|
||||||
HOST: host
|
HOST: host
|
||||||
],
|
],
|
||||||
body: [devicetype: "$token-0"]], "${selectedHue}", [callback: "usernameHandler"]))
|
body: [devicetype: "$token-0"]], "${selectedHue}", [callback: "usernameHandler"]))
|
||||||
}
|
}
|
||||||
|
|
||||||
private discoverHueBulbs() {
|
private discoverHueBulbs() {
|
||||||
def host = getBridgeIP()
|
def host = getBridgeIP()
|
||||||
sendHubCommand(new physicalgraph.device.HubAction([
|
sendHubCommand(new physicalgraph.device.HubAction([
|
||||||
method: "GET",
|
method: "GET",
|
||||||
path: "/api/${state.username}/lights",
|
path: "/api/${state.username}/lights",
|
||||||
headers: [
|
headers: [
|
||||||
HOST: host
|
HOST: host
|
||||||
]], "${selectedHue}", [callback: "lightsHandler"]))
|
]], "${selectedHue}", [callback: "lightsHandler"]))
|
||||||
}
|
}
|
||||||
|
|
||||||
private verifyHueBridge(String deviceNetworkId, String host) {
|
private verifyHueBridge(String deviceNetworkId, String host) {
|
||||||
log.trace "Verify Hue Bridge $deviceNetworkId"
|
log.trace "Verify Hue Bridge $deviceNetworkId"
|
||||||
sendHubCommand(new physicalgraph.device.HubAction([
|
sendHubCommand(new physicalgraph.device.HubAction([
|
||||||
method: "GET",
|
method: "GET",
|
||||||
path: "/description.xml",
|
path: "/description.xml",
|
||||||
headers: [
|
headers: [
|
||||||
HOST: host
|
HOST: host
|
||||||
]], deviceNetworkId, [callback: "bridgeDescriptionHandler"]))
|
]], deviceNetworkId, [callback: "bridgeDescriptionHandler"]))
|
||||||
}
|
}
|
||||||
|
|
||||||
private verifyHueBridges() {
|
private verifyHueBridges() {
|
||||||
@@ -399,7 +400,7 @@ def addBulbs() {
|
|||||||
log.debug "$dni in not longer paired to the Hue Bridge or ID changed"
|
log.debug "$dni in not longer paired to the Hue Bridge or ID changed"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//backwards compatable
|
//backwards compatable
|
||||||
newHueBulb = bulbs.find { (app.id + "/" + it.id) == dni }
|
newHueBulb = bulbs.find { (app.id + "/" + it.id) == dni }
|
||||||
d = addChildBulb(dni, "Extended Color Light", newHueBulb?.value?.name, newHueBulb?.value?.hub)
|
d = addChildBulb(dni, "Extended Color Light", newHueBulb?.value?.name, newHueBulb?.value?.hub)
|
||||||
d?.completedSetup = true
|
d?.completedSetup = true
|
||||||
@@ -1151,7 +1152,7 @@ def setColorTemperature(childDevice, huesettings) {
|
|||||||
def ct = hueSettings == 6500 ? 153 : Math.round(1000000/huesettings)
|
def ct = hueSettings == 6500 ? 153 : Math.round(1000000/huesettings)
|
||||||
createSwitchEvent(childDevice, "on")
|
createSwitchEvent(childDevice, "on")
|
||||||
put("lights/$id/state", [ct: ct, on: true])
|
put("lights/$id/state", [ct: ct, on: true])
|
||||||
return "Setting color temperature to $percent"
|
return "Setting color temperature to $ct"
|
||||||
}
|
}
|
||||||
|
|
||||||
def setColor(childDevice, huesettings) {
|
def setColor(childDevice, huesettings) {
|
||||||
@@ -1226,7 +1227,7 @@ private poll() {
|
|||||||
def uri = "/api/${state.username}/lights/"
|
def uri = "/api/${state.username}/lights/"
|
||||||
log.debug "GET: $host$uri"
|
log.debug "GET: $host$uri"
|
||||||
sendHubCommand(new physicalgraph.device.HubAction("GET ${uri} HTTP/1.1\r\n" +
|
sendHubCommand(new physicalgraph.device.HubAction("GET ${uri} HTTP/1.1\r\n" +
|
||||||
"HOST: ${host}\r\n\r\n", physicalgraph.device.Protocol.LAN, selectedHue))
|
"HOST: ${host}\r\n\r\n", physicalgraph.device.Protocol.LAN, selectedHue))
|
||||||
}
|
}
|
||||||
|
|
||||||
private isOnline(id) {
|
private isOnline(id) {
|
||||||
@@ -1243,10 +1244,10 @@ private put(path, body) {
|
|||||||
log.debug "BODY: ${bodyJSON}"
|
log.debug "BODY: ${bodyJSON}"
|
||||||
|
|
||||||
sendHubCommand(new physicalgraph.device.HubAction("PUT $uri HTTP/1.1\r\n" +
|
sendHubCommand(new physicalgraph.device.HubAction("PUT $uri HTTP/1.1\r\n" +
|
||||||
"HOST: ${host}\r\n" +
|
"HOST: ${host}\r\n" +
|
||||||
"Content-Length: ${length}\r\n" +
|
"Content-Length: ${length}\r\n" +
|
||||||
"\r\n" +
|
"\r\n" +
|
||||||
"${bodyJSON}", physicalgraph.device.Protocol.LAN, "${selectedHue}"))
|
"${bodyJSON}", physicalgraph.device.Protocol.LAN, "${selectedHue}"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -346,7 +346,7 @@ def devicesList(selector = '') {
|
|||||||
if (resp.status == 200) {
|
if (resp.status == 200) {
|
||||||
return resp.data
|
return resp.data
|
||||||
} else {
|
} else {
|
||||||
log.error("Non-200 from device list call. ${resp.status} ${resp.data}")
|
log.debug("No response from device list call. ${resp.status} ${resp.data}")
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -418,9 +418,15 @@ def updateDevices() {
|
|||||||
}
|
}
|
||||||
getChildDevices().findAll { !selectors.contains("${it.deviceNetworkId}") }.each {
|
getChildDevices().findAll { !selectors.contains("${it.deviceNetworkId}") }.each {
|
||||||
log.info("Deleting ${it.deviceNetworkId}")
|
log.info("Deleting ${it.deviceNetworkId}")
|
||||||
state.devices[it.deviceNetworkId] = null
|
if (state.devices[it.deviceNetworkId])
|
||||||
deleteChildDevice(it.deviceNetworkId)
|
state.devices[it.deviceNetworkId] = null
|
||||||
|
// The reason the implementation is trying to delete this bulb is because it is not longer connected to the LIFX location.
|
||||||
|
// Adding "try" will prevent this exception from happening.
|
||||||
|
// Ideally device health would show to the user that the device is not longer accessible so that the user can either force delete it or remove it from the SmartApp.
|
||||||
|
try {
|
||||||
|
deleteChildDevice(it.deviceNetworkId)
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.debug("Can't remove this device because it's being used by an SmartApp")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,334 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2015 SmartThings
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
||||||
* in compliance with the License. You may obtain a copy of the License at:
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
|
|
||||||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
|
|
||||||
* for the specific language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
* Speaker Control
|
|
||||||
*
|
|
||||||
* Author: SmartThings
|
|
||||||
*
|
|
||||||
* Date: 2013-12-10
|
|
||||||
* Modifications Author: Richard Bourne
|
|
||||||
* Date: 2017-18-02
|
|
||||||
* Volume control currently does not work for R1 speakers.
|
|
||||||
*/
|
|
||||||
definition(
|
|
||||||
name: "Samsung Multiroom URL Speaker Control",
|
|
||||||
namespace: "smartthings",
|
|
||||||
author: "Richard Bourne",
|
|
||||||
description: "Play or pause your Samsung Speaker when certain actions take place in your home. Use the URL to define source of audio e.g. Radio/audio server.",
|
|
||||||
category: "SmartThings Labs",
|
|
||||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
|
|
||||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png"
|
|
||||||
)
|
|
||||||
|
|
||||||
preferences {
|
|
||||||
page(name: "mainPage", title: "Control your Speaker when something happens", install: true, uninstall: true)
|
|
||||||
page(name: "timeIntervalInput", title: "Only during a certain time") {
|
|
||||||
section {
|
|
||||||
input "starting", "time", title: "Starting", required: false
|
|
||||||
input "ending", "time", title: "Ending", required: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def mainPage() {
|
|
||||||
dynamicPage(name: "mainPage") {
|
|
||||||
def anythingSet = anythingSet()
|
|
||||||
if (anythingSet) {
|
|
||||||
section("When..."){
|
|
||||||
ifSet "motion", "capability.motionSensor", title: "Motion Here", required: false, multiple: true
|
|
||||||
ifSet "contact", "capability.contactSensor", title: "Contact Opens", required: false, multiple: true
|
|
||||||
ifSet "contactClosed", "capability.contactSensor", title: "Contact Closes", required: false, multiple: true
|
|
||||||
ifSet "acceleration", "capability.accelerationSensor", title: "Acceleration Detected", required: false, multiple: true
|
|
||||||
ifSet "mySwitch", "capability.switch", title: "Switch Turned On", required: false, multiple: true
|
|
||||||
ifSet "mySwitchOff", "capability.switch", title: "Switch Turned Off", required: false, multiple: true
|
|
||||||
ifSet "arrivalPresence", "capability.presenceSensor", title: "Arrival Of", required: false, multiple: true
|
|
||||||
ifSet "departurePresence", "capability.presenceSensor", title: "Departure Of", required: false, multiple: true
|
|
||||||
ifSet "smoke", "capability.smokeDetector", title: "Smoke Detected", required: false, multiple: true
|
|
||||||
ifSet "water", "capability.waterSensor", title: "Water Sensor Wet", required: false, multiple: true
|
|
||||||
ifSet "button1", "capability.button", title: "Button Press", required:false, multiple:true //remove from production
|
|
||||||
ifSet "triggerModes", "mode", title: "System Changes Mode", required: false, multiple: true
|
|
||||||
ifSet "timeOfDay", "time", title: "At a Scheduled Time", required: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
section(anythingSet ? "Select additional triggers" : "When...", hideable: anythingSet, hidden: true){
|
|
||||||
ifUnset "motion", "capability.motionSensor", title: "Motion Here", required: false, multiple: true
|
|
||||||
ifUnset "contact", "capability.contactSensor", title: "Contact Opens", required: false, multiple: true
|
|
||||||
ifUnset "contactClosed", "capability.contactSensor", title: "Contact Closes", required: false, multiple: true
|
|
||||||
ifUnset "acceleration", "capability.accelerationSensor", title: "Acceleration Detected", required: false, multiple: true
|
|
||||||
ifUnset "mySwitch", "capability.switch", title: "Switch Turned On", required: false, multiple: true
|
|
||||||
ifUnset "mySwitchOff", "capability.switch", title: "Switch Turned Off", required: false, multiple: true
|
|
||||||
ifUnset "arrivalPresence", "capability.presenceSensor", title: "Arrival Of", required: false, multiple: true
|
|
||||||
ifUnset "departurePresence", "capability.presenceSensor", title: "Departure Of", required: false, multiple: true
|
|
||||||
ifUnset "smoke", "capability.smokeDetector", title: "Smoke Detected", required: false, multiple: true
|
|
||||||
ifUnset "water", "capability.waterSensor", title: "Water Sensor Wet", required: false, multiple: true
|
|
||||||
ifUnset "button1", "capability.button", title: "Button Press", required:false, multiple:true //remove from production
|
|
||||||
ifUnset "triggerModes", "mode", title: "System Changes Mode", required: false, multiple: true
|
|
||||||
ifUnset "timeOfDay", "time", title: "At a Scheduled Time", required: false
|
|
||||||
}
|
|
||||||
section("Perform this action"){
|
|
||||||
input "actionType", "enum", title: "Action?", required: true, defaultValue: "play", options: [
|
|
||||||
"Play URL",
|
|
||||||
"Play",
|
|
||||||
"Stop Playing",
|
|
||||||
"Toggle Play/Pause",
|
|
||||||
"Skip to Next Track",
|
|
||||||
"Play Previous Track"
|
|
||||||
|
|
||||||
]
|
|
||||||
}
|
|
||||||
section {
|
|
||||||
input "samsungspeaker", "capability.musicPlayer", title: "Speaker music player", required: true
|
|
||||||
}
|
|
||||||
section("More options", hideable: true, hidden: true) {
|
|
||||||
input "volume", "number", title: "Set the volume", description: "0-100%", required: false
|
|
||||||
input "frequency", "decimal", title: "Minimum time between actions (defaults to every event)", description: "Minutes", required: false
|
|
||||||
href "timeIntervalInput", title: "Only during a certain time", description: timeLabel ?: "Tap to set", state: timeLabel ? "complete" : "incomplete"
|
|
||||||
input "days", "enum", title: "Only on certain days of the week", multiple: true, required: false,
|
|
||||||
options: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
|
|
||||||
if (settings.modes) {
|
|
||||||
input "modes", "mode", title: "Only when mode is", multiple: true, required: false
|
|
||||||
}
|
|
||||||
input "oncePerDay", "bool", title: "Only once per day", required: false, defaultValue: false
|
|
||||||
}
|
|
||||||
section([mobileOnly:true]) {
|
|
||||||
label title: "Assign a name", required: false
|
|
||||||
mode title: "Set for specific mode(s)"
|
|
||||||
}
|
|
||||||
section("Define a URL") {
|
|
||||||
input "URL", "text", title: "URL link:", defaultValue: "http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio1_mf_p", required: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private anythingSet() {
|
|
||||||
for (name in ["motion","contact","contactClosed","acceleration","mySwitch","mySwitchOff","arrivalPresence","departurePresence","smoke","water","button1","triggerModes","timeOfDay"]) {
|
|
||||||
if (settings[name]) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
private ifUnset(Map options, String name, String capability) {
|
|
||||||
if (!settings[name]) {
|
|
||||||
input(options, name, capability)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ifSet(Map options, String name, String capability) {
|
|
||||||
if (settings[name]) {
|
|
||||||
input(options, name, capability)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def installed() {
|
|
||||||
log.debug "Installed with settings: ${settings}"
|
|
||||||
subscribeToEvents()
|
|
||||||
}
|
|
||||||
|
|
||||||
def updated() {
|
|
||||||
log.debug "Updated with settings: ${settings}"
|
|
||||||
unsubscribe()
|
|
||||||
unschedule()
|
|
||||||
subscribeToEvents()
|
|
||||||
}
|
|
||||||
|
|
||||||
def subscribeToEvents() {
|
|
||||||
log.trace "subscribeToEvents()"
|
|
||||||
subscribe(app, appTouchHandler)
|
|
||||||
subscribe(contact, "contact.open", eventHandler)
|
|
||||||
subscribe(contactClosed, "contact.closed", eventHandler)
|
|
||||||
subscribe(acceleration, "acceleration.active", eventHandler)
|
|
||||||
subscribe(motion, "motion.active", eventHandler)
|
|
||||||
subscribe(mySwitch, "switch.on", eventHandler)
|
|
||||||
subscribe(mySwitchOff, "switch.off", eventHandler)
|
|
||||||
subscribe(arrivalPresence, "presence.present", eventHandler)
|
|
||||||
subscribe(departurePresence, "presence.not present", eventHandler)
|
|
||||||
subscribe(smoke, "smoke.detected", eventHandler)
|
|
||||||
subscribe(smoke, "smoke.tested", eventHandler)
|
|
||||||
subscribe(smoke, "carbonMonoxide.detected", eventHandler)
|
|
||||||
subscribe(water, "water.wet", eventHandler)
|
|
||||||
subscribe(button1, "button.pushed", eventHandler)
|
|
||||||
|
|
||||||
if (triggerModes) {
|
|
||||||
subscribe(location, modeChangeHandler)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timeOfDay) {
|
|
||||||
schedule(timeOfDay, scheduledTimeHandler)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def eventHandler(evt) {
|
|
||||||
if (allOk) {
|
|
||||||
def lastTime = state[frequencyKey(evt)]
|
|
||||||
if (oncePerDayOk(lastTime)) {
|
|
||||||
if (frequency) {
|
|
||||||
if (lastTime == null || now() - lastTime >= frequency * 60000) {
|
|
||||||
takeAction(evt)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log.debug "Not taking action because $frequency minutes have not elapsed since last action"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
takeAction(evt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log.debug "Not taking action because it was already taken today"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def modeChangeHandler(evt) {
|
|
||||||
log.trace "modeChangeHandler $evt.name: $evt.value ($triggerModes)"
|
|
||||||
if (evt.value in triggerModes) {
|
|
||||||
eventHandler(evt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def scheduledTimeHandler() {
|
|
||||||
eventHandler(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
def appTouchHandler(evt) {
|
|
||||||
takeAction(evt)
|
|
||||||
}
|
|
||||||
|
|
||||||
private takeAction(evt) {
|
|
||||||
log.debug "takeAction($actionType)"
|
|
||||||
def options = [:]
|
|
||||||
|
|
||||||
if (settings.volume) {
|
|
||||||
log.debug "volume altered ($options)"
|
|
||||||
samsungspeaker.setLevel(settings.volume as Number)
|
|
||||||
pause(500)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (actionType) {
|
|
||||||
case "Play":
|
|
||||||
options ? samsungspeaker.on(options) : samsungspeaker.on()
|
|
||||||
break
|
|
||||||
case "Stop Playing":
|
|
||||||
options ? samsungspeaker.off(options) : samsungspeaker.off()
|
|
||||||
break
|
|
||||||
case "Toggle Play/Pause":
|
|
||||||
def currentStatus = samsungspeaker.currentValue("status")
|
|
||||||
if (currentStatus == "playing") {
|
|
||||||
options ? samsungspeaker.pause(options) : samsungspeaker.pause()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
options ? samsungspeaker.play(options) : samsungspeaker.play()
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case "Skip to Next Track":
|
|
||||||
options ? samsungspeaker.nextTrack(options) : samsungspeaker.nextTrack()
|
|
||||||
break
|
|
||||||
case "Play Previous Track":
|
|
||||||
options ? samsungspeaker.previousTrack(options) : samsungspeaker.previousTrack()
|
|
||||||
break
|
|
||||||
case "Play URL":
|
|
||||||
samsungspeaker.playTrack(settings.URL as String)
|
|
||||||
break
|
|
||||||
case "5":
|
|
||||||
samsungspeaker.playTrack(settings.URL as String)
|
|
||||||
break
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
log.error "Action type '$actionType' not defined"
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frequency) {
|
|
||||||
state.lastActionTimeStamp = now()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private frequencyKey(evt) {
|
|
||||||
//evt.deviceId ?: evt.value
|
|
||||||
"lastActionTimeStamp"
|
|
||||||
}
|
|
||||||
|
|
||||||
private dayString(Date date) {
|
|
||||||
def df = new java.text.SimpleDateFormat("yyyy-MM-dd")
|
|
||||||
if (location.timeZone) {
|
|
||||||
df.setTimeZone(location.timeZone)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
df.setTimeZone(TimeZone.getTimeZone("America/New_York"))
|
|
||||||
}
|
|
||||||
df.format(date)
|
|
||||||
}
|
|
||||||
|
|
||||||
private oncePerDayOk(Long lastTime) {
|
|
||||||
def result = true
|
|
||||||
if (oncePerDay) {
|
|
||||||
result = lastTime ? dayString(new Date()) != dayString(new Date(lastTime)) : true
|
|
||||||
log.trace "oncePerDayOk = $result"
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO - centralize somehow
|
|
||||||
private getAllOk() {
|
|
||||||
modeOk && daysOk && timeOk
|
|
||||||
}
|
|
||||||
|
|
||||||
private getModeOk() {
|
|
||||||
def result = !modes || modes.contains(location.mode)
|
|
||||||
log.trace "modeOk = $result"
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
private getDaysOk() {
|
|
||||||
def result = true
|
|
||||||
if (days) {
|
|
||||||
def df = new java.text.SimpleDateFormat("EEEE")
|
|
||||||
if (location.timeZone) {
|
|
||||||
df.setTimeZone(location.timeZone)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
df.setTimeZone(TimeZone.getTimeZone("America/New_York"))
|
|
||||||
}
|
|
||||||
def day = df.format(new Date())
|
|
||||||
result = days.contains(day)
|
|
||||||
}
|
|
||||||
log.trace "daysOk = $result"
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
private getTimeOk() {
|
|
||||||
def result = true
|
|
||||||
if (starting && ending) {
|
|
||||||
def currTime = now()
|
|
||||||
def start = timeToday(starting, location?.timeZone).time
|
|
||||||
def stop = timeToday(ending, location?.timeZone).time
|
|
||||||
result = start < stop ? currTime >= start && currTime <= stop : currTime <= stop || currTime >= start
|
|
||||||
}
|
|
||||||
log.trace "timeOk = $result"
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
private hhmm(time, fmt = "h:mm a")
|
|
||||||
{
|
|
||||||
def t = timeToday(time, location.timeZone)
|
|
||||||
def f = new java.text.SimpleDateFormat(fmt)
|
|
||||||
f.setTimeZone(location.timeZone ?: timeZone(time))
|
|
||||||
f.format(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
private timeIntervalLabel()
|
|
||||||
{
|
|
||||||
(starting && ending) ? hhmm(starting) + "-" + hhmm(ending, "h:mm a z") : ""
|
|
||||||
}
|
|
||||||
// TODO - End Centralize
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user