From 950a33dc74af2952f5ec2109271954511d4358fa Mon Sep 17 00:00:00 2001 From: Parijat Das Date: Mon, 13 Mar 2017 16:26:46 -0700 Subject: [PATCH 01/16] Added health-check for FortrezZ Water Valve --- .../fortrezz-water-valve.src/.st-ignore | 2 + .../fortrezz-water-valve.src/README.md | 39 +++++++++++++++++++ .../fortrezz-water-valve.groovy | 14 +++++++ 3 files changed, 55 insertions(+) create mode 100644 devicetypes/smartthings/fortrezz-water-valve.src/.st-ignore create mode 100644 devicetypes/smartthings/fortrezz-water-valve.src/README.md diff --git a/devicetypes/smartthings/fortrezz-water-valve.src/.st-ignore b/devicetypes/smartthings/fortrezz-water-valve.src/.st-ignore new file mode 100644 index 0000000..f78b46e --- /dev/null +++ b/devicetypes/smartthings/fortrezz-water-valve.src/.st-ignore @@ -0,0 +1,2 @@ +.st-ignore +README.md diff --git a/devicetypes/smartthings/fortrezz-water-valve.src/README.md b/devicetypes/smartthings/fortrezz-water-valve.src/README.md new file mode 100644 index 0000000..40c31df --- /dev/null +++ b/devicetypes/smartthings/fortrezz-water-valve.src/README.md @@ -0,0 +1,39 @@ +# FortrezZ Water Valve + +Cloud Execution + +Works with: + +* [FortrezZ Water Valve](https://www.smartthings.com/works-with-smartthings/other/fortrezz-water-valve) + +## Table of contents + +* [Capabilities](#capabilities) +* [Health](#device-health) +* [Troubleshooting](#troubleshooting) + +## Capabilities + +* **Actuator** - represents that a Device has commands +* **Health Check** - indicates ability to get device health notifications +* **Valve** - allows for the control of a valve device +* **Refresh** - _refresh()_ command for status updates +* **Sensor** - detects sensor events + +## Device Health + +FortrezZ Water Valve is polled by the hub. +As of hubCore version 0.14.38 the hub sends up reports every 15 minutes regardless of whether the state changed. +Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*15 + 2)mins = 32 mins. +Not to mention after going OFFLINE when the device is plugged back in, it might take a considerable amount of time for +the device to appear as ONLINE again. This is because if this listening device does not respond to two poll requests in a row, +it is not polled for 5 minutes by the hub. This can delay up the process of being marked ONLINE by quite some time. + +* __32min__ checkInterval + +## Troubleshooting + +If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range. +Pairing needs to be tried again by placing the device closer to the hub. +Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link: +* [FortrezZ Water Valve Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/202088434-FortrezZ-Water-Valve-Shutoff) \ No newline at end of file diff --git a/devicetypes/smartthings/fortrezz-water-valve.src/fortrezz-water-valve.groovy b/devicetypes/smartthings/fortrezz-water-valve.src/fortrezz-water-valve.groovy index 1b67c5d..77b9595 100644 --- a/devicetypes/smartthings/fortrezz-water-valve.src/fortrezz-water-valve.groovy +++ b/devicetypes/smartthings/fortrezz-water-valve.src/fortrezz-water-valve.groovy @@ -14,11 +14,13 @@ metadata { definition (name: "Fortrezz Water Valve", namespace: "smartthings", author: "SmartThings") { capability "Actuator" + capability "Health Check" capability "Valve" capability "Refresh" capability "Sensor" fingerprint deviceId: "0x1000", inClusters: "0x25,0x72,0x86,0x71,0x22,0x70" + fingerprint mfr:"0084", prod:"0213", model:"0215", deviceJoinName: "FortrezZ Water Valve" } // simulator metadata @@ -48,6 +50,11 @@ metadata { } } +def updated(){ +// Device-Watch simply pings if no device events received for 32min(checkInterval) + sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) +} + def parse(String description) { log.trace description def result = null @@ -76,6 +83,13 @@ def close() { zwave.switchBinaryV1.switchBinarySet(switchValue: 0xFF).format() } +/** + * PING is used by Device-Watch in attempt to reach the Device + * */ +def ping() { + refresh() +} + def refresh() { zwave.switchBinaryV1.switchBinaryGet().format() } From 7a7a08ea6ea413de32a5fb67ba219fff077e1bbc Mon Sep 17 00:00:00 2001 From: Parijat Das Date: Mon, 13 Mar 2017 18:05:22 -0700 Subject: [PATCH 02/16] Added health-check for FortrezZ Siren Strobe Alarm --- .../smartthings/zwave-siren.src/.st-ignore | 2 + .../smartthings/zwave-siren.src/README.md | 42 +++++++++++++++++++ .../zwave-siren.src/zwave-siren.groovy | 14 +++++++ 3 files changed, 58 insertions(+) create mode 100644 devicetypes/smartthings/zwave-siren.src/.st-ignore create mode 100644 devicetypes/smartthings/zwave-siren.src/README.md diff --git a/devicetypes/smartthings/zwave-siren.src/.st-ignore b/devicetypes/smartthings/zwave-siren.src/.st-ignore new file mode 100644 index 0000000..f78b46e --- /dev/null +++ b/devicetypes/smartthings/zwave-siren.src/.st-ignore @@ -0,0 +1,2 @@ +.st-ignore +README.md diff --git a/devicetypes/smartthings/zwave-siren.src/README.md b/devicetypes/smartthings/zwave-siren.src/README.md new file mode 100644 index 0000000..ed17b1e --- /dev/null +++ b/devicetypes/smartthings/zwave-siren.src/README.md @@ -0,0 +1,42 @@ +# Z-wave Siren + +Cloud Execution + +Works with: + +* [FortrezZ Siren Strobe Alarm](https://www.smartthings.com/works-with-smartthings/other/fortrezz-water-valve) + +## Table of contents + +* [Capabilities](#capabilities) +* [Health](#device-health) +* [Troubleshooting](#troubleshooting) + +## Capabilities + +* **Actuator** - represents that a Device has commands +* **Alarm** - allows for interacting with devices that serve as alarms +* **Battery** - defines device uses a battery +* **Health Check** - indicates ability to get device health notifications +* **Polling** - represents that poll() can be implemented for the device +* **Refresh** - _refresh()_ command for status updates +* **Sensor** - detects sensor events +* **Switch** - can detect state (possible values: on/off) + +## Device Health + +FortrezZ Siren Strobe Alarm is polled by the hub. +As of hubCore version 0.14.38 the hub sends up reports every 15 minutes regardless of whether the state changed. +Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*15 + 2)mins = 32 mins. +Not to mention after going OFFLINE when the device is plugged back in, it might take a considerable amount of time for +the device to appear as ONLINE again. This is because if this listening device does not respond to two poll requests in a row, +it is not polled for 5 minutes by the hub. This can delay up the process of being marked ONLINE by quite some time. + +* __32min__ checkInterval + +## Troubleshooting + +If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range. +Pairing needs to be tried again by placing the device closer to the hub. +Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link: +* [FortrezZ Siren Strobe Alarm Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/202294760-FortrezZ-Siren-Strobe-Alarm) \ No newline at end of file diff --git a/devicetypes/smartthings/zwave-siren.src/zwave-siren.groovy b/devicetypes/smartthings/zwave-siren.src/zwave-siren.groovy index 9ee8071..d368610 100644 --- a/devicetypes/smartthings/zwave-siren.src/zwave-siren.groovy +++ b/devicetypes/smartthings/zwave-siren.src/zwave-siren.groovy @@ -20,6 +20,7 @@ metadata { capability "Actuator" capability "Alarm" capability "Battery" + capability "Health Check" capability "Polling" capability "Refresh" capability "Sensor" @@ -27,6 +28,7 @@ metadata { fingerprint inClusters: "0x20,0x25,0x86,0x80,0x85,0x72,0x71" + fingerprint mfr:"0084", prod:"0313", model:"010B", deviceJoinName: "FortrezZ Siren Strobe Alarm" } simulator { @@ -58,6 +60,11 @@ metadata { } } +def updated(){ +// Device-Watch simply pings if no device events received for 32min(checkInterval) + sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) +} + def createEvents(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) { def map = [ name: "battery", unit: "%" ] if (cmd.batteryLevel == 0xFF) { @@ -119,6 +126,13 @@ def both() { on() } +/** + * PING is used by Device-Watch in attempt to reach the Device + * */ +def ping() { + refresh() +} + def refresh() { log.debug "sending battery refresh command" zwave.batteryV1.batteryGet().format() From d30494172f9996f0fde5a20b339e76ef52199e1a Mon Sep 17 00:00:00 2001 From: Parijat Das Date: Wed, 15 Mar 2017 14:34:04 -0700 Subject: [PATCH 03/16] Added health-check for Linear GoControl Garage Door Opener --- .../zwave-garage-door-opener.src/.st-ignore | 2 + .../zwave-garage-door-opener.src/README.md | 41 +++++++++++++++++++ .../zwave-garage-door-opener.groovy | 14 +++++++ 3 files changed, 57 insertions(+) create mode 100644 devicetypes/smartthings/zwave-garage-door-opener.src/.st-ignore create mode 100644 devicetypes/smartthings/zwave-garage-door-opener.src/README.md diff --git a/devicetypes/smartthings/zwave-garage-door-opener.src/.st-ignore b/devicetypes/smartthings/zwave-garage-door-opener.src/.st-ignore new file mode 100644 index 0000000..f78b46e --- /dev/null +++ b/devicetypes/smartthings/zwave-garage-door-opener.src/.st-ignore @@ -0,0 +1,2 @@ +.st-ignore +README.md diff --git a/devicetypes/smartthings/zwave-garage-door-opener.src/README.md b/devicetypes/smartthings/zwave-garage-door-opener.src/README.md new file mode 100644 index 0000000..188521d --- /dev/null +++ b/devicetypes/smartthings/zwave-garage-door-opener.src/README.md @@ -0,0 +1,41 @@ +# Z-wave Garage Door Opener + +Cloud Execution + +Works with: + +* [Linear GoControl Garage Door Opener](https://www.smartthings.com/works-with-smartthings/other/linear-gocontrol-garage-door-opener) + +## Table of contents + +* [Capabilities](#capabilities) +* [Health](#device-health) +* [Troubleshooting](#troubleshooting) + +## Capabilities + +* **Actuator** - represents that a Device has commands +* **Door Control** - allow for the control of a door +* **Garage Door Control** - allow for the control of a garage door +* **Health Check** - indicates ability to get device health notifications +* **Contact Sensor** - can detect contact (with possible values - open/closed) +* **Refresh** - _refresh()_ command for status updates +* **Sensor** - detects sensor events + +## Device Health + +Linear GoControl Garage Door Opener is polled by the hub. +As of hubCore version 0.14.38 the hub sends up reports every 15 minutes regardless of whether the state changed. +Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*15 + 2)mins = 32 mins. +Not to mention after going OFFLINE when the device is plugged back in, it might take a considerable amount of time for +the device to appear as ONLINE again. This is because if this listening device does not respond to two poll requests in a row, +it is not polled for 5 minutes by the hub. This can delay up the process of being marked ONLINE by quite some time. + +* __32min__ checkInterval + +## Troubleshooting + +If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range. +Pairing needs to be tried again by placing the device closer to the hub. +Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link: +* [Linear GoControl Garage Door Opener Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/204831116-GoControl-Linear-Garage-Door-Opener-GD00Z-4-) \ No newline at end of file diff --git a/devicetypes/smartthings/zwave-garage-door-opener.src/zwave-garage-door-opener.groovy b/devicetypes/smartthings/zwave-garage-door-opener.src/zwave-garage-door-opener.groovy index f22faf8..a0fa61e 100644 --- a/devicetypes/smartthings/zwave-garage-door-opener.src/zwave-garage-door-opener.groovy +++ b/devicetypes/smartthings/zwave-garage-door-opener.src/zwave-garage-door-opener.groovy @@ -18,12 +18,14 @@ metadata { capability "Actuator" capability "Door Control" capability "Garage Door Control" + capability "Health Check" capability "Contact Sensor" capability "Refresh" capability "Sensor" fingerprint deviceId: "0x4007", inClusters: "0x98" fingerprint deviceId: "0x4006", inClusters: "0x98" + fingerprint mfr:"014F", prod:"4744", model:"3030", deviceJoinName: "Linear GoControl Garage Door Opener" } simulator { @@ -63,6 +65,11 @@ metadata { import physicalgraph.zwave.commands.barrieroperatorv1.* +def updated(){ +// Device-Watch simply pings if no device events received for 32min(checkInterval) + sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) +} + def parse(String description) { def result = null if (description.startsWith("Err")) { @@ -287,6 +294,13 @@ def close() { secure(zwave.barrierOperatorV1.barrierOperatorSet(requestedBarrierState: BarrierOperatorSet.REQUESTED_BARRIER_STATE_CLOSE)) } +/** + * PING is used by Device-Watch in attempt to reach the Device + * */ +def ping() { + refresh() +} + def refresh() { secure(zwave.barrierOperatorV1.barrierOperatorGet()) } From 1326881142d8f516b82729760ca0d4bb7ed04ef8 Mon Sep 17 00:00:00 2001 From: "sushant.k1" Date: Wed, 15 Mar 2017 19:46:07 +0530 Subject: [PATCH 04/16] Implemented of Health Check for Aeon Siren. --- .../smartthings/aeon-siren.src/.st-ignore | 2 + .../smartthings/aeon-siren.src/README.md | 37 +++++++++++++++++++ .../aeon-siren.src/aeon-siren.groovy | 13 ++++++- 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 devicetypes/smartthings/aeon-siren.src/.st-ignore create mode 100644 devicetypes/smartthings/aeon-siren.src/README.md diff --git a/devicetypes/smartthings/aeon-siren.src/.st-ignore b/devicetypes/smartthings/aeon-siren.src/.st-ignore new file mode 100644 index 0000000..f78b46e --- /dev/null +++ b/devicetypes/smartthings/aeon-siren.src/.st-ignore @@ -0,0 +1,2 @@ +.st-ignore +README.md diff --git a/devicetypes/smartthings/aeon-siren.src/README.md b/devicetypes/smartthings/aeon-siren.src/README.md new file mode 100644 index 0000000..f4e0166 --- /dev/null +++ b/devicetypes/smartthings/aeon-siren.src/README.md @@ -0,0 +1,37 @@ +# Aeon Siren + +Cloud Execution + +Works with: + +* [Aeon Labs Siren (Gen 5)](https://www.smartthings.com/works-with-smartthings/aeon-labs/aeon-labs-siren-gen-5) + +## Table of contents + +* [Capabilities](#capabilities) +* [Health](#device-health) + +## Capabilities + +* **Actuator** - represents that a Device has commands +* **Alarm** - allows for interacting with devices that serve as alarms +* **Switch** - can detect state (possible values: on/off) +* **Health Check** - indicates ability to get device health notifications + +## Device Health + +Aeon Labs Siren (Gen 5) is polled by the hub. +As of hubCore version 0.14.38 the hub sends up reports every 15 minutes regardless of whether the state changed. +Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*15 + 2)mins = 32 mins. +Not to mention after going OFFLINE when the device is plugged back in, it might take a considerable amount of time for +the device to appear as ONLINE again. This is because if this listening device does not respond to two poll requests in a row, +it is not polled for 5 minutes by the hub. This can delay up the process of being marked ONLINE by quite some time. + +* __32min__ checkInterval + +## Troubleshooting + +If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range. +Pairing needs to be tried again by placing the device closer to the hub. +Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link: +* [Aeon Labs Siren (Gen 5) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/204555240-Aeon-Labs-Siren-Gen-5-) \ No newline at end of file diff --git a/devicetypes/smartthings/aeon-siren.src/aeon-siren.groovy b/devicetypes/smartthings/aeon-siren.src/aeon-siren.groovy index a0fafb3..8b961aa 100644 --- a/devicetypes/smartthings/aeon-siren.src/aeon-siren.groovy +++ b/devicetypes/smartthings/aeon-siren.src/aeon-siren.groovy @@ -20,10 +20,11 @@ metadata { capability "Actuator" capability "Alarm" capability "Switch" + capability "Health Check" command "test" - fingerprint deviceId: "0x1005", inClusters: "0x5E,0x98" + fingerprint deviceId: "0x1005", inClusters: "0x5E,0x98", deviceJoinName: "Aeon Labs Siren (Gen 5)" } simulator { @@ -58,6 +59,9 @@ metadata { } def updated() { +// Device-Watch simply pings if no device events received for 32min(checkInterval) + sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) + if(!state.sound) state.sound = 1 if(!state.volume) state.volume = 3 @@ -148,3 +152,10 @@ def test() { private secure(physicalgraph.zwave.Command cmd) { zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format() } + +/** + * PING is used by Device-Watch in attempt to reach the Device + * */ +def ping() { + secure(zwave.basicV1.basicGet()) +} \ No newline at end of file From 0a4d56be04e22c58a7caf929be1f4cd082008a6f Mon Sep 17 00:00:00 2001 From: "piyush.c" Date: Wed, 15 Mar 2017 19:09:17 +0530 Subject: [PATCH 05/16] [CHF-551] Health Check Z-Wave Lock --- .../smartthings/zwave-lock.src/.st-ignore | 2 + .../smartthings/zwave-lock.src/README.md | 45 +++++++++++++++++++ .../zwave-lock.src/zwave-lock.groovy | 11 +++++ 3 files changed, 58 insertions(+) create mode 100644 devicetypes/smartthings/zwave-lock.src/.st-ignore create mode 100644 devicetypes/smartthings/zwave-lock.src/README.md diff --git a/devicetypes/smartthings/zwave-lock.src/.st-ignore b/devicetypes/smartthings/zwave-lock.src/.st-ignore new file mode 100644 index 0000000..f78b46e --- /dev/null +++ b/devicetypes/smartthings/zwave-lock.src/.st-ignore @@ -0,0 +1,2 @@ +.st-ignore +README.md diff --git a/devicetypes/smartthings/zwave-lock.src/README.md b/devicetypes/smartthings/zwave-lock.src/README.md new file mode 100644 index 0000000..ae64536 --- /dev/null +++ b/devicetypes/smartthings/zwave-lock.src/README.md @@ -0,0 +1,45 @@ +# Z-Wave Switch + +Cloud Execution + +Works with: + +* [Yale Key Free Touchscreen Deadbolt (YRD240)](https://www.smartthings.com/works-with-smartthings/yale/yale-key-free-touchscreen-deadbolt-yrd240) + + +## Table of contents + +* [Capabilities](#capabilities) +* [Health](#device-health) +* [Troubleshooting](#Troubleshooting) + +## Capabilities + +* **Actuator** - represents that a Device has commands +* **Battery** - defines device uses a battery +* **Lock** - allows for the control of a lock device +* **Lock Codes** - allows for the lock code control of a lock device +* **Polling** - represents that poll() can be implemented for the device +* **Refresh** - _refresh()_ command for status updates +* **Sensor** - detects sensor events +* **Health Check** - indicates ability to get device health notifications + +## Device Health + +Z-Wave Locks are polled by the hub. +As of hubCore version 0.14.38 the hub sends up reports every 15 minutes regardless of whether the state changed. +Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*15 + 2)mins = 32 mins. +Not to mention after going OFFLINE when the device is plugged back in, it might take a considerable amount of time for +the device to appear as ONLINE again. This is because if this listening device does not respond to two poll requests in a row, +it is not polled for 5 minutes by the hub. This can delay up the process of being marked ONLINE by quite some time. + +* __32min__ checkInterval + +## Troubleshooting + +If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range. +Pairing needs to be tried again by placing the device closer to the hub. +Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link: +* [General Z-Wave/ZigBee Yale Lock Troubleshooting](https://support.smartthings.com/hc/en-us/articles/205138400-How-to-connect-Yale-locks) + + diff --git a/devicetypes/smartthings/zwave-lock.src/zwave-lock.groovy b/devicetypes/smartthings/zwave-lock.src/zwave-lock.groovy index 0535ffa..2785467 100644 --- a/devicetypes/smartthings/zwave-lock.src/zwave-lock.groovy +++ b/devicetypes/smartthings/zwave-lock.src/zwave-lock.groovy @@ -20,11 +20,13 @@ metadata { capability "Sensor" capability "Lock Codes" capability "Battery" + capability "Health Check" command "unlockwtimeout" fingerprint deviceId: "0x4003", inClusters: "0x98" fingerprint deviceId: "0x4004", inClusters: "0x98" + fingerprint mfr:"0129", prod:"0002", model:"0000", deviceJoinName: "Yale Key Free Touchscreen Deadbolt" } simulator { @@ -67,6 +69,8 @@ import physicalgraph.zwave.commands.doorlockv1.* import physicalgraph.zwave.commands.usercodev1.* def updated() { + // Device-Watch simply pings if no device events received for 32min(checkInterval) + sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) try { if (!state.init) { state.init = true @@ -504,6 +508,13 @@ def unlockwtimeout() { lockAndCheck(DoorLockOperationSet.DOOR_LOCK_MODE_DOOR_UNSECURED_WITH_TIMEOUT) } +/** + * PING is used by Device-Watch in attempt to reach the Device + * */ +def ping() { + refresh() +} + def refresh() { def cmds = [secure(zwave.doorLockV1.doorLockOperationGet())] if (state.assoc == zwaveHubNodeId) { From a79d56e4676ee651519fe4459715b20e913d770e Mon Sep 17 00:00:00 2001 From: Zach Varberg Date: Thu, 16 Mar 2017 08:24:10 -0500 Subject: [PATCH 06/16] Properly handle tempOffset in smartsense sensors This was accidentally dropped as a part of the zigbee DTH cleanup that was done a while ago. This properly adjusts according to the offset. This resolves: https://smartthings.atlassian.net/browse/DVCSMP-2516 --- .../smartsense-moisture-sensor.groovy | 6 ++++++ .../smartsense-motion-sensor.groovy | 6 ++++++ .../smartsense-open-closed-sensor.groovy | 6 ++++++ .../smartsense-temp-humidity-sensor.groovy | 6 ++++++ 4 files changed, 24 insertions(+) diff --git a/devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy b/devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy index 4d27081..a9b68cd 100644 --- a/devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy +++ b/devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy @@ -106,6 +106,12 @@ def parse(String description) { } } } + } else if (map.name == "temperature") { + if (tempOffset) { + map.value = (int) map.value + (int) tempOffset + } + map.descriptionText = temperatureScale == 'C' ? '{{ device.displayName }} was {{ value }}°C' : '{{ device.displayName }} was {{ value }}°F' + map.translatable = true } log.debug "Parse returned $map" diff --git a/devicetypes/smartthings/smartsense-motion-sensor.src/smartsense-motion-sensor.groovy b/devicetypes/smartthings/smartsense-motion-sensor.src/smartsense-motion-sensor.groovy index 2032d3f..c2265a2 100644 --- a/devicetypes/smartthings/smartsense-motion-sensor.src/smartsense-motion-sensor.groovy +++ b/devicetypes/smartthings/smartsense-motion-sensor.src/smartsense-motion-sensor.groovy @@ -112,6 +112,12 @@ def parse(String description) { map = getMotionResult(value) } } + } else if (map.name == "temperature") { + if (tempOffset) { + map.value = (int) map.value + (int) tempOffset + } + map.descriptionText = temperatureScale == 'C' ? '{{ device.displayName }} was {{ value }}°C' : '{{ device.displayName }} was {{ value }}°F' + map.translatable = true } log.debug "Parse returned $map" diff --git a/devicetypes/smartthings/smartsense-open-closed-sensor.src/smartsense-open-closed-sensor.groovy b/devicetypes/smartthings/smartsense-open-closed-sensor.src/smartsense-open-closed-sensor.groovy index cf68b3a..fc08a0a 100644 --- a/devicetypes/smartthings/smartsense-open-closed-sensor.src/smartsense-open-closed-sensor.groovy +++ b/devicetypes/smartthings/smartsense-open-closed-sensor.src/smartsense-open-closed-sensor.groovy @@ -95,6 +95,12 @@ def parse(String description) { } } } + } else if (map.name == "temperature") { + if (tempOffset) { + map.value = (int) map.value + (int) tempOffset + } + map.descriptionText = temperatureScale == 'C' ? '{{ device.displayName }} was {{ value }}°C' : '{{ device.displayName }} was {{ value }}°F' + map.translatable = true } log.debug "Parse returned $map" diff --git a/devicetypes/smartthings/smartsense-temp-humidity-sensor.src/smartsense-temp-humidity-sensor.groovy b/devicetypes/smartthings/smartsense-temp-humidity-sensor.src/smartsense-temp-humidity-sensor.groovy index c0fe4b0..a655c21 100644 --- a/devicetypes/smartthings/smartsense-temp-humidity-sensor.src/smartsense-temp-humidity-sensor.groovy +++ b/devicetypes/smartthings/smartsense-temp-humidity-sensor.src/smartsense-temp-humidity-sensor.groovy @@ -88,6 +88,12 @@ def parse(String description) { log.warn "TEMP REPORTING CONFIG FAILED- error code: ${descMap.data[0]}" } } + } else if (map.name == "temperature") { + if (tempOffset) { + map.value = (int) map.value + (int) tempOffset + } + map.descriptionText = temperatureScale == 'C' ? '{{ device.displayName }} was {{ value }}°C' : '{{ device.displayName }} was {{ value }}°F' + map.translatable = true } log.debug "Parse returned $map" From 8a3c9edf0ab0fc6abf2d1721327f76eafc6a95d5 Mon Sep 17 00:00:00 2001 From: Parijat Das Date: Mon, 20 Mar 2017 14:54:14 -0700 Subject: [PATCH 07/16] Added health-check for Aeon Multisensor Gen5 --- .../aeon-multisensor-gen5.src/.st-ignore | 2 + .../aeon-multisensor-gen5.src/README.md | 43 +++++++++++++++++++ .../aeon-multisensor-gen5.groovy | 14 ++++++ 3 files changed, 59 insertions(+) create mode 100644 devicetypes/smartthings/aeon-multisensor-gen5.src/.st-ignore create mode 100644 devicetypes/smartthings/aeon-multisensor-gen5.src/README.md diff --git a/devicetypes/smartthings/aeon-multisensor-gen5.src/.st-ignore b/devicetypes/smartthings/aeon-multisensor-gen5.src/.st-ignore new file mode 100644 index 0000000..f78b46e --- /dev/null +++ b/devicetypes/smartthings/aeon-multisensor-gen5.src/.st-ignore @@ -0,0 +1,2 @@ +.st-ignore +README.md diff --git a/devicetypes/smartthings/aeon-multisensor-gen5.src/README.md b/devicetypes/smartthings/aeon-multisensor-gen5.src/README.md new file mode 100644 index 0000000..62a8f9a --- /dev/null +++ b/devicetypes/smartthings/aeon-multisensor-gen5.src/README.md @@ -0,0 +1,43 @@ +# Aeon Multisensor Gen5 + +Cloud Execution + +Works with: + +* [Aeon Labs MultiSensor (Gen 5)](https://www.smartthings.com/works-with-smartthings/sensors/aeon-labs-multisensor-gen-5) + +## Table of contents + +* [Capabilities](#capabilities) +* [Health](#device-health) +* [Troubleshooting](#troubleshooting) + +## Capabilities + +* **Motion Sensor** - can detect motion +* **Temperature Measurement** - defines device measures current temperature +* **Relative Humidity Measurement** - allow reading the relative humidity from devices that support it +* **Illuminance Measurement** - gives the illuminance reading from devices that support it +* **Configuration** - _configure()_ command called when device is installed or device preferences updated +* **Sensor** - detects sensor events +* **Battery** - defines device uses a battery +* **Health Check** - indicates ability to get device health notifications + + +## Device Health + +Aeon Labs MultiSensor (Gen 5) is polled by the hub. +As of hubCore version 0.14.38 the hub sends up reports every 15 minutes regardless of whether the state changed. +Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*15 + 2)mins = 32 mins. +Not to mention after going OFFLINE when the device is plugged back in, it might take a considerable amount of time for +the device to appear as ONLINE again. This is because if this listening device does not respond to two poll requests in a row, +it is not polled for 5 minutes by the hub. This can delay up the process of being marked ONLINE by quite some time. + +* __32min__ checkInterval + +## Troubleshooting + +If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range. +Pairing needs to be tried again by placing the device closer to the hub. +Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link: +* [Aeon Labs MultiSensor (Gen 5) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206157226-Aeon-Labs-MultiSensor-Gen-5-) \ No newline at end of file diff --git a/devicetypes/smartthings/aeon-multisensor-gen5.src/aeon-multisensor-gen5.groovy b/devicetypes/smartthings/aeon-multisensor-gen5.src/aeon-multisensor-gen5.groovy index 04888d3..09e3f2b 100644 --- a/devicetypes/smartthings/aeon-multisensor-gen5.src/aeon-multisensor-gen5.groovy +++ b/devicetypes/smartthings/aeon-multisensor-gen5.src/aeon-multisensor-gen5.groovy @@ -20,10 +20,12 @@ metadata { capability "Configuration" capability "Sensor" capability "Battery" + capability "Health Check" command "configureAfterSecure" fingerprint deviceId: "0x0701", inClusters: "0x5E,0x86,0x72,0x59,0x85,0x73,0x71,0x84,0x80,0x30,0x31,0x70,0x98,0x7A", outClusters:"0x5A" + fingerprint mfr:"0086", prod:"0102", model:"004A", deviceJoinName: "Aeon Labs MultiSensor (Gen 5)" } simulator { @@ -98,6 +100,11 @@ metadata { } } +def updated(){ +// Device-Watch simply pings if no device events received for 32min(checkInterval) + sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) +} + def parse(String description) { def result = null @@ -244,6 +251,13 @@ def configureAfterSecure() { secureSequence(request) + ["delay 20000", zwave.wakeUpV1.wakeUpNoMoreInformation().format()] } +/** + * PING is used by Device-Watch in attempt to reach the Device + * */ +def ping() { + secure(zwave.batteryV1.batteryGet()) +} + def configure() { // log.debug "configure()" //["delay 30000"] + secure(zwave.securityV1.securityCommandsSupportedGet()) From 26f9690190b4e412269903642674151284082a11 Mon Sep 17 00:00:00 2001 From: Parijat Das Date: Wed, 15 Mar 2017 15:29:45 -0700 Subject: [PATCH 08/16] Added health-check for First Alert Smoke Detector and Carbon Monoxide Alarm (ZCOMBO) --- .../zwave-smoke-alarm.src/.st-ignore | 2 + .../zwave-smoke-alarm.src/README.md | 40 +++++++++++++++++++ .../zwave-smoke-alarm.groovy | 8 +++- 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 devicetypes/smartthings/zwave-smoke-alarm.src/.st-ignore create mode 100644 devicetypes/smartthings/zwave-smoke-alarm.src/README.md diff --git a/devicetypes/smartthings/zwave-smoke-alarm.src/.st-ignore b/devicetypes/smartthings/zwave-smoke-alarm.src/.st-ignore new file mode 100644 index 0000000..f78b46e --- /dev/null +++ b/devicetypes/smartthings/zwave-smoke-alarm.src/.st-ignore @@ -0,0 +1,2 @@ +.st-ignore +README.md diff --git a/devicetypes/smartthings/zwave-smoke-alarm.src/README.md b/devicetypes/smartthings/zwave-smoke-alarm.src/README.md new file mode 100644 index 0000000..846990c --- /dev/null +++ b/devicetypes/smartthings/zwave-smoke-alarm.src/README.md @@ -0,0 +1,40 @@ +# Z-wave Smoke Alarm + +Cloud Execution + +Works with: + +* [First Alert Smoke Detector and Carbon Monoxide Alarm (ZCOMBO)](https://www.smartthings.com/works-with-smartthings/sensors/first-alert-smoke-detector-and-carbon-monoxide-alarm-zcombo) + +## Table of contents + +* [Capabilities](#capabilities) +* [Health](#device-health) +* [Battery](#battery-specification) +* [Troubleshooting](#troubleshooting) + +## Capabilities + +* **Smoke Detector** - measure smoke and optionally carbon monoxide levels +* **Carbon Monoxide Detector** - measure carbon monoxide levels +* **Sensor** - detects sensor events +* **Battery** - defines device uses a battery +* **Health Check** - indicates ability to get device health notifications + +## Device Health + +First Alert Smoke Detector and Carbon Monoxide Alarm (ZCOMBO) is a Z-wave sleepy device and checks in every 1 hour. +Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*60 + 2)mins = 122 mins. + +* __122min__ checkInterval + +## Battery Specification + +Two AA 1.5V batteries are required. + +## Troubleshooting + +If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range. +Pairing needs to be tried again by placing the device closer to the hub. +Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link: +* [First Alert Smoke Detector and Carbon Monoxide Alarm (ZCOMBO) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/201581984-First-Alert-Smoke-Detector-and-Carbon-Monoxide-Alarm-ZCOMBO-) \ No newline at end of file diff --git a/devicetypes/smartthings/zwave-smoke-alarm.src/zwave-smoke-alarm.groovy b/devicetypes/smartthings/zwave-smoke-alarm.src/zwave-smoke-alarm.groovy index aa426e4..f644386 100644 --- a/devicetypes/smartthings/zwave-smoke-alarm.src/zwave-smoke-alarm.groovy +++ b/devicetypes/smartthings/zwave-smoke-alarm.src/zwave-smoke-alarm.groovy @@ -17,10 +17,12 @@ metadata { capability "Carbon Monoxide Detector" capability "Sensor" capability "Battery" + capability "Health Check" attribute "alarmState", "string" fingerprint deviceId: "0xA100", inClusters: "0x20,0x80,0x70,0x85,0x71,0x72,0x86" + fingerprint mfr:"0138", prod:"0001", model:"0002", deviceJoinName: "First Alert Smoke Detector and Carbon Monoxide Alarm (ZCOMBO)" } simulator { @@ -51,6 +53,11 @@ metadata { } } +def updated(){ +// Device checks in every hour, this interval allows us to miss one check-in notification before marking offline + sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) +} + def parse(String description) { def results = [] if (description.startsWith("Err")) { @@ -65,7 +72,6 @@ def parse(String description) { return results } - def createSmokeOrCOEvents(name, results) { def text = null switch (name) { From 668f71a217195248e6f0ea9db7dfa61921905ac0 Mon Sep 17 00:00:00 2001 From: Lars Finander Date: Mon, 20 Mar 2017 16:43:22 -0600 Subject: [PATCH 09/16] Hue: Add localization for Hue (Connect) -Added i18 files -Updates strings --- .../hue-connect.src/hue-connect.groovy | 264 +++++++++--------- .../hue-connect.src/i18n/ar_AE.properties | 19 ++ .../hue-connect.src/i18n/bg_BG.properties | 19 ++ .../hue-connect.src/i18n/cs_CZ.properties | 19 ++ .../hue-connect.src/i18n/da_DK.properties | 19 ++ .../hue-connect.src/i18n/de_AT.properties | 19 ++ .../hue-connect.src/i18n/de_CH.properties | 19 ++ .../hue-connect.src/i18n/de_DE.properties | 19 ++ .../hue-connect.src/i18n/el_GR.properties | 19 ++ .../hue-connect.src/i18n/en_AU.properties | 19 ++ .../hue-connect.src/i18n/en_CA.properties | 19 ++ .../hue-connect.src/i18n/en_GB.properties | 19 ++ .../hue-connect.src/i18n/en_IE.properties | 19 ++ .../hue-connect.src/i18n/en_NZ.properties | 19 ++ .../hue-connect.src/i18n/en_PH.properties | 19 ++ .../hue-connect.src/i18n/en_ZA.properties | 19 ++ .../hue-connect.src/i18n/es_ES.properties | 19 ++ .../hue-connect.src/i18n/es_US.properties | 19 ++ .../hue-connect.src/i18n/et_EE.properties | 19 ++ .../hue-connect.src/i18n/fi_FI.properties | 19 ++ .../hue-connect.src/i18n/fr_BE.properties | 19 ++ .../hue-connect.src/i18n/fr_CA.properties | 19 ++ .../hue-connect.src/i18n/fr_CH.properties | 19 ++ .../hue-connect.src/i18n/fr_FR.properties | 19 ++ .../hue-connect.src/i18n/hr_HR.properties | 19 ++ .../hue-connect.src/i18n/hu_HU.properties | 19 ++ .../hue-connect.src/i18n/it_IT.properties | 19 ++ .../hue-connect.src/i18n/ko_KR.properties | 19 ++ .../hue-connect.src/i18n/nb_NO.properties | 19 ++ .../hue-connect.src/i18n/nl_BE.properties | 19 ++ .../hue-connect.src/i18n/nl_NL.properties | 19 ++ .../hue-connect.src/i18n/pl_PL.properties | 19 ++ .../hue-connect.src/i18n/pt_BR.properties | 19 ++ .../hue-connect.src/i18n/pt_PT.properties | 19 ++ .../hue-connect.src/i18n/ro_RO.properties | 19 ++ .../hue-connect.src/i18n/ru_RU.properties | 19 ++ .../hue-connect.src/i18n/sk_SK.properties | 19 ++ .../hue-connect.src/i18n/sl_SI.properties | 19 ++ .../hue-connect.src/i18n/sq_AL.properties | 19 ++ .../hue-connect.src/i18n/sr_RS.properties | 19 ++ .../hue-connect.src/i18n/sv_SE.properties | 19 ++ .../hue-connect.src/i18n/th_TH.properties | 19 ++ .../hue-connect.src/i18n/tr_TR.properties | 19 ++ .../hue-connect.src/i18n/zh_CN.properties | 19 ++ 44 files changed, 946 insertions(+), 135 deletions(-) create mode 100644 smartapps/smartthings/hue-connect.src/i18n/ar_AE.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/bg_BG.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/cs_CZ.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/da_DK.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/de_AT.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/de_CH.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/de_DE.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/el_GR.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/en_AU.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/en_CA.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/en_GB.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/en_IE.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/en_NZ.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/en_PH.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/en_ZA.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/es_ES.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/es_US.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/et_EE.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/fi_FI.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/fr_BE.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/fr_CA.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/fr_CH.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/fr_FR.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/hr_HR.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/hu_HU.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/it_IT.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/ko_KR.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/nb_NO.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/nl_BE.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/nl_NL.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/pl_PL.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/pt_BR.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/pt_PT.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/ro_RO.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/ru_RU.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/sk_SK.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/sl_SI.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/sq_AL.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/sr_RS.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/sv_SE.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/th_TH.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/tr_TR.properties create mode 100644 smartapps/smartthings/hue-connect.src/i18n/zh_CN.properties diff --git a/smartapps/smartthings/hue-connect.src/hue-connect.groovy b/smartapps/smartthings/hue-connect.src/hue-connect.groovy index 8870987..5ded2b2 100644 --- a/smartapps/smartthings/hue-connect.src/hue-connect.groovy +++ b/smartapps/smartthings/hue-connect.src/hue-connect.groovy @@ -15,12 +15,13 @@ * for the specific language governing permissions and limitations under the License. * */ +include 'localization' definition( name: "Hue (Connect)", namespace: "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. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.", category: "SmartThings Labs", iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/hue.png", iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/hue@2x.png", @@ -28,11 +29,11 @@ definition( ) preferences { - page(name:"mainPage", title:"Hue Device Setup", content:"mainPage", refreshTimeout:5) - page(name:"bridgeDiscovery", title:"Hue Bridge Discovery", content:"bridgeDiscovery", refreshTimeout:5) - page(name:"bridgeDiscoveryFailed", title:"Bridge Discovery Failed", content:"bridgeDiscoveryFailed", refreshTimeout:0) - page(name:"bridgeBtnPush", title:"Linking with your Hue", content:"bridgeLinking", refreshTimeout:5) - page(name:"bulbDiscovery", title:"Hue Device Setup", content:"bulbDiscovery", refreshTimeout:5) + page(name: "mainPage", title: "", content: "mainPage", refreshTimeout: 5) + page(name: "bridgeDiscovery", title: "", content: "bridgeDiscovery", refreshTimeout: 5) + page(name: "bridgeDiscoveryFailed", title: "", content: "bridgeDiscoveryFailed", refreshTimeout: 0) + page(name: "bridgeBtnPush", title: "", content: "bridgeLinking", refreshTimeout: 5) + page(name: "bulbDiscovery", title: "", content: "bulbDiscovery", refreshTimeout: 5) } def mainPage() { @@ -47,15 +48,14 @@ def mainPage() { } } -def bridgeDiscovery(params=[:]) -{ +def bridgeDiscovery(params = [:]) { def bridges = bridgesDiscovered() int bridgeRefreshCount = !state.bridgeRefreshCount ? 0 : state.bridgeRefreshCount as int state.bridgeRefreshCount = bridgeRefreshCount + 1 def refreshInterval = 3 def options = bridges ?: [] - def numFound = options.size() ?: 0 + def numFound = options.size() ?: "0" if (numFound == 0) { if (state.bridgeRefreshCount == 25) { log.trace "Cleaning old bridges memory" @@ -75,25 +75,26 @@ def bridgeDiscovery(params=[:]) ssdpSubscribe() //bridge discovery request every 15 //25 seconds - if((bridgeRefreshCount % 5) == 0) { + if ((bridgeRefreshCount % 5) == 0) { discoverBridges() } //setup.xml request every 3 seconds except on discoveries - if(((bridgeRefreshCount % 3) == 0) && ((bridgeRefreshCount % 5) != 0)) { + if (((bridgeRefreshCount % 3) == 0) && ((bridgeRefreshCount % 5) != 0)) { verifyHueBridges() } - return dynamicPage(name:"bridgeDiscovery", title:"Discovery Started!", nextPage:"bridgeBtnPush", refreshInterval:refreshInterval, uninstall: true) { - 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 + return dynamicPage(name: "bridgeDiscovery", title: "Discovery Started!", nextPage: "bridgeBtnPush", refreshInterval: refreshInterval, uninstall: true) { + 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(name: "selectedHue", type: "enum", required: false, title: "Select Hue Bridge ({{numFound}} found)", messageArgs: [numFound: numFound], multiple: false, options: options, submitOnChange: true) } } } def bridgeDiscoveryFailed() { - return dynamicPage(name:"bridgeDiscoveryFailed", title: "Bridge Discovery Failed", nextPage: "bridgeDiscovery") { + return dynamicPage(name: "bridgeDiscoveryFailed", title: "Bridge Discovery Failed!", nextPage: "bridgeDiscovery") { section("Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.") { } } @@ -109,12 +110,12 @@ def bridgeLinking() { def paragraphText if (selectedHue) { if (state.refreshUsernameNeeded) { - paragraphText = "The current Hue username is invalid.\n\nPlease press the button on your Hue Bridge to re-link. " + paragraphText = "The current Hue username is invalid. Please press the button on your Hue Bridge to relink." } else { - paragraphText = "Press the button on your Hue Bridge to setup a link. " + paragraphText = "Press the button on your Hue Bridge to setup a link." } } else { - paragraphText = "You haven't selected a Hue Bridge, please Press \"Done\" and select one before clicking next." + paragraphText = "You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next." } if (state.username) { //if discovery worked if (state.refreshUsernameNeeded) { @@ -127,13 +128,13 @@ def bridgeLinking() { paragraphText = "Linking to your hub was a success! Please click 'Next'!" } - if((linkRefreshcount % 2) == 0 && !state.username) { + if ((linkRefreshcount % 2) == 0 && !state.username) { sendDeveloperReq() } - return dynamicPage(name:"bridgeBtnPush", title:title, nextPage:nextPage, refreshInterval:refreshInterval) { + return dynamicPage(name: "bridgeBtnPush", title: title, nextPage: nextPage, refreshInterval: refreshInterval) { section("") { - paragraph """${paragraphText}""" + paragraph "$paragraphText" } } } @@ -149,18 +150,18 @@ def bulbDiscovery() { def allLightsFound = bulbsDiscovered() ?: [:] // List lights currently not added to the user (editable) - def newLights = allLightsFound.findAll {getChildDevice(it.key) == null} ?: [:] - newLights = newLights.sort {it.value.toLowerCase()} + def newLights = allLightsFound.findAll { getChildDevice(it.key) == null } ?: [:] + newLights = newLights.sort { it.value.toLowerCase() } // List lights already added to the user (not editable) - def existingLights = allLightsFound.findAll {getChildDevice(it.key) != null} ?: [:] - existingLights = existingLights.sort {it.value.toLowerCase()} + def existingLights = allLightsFound.findAll { getChildDevice(it.key) != null } ?: [:] + existingLights = existingLights.sort { it.value.toLowerCase() } - def numFound = newLights.size() ?: 0 - if (numFound == 0) + def numFound = newLights.size() ?: "0" + if (numFound == "0") app.updateSetting("selectedBulbs", "") - if((bulbRefreshCount % 5) == 0) { + if ((bulbRefreshCount % 5) == 0) { discoverHueBulbs() } def selectedBridge = state.bridges.find { key, value -> value?.serialNumber?.equalsIgnoreCase(selectedHue) } @@ -178,14 +179,14 @@ def bulbDiscovery() { } } - if (bulbRefreshCount > 200 && numFound == 0) { + def existingLightsSize = "${existingLights.size()}" + if (bulbRefreshCount > 200 && numFound == "0") { // Time out after 10 minutes state.inBulbDiscovery = false bulbRefreshCount = 0 - return dynamicPage(name:"bulbDiscovery", title:"Light Discovery Failed!", nextPage:"", refreshInterval:0, install:true, uninstall: true) { - section("Failed to discover any lights, please try again later. Click Done to exit.") { - //input "selectedBulbs", "enum", required:false, title:"Select Hue Lights to add (${numFound} found)", multiple:true, submitOnChange: true, options:newLights - paragraph title: "Previously added Hue Lights (${existingLights.size()} added)", existingLightsDescription + return dynamicPage(name: "bulbDiscovery", title: "Light Discovery Failed!", nextPage: "", refreshInterval: 0, install: true, uninstall: true) { + section("Failed to discover any lights, please try again later. Click 'Done' to exit.") { + paragraph title: "Previously added Hue Lights ({{existingLightsSize}} added)", messageArgs: [existingLightsSize: existingLightsSize], existingLightsDescription } section { href "bridgeDiscovery", title: title, description: "", state: selectedHue ? "complete" : "incomplete", params: [override: true] @@ -193,10 +194,10 @@ def bulbDiscovery() { } } else { - return dynamicPage(name:"bulbDiscovery", title:"Light Discovery Started!", nextPage:"", refreshInterval:refreshInterval, install:true, uninstall: true) { + return dynamicPage(name: "bulbDiscovery", title: "Light Discovery Started!", nextPage: "", refreshInterval: refreshInterval, install: true, uninstall: true) { section("Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.") { - input "selectedBulbs", "enum", required:false, title:"Select Hue Lights to add (${numFound} found)", multiple:true, submitOnChange: true, options:newLights - paragraph title: "Previously added Hue Lights (${existingLights.size()} added)", existingLightsDescription + input(name: "selectedBulbs", type: "enum", required: false, title: "Select Hue Lights to add ({{numFound}} found)", messageArgs: [numFound: numFound], multiple: true, submitOnChange: true, options: newLights) + paragraph title: "Previously added Hue Lights ({{existingLightsSize}} added)", messageArgs: [existingLightsSize: existingLightsSize], existingLightsDescription } section { href "bridgeDiscovery", title: title, description: "", state: selectedHue ? "complete" : "incomplete", params: [override: true] @@ -217,19 +218,19 @@ private sendDeveloperReq() { def token = app.id def host = getBridgeIP() sendHubCommand(new physicalgraph.device.HubAction([ - method: "POST", - path: "/api", + method : "POST", + path : "/api", headers: [ HOST: host ], - body: [devicetype: "$token-0"]], "${selectedHue}", [callback: "usernameHandler"])) + body : [devicetype: "$token-0"]], "${selectedHue}", [callback: "usernameHandler"])) } private discoverHueBulbs() { def host = getBridgeIP() sendHubCommand(new physicalgraph.device.HubAction([ - method: "GET", - path: "/api/${state.username}/lights", + method : "GET", + path : "/api/${state.username}/lights", headers: [ HOST: host ]], "${selectedHue}", [callback: "lightsHandler"])) @@ -238,8 +239,8 @@ private discoverHueBulbs() { private verifyHueBridge(String deviceNetworkId, String host) { log.trace "Verify Hue Bridge $deviceNetworkId" sendHubCommand(new physicalgraph.device.HubAction([ - method: "GET", - path: "/description.xml", + method : "GET", + path : "/description.xml", headers: [ HOST: host ]], deviceNetworkId, [callback: "bridgeDescriptionHandler"])) @@ -266,18 +267,18 @@ Map bridgesDiscovered() { } Map bulbsDiscovered() { - def bulbs = getHueBulbs() + def bulbs = getHueBulbs() def bulbmap = [:] if (bulbs instanceof java.util.Map) { bulbs.each { def value = "${it.value.name}" - def key = app.id +"/"+ it.value.id + def key = app.id + "/" + it.value.id bulbmap["${key}"] = value } } else { //backwards compatable bulbs.each { def value = "${it.name}" - def key = app.id +"/"+ it.id + def key = app.id + "/" + it.id logg += "$value - $key, " bulbmap["${key}"] = value } @@ -294,7 +295,7 @@ def getHueBridges() { } def getVerifiedHueBridges() { - getHueBridges().findAll{ it?.value?.verified == true } + getHueBridges().findAll { it?.value?.verified == true } } def installed() { @@ -331,7 +332,7 @@ def manualRefresh() { poll() } -def uninstalled(){ +def uninstalled() { // Remove bridgedevice connection to allow uninstall of smartapp even though bridge is listed // as user of smartapp app.updateSetting("bridgeDevice", null) @@ -371,7 +372,7 @@ private getDeviceType(hueType) { return null } -private addChildBulb(dni, hueType, name, hub, update=false, device = null) { +private addChildBulb(dni, hueType, name, hub, update = false, device = null) { def deviceType = getDeviceType(hueType) if (deviceType) { @@ -386,7 +387,7 @@ def addBulbs() { def bulbs = getHueBulbs() selectedBulbs?.each { dni -> def d = getChildDevice(dni) - if(!d) { + if (!d) { def newHueBulb if (bulbs instanceof java.util.Map) { newHueBulb = bulbs.find { (app.id + "/" + it.value.id) == dni } @@ -419,11 +420,11 @@ def addBulbs() { def addBridge() { def vbridges = getVerifiedHueBridges() - def vbridge = vbridges.find {"${it.value.mac}" == selectedHue} + def vbridge = vbridges.find { "${it.value.mac}" == selectedHue } - if(vbridge) { + if (vbridge) { def d = getChildDevice(selectedHue) - if(!d) { + if (!d) { // compatibility with old devices def newbridge = true childDevices.each { @@ -458,20 +459,22 @@ def addBridge() { childDevice?.sendEvent(name: "idNumber", value: idNumber) if (vbridge.value.ip && vbridge.value.port) { if (vbridge.value.ip.contains(".")) { - childDevice.sendEvent(name: "networkAddress", value: vbridge.value.ip + ":" + vbridge.value.port) - childDevice.updateDataValue("networkAddress", vbridge.value.ip + ":" + vbridge.value.port) + childDevice.sendEvent(name: "networkAddress", value: vbridge.value.ip + ":" + vbridge.value.port) + childDevice.updateDataValue("networkAddress", vbridge.value.ip + ":" + vbridge.value.port) } else { - childDevice.sendEvent(name: "networkAddress", value: convertHexToIP(vbridge.value.ip) + ":" + convertHexToInt(vbridge.value.port)) - childDevice.updateDataValue("networkAddress", convertHexToIP(vbridge.value.ip) + ":" + convertHexToInt(vbridge.value.port)) + childDevice.sendEvent(name: "networkAddress", value: convertHexToIP(vbridge.value.ip) + ":" + convertHexToInt(vbridge.value.port)) + childDevice.updateDataValue("networkAddress", convertHexToIP(vbridge.value.ip) + ":" + convertHexToInt(vbridge.value.port)) } } else { - childDevice.sendEvent(name: "networkAddress", value: convertHexToIP(vbridge.value.networkAddress) + ":" + convertHexToInt(vbridge.value.deviceAddress)) - childDevice.updateDataValue("networkAddress", convertHexToIP(vbridge.value.networkAddress) + ":" + convertHexToInt(vbridge.value.deviceAddress)) + childDevice.sendEvent(name: "networkAddress", value: convertHexToIP(vbridge.value.networkAddress) + ":" + convertHexToInt(vbridge.value.deviceAddress)) + childDevice.updateDataValue("networkAddress", convertHexToIP(vbridge.value.networkAddress) + ":" + convertHexToInt(vbridge.value.deviceAddress)) } } else { log.error "Failed to create Hue Bridge device" } } + } else { + log.debug "found ${d.displayName} with id $selectedHue already exists" } } } @@ -482,14 +485,14 @@ def ssdpBridgeHandler(evt) { def hub = evt?.hubId def parsedEvent = parseLanMessage(description) - parsedEvent << ["hub":hub] + parsedEvent << ["hub": hub] def bridges = getHueBridges() log.trace bridges.toString() if (!(bridges."${parsedEvent.ssdpUSN.toString()}")) { //bridge does not exist log.trace "Adding bridge ${parsedEvent.ssdpUSN}" - bridges << ["${parsedEvent.ssdpUSN.toString()}":parsedEvent] + bridges << ["${parsedEvent.ssdpUSN.toString()}": parsedEvent] } else { // update the values def ip = convertHexToIP(parsedEvent.networkAddress) @@ -510,7 +513,7 @@ def ssdpBridgeHandler(evt) { bridge.setDeviceNetworkId("${dniReceived}") dstate.mac = dniReceived // Check to see if selectedHue is a valid bridge, otherwise update it - def isSelectedValid = bridges?.find {it.value?.mac == selectedHue} + def isSelectedValid = bridges?.find { it.value?.mac == selectedHue } if (isSelectedValid == null) { log.warn "Correcting selectedHue in state" app.updateSetting("selectedHue", dniReceived) @@ -530,7 +533,7 @@ def ssdpBridgeHandler(evt) { dstate.ip = ip dstate.port = port dstate.name = "Philips hue ($ip)" - d.sendEvent(name:"networkAddress", value: host) + d.sendEvent(name: "networkAddress", value: host) d.updateDataValue("networkAddress", host) } if (dstate.mac != dniReceived) { @@ -539,7 +542,7 @@ def ssdpBridgeHandler(evt) { } if (selectedHue != dniReceived) { // Check to see if selectedHue is a valid bridge, otherwise update it - def isSelectedValid = bridges?.find {it.value?.mac == selectedHue} + def isSelectedValid = bridges?.find { it.value?.mac == selectedHue } if (isSelectedValid == null) { log.warn "Correcting selectedHue in state" app.updateSetting("selectedHue", dniReceived) @@ -554,7 +557,7 @@ void bridgeDescriptionHandler(physicalgraph.device.HubResponse hubResponse) { def body = hubResponse.xml if (body?.device?.modelName?.text()?.startsWith("Philips hue bridge")) { def bridges = getHueBridges() - def bridge = bridges.find {it?.key?.contains(body?.device?.UDN?.text())} + def bridge = bridges.find { it?.key?.contains(body?.device?.UDN?.text()) } if (bridge) { def idNumber = getBridgeIdNumber(body?.device?.serialNumber?.text()) @@ -563,10 +566,10 @@ void bridgeDescriptionHandler(physicalgraph.device.HubResponse hubResponse) { def name = body?.device?.friendlyName?.text() def index = name?.indexOf('(') if (index != -1) { - name = name.substring(0,index) + name = name.substring(0, index) name += " ($idNumber)" } - bridge.value << [name:name, serialNumber:body?.device?.serialNumber?.text(), idNumber: idNumber, verified: true] + bridge.value << [name: name, serialNumber: body?.device?.serialNumber?.text(), idNumber: idNumber, verified: true] } else { log.error "/description.xml returned a bridge that didn't exist" } @@ -609,7 +612,7 @@ def locationHandler(evt) { def hub = evt?.hubId def parsedEvent = parseLanMessage(description) - parsedEvent << ["hub":hub] + parsedEvent << ["hub": hub] if (parsedEvent?.ssdpTerm?.contains("urn:schemas-upnp-org:device:basic:1")) { //SSDP DISCOVERY EVENTS @@ -619,7 +622,7 @@ def locationHandler(evt) { if (!(bridges."${parsedEvent.ssdpUSN.toString()}")) { //bridge does not exist log.trace "Adding bridge ${parsedEvent.ssdpUSN}" - bridges << ["${parsedEvent.ssdpUSN.toString()}":parsedEvent] + bridges << ["${parsedEvent.ssdpUSN.toString()}": parsedEvent] } else { // update the values def ip = convertHexToIP(parsedEvent.networkAddress) @@ -654,12 +657,12 @@ def locationHandler(evt) { networkAddress = d.latestState('networkAddress').stringValue } log.trace "Host: $host - $networkAddress" - if(host != networkAddress) { + if (host != networkAddress) { log.debug "Device's port or ip changed for device $d..." dstate.ip = ip dstate.port = port dstate.name = "Philips hue ($ip)" - d.sendEvent(name:"networkAddress", value: host) + d.sendEvent(name: "networkAddress", value: host) d.updateDataValue("networkAddress", host) } } @@ -672,14 +675,14 @@ def locationHandler(evt) { def body = new XmlSlurper().parseText(parsedEvent.body) if (body?.device?.modelName?.text().startsWith("Philips hue bridge")) { def bridges = getHueBridges() - def bridge = bridges.find {it?.key?.contains(body?.device?.UDN?.text())} + def bridge = bridges.find { it?.key?.contains(body?.device?.UDN?.text()) } if (bridge) { - bridge.value << [name:body?.device?.friendlyName?.text(), serialNumber:body?.device?.serialNumber?.text(), verified: true] + bridge.value << [name: body?.device?.friendlyName?.text(), serialNumber: body?.device?.serialNumber?.text(), verified: true] } else { log.error "/description.xml returned a bridge that didn't exist" } } - } else if(headerString?.contains("json") && isValidSource(parsedEvent.mac)) { + } else if (headerString?.contains("json") && isValidSource(parsedEvent.mac)) { log.trace "description.xml response (application/json)" def body = new groovy.json.JsonSlurper().parseText(parsedEvent.body) if (body.success != null) { @@ -704,7 +707,7 @@ def locationHandler(evt) { } } -def doDeviceSync(){ +def doDeviceSync() { log.trace "Doing Hue Device Sync!" // Check if state.updating failed to clear @@ -713,9 +716,6 @@ def doDeviceSync(){ log.warn "state.updating failed to clear" } - if (selectedHue) { - addBridge() - } convertBulbListToMap() poll() ssdpSubscribe() @@ -788,7 +788,7 @@ private void checkBridgeStatus() { def isValidSource(macAddress) { def vbridges = getVerifiedHueBridges() - return (vbridges?.find {"${it.value.mac}" == macAddress}) != null + return (vbridges?.find { "${it.value.mac}" == macAddress }) != null } def isInBulbDiscovery() { @@ -802,19 +802,19 @@ private updateBulbState(messageBody, hub) { def toRemove = [:] toRemove << bulbs - messageBody.each { k,v -> + messageBody.each { k, v -> if (v instanceof Map) { if (bulbs[k] == null) { bulbs[k] = [:] } - bulbs[k] << [id: k, name: v.name, type: v.type, modelid: v.modelid, hub:hub, remove: false] + bulbs[k] << [id: k, name: v.name, type: v.type, modelid: v.modelid, hub: hub, remove: false] toRemove.remove(k) } } // Remove bulbs from state that are no longer discovered - toRemove.each { k,v -> + toRemove.each { k, v -> log.warn "${bulbs[k].name} no longer exists on bridge, removing" bulbs.remove(k) } @@ -938,12 +938,11 @@ private sendBasicEvents(device, param, value) { * * Example payload * [, - * {"success":{"/lights/5/state/bri":87}}, - * {"success":{"/lights/5/state/transitiontime":4}}, - * {"success":{"/lights/5/state/on":true}}, - * {"success":{"/lights/5/state/xy":[0.4152,0.5336]}}, - * {"success":{"/lights/5/state/alert":"none"}} - * ] + *{"success":{"/lights/5/state/bri":87}}, + *{"success":{"/lights/5/state/transitiontime":4}}, + *{"success":{"/lights/5/state/on":true}}, + *{"success":{"/lights/5/state/xy":[0.4152,0.5336]}}, + *{"success":{"/lights/5/state/alert":"none"}}* ] * * @param body a data structure of lists and maps based on a JSON data * @return empty array @@ -996,7 +995,7 @@ private handleCommandResponse(body) { * * Example payload * - * {"5":{"state": {"on":true,"bri":102,"hue":25600,"sat":254,"effect":"none","xy":[0.1700,0.7000],"ct":153,"alert":"none", + *{"5":{"state": {"on":true,"bri":102,"hue":25600,"sat":254,"effect":"none","xy":[0.1700,0.7000],"ct":153,"alert":"none", * "colormode":"xy","reachable":true}, "type": "Extended color light", "name": "Go", "modelid": "LLC020", "manufacturername": "Philips", * "uniqueid":"00:17:88:01:01:13:d5:11-0b", "swversion": "5.38.1.14378"}, * "6":{"state": {"on":true,"bri":103,"hue":14910,"sat":144,"effect":"none","xy":[0.4596,0.4105],"ct":370,"alert":"none", @@ -1070,9 +1069,9 @@ def hubVerification(bodytext) { def body = new XmlSlurper().parseText(bodytext) if (body?.device?.modelName?.text().startsWith("Philips hue bridge")) { def bridges = getHueBridges() - def bridge = bridges.find {it?.key?.contains(body?.device?.UDN?.text())} + def bridge = bridges.find { it?.key?.contains(body?.device?.UDN?.text()) } if (bridge) { - bridge.value << [name:body?.device?.friendlyName?.text(), serialNumber:body?.device?.serialNumber?.text(), verified: true] + bridge.value << [name: body?.device?.friendlyName?.text(), serialNumber: body?.device?.serialNumber?.text(), verified: true] } else { log.error "/description.xml returned a bridge that didn't exist" } @@ -1108,7 +1107,7 @@ def setLevel(childDevice, percent) { else level = Math.min(Math.round(percent * 254 / 100), 254) - createSwitchEvent(childDevice, level > 0 ,percent) + createSwitchEvent(childDevice, level > 0, percent) // For Zigbee lights, if level is set to 0 ST just turns them off without changing level // that means that the light will still be on when on is called next time @@ -1138,7 +1137,7 @@ def setHue(childDevice, percent) { def id = getId(childDevice) updateInProgress() // 0 - 65535 - def level = Math.min(Math.round(percent * 65535 / 100), 65535) + def level = Math.min(Math.round(percent * 65535 / 100), 65535) // TODO should this be done by app only or should we default to on? createSwitchEvent(childDevice, "on") put("lights/$id/state", [hue: level, on: true]) @@ -1150,7 +1149,7 @@ def setColorTemperature(childDevice, huesettings) { def id = getId(childDevice) updateInProgress() // 153 (6500K) to 500 (2000K) - def ct = hueSettings == 6500 ? 153 : Math.round(1000000/huesettings) + def ct = hueSettings == 6500 ? 153 : Math.round(1000000 / huesettings) createSwitchEvent(childDevice, "on") put("lights/$id/state", [ct: ct, on: true]) return "Setting color temperature to $ct" @@ -1268,7 +1267,7 @@ private getBridgeIP() { def d = getChildDevice(selectedHue) if (d) { if (d.getDeviceDataByName("networkAddress")) - host = d.getDeviceDataByName("networkAddress") + host = d.getDeviceDataByName("networkAddress") else host = d.latestState('networkAddress').stringValue } @@ -1292,26 +1291,26 @@ private getBridgeIP() { } private Integer convertHexToInt(hex) { - Integer.parseInt(hex,16) + Integer.parseInt(hex, 16) } def convertBulbListToMap() { try { if (state.bulbs instanceof java.util.List) { def map = [:] - state.bulbs?.unique {it.id}.each { bulb -> - map << ["${bulb.id}":["id":bulb.id, "name":bulb.name, "type": bulb.type, "modelid": bulb.modelid, "hub":bulb.hub, "online": bulb.online]] + state.bulbs?.unique { it.id }.each { bulb -> + map << ["${bulb.id}": ["id": bulb.id, "name": bulb.name, "type": bulb.type, "modelid": bulb.modelid, "hub": bulb.hub, "online": bulb.online]] } state.bulbs = map } } - catch(Exception e) { + catch (Exception e) { log.error "Caught error attempting to convert bulb list to map: $e" } } private String convertHexToIP(hex) { - [convertHexToInt(hex[0..1]),convertHexToInt(hex[2..3]),convertHexToInt(hex[4..5]),convertHexToInt(hex[6..7])].join(".") + [convertHexToInt(hex[0..1]), convertHexToInt(hex[2..3]), convertHexToInt(hex[4..5]), convertHexToInt(hex[6..7])].join(".") } private Boolean hasAllHubsOver(String desiredFirmware) { @@ -1328,7 +1327,7 @@ private List getRealHubFirmwareVersions() { * @param childDevice device to send event for * @param setSwitch The new switch state, "on" or "off" * @param setLevel Optional, switchLevel between 0-100, used if you set level to 0 for example since - * that should generate "off" instead of level change + * that should generate "off" instead of level change */ private void createSwitchEvent(childDevice, setSwitch, setLevel = null) { @@ -1369,12 +1368,12 @@ private colorPointsForModel(model = null) { case "LLC013": /* Storylight */ case "LST001": /* Light Strips */ case "LLC010": /* Hue Living Colors Iris + */ - result = [r:[x: 0.704f, y: 0.296f], g:[x: 0.2151f, y: 0.7106f], b:[x: 0.138f, y: 0.08f]]; + result = [r: [x: 0.704f, y: 0.296f], g: [x: 0.2151f, y: 0.7106f], b: [x: 0.138f, y: 0.08f]]; break // Gamut C case "LLC020": /* Hue Go */ case "LST002": /* Hue LightStrips Plus */ - result = [r:[x: 0.692f, y: 0.308f], g:[x: 0.17f, y: 0.7f], b:[x: 0.153f, y: 0.048f]]; + result = [r: [x: 0.692f, y: 0.308f], g: [x: 0.17f, y: 0.7f], b: [x: 0.153f, y: 0.048f]]; break // Gamut B case "LCT001": /* Hue A19 */ @@ -1383,7 +1382,7 @@ private colorPointsForModel(model = null) { case "LCT007": /* Hue A19 + */ case "LLM001": /* Color Light Module + */ default: - result = [r:[x: 0.675f, y: 0.322f], g:[x: 0.4091f, y: 0.518f], b:[x: 0.167f, y: 0.04f]]; + result = [r: [x: 0.675f, y: 0.322f], g: [x: 0.4091f, y: 0.518f], b: [x: 0.167f, y: 0.04f]]; } return result; @@ -1402,9 +1401,9 @@ private colorPointsForModel(model = null) { private float[] calculateXY(colorStr, model = null) { // #ffa013 - def cred = Integer.valueOf( colorStr.substring( 1, 3 ), 16 ) - def cgreen = Integer.valueOf( colorStr.substring( 3, 5 ), 16 ) - def cblue = Integer.valueOf( colorStr.substring( 5, 7 ), 16 ) + def cred = Integer.valueOf(colorStr.substring(1, 3), 16) + def cgreen = Integer.valueOf(colorStr.substring(3, 5), 16) + def cblue = Integer.valueOf(colorStr.substring(5, 7), 16) float red = cred / 255.0f; float green = cgreen / 255.0f; @@ -1474,7 +1473,6 @@ private float[] calculateXY(colorStr, model = null) { // xy[0] = PHHueHelper.precision(4, xy[0]); // xy[1] = PHHueHelper.precision(4, xy[1]); - // TODO needed, assume it just sets number of decimals? //xy[0] = PHHueHelper.precision(xy[0]); //xy[1] = PHHueHelper.precision(xy[1]); @@ -1490,10 +1488,10 @@ private float[] calculateXY(colorStr, model = null) { * * @param points the float array contain x and the y value. [x,y] * @param model the model of the lamp, example: "LCT001" for hue bulb. Used to calculate the color gamut. - * If this value is empty the default gamut values are used. + * If this value is empty the default gamut values are used. * @return the color value in hex (#ff03d3). If xy is null OR xy is not an array of size 2, Color. BLACK will be returned */ -private String colorFromXY(points, model ) { +private String colorFromXY(points, model) { if (points == null || model == null) { log.warn "Input color missing" @@ -1551,9 +1549,9 @@ private String colorFromXY(points, model ) { // float b = X * 0.0556f - Y * 0.2040f + Z * 1.0570f; // sRGB D65 conversion - float r = x2 * 1.656492f - y2 * 0.354851f - z2 * 0.255038f; - float g = -x2 * 0.707196f + y2 * 1.655397f + z2 * 0.036152f; - float b = x2 * 0.051713f - y2 * 0.121364f + z2 * 1.011530f; + float r = x2 * 1.656492f - y2 * 0.354851f - z2 * 0.255038f; + float g = -x2 * 0.707196f + y2 * 1.655397f + z2 * 0.036152f; + float b = x2 * 0.051713f - y2 * 0.121364f + z2 * 1.011530f; if (r > b && r > g && r > 1.0f) { // red is too big @@ -1615,7 +1613,6 @@ private String colorFromXY(points, model ) { return "#$r1$g1$b1" } - /** * Calculates crossProduct of two 2D vectors / points. * @@ -1644,8 +1641,8 @@ private getClosestPointToPoints(A, B, P) { def AP = [x: (P.x - A.x), y: (P.y - A.y)]; def AB = [x: (B.x - A.x), y: (B.y - A.y)]; - float ab2 = AB.x*AB.x + AB.y*AB.y; - float ap_ab = AP.x*AB.x + AP.y*AB.y; + float ab2 = AB.x * AB.x + AB.y * AB.y; + float ap_ab = AP.x * AB.x + AP.y * AB.y; float t = ap_ab / ab2; @@ -1685,9 +1682,9 @@ private float getDistanceBetweenTwoPoints(one, two) { */ private boolean checkPointInLampsReach(p, colorPoints) { - def red = colorPoints.r; + def red = colorPoints.r; def green = colorPoints.g; - def blue = colorPoints.b; + def blue = colorPoints.b; def v1 = [x: (green.x - red.x), y: (green.y - red.y)]; def v2 = [x: (blue.x - red.x), y: (blue.y - red.y)]; @@ -1697,12 +1694,9 @@ private boolean checkPointInLampsReach(p, colorPoints) { float s = crossProduct(q, v2) / crossProduct(v1, v2); float t = crossProduct(v1, q) / crossProduct(v1, v2); - if ( (s >= 0.0f) && (t >= 0.0f) && (s + t <= 1.0f)) - { + if ((s >= 0.0f) && (t >= 0.0f) && (s + t <= 1.0f)) { return true; - } - else - { + } else { return false; } } @@ -1715,10 +1709,10 @@ private boolean checkPointInLampsReach(p, colorPoints) { * * @return HSV representation in an array (0-100) [hue, sat, value] */ -def hexToHsv(colorStr){ - def r = Integer.valueOf( colorStr.substring( 1, 3 ), 16 ) / 255 - def g = Integer.valueOf( colorStr.substring( 3, 5 ), 16 ) / 255 - def b = Integer.valueOf( colorStr.substring( 5, 7 ), 16 ) / 255 +def hexToHsv(colorStr) { + def r = Integer.valueOf(colorStr.substring(1, 3), 16) / 255 + def g = Integer.valueOf(colorStr.substring(3, 5), 16) / 255 + def b = Integer.valueOf(colorStr.substring(5, 7), 16) / 255 def max = Math.max(Math.max(r, g), b) def min = Math.min(Math.min(r, g), b) @@ -1728,10 +1722,10 @@ def hexToHsv(colorStr){ def d = max - min s = max == 0 ? 0 : d / max - if(max == min){ + if (max == min) { h = 0 - }else{ - switch(max){ + } else { + switch (max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break case g: h = (b - r) / d + 2; break case b: h = (r - g) / d + 4; break @@ -1746,13 +1740,13 @@ def hexToHsv(colorStr){ * Converts HSV/HSB color to RGB in hex. * Algorithm based on http://en.wikipedia.org/wiki/HSV_color_space. * - * @param hue hue 0-100 - * @param sat saturation 0-100 - * @param value value 0-100 (defaults to 100) + * @param hue hue 0-100 + * @param sat saturation 0-100 + * @param value value 0-100 (defaults to 100) * @return the color in hex (#ff03d3) */ -def hsvToHex(hue, sat, value = 100){ +def hsvToHex(hue, sat, value = 100) { def r, g, b; def h = hue / 100 def s = sat / 100 diff --git a/smartapps/smartthings/hue-connect.src/i18n/ar_AE.properties b/smartapps/smartthings/hue-connect.src/i18n/ar_AE.properties new file mode 100644 index 0000000..f637d4c --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/ar_AE.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=يوفر لك إمكانية توصيل مصابيح Philips Hue بـ SmartThings والتحكم بها من منطقة Things أو لوحة المعلومات في تطبيق SmartThings للهواتف المحمولة. يُرجى تحديث Hue Bridge أولاً، خارج تطبيق SmartThings، باستخدام تطبيق Philips Hue. +'''Discovery Started!'''=بدأ الاكتشاف! +'''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.'''=يُرجى الانتظار ريثما نكتشف Hue Bridge الخاص بك. تجدر الإشارة إلى أنه عليك أوّلاً تكوين Hue Bridge والمصابيح باستخدام تطبيق Philips Hue. قد يستغرق الاكتشاف خمس دقائق أو أكثر، لذا اجلس واسترخِ! اختر جهازك أدناه بمجرد اكتشافه. +'''Select Hue Bridge ({{numFound}} found)'''=تحديد Hue Bridge ‏(تم العثور على ‎{{numFound}}‎) +'''Bridge Discovery Failed!'''=فشل اكتشاف Bridge +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=فشل اكتشاف أي Hue Bridges. يُرجى التأكد من اتصال Hue Bridge بالشبكة نفسها التي يتصل بها موزع SmartThings الخاص بك، ومن أنه متصل بمصدر طاقة أيضاً. +'''Linking with your Hue'''=الارتباط بجهاز Hue الخاص بك +'''The current Hue username is invalid. Please press the button on your Hue Bridge to relink.'''=اسم مستخدم Hue الحالي غير صالح. يُرجى الضغط على الزر الموجود على Hue Bridge الخاص بك لإعادة الارتباط. +'''Press the button on your Hue Bridge to setup a link.'''=اضغط على الزر الموجود على Hue Bridge الخاص بك لإعداد رابط. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=لم تحدد Hue Bridge، يُرجى الضغط على 'تم' وتحديد واحد قبل النقر فوق التالي. +'''Success!'''=نجحت العملية! +'''Linking to your hub was a success! Please click 'Next'!'''=نجح الارتباط بالموزع الخاص بك! يُرجى النقر فوق ”التالي“! +'''Find bridges'''=بحث عن أجهزة bridges +'''Light Discovery Failed!'''=فشل اكتشاف المصباح! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=فشل اكتشاف أي مصابيح، يُرجى المحاولة مرة أخرى لاحقاً. انقر فوق تم للخروج. +'''Select Hue Lights to add ({{numFound}} found)'''=حدد مصابيح Hue التي تريد إضافتها ‏(تم العثور على ‎{{numFound}}‎) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=مصابيح Hue المضافة مُسبقاً (تمت إضافة ‎{{existingLightsSize}}‎) +'''Light Discovery Started!'''=بدأ اكتشاف المصباح! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=يُرجى الانتظار ريثما نكتشف مصابيح Hue الخاصة بك. قد يستغرق الاكتشاف خمس دقائق أو أكثر، لذا اجلس واسترخِ! اختر جهازك أدناه بمجرد اكتشافه. diff --git a/smartapps/smartthings/hue-connect.src/i18n/bg_BG.properties b/smartapps/smartthings/hue-connect.src/i18n/bg_BG.properties new file mode 100644 index 0000000..bb61c1b --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/bg_BG.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Позволява да свържете Philips Hue lights (лампи) със SmartThings и да ги управлявате от областта Things (Уреди) или Dashboard (Табло) в приложението SmartThings Mobile. Първо актуализирайте своя Hue Bridge (Мост) извън приложението SmartThings, като използвате приложението Philips Hue. +'''Discovery Started!'''=Откриването е стартирано! +'''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.'''=Изчакайте, докато намерим вашия Hue Bridge (Мост). Обърнете внимание, че първо трябва да конфигурирате своя Hue Bridge (Мост) и Lights (Лампи) с помощта на приложението Philips Hue. Намирането може да отнеме пет минути или повече, така че седнете и се отпуснете! Изберете устройството си по-долу, след като бъде открито. +'''Select Hue Bridge ({{numFound}} found)'''=Избор на Hue Bridge (Мост) ({{numFound}} са открити) +'''Bridge Discovery Failed!'''=Откриването на Bridge (Мост) е неуспешно! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Неуспешно откриване на Hue Bridges (Мост). Уверете се, че Hue Bridge (Мост) е свързан към същата мрежа като концентратора на SmartThings, както и че има захранване. +'''Linking with your Hue'''=Свързване с Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Текущото потребителско име за Hue е невалидно. Натиснете бутона на вашия Hue Bridge (Мост) за повторно свързване. +'''Press the button on your Hue Bridge to setup a link.'''=Натиснете бутона на вашия Hue Bridge (Мост), за да установите връзка. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Не сте избрали Hue Bridge (Мост), натиснете „Done“ (Готово) и изберете един, преди да щракнете върху Next (Напред). +'''Success!'''=Успех! +'''Linking to your hub was a success! Please click 'Next'!'''=Свързването с вашия концентратор е успешно. Щракнете върху „Next“ (Напред)! +'''Find bridges'''=Откриване на мостове +'''Light Discovery Failed!'''=Откриването на лампата е неуспешно! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Неуспешно откриване на лампи, опитайте отново по-късно. Щракнете върху Done (Готово) за изход. +'''Select Hue Lights to add ({{numFound}} found)'''=Изберете Hue Lights (Лампи) за добавяне ({{numFound}} са открити) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=По-рано добавени Hue Lights (Лампи) ({{existingLightsSize}} са добавени) +'''Light Discovery Started!'''=Откриването на лампи е стартирано! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Изчакайте, докато намерим вашите Hue Lights (Лампи). Намирането може да отнеме пет минути или повече, така че седнете и се отпуснете! Изберете устройството си по-долу, след като бъде открито. diff --git a/smartapps/smartthings/hue-connect.src/i18n/cs_CZ.properties b/smartapps/smartthings/hue-connect.src/i18n/cs_CZ.properties new file mode 100644 index 0000000..0f23b67 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/cs_CZ.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Umožňuje připojit světla Philips Hue lights (světla) pomocí SmartThings a ovládat je z oblasti Things (Věci) nebo z Dashboard (Řídicí panel) v mobilní aplikaci SmartThings. Nejprve aktualizujte Hue Bridge (můstek) mimo aplikaci SmartThings, pomocí aplikace Philips Hue. +'''Discovery Started!'''=Zjišťování byla zahájeno! +'''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.'''=Počkejte na rozpoznání Hue Bridge (můstek). Uvědomte si, že musíte nejprve nakonfigurovat Hue Bridge (můstek) a Lights (světla) pomocí aplikace Philips Hue. Rozpoznání může trvat pět minut i déle, proto se klidně posaďte a počkejte! Po rozpoznání vyberte níže dané zařízení. +'''Select Hue Bridge ({{numFound}} found)'''=Vyberte Hue Bridge (můstek) (nalezeno {{numFound}}) +'''Bridge Discovery Failed!'''=Zjišťování Bridge (můstek) se nezdařilo! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Nepodařilo se najít žádný Hue Bridge (můstek). Zkontrolujte, zda je Hue Bridge (můstek) připojený ke stejné síti jako SmartThings Hub a zda je napájený. +'''Linking with your Hue'''=Propojení s Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Aktuální uživatelské jméno Hue je neplatné. Stiskněte tlačítko na Hue Bridge (můstek) a obnovte propojení. +'''Press the button on your Hue Bridge to setup a link.'''=Stiskněte tlačítko na Hue Bridge (můstek) a nastavte propojení. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Nevybrali jste Hue Bridge (můstek); stiskněte tlačítko „Done“ (Hotovo) a jeden vyberte, než klepnete na tlačítko Next (Další). +'''Success!'''=Úspěch! +'''Linking to your hub was a success! Please click 'Next'!'''=Propojení s hub bylo úspěšně navázáno! Klepněte na tlačítko „Next“ (Další)! +'''Find bridges'''=Najít bridge +'''Light Discovery Failed!'''=Zjišťování světel se nezdařilo! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Nepodařilo najít žádná světla, opakujte akci později. Ukončete akci klepnutím na tlačítko Done (Hotovo). +'''Select Hue Lights to add ({{numFound}} found)'''=Vyberte Hue lights (světla), která chcete přidat (nalezeno {{numFound}}) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Dříve přidaná Hue Lights (světla) (přidáno {{existingLightsSize}}) +'''Light Discovery Started!'''=Zjišťování světel bylo zahájeno! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Počkejte na rozpoznání Hue Lights (světla). Rozpoznání může trvat pět minut i déle, proto se klidně posaďte a počkejte! Po rozpoznání vyberte níže dané zařízení. diff --git a/smartapps/smartthings/hue-connect.src/i18n/da_DK.properties b/smartapps/smartthings/hue-connect.src/i18n/da_DK.properties new file mode 100644 index 0000000..281a0ac --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/da_DK.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Giver dig mulighed for at forbinde dine Philips Hue Lights (Philips Hue-lamper) med SmartThings og styre dem fra dit Things-område eller dit Dashboard i SmartThings-mobilappen. Opdater din Hue Bridge (Hue-bro) først (uden for SmartThings-appen) ved hjælp af Philips Hue-appen. +'''Discovery Started!'''=Opdagelse er startet! +'''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.'''=Vent, mens vi finder din Hue Bridge (Hue-bro). Bemærk, at du først skal konfigurere din Hue Bridge og Lights (Lamper) med Philips Hue-applikationen. Det kan tage fem minutter eller mere at finde enheden, så bare læn dig tilbage, og slap af! Vælg din enhed herunder, når den er fundet. +'''Select Hue Bridge ({{numFound}} found)'''=Vælg Hue Bridge (Hue-bro) ({{numFound}} fundet) +'''Bridge Discovery Failed!'''=Opdagelse af Bridge (bro) mislykkedes! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Kunne ikke finde nogen Hue Bridges (Hue-broer). Bekræft, at Hue Bridge (Hue-broen) er tilsluttet det samme netværk som din SmartThings-hub, og at der er strøm på den. +'''Linking with your Hue'''=Sammenkædning med din Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Det aktuelle Hue-brugernavn er ugyldigt. Tryk på knappen på din Hue Bridge (Hue-bro) for at tilknytte igen. +'''Press the button on your Hue Bridge to setup a link.'''=Tryk på knappen på din Hue Bridge (Hue-bro) for at oprette et link. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Du har ikke valgt en Hue Bridge (Hue-bro). Tryk på “Done” (Udført), og vælg én, inden du klikker på Next (Næste). +'''Success!'''=Succes! +'''Linking to your hub was a success! Please click 'Next'!'''=Sammenkædningen med din hub blev gennemført! Klik på “Next” (Næste)! +'''Find bridges'''=Find bridges (broer) +'''Light Discovery Failed!'''=Opdagelse af lights (lamper) mislykkedes! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Kunne ikke finde nogen lights (lamper). Prøv igen senere. Klik på Done (Udført) for at afslutte. +'''Select Hue Lights to add ({{numFound}} found)'''=Vælg Hue Lights (Hue-lamper), der skal tilføjes ({{numFound}} fundet) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Tidligere tilføjede Hue Lights (Hue-lamper) ({{existingLightsSize}} tilføjet) +'''Light Discovery Started!'''=Opdagelse af lights (lamper) er startet! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Vent, mens vi finder dine Hue Lights (Hue-lamper). Det kan tage fem minutter eller mere at finde enheden, så bare læn dig tilbage, og slap af! Vælg din enhed herunder, når den er fundet. diff --git a/smartapps/smartthings/hue-connect.src/i18n/de_AT.properties b/smartapps/smartthings/hue-connect.src/i18n/de_AT.properties new file mode 100644 index 0000000..def2273 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/de_AT.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Sie können Ihre Phillips Hue Lights (Lichter) mit SmartThings verbinden und aus Ihrem Things-Bereich oder dem Dashboard in der SmartThings-Mobile-App aus steuern. Bitte aktualisieren Sie zunächst Ihre Hue Bridge (Brücke) außerhalb der SmartThings-App mit der Phillips-Hue-App. +'''Discovery Started!'''=Erkennung gestartet! +'''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.'''=Bitte warten Sie, bis Ihre Hue Bridge (Brücke) erkannt wurde. Beachten Sie bitte, dass Sie Ihre Hue Bridge (Brücke) und Lights (Lichter) zunächst mit der Philips Hue-Anwendung konfigurieren müssen. Die Erkennung kann fünf Minuten oder länger dauern. Lehnen Sie sich zurück und entspannen Sie sich! Wählen Sie nach der Erkennung unten ein Gerät aus. +'''Select Hue Bridge ({{numFound}} found)'''=Hue Bridge (Brücke) auswählen ({{numFound}} gefunden) +'''Bridge Discovery Failed!'''=Bridge (Brücke)-Erkennung fehlgeschlagen! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Es konnten keine Hue Bridges (Brücken) gefunden werden. Bitte bestätigen Sie, dass die Hue Bridge (Brücke) am gleichen Netzwerk wie Ihr SmartThings Hub angeschlossen ist und Strom erhält. +'''Linking with your Hue'''=Kopplung mit Ihrem Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Der aktuelle Hue-Benutzername ist ungültig. Bitte drücken Sie für eine erneute Kopplung die Taste auf Ihrer Hue Bridge (Brücke). +'''Press the button on your Hue Bridge to setup a link.'''=Drücken Sie die Taste auf Ihrer Hue-Bridge (Brücke), um eine Kopplung einzurichten. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Sie haben keine Hue Bridge (Brücke) ausgewählt. Bitte drücken Sie ‚Done‘ (OK) und wählen Sie eine aus, bevor Sie auf Next (Weiter) drücken. +'''Success!'''=Erfolgreich verbunden! +'''Linking to your hub was a success! Please click 'Next'!'''=Die Kopplung mit Ihrem Hub war erfolgreich! Bitte klicken Sie auf ‚Next‘ (Weiter)! +'''Find bridges'''=Bridges (Brücken) suchen +'''Light Discovery Failed!'''=Lichterkennung fehlgeschlagen! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Es wurden keine Lichter erkannt. Bitte versuchen Sie es später erneut. Klicken Sie zum Beenden auf „Done“ (OK). +'''Select Hue Lights to add ({{numFound}} found)'''=Wählen Sie die hinzuzufügenden Hue Lights (Lichter) aus ({{numFound}} gefunden) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Zuvor hinzugefügte Hue Lights (Lichter) ({{existingLightsSize}} hinzugefügt) +'''Light Discovery Started!'''=Lichterkennung gestartet! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Bitte warten Sie, bis Ihre Hue Lights (Lichter) erkannt wurden. Die Erkennung kann fünf Minuten oder länger dauern. Lehnen Sie sich zurück und entspannen Sie sich! Wählen Sie nach der Erkennung unten ein Gerät aus. diff --git a/smartapps/smartthings/hue-connect.src/i18n/de_CH.properties b/smartapps/smartthings/hue-connect.src/i18n/de_CH.properties new file mode 100644 index 0000000..def2273 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/de_CH.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Sie können Ihre Phillips Hue Lights (Lichter) mit SmartThings verbinden und aus Ihrem Things-Bereich oder dem Dashboard in der SmartThings-Mobile-App aus steuern. Bitte aktualisieren Sie zunächst Ihre Hue Bridge (Brücke) außerhalb der SmartThings-App mit der Phillips-Hue-App. +'''Discovery Started!'''=Erkennung gestartet! +'''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.'''=Bitte warten Sie, bis Ihre Hue Bridge (Brücke) erkannt wurde. Beachten Sie bitte, dass Sie Ihre Hue Bridge (Brücke) und Lights (Lichter) zunächst mit der Philips Hue-Anwendung konfigurieren müssen. Die Erkennung kann fünf Minuten oder länger dauern. Lehnen Sie sich zurück und entspannen Sie sich! Wählen Sie nach der Erkennung unten ein Gerät aus. +'''Select Hue Bridge ({{numFound}} found)'''=Hue Bridge (Brücke) auswählen ({{numFound}} gefunden) +'''Bridge Discovery Failed!'''=Bridge (Brücke)-Erkennung fehlgeschlagen! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Es konnten keine Hue Bridges (Brücken) gefunden werden. Bitte bestätigen Sie, dass die Hue Bridge (Brücke) am gleichen Netzwerk wie Ihr SmartThings Hub angeschlossen ist und Strom erhält. +'''Linking with your Hue'''=Kopplung mit Ihrem Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Der aktuelle Hue-Benutzername ist ungültig. Bitte drücken Sie für eine erneute Kopplung die Taste auf Ihrer Hue Bridge (Brücke). +'''Press the button on your Hue Bridge to setup a link.'''=Drücken Sie die Taste auf Ihrer Hue-Bridge (Brücke), um eine Kopplung einzurichten. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Sie haben keine Hue Bridge (Brücke) ausgewählt. Bitte drücken Sie ‚Done‘ (OK) und wählen Sie eine aus, bevor Sie auf Next (Weiter) drücken. +'''Success!'''=Erfolgreich verbunden! +'''Linking to your hub was a success! Please click 'Next'!'''=Die Kopplung mit Ihrem Hub war erfolgreich! Bitte klicken Sie auf ‚Next‘ (Weiter)! +'''Find bridges'''=Bridges (Brücken) suchen +'''Light Discovery Failed!'''=Lichterkennung fehlgeschlagen! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Es wurden keine Lichter erkannt. Bitte versuchen Sie es später erneut. Klicken Sie zum Beenden auf „Done“ (OK). +'''Select Hue Lights to add ({{numFound}} found)'''=Wählen Sie die hinzuzufügenden Hue Lights (Lichter) aus ({{numFound}} gefunden) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Zuvor hinzugefügte Hue Lights (Lichter) ({{existingLightsSize}} hinzugefügt) +'''Light Discovery Started!'''=Lichterkennung gestartet! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Bitte warten Sie, bis Ihre Hue Lights (Lichter) erkannt wurden. Die Erkennung kann fünf Minuten oder länger dauern. Lehnen Sie sich zurück und entspannen Sie sich! Wählen Sie nach der Erkennung unten ein Gerät aus. diff --git a/smartapps/smartthings/hue-connect.src/i18n/de_DE.properties b/smartapps/smartthings/hue-connect.src/i18n/de_DE.properties new file mode 100644 index 0000000..def2273 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/de_DE.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Sie können Ihre Phillips Hue Lights (Lichter) mit SmartThings verbinden und aus Ihrem Things-Bereich oder dem Dashboard in der SmartThings-Mobile-App aus steuern. Bitte aktualisieren Sie zunächst Ihre Hue Bridge (Brücke) außerhalb der SmartThings-App mit der Phillips-Hue-App. +'''Discovery Started!'''=Erkennung gestartet! +'''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.'''=Bitte warten Sie, bis Ihre Hue Bridge (Brücke) erkannt wurde. Beachten Sie bitte, dass Sie Ihre Hue Bridge (Brücke) und Lights (Lichter) zunächst mit der Philips Hue-Anwendung konfigurieren müssen. Die Erkennung kann fünf Minuten oder länger dauern. Lehnen Sie sich zurück und entspannen Sie sich! Wählen Sie nach der Erkennung unten ein Gerät aus. +'''Select Hue Bridge ({{numFound}} found)'''=Hue Bridge (Brücke) auswählen ({{numFound}} gefunden) +'''Bridge Discovery Failed!'''=Bridge (Brücke)-Erkennung fehlgeschlagen! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Es konnten keine Hue Bridges (Brücken) gefunden werden. Bitte bestätigen Sie, dass die Hue Bridge (Brücke) am gleichen Netzwerk wie Ihr SmartThings Hub angeschlossen ist und Strom erhält. +'''Linking with your Hue'''=Kopplung mit Ihrem Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Der aktuelle Hue-Benutzername ist ungültig. Bitte drücken Sie für eine erneute Kopplung die Taste auf Ihrer Hue Bridge (Brücke). +'''Press the button on your Hue Bridge to setup a link.'''=Drücken Sie die Taste auf Ihrer Hue-Bridge (Brücke), um eine Kopplung einzurichten. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Sie haben keine Hue Bridge (Brücke) ausgewählt. Bitte drücken Sie ‚Done‘ (OK) und wählen Sie eine aus, bevor Sie auf Next (Weiter) drücken. +'''Success!'''=Erfolgreich verbunden! +'''Linking to your hub was a success! Please click 'Next'!'''=Die Kopplung mit Ihrem Hub war erfolgreich! Bitte klicken Sie auf ‚Next‘ (Weiter)! +'''Find bridges'''=Bridges (Brücken) suchen +'''Light Discovery Failed!'''=Lichterkennung fehlgeschlagen! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Es wurden keine Lichter erkannt. Bitte versuchen Sie es später erneut. Klicken Sie zum Beenden auf „Done“ (OK). +'''Select Hue Lights to add ({{numFound}} found)'''=Wählen Sie die hinzuzufügenden Hue Lights (Lichter) aus ({{numFound}} gefunden) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Zuvor hinzugefügte Hue Lights (Lichter) ({{existingLightsSize}} hinzugefügt) +'''Light Discovery Started!'''=Lichterkennung gestartet! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Bitte warten Sie, bis Ihre Hue Lights (Lichter) erkannt wurden. Die Erkennung kann fünf Minuten oder länger dauern. Lehnen Sie sich zurück und entspannen Sie sich! Wählen Sie nach der Erkennung unten ein Gerät aus. diff --git a/smartapps/smartthings/hue-connect.src/i18n/el_GR.properties b/smartapps/smartthings/hue-connect.src/i18n/el_GR.properties new file mode 100644 index 0000000..4024ba9 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/el_GR.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Σας επιτρέπει να συνδέσετε τους λαμπτήρες Philips Hue με το SmartThings και να τους ελέγχετε από την περιοχή Things στο Dashboard της εφαρμογής SmartThings για κινητές συσκευές. Ενημερώστε πρώτα το Hue Bridge εκτός της εφαρμογής SmartThings, χρησιμοποιώντας την εφαρμογή Philips Hue. +'''Discovery Started!'''=Η ανακάλυψη ξεκίνησε! +'''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.'''=Περιμένετε μέχρι να ολοκληρωθεί η ανακάλυψη του Hue Bridge σας. Έχετε υπόψη ότι θα πρέπει πρώτα να διαμορφώσετε το Hue Bridge και τους λαμπτήρες, χρησιμοποιώντας την εφαρμογή Philips Hue. Η ανακάλυψη μπορεί να διαρκέσει πέντε λεπτά ή περισσότερο, επομένως, χαλαρώστε και περιμένετε! Επιλέξτε τη συσκευή σας παρακάτω μόλις ανακαλυφθεί. +'''Select Hue Bridge ({{numFound}} found)'''=Επιλογή Hue Bridge (βρέθηκαν {{numFound}}) +'''Bridge Discovery Failed!'''=Η ανακάλυψη Bridge απέτυχε! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Δεν ανακαλύφθηκε κανένα Hue Bridge. Βεβαιωθείτε ότι το Hue Bridge είναι συνδεδεμένο στο ίδιο δίκτυο με το SmartThings Hub και ότι τροφοδοτείται με ρεύμα. +'''Linking with your Hue'''=Γίνεται σύνδεση με το Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Το τρέχον όνομα χρήστη Hue δεν είναι έγκυρο. Πατήστε το κουμπί στο Hue Bridge για επανασύνδεση. +'''Press the button on your Hue Bridge to setup a link.'''=Πατήστε το κουμπί στο Hue Bridge σας για να ρυθμίσετε μια σύνδεση. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Δεν έχετε επιλέξτε ένα Hue Bridge. Πατήστε «Done» (Τέλος) και επιλέξτε ένα πριν κάνετε κλικ στην επιλογή Next (Επόμενο). +'''Success!'''=Επιτυχία! +'''Linking to your hub was a success! Please click 'Next'!'''=Η σύνδεση με το διανομέα σας ολοκληρώθηκε με επιτυχία. Κάντε κλικ στην επιλογή 'Next' (Επόμενο)! +'''Find bridges'''=Εύρεση bridge +'''Light Discovery Failed!'''=Η ανακάλυψη λαμπτήρων απέτυχε! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Η ανακάλυψη λαμπτήρων απέτυχε, δοκιμάστε ξανά αργότερα. Κάντε κλικ στην επιλογή "Done" (Τέλος) για έξοδο. +'''Select Hue Lights to add ({{numFound}} found)'''=Επιλογή λαμπτήρων Hue για προσθήκη (βρέθηκαν {{numFound}}) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Λαμπτήρες Hue που προστέθηκαν παλαιότερα (προστέθηκαν {{existingLightsSize}}) +'''Light Discovery Started!'''=Η ανακάλυψη λαμπτήρων ξεκίνησε! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Περιμένετε μέχρι να ολοκληρωθεί η ανακάλυψη των λαμπτήρων Hue σας. Η ανακάλυψη μπορεί να διαρκέσει πέντε λεπτά ή περισσότερο, επομένως, χαλαρώστε και περιμένετε! Επιλέξτε τη συσκευή σας παρακάτω μόλις ανακαλυφθεί. diff --git a/smartapps/smartthings/hue-connect.src/i18n/en_AU.properties b/smartapps/smartthings/hue-connect.src/i18n/en_AU.properties new file mode 100644 index 0000000..2d11c28 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/en_AU.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Enables you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, from outside the SmartThings app, using the Philips Hue app. +'''Discovery Started!'''=Discovery Started! +'''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.'''=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 longer, so sit back and relax! Select your device below once it's been discovered. +'''Select Hue Bridge ({{numFound}} found)'''=Select Hue Bridge ({{numFound}} found) +'''Bridge Discovery Failed!'''=Bridge Discovery Failed +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=No Hue Bridges discovered. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power. +'''Linking with your Hue'''=Linking with your Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=The current Hue username is invalid. Please press the button on your Hue Bridge to re-link. +'''Press the button on your Hue Bridge to setup a link.'''=Press the button on your Hue Bridge to set up a link. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=You haven't selected a Hue Bridge. Please press 'Done' and select one before clicking 'Next'. +'''Success!'''=Success! +'''Linking to your hub was a success! Please click 'Next'!'''=Linking to your hub was successful! Please click 'Next'! +'''Find bridges'''=Find Bridges +'''Light Discovery Failed!'''=Light Discovery Failed! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=No lights discovered. Please try again later. Click Done to exit. +'''Select Hue Lights to add ({{numFound}} found)'''=Select Hue Lights to add ({{numFound}} found) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Previously added Hue Lights ({{existingLightsSize}} added) +'''Light Discovery Started!'''=Light Discovery Started! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Please wait while we discover your Hue Lights. Discovery can take five minutes or longer, so sit back and relax! Select your light below once it's been discovered. diff --git a/smartapps/smartthings/hue-connect.src/i18n/en_CA.properties b/smartapps/smartthings/hue-connect.src/i18n/en_CA.properties new file mode 100644 index 0000000..2d11c28 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/en_CA.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Enables you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, from outside the SmartThings app, using the Philips Hue app. +'''Discovery Started!'''=Discovery Started! +'''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.'''=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 longer, so sit back and relax! Select your device below once it's been discovered. +'''Select Hue Bridge ({{numFound}} found)'''=Select Hue Bridge ({{numFound}} found) +'''Bridge Discovery Failed!'''=Bridge Discovery Failed +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=No Hue Bridges discovered. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power. +'''Linking with your Hue'''=Linking with your Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=The current Hue username is invalid. Please press the button on your Hue Bridge to re-link. +'''Press the button on your Hue Bridge to setup a link.'''=Press the button on your Hue Bridge to set up a link. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=You haven't selected a Hue Bridge. Please press 'Done' and select one before clicking 'Next'. +'''Success!'''=Success! +'''Linking to your hub was a success! Please click 'Next'!'''=Linking to your hub was successful! Please click 'Next'! +'''Find bridges'''=Find Bridges +'''Light Discovery Failed!'''=Light Discovery Failed! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=No lights discovered. Please try again later. Click Done to exit. +'''Select Hue Lights to add ({{numFound}} found)'''=Select Hue Lights to add ({{numFound}} found) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Previously added Hue Lights ({{existingLightsSize}} added) +'''Light Discovery Started!'''=Light Discovery Started! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Please wait while we discover your Hue Lights. Discovery can take five minutes or longer, so sit back and relax! Select your light below once it's been discovered. diff --git a/smartapps/smartthings/hue-connect.src/i18n/en_GB.properties b/smartapps/smartthings/hue-connect.src/i18n/en_GB.properties new file mode 100644 index 0000000..2d11c28 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/en_GB.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Enables you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, from outside the SmartThings app, using the Philips Hue app. +'''Discovery Started!'''=Discovery Started! +'''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.'''=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 longer, so sit back and relax! Select your device below once it's been discovered. +'''Select Hue Bridge ({{numFound}} found)'''=Select Hue Bridge ({{numFound}} found) +'''Bridge Discovery Failed!'''=Bridge Discovery Failed +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=No Hue Bridges discovered. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power. +'''Linking with your Hue'''=Linking with your Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=The current Hue username is invalid. Please press the button on your Hue Bridge to re-link. +'''Press the button on your Hue Bridge to setup a link.'''=Press the button on your Hue Bridge to set up a link. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=You haven't selected a Hue Bridge. Please press 'Done' and select one before clicking 'Next'. +'''Success!'''=Success! +'''Linking to your hub was a success! Please click 'Next'!'''=Linking to your hub was successful! Please click 'Next'! +'''Find bridges'''=Find Bridges +'''Light Discovery Failed!'''=Light Discovery Failed! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=No lights discovered. Please try again later. Click Done to exit. +'''Select Hue Lights to add ({{numFound}} found)'''=Select Hue Lights to add ({{numFound}} found) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Previously added Hue Lights ({{existingLightsSize}} added) +'''Light Discovery Started!'''=Light Discovery Started! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Please wait while we discover your Hue Lights. Discovery can take five minutes or longer, so sit back and relax! Select your light below once it's been discovered. diff --git a/smartapps/smartthings/hue-connect.src/i18n/en_IE.properties b/smartapps/smartthings/hue-connect.src/i18n/en_IE.properties new file mode 100644 index 0000000..2d11c28 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/en_IE.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Enables you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, from outside the SmartThings app, using the Philips Hue app. +'''Discovery Started!'''=Discovery Started! +'''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.'''=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 longer, so sit back and relax! Select your device below once it's been discovered. +'''Select Hue Bridge ({{numFound}} found)'''=Select Hue Bridge ({{numFound}} found) +'''Bridge Discovery Failed!'''=Bridge Discovery Failed +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=No Hue Bridges discovered. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power. +'''Linking with your Hue'''=Linking with your Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=The current Hue username is invalid. Please press the button on your Hue Bridge to re-link. +'''Press the button on your Hue Bridge to setup a link.'''=Press the button on your Hue Bridge to set up a link. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=You haven't selected a Hue Bridge. Please press 'Done' and select one before clicking 'Next'. +'''Success!'''=Success! +'''Linking to your hub was a success! Please click 'Next'!'''=Linking to your hub was successful! Please click 'Next'! +'''Find bridges'''=Find Bridges +'''Light Discovery Failed!'''=Light Discovery Failed! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=No lights discovered. Please try again later. Click Done to exit. +'''Select Hue Lights to add ({{numFound}} found)'''=Select Hue Lights to add ({{numFound}} found) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Previously added Hue Lights ({{existingLightsSize}} added) +'''Light Discovery Started!'''=Light Discovery Started! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Please wait while we discover your Hue Lights. Discovery can take five minutes or longer, so sit back and relax! Select your light below once it's been discovered. diff --git a/smartapps/smartthings/hue-connect.src/i18n/en_NZ.properties b/smartapps/smartthings/hue-connect.src/i18n/en_NZ.properties new file mode 100644 index 0000000..2d11c28 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/en_NZ.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Enables you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, from outside the SmartThings app, using the Philips Hue app. +'''Discovery Started!'''=Discovery Started! +'''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.'''=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 longer, so sit back and relax! Select your device below once it's been discovered. +'''Select Hue Bridge ({{numFound}} found)'''=Select Hue Bridge ({{numFound}} found) +'''Bridge Discovery Failed!'''=Bridge Discovery Failed +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=No Hue Bridges discovered. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power. +'''Linking with your Hue'''=Linking with your Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=The current Hue username is invalid. Please press the button on your Hue Bridge to re-link. +'''Press the button on your Hue Bridge to setup a link.'''=Press the button on your Hue Bridge to set up a link. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=You haven't selected a Hue Bridge. Please press 'Done' and select one before clicking 'Next'. +'''Success!'''=Success! +'''Linking to your hub was a success! Please click 'Next'!'''=Linking to your hub was successful! Please click 'Next'! +'''Find bridges'''=Find Bridges +'''Light Discovery Failed!'''=Light Discovery Failed! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=No lights discovered. Please try again later. Click Done to exit. +'''Select Hue Lights to add ({{numFound}} found)'''=Select Hue Lights to add ({{numFound}} found) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Previously added Hue Lights ({{existingLightsSize}} added) +'''Light Discovery Started!'''=Light Discovery Started! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Please wait while we discover your Hue Lights. Discovery can take five minutes or longer, so sit back and relax! Select your light below once it's been discovered. diff --git a/smartapps/smartthings/hue-connect.src/i18n/en_PH.properties b/smartapps/smartthings/hue-connect.src/i18n/en_PH.properties new file mode 100644 index 0000000..2d11c28 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/en_PH.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Enables you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, from outside the SmartThings app, using the Philips Hue app. +'''Discovery Started!'''=Discovery Started! +'''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.'''=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 longer, so sit back and relax! Select your device below once it's been discovered. +'''Select Hue Bridge ({{numFound}} found)'''=Select Hue Bridge ({{numFound}} found) +'''Bridge Discovery Failed!'''=Bridge Discovery Failed +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=No Hue Bridges discovered. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power. +'''Linking with your Hue'''=Linking with your Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=The current Hue username is invalid. Please press the button on your Hue Bridge to re-link. +'''Press the button on your Hue Bridge to setup a link.'''=Press the button on your Hue Bridge to set up a link. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=You haven't selected a Hue Bridge. Please press 'Done' and select one before clicking 'Next'. +'''Success!'''=Success! +'''Linking to your hub was a success! Please click 'Next'!'''=Linking to your hub was successful! Please click 'Next'! +'''Find bridges'''=Find Bridges +'''Light Discovery Failed!'''=Light Discovery Failed! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=No lights discovered. Please try again later. Click Done to exit. +'''Select Hue Lights to add ({{numFound}} found)'''=Select Hue Lights to add ({{numFound}} found) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Previously added Hue Lights ({{existingLightsSize}} added) +'''Light Discovery Started!'''=Light Discovery Started! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Please wait while we discover your Hue Lights. Discovery can take five minutes or longer, so sit back and relax! Select your light below once it's been discovered. diff --git a/smartapps/smartthings/hue-connect.src/i18n/en_ZA.properties b/smartapps/smartthings/hue-connect.src/i18n/en_ZA.properties new file mode 100644 index 0000000..2d11c28 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/en_ZA.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Enables you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, from outside the SmartThings app, using the Philips Hue app. +'''Discovery Started!'''=Discovery Started! +'''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.'''=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 longer, so sit back and relax! Select your device below once it's been discovered. +'''Select Hue Bridge ({{numFound}} found)'''=Select Hue Bridge ({{numFound}} found) +'''Bridge Discovery Failed!'''=Bridge Discovery Failed +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=No Hue Bridges discovered. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power. +'''Linking with your Hue'''=Linking with your Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=The current Hue username is invalid. Please press the button on your Hue Bridge to re-link. +'''Press the button on your Hue Bridge to setup a link.'''=Press the button on your Hue Bridge to set up a link. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=You haven't selected a Hue Bridge. Please press 'Done' and select one before clicking 'Next'. +'''Success!'''=Success! +'''Linking to your hub was a success! Please click 'Next'!'''=Linking to your hub was successful! Please click 'Next'! +'''Find bridges'''=Find Bridges +'''Light Discovery Failed!'''=Light Discovery Failed! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=No lights discovered. Please try again later. Click Done to exit. +'''Select Hue Lights to add ({{numFound}} found)'''=Select Hue Lights to add ({{numFound}} found) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Previously added Hue Lights ({{existingLightsSize}} added) +'''Light Discovery Started!'''=Light Discovery Started! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Please wait while we discover your Hue Lights. Discovery can take five minutes or longer, so sit back and relax! Select your light below once it's been discovered. diff --git a/smartapps/smartthings/hue-connect.src/i18n/es_ES.properties b/smartapps/smartthings/hue-connect.src/i18n/es_ES.properties new file mode 100644 index 0000000..149f802 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/es_ES.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Permite conectar sus Philips Hue Lights (Luces) con SmartThings y controlarlas desde Things area (Área de cosas) o Dashboard (Panel) en la aplicación móvil SmartThings. Actualice primero el Hue Bridge (Puente), fuera de la aplicación SmartThings, usando la aplicación Philips Hue. +'''Discovery Started!'''=¡Se ha iniciado la detección! +'''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.'''=Espere mientras detectamos su Hue Bridge (Puente). Tenga en cuenta que primero tiene que configurar su Hue Bridge (Puente) y Hue Lights (Luces) mediante la aplicación Philips Hue. La detección puede tardar cinco minutos o más. Así que tómeselo con tranquilidad. Seleccione su dispositivo cuando se haya detectado. +'''Select Hue Bridge ({{numFound}} found)'''=Seleccionar Hue Bridge (Puente) ({{numFound}} encontrados) +'''Bridge Discovery Failed!'''=¡Error al detectar Bridge (Puente)! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Error al detectar Hue Bridges (Puentes). Confirme que el Hue Bridge (Puente) está conectado a la misma red que su Hub SmartThings y que está enchufado a una toma eléctrica. +'''Linking with your Hue'''=Vincular con su Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=El nombre de usuario del Hue actual no es válido. Pulse el botón en su Hue Bridge (Puente) para volver a vincular. +'''Press the button on your Hue Bridge to setup a link.'''=Pulse el botón en su Hue Bridge (Puente) para configurar el vínculo. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=No ha seleccionado ningún Hue Bridge (Puente). Pulse “Done” (Hecho) y seleccione uno antes de hacer clic en Next (Siguiente). +'''Success!'''=Operación realizada correctamente. +'''Linking to your hub was a success! Please click 'Next'!'''=Se ha vinculado su Hub correctamente. Haga clic en Next (Siguiente). +'''Find bridges'''=Encontrar Bridges (Puentes) +'''Light Discovery Failed!'''=Error al detectar luces. +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Error al detectar luces. Inténtelo de nuevo más tarde. Haga clic en Done (Hecho) para salir. +'''Select Hue Lights to add ({{numFound}} found)'''=Seleccione Hue Lights (Luces) para añadir ({{numFound}} encontradas) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Hue Lights (Luces) añadidas anteriormente ({{existingLightsSize}} añadidas) +'''Light Discovery Started!'''=Se ha iniciado la detección de luces. +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Espere mientras detectamos sus Hue Lights (Luces). La detección puede tardar cinco minutos o más. Así que tómeselo con tranquilidad. Seleccione su dispositivo cuando se haya detectado. diff --git a/smartapps/smartthings/hue-connect.src/i18n/es_US.properties b/smartapps/smartthings/hue-connect.src/i18n/es_US.properties new file mode 100644 index 0000000..e32b020 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/es_US.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Le permite conectar sus Philips Hue lights (luces Philips Hue) con SmartThings y controlarlas desde el área de Objetos o el Panel de la aplicación SmartThings Mobile. Primero actualice su Hue Bridge (puente Hue) desde fuera de la aplicación de SmartThings, mediante la aplicación de Philips Hue. +'''Discovery Started!'''=Descubrimiento iniciado +'''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.'''=Espere mientras descubrimos su Hue Bridge (puente Hue). Tenga en cuenta que primero debe configurar Hue Bridge y Hue Lights (luces Hue) mediante la aplicación de Hue. El descubrimiento puede tomar cinco minutos o más, por lo que le sugerimos que se ponga cómodo y se relaje. Una vez descubierto, seleccione su dispositivo. +'''Select Hue Bridge ({{numFound}} found)'''=Seleccione Hue Bridge (Puente Hue) (se encontraron {{numFound}}) +'''Bridge Discovery Failed!'''=Error al descubrir Bridges (puentes). +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=No se descubrieron Hue Bridges (Puentes Hue). Confirme que el Hue Bridge (Puente Hue) está conectado a la misma red que su unidad central de SmartThings, y que está conectado a la red eléctrica. +'''Linking with your Hue'''=Vinculando con su Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=El nombre de usuario Hue actual no es válido. Presione el botón de su Hue Bridge (Puente Hue) para volver a vincular. +'''Press the button on your Hue Bridge to setup a link.'''=Presione el botón de su Hue Bridge (Puente Hue) para configurar un vínculo. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=No seleccionó un Hue Bridge (puente Hue). Presione “Done” (Realizado) y seleccione uno antes de hacer clic en Next (Siguiente). +'''Success!'''=¡Logrado! +'''Linking to your hub was a success! Please click 'Next'!'''=El vínculo con su unidad central se realizó correctamente. Haga clic en 'Next' (Siguiente). +'''Find bridges'''=Encontrar puentes +'''Light Discovery Failed!'''=Error al descubrir luces +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=No se descubrió ninguna luz. Vuelva a intentarlo de nuevo más tarde. Haga clic en Done (Realizado) para salir. +'''Select Hue Lights to add ({{numFound}} found)'''=Seleccione Hue Lights (Luces Hue) que desea agregar (se encontraron {{numFound}}) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Hue Lights (Luces Hue) agregadas anteriormente (se agregaron {{existingLightsSize}}) +'''Light Discovery Started!'''=Descubrimiento de luces iniciado +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Espere mientras descubrimos sus Hue Lights (Luces Hue). El descubrimiento puede tomar cinco minutos o más, por lo que le sugerimos que se ponga cómodo y se relaje. Una vez descubierto, seleccione su dispositivo. diff --git a/smartapps/smartthings/hue-connect.src/i18n/et_EE.properties b/smartapps/smartthings/hue-connect.src/i18n/et_EE.properties new file mode 100644 index 0000000..d5f3c29 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/et_EE.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Võimaldab teil ühendada teie Philips Hue tuled SmartThingsiga ja juhtida neid oma Thingsi piirkonnast või SmartThingsi mobiilirakenduse esipaneelilt. Värskendage esmalt oma Hue Bridge’i väljaspool SmartThingsi rakendust, kasutades Philips Hue rakendust. +'''Discovery Started!'''=Tuvastamine algas! +'''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.'''=Oodake, kuni me tuvastame teie Hue Bridge’i. Pange tähele, et peate esmalt oma Hue Bridge and Lights’i süsteemi rakenduse Philips Hue abil konfigureerima. Tuvastamisele võib kuluda üle viie minuti, seega oodake rahulikult! Pärast tuvastamist valige all oma seade. +'''Select Hue Bridge ({{numFound}} found)'''=Valige Hue Bridge ({{numFound}} leitud) +'''Bridge Discovery Failed!'''=Bridge’i tuvastamine nurjus! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Ei leitud ühtki Hue Bridge’i. Kontrollige, kas Hue Bridge on ühendatud teie SmartThingsi jaoturiga samasse võrku ja et sellel on toide olemas. +'''Linking with your Hue'''=Huega ühendamine +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Praegune Hue kasutajanimi on vale. Vajutage nuppu oma Hue Bridge’il, et uuesti ühendada. +'''Press the button on your Hue Bridge to setup a link.'''=Vajutage nuppu oma Hue Bridge’il, et ühendust seadistada. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Te pole valinud Hue Bridge’i, vajutage nuppu „Valmis” ja valige mõni, enne kui klõpsate jätkamiseks. +'''Success!'''=Edukas! +'''Linking to your hub was a success! Please click 'Next'!'''=Teie jaoturiga ühendamine õnnestus! Klõpsake nuppu Järgmine! +'''Find bridges'''=Bridge’ide leidmine +'''Light Discovery Failed!'''=Tulede tuvastamine nurjus! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Tulede tuvastamine nurjus, proovige hiljem uuesti. Klõpsake väljumiseks nuppu Valmis. +'''Select Hue Lights to add ({{numFound}} found)'''=Valige lisamiseks Hue tuled ({{numFound}} leitud) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Varem lisatud Hue tuled ({{existingLightsSize}} lisatud) +'''Light Discovery Started!'''=Tulede tuvastamine algas! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Oodake, kuni me tuvastame teie Hue tuled. Tuvastamisele võib kuluda üle viie minuti, seega oodake rahulikult! Pärast tuvastamist valige all oma seade. diff --git a/smartapps/smartthings/hue-connect.src/i18n/fi_FI.properties b/smartapps/smartthings/hue-connect.src/i18n/fi_FI.properties new file mode 100644 index 0000000..8e329e8 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/fi_FI.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Antaa sinun yhdistää Philips Hue Lights -valot SmartThingsiin ja hallita niitä SmartThings-mobiilisovelluksen Things (Laitteet) -alueelta tai koontinäytöstä. Päivitä ensin Hue Bridge -silta SmartThings-sovelluksen ulkopuolella Philips Hue -sovelluksen avulla. +'''Discovery Started!'''=Etsintä aloitettu! +'''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.'''=Odota, kunnes Hue Bridge -silta löytyy. Huomaa, että sinun on ensin päivitettävä Hue Bridge -silta ja Hue Lights -valot Philips Hue -sovelluksen avulla. Etsintä voi kestää jopa yli viisi minuuttia, joten odota kärsivällisesti! Valitse laite alta, kun se on löytynyt. +'''Select Hue Bridge ({{numFound}} found)'''=Valitse Hue Bridge -silta ({{numFound}} löydetty) +'''Bridge Discovery Failed!'''=Sillan etsintä epäonnistui! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Hue Bridge -siltoja ei löytynyt. Varmista, että Hue Bridge -silta on yhdistetty SmartThings-keskittimen kanssa samaan verkkoon ja että se saa virtaa. +'''Linking with your Hue'''=Hue-linkin muodostaminen +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Huen nykyinen käyttäjänimi ei kelpaa. Muodosta linkki uudelleen painamalla Hue Bridge -sillassa olevaa painiketta. +'''Press the button on your Hue Bridge to setup a link.'''=Määritä linkki painamalla Hue Bridge -sillassa olevaa painiketta. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Et ole valinnut Hue Bridge -siltaa. Paina Done (Valmis) -painiketta ja valitse silta, ennen kuin napsautat Next (Seuraava) -painiketta. +'''Success!'''=Onnistui! +'''Linking to your hub was a success! Please click 'Next'!'''=Keskittimen linkittäminen onnistui! Valitse Next (Seuraava)! +'''Find bridges'''=Etsi siltoja +'''Light Discovery Failed!'''=Valojen etsintä epäonnistui! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Valoja ei löytynyt. Yritä myöhemmin uudelleen. Lopeta valitsemalla Done (Valmis). +'''Select Hue Lights to add ({{numFound}} found)'''=Valitse lisättävät Hue Lights -valot ({{numFound}} löydetty) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Aikaisemmin lisätyt Hue Lights -valot ({{existingLightsSize}} lisätty) +'''Light Discovery Started!'''=Valojen etsintä aloitettu! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Odota, kunnes Hue Lights -valot löytyvät. Etsintä voi kestää jopa yli viisi minuuttia, joten odota kärsivällisesti! Valitse laite alta, kun se on löytynyt. diff --git a/smartapps/smartthings/hue-connect.src/i18n/fr_BE.properties b/smartapps/smartthings/hue-connect.src/i18n/fr_BE.properties new file mode 100644 index 0000000..9119bfc --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/fr_BE.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Vous permet de connecter vos lampes Philips Hue à SmartThings et de les contrôler depuis votre zone Things (Objets) ou du tableau de bord dans l'application mobile SmartThings. Veuillez d'abord mettre à jour votre pont Hue, en dehors de l'application SmartThings, à l'aide de l'application Philips Hue. +'''Discovery Started!'''=La détection a commencé ! +'''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.'''=Veuillez patienter pendant la détection de votre pont Hue. Vous devez d'abord configurer votre pont et vos lampes Hue à l'aide de l'application Philips Hue. La détection peut prendre cinq minutes voire plus. Alors, détendez-vous en attendant ! Une fois qu'il a été détecté, sélectionnez votre appareil ci-dessous. +'''Select Hue Bridge ({{numFound}} found)'''=Sélectionnez le pont Hue ({{numFound}} trouvé(s)) +'''Bridge Discovery Failed!'''=Échec de la détection du pont ! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=La détection des ponts Hue a échoué. Veuillez confirmer que le pont Hue est connecté au même réseau que votre concentrateur SmartThings, et qu'il est sous tension. +'''Linking with your Hue'''=Association avec votre Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Le nom d'utilisateur Hue actuel n'est pas valide. Veuillez appuyer sur la touche de votre pont Hue pour l'associer de nouveau. +'''Press the button on your Hue Bridge to setup a link.'''=Appuyez sur la touche de votre pont Hue pour configurer une association. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Vous n'avez pas sélectionné de pont Hue. Appuyez sur “Done” (Terminé), puis sélectionnez-en un avant de cliquer sur Next (Suivant). +'''Success!'''=Opération réussie ! +'''Linking to your hub was a success! Please click 'Next'!'''=Vous avez réussi à associer votre concentrateur. Veuillez cliquer sur « Suivant » ! +'''Find bridges'''=Trouver des ponts +'''Light Discovery Failed!'''=La détection du pont a échoué ! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Échec de la détection des lampes, veuillez réessayer ultérieurement. Cliquez sur Done (Terminé) pour quitter. +'''Select Hue Lights to add ({{numFound}} found)'''=Sélectionnez les lampes Hue à ajouter ({{numFound}} trouvée(s)) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Lampes Hue précédemment ajoutées ({{existingLightsSize}} ajoutée(s)) +'''Light Discovery Started!'''=La détection des lampes a commencé ! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Veuillez patienter pendant la détection de vos lampes Hue La détection peut prendre cinq minutes voire plus. Alors, détendez-vous en attendant ! Une fois qu'il a été détecté, sélectionnez votre appareil ci-dessous. diff --git a/smartapps/smartthings/hue-connect.src/i18n/fr_CA.properties b/smartapps/smartthings/hue-connect.src/i18n/fr_CA.properties new file mode 100644 index 0000000..1ee3a16 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/fr_CA.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Vous permet de connecter vos Philips Hue Lights (lumières Philips Hue) avec SmartThings et de les contrôler depuis Things (choses) ou Dashboard (tableau de bord) dans l’application mobile SmartThings. Veuillez d’abord mettre à jour votre Hue Bridge (pont Hue) à l’extérieur de l’application SmartThings, à l’aide de l’application Philips Hue. +'''Discovery Started!'''=Début de la détection. +'''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.'''=Veuillez patienter pendant que nous détectons votre Hue Bridge (pont Hue). Veuillez noter que vous devez d’abord configurer votre Hue Bridge (pont Hue) et vos Hue Lights (lumières Hue) à l’aide de l’application Philips Hue. La détection peut prendre cinq minutes ou plus, donc détendez-vous. Sélectionnez votre appareil ci-dessous une fois qu’il est détecté. +'''Select Hue Bridge ({{numFound}} found)'''=Sélectionnez le Hue Bridge (pont Hue; {{numFound}} trouvé(s)) +'''Bridge Discovery Failed!'''=Échec de détection du pont! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Échec de détection d’un Hue Bridge (pont Hue). Veuillez vous assurer que le Hue Bridge (pont Hue) est connecté au même réseau que votre borne SmartThings et qu’il est alimenté. +'''Linking with your Hue'''=Jumelage avec votre Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Le nom d’utilisateur Hue que vous utilisez n’est pas valide. Appuyez sur le bouton qui se trouve sur votre Hue Bridge (pont Hue) pour effectuer le jumelage de nouveau. +'''Press the button on your Hue Bridge to setup a link.'''=Appuyez sur le bouton qui se trouve sur le Hue Bridge (pont Hue) afin de configurer un lien. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Vous n’avez pas sélectionné de Hue Bridge (pont Hue). Veuillez appuyez sur « Done » (terminé) et sélectionnez-en un avant de cliquer sur Next (suivant). +'''Success!'''=Réussite! +'''Linking to your hub was a success! Please click 'Next'!'''=Le jumelage avec votre portail est un succès! Veuillez cliquer sur Next (suivant)! +'''Find bridges'''=Trouver des ponts +'''Light Discovery Failed!'''=Échec de détection de lumière! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Impossible de détecter de la lumière. Veuillez réessayer plus tard. Cliquez sur Done (terminé) pour quitter. +'''Select Hue Lights to add ({{numFound}} found)'''=Sélectionnez les Hue Lights (lumières Hue) que vous souhaitez ajouter ({{numFound}} trouvée(s)) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Hue Lights (lumières Hue) ajoutées précédemment ({{existingLightsSize}} ajoutée(s)) +'''Light Discovery Started!'''=Début de la détection de lumières! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Veuillez patienter pendant que nous détectons vos Hue Lights (lumières Hue). La détection peut prendre cinq minutes ou plus, donc détendez-vous. Sélectionnez votre appareil ci-dessous une fois qu’il est détecté. diff --git a/smartapps/smartthings/hue-connect.src/i18n/fr_CH.properties b/smartapps/smartthings/hue-connect.src/i18n/fr_CH.properties new file mode 100644 index 0000000..9119bfc --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/fr_CH.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Vous permet de connecter vos lampes Philips Hue à SmartThings et de les contrôler depuis votre zone Things (Objets) ou du tableau de bord dans l'application mobile SmartThings. Veuillez d'abord mettre à jour votre pont Hue, en dehors de l'application SmartThings, à l'aide de l'application Philips Hue. +'''Discovery Started!'''=La détection a commencé ! +'''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.'''=Veuillez patienter pendant la détection de votre pont Hue. Vous devez d'abord configurer votre pont et vos lampes Hue à l'aide de l'application Philips Hue. La détection peut prendre cinq minutes voire plus. Alors, détendez-vous en attendant ! Une fois qu'il a été détecté, sélectionnez votre appareil ci-dessous. +'''Select Hue Bridge ({{numFound}} found)'''=Sélectionnez le pont Hue ({{numFound}} trouvé(s)) +'''Bridge Discovery Failed!'''=Échec de la détection du pont ! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=La détection des ponts Hue a échoué. Veuillez confirmer que le pont Hue est connecté au même réseau que votre concentrateur SmartThings, et qu'il est sous tension. +'''Linking with your Hue'''=Association avec votre Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Le nom d'utilisateur Hue actuel n'est pas valide. Veuillez appuyer sur la touche de votre pont Hue pour l'associer de nouveau. +'''Press the button on your Hue Bridge to setup a link.'''=Appuyez sur la touche de votre pont Hue pour configurer une association. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Vous n'avez pas sélectionné de pont Hue. Appuyez sur “Done” (Terminé), puis sélectionnez-en un avant de cliquer sur Next (Suivant). +'''Success!'''=Opération réussie ! +'''Linking to your hub was a success! Please click 'Next'!'''=Vous avez réussi à associer votre concentrateur. Veuillez cliquer sur « Suivant » ! +'''Find bridges'''=Trouver des ponts +'''Light Discovery Failed!'''=La détection du pont a échoué ! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Échec de la détection des lampes, veuillez réessayer ultérieurement. Cliquez sur Done (Terminé) pour quitter. +'''Select Hue Lights to add ({{numFound}} found)'''=Sélectionnez les lampes Hue à ajouter ({{numFound}} trouvée(s)) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Lampes Hue précédemment ajoutées ({{existingLightsSize}} ajoutée(s)) +'''Light Discovery Started!'''=La détection des lampes a commencé ! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Veuillez patienter pendant la détection de vos lampes Hue La détection peut prendre cinq minutes voire plus. Alors, détendez-vous en attendant ! Une fois qu'il a été détecté, sélectionnez votre appareil ci-dessous. diff --git a/smartapps/smartthings/hue-connect.src/i18n/fr_FR.properties b/smartapps/smartthings/hue-connect.src/i18n/fr_FR.properties new file mode 100644 index 0000000..9119bfc --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/fr_FR.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Vous permet de connecter vos lampes Philips Hue à SmartThings et de les contrôler depuis votre zone Things (Objets) ou du tableau de bord dans l'application mobile SmartThings. Veuillez d'abord mettre à jour votre pont Hue, en dehors de l'application SmartThings, à l'aide de l'application Philips Hue. +'''Discovery Started!'''=La détection a commencé ! +'''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.'''=Veuillez patienter pendant la détection de votre pont Hue. Vous devez d'abord configurer votre pont et vos lampes Hue à l'aide de l'application Philips Hue. La détection peut prendre cinq minutes voire plus. Alors, détendez-vous en attendant ! Une fois qu'il a été détecté, sélectionnez votre appareil ci-dessous. +'''Select Hue Bridge ({{numFound}} found)'''=Sélectionnez le pont Hue ({{numFound}} trouvé(s)) +'''Bridge Discovery Failed!'''=Échec de la détection du pont ! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=La détection des ponts Hue a échoué. Veuillez confirmer que le pont Hue est connecté au même réseau que votre concentrateur SmartThings, et qu'il est sous tension. +'''Linking with your Hue'''=Association avec votre Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Le nom d'utilisateur Hue actuel n'est pas valide. Veuillez appuyer sur la touche de votre pont Hue pour l'associer de nouveau. +'''Press the button on your Hue Bridge to setup a link.'''=Appuyez sur la touche de votre pont Hue pour configurer une association. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Vous n'avez pas sélectionné de pont Hue. Appuyez sur “Done” (Terminé), puis sélectionnez-en un avant de cliquer sur Next (Suivant). +'''Success!'''=Opération réussie ! +'''Linking to your hub was a success! Please click 'Next'!'''=Vous avez réussi à associer votre concentrateur. Veuillez cliquer sur « Suivant » ! +'''Find bridges'''=Trouver des ponts +'''Light Discovery Failed!'''=La détection du pont a échoué ! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Échec de la détection des lampes, veuillez réessayer ultérieurement. Cliquez sur Done (Terminé) pour quitter. +'''Select Hue Lights to add ({{numFound}} found)'''=Sélectionnez les lampes Hue à ajouter ({{numFound}} trouvée(s)) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Lampes Hue précédemment ajoutées ({{existingLightsSize}} ajoutée(s)) +'''Light Discovery Started!'''=La détection des lampes a commencé ! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Veuillez patienter pendant la détection de vos lampes Hue La détection peut prendre cinq minutes voire plus. Alors, détendez-vous en attendant ! Une fois qu'il a été détecté, sélectionnez votre appareil ci-dessous. diff --git a/smartapps/smartthings/hue-connect.src/i18n/hr_HR.properties b/smartapps/smartthings/hue-connect.src/i18n/hr_HR.properties new file mode 100644 index 0000000..541bde5 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/hr_HR.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Omogućava vam da povežete Philips Hue lights (svjetla Philips Hue) i SmartThings te da upravljate njima iz dijela Things area (Područje za stvari) ili Dashboard (Nadzorna ploča) u mobilnoj aplikaciji SmartThings. Najprije aktualizirajte Hue Bridge (Hue most) izvan aplikacije SmartThings s pomoću aplikacije Philips Hue. +'''Discovery Started!'''=Otkrivanje je započelo! +'''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.'''=Pričekajte dok otkrivamo vaš Hue Bridge (Hue most). Imajte na umu da najprije morate konfigurirati vaš Hue Bridge (Hue most) i Lights (svjetla) s pomoću aplikacije Philips Hue. Otkrivanje može trajati pet minuta ili dulje, stoga sjednite i opustite se! Kada bude otkriven, odaberite svoj uređaj u nastavku. +'''Select Hue Bridge ({{numFound}} found)'''=Odaberite Hue Bridge (Hue most) (pronađeno: {{numFound}}) +'''Bridge Discovery Failed!'''=Neuspješno otkrivanje Bridgea (mosta)! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Nije otkriven nijedan Hue Bridge (Hue most). Potvrdite da je Hue Bridge (Hue most) povezan na istu mrežu kao i SmartThings Hub i da je uključen. +'''Linking with your Hue'''=Povezivanje s uređajem Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Neispravno je trenutačno korisničko ime za Hue. Pritisnite gumb za ponovno povezivanje na Hue Bridgeu (Hue most). +'''Press the button on your Hue Bridge to setup a link.'''=Pritisnite gumb na uređaju Hue Bridge (Hue most) da biste postavili vezu. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Niste odabrali nijedan Hue Bridge (Hue most), pritisnite „Done” (Gotovo) i odaberite jedan prije nego što kliknete next (dalje). +'''Success!'''=Uspjeh! +'''Linking to your hub was a success! Please click 'Next'!'''=Povezivanje na koncentrator bilo je uspješno! Kliknite „Next” (Dalje)! +'''Find bridges'''=Pronađi mostove +'''Light Discovery Failed!'''=Otkrivanje svjetla nije uspjelo! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Nije otkriveno nijedno svjetlo, pokušajte ponovno kasnije. Kliknite Done (Gotovo) za izlaz. +'''Select Hue Lights to add ({{numFound}} found)'''=Odaberite Hue Lights (svjetla Hue) za dodavanje (pronađeno: {{numFound}}) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Hue Lights (svjetla Hue) koja su prethodno dodana (dodano: {{existingLightsSize}}) +'''Light Discovery Started!'''=Započelo je otkrivanje svjetla! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Pričekajte dok otkrivamo Hue Lights (svjetla Hue). Otkrivanje može trajati pet minuta ili dulje, stoga sjednite i opustite se! Kada bude otkriven, odaberite svoj uređaj u nastavku. diff --git a/smartapps/smartthings/hue-connect.src/i18n/hu_HU.properties b/smartapps/smartthings/hue-connect.src/i18n/hu_HU.properties new file mode 100644 index 0000000..ae106f6 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/hu_HU.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Lehetővé teszi a Philips Hue Lights (lámpák) összekapcsolását a SmartThings rendszerrel és vezérlésüket a SmartThings Mobile alkalmazás Things (Tárgyak) területéről vagy a Dashboard (Vezérlőpult) segítségével. Előbb frissítse a Hue Bridge (híd) eszközt a SmartThings alkalmazáson kívülről, a Philips Hue alkalmazás segítségével. +'''Discovery Started!'''=Megkezdődött a keresés! +'''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.'''=Kis türelmet kérünk, amíg megtaláljuk a Hue Bridge (híd) eszközt. Felhívjuk figyelmét, hogy előbb el kell végeznie a Hue Bridge (híd) és Lights (lámpák) konfigurálását a Philips Hue alkalmazással. Ez akár öt percnél is tovább tarthat, így némi türelemre lesz szükség! Az eszköz megtalálása után alább kiválaszthatja azt. +'''Select Hue Bridge ({{numFound}} found)'''=Válassza ki a Hue Bridge (híd) eszközt ({{numFound}} találat) +'''Bridge Discovery Failed!'''=A Bridge (híd) keresése sikertelen volt! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Nem sikerült Hue Bridge (híd) eszközt találni. Győződjön meg róla, hogy a Hue Bridge (híd) ugyanahhoz a hálózathoz kapcsolódik, mint a SmartThings Hub, és be van kapcsolva. +'''Linking with your Hue'''=Összekapcsolás a Hue-val +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=A jelenleg Hue-felhasználónév érvénytelen. Nyomja meg a Hue Bridge (híd) gombját az újbóli összekapcsoláshoz. +'''Press the button on your Hue Bridge to setup a link.'''=Az összekapcsolás beállításához nyomja meg a Hue Bridge (híd) gombját. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Nem választott ki Hue Bridge (híd) eszközt. Nyomja meg a „Done” (Kész) gombot, és válasszon, mielőtt a Next (Tovább) gombra kattintana. +'''Success!'''=Sikerült! +'''Linking to your hub was a success! Please click 'Next'!'''=Sikeresen összekapcsolódott a hubbal! Kattintson a „Next” (Tovább) gombra! +'''Find bridges'''=Bridge (híd) eszközök keresése +'''Light Discovery Failed!'''=A Light (lámpa) keresése sikertelen volt! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Nem sikerült Light (lámpa) eszközt találni, próbálja meg később. Kattintson a Done (Kész) gombra a kilépéshez. +'''Select Hue Lights to add ({{numFound}} found)'''=Válassza ki a hozzáadni kívánt Hue Light (lámpa) eszközöket ({{numFound}} találat) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Előzőleg hozzáadott Hue Lights (lámpák) ({{existingLightsSize}} hozzáadva) +'''Light Discovery Started!'''=Megkezdődött a Light (lámpa) eszközök keresése! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Kis türelmet kérünk, amíg megtaláljuk a Hue Light (lámpa) eszközöket. Ez akár öt percnél is tovább tarthat, így némi türelemre lesz szükség! Az eszköz megtalálása után alább kiválaszthatja azt. diff --git a/smartapps/smartthings/hue-connect.src/i18n/it_IT.properties b/smartapps/smartthings/hue-connect.src/i18n/it_IT.properties new file mode 100644 index 0000000..891cf93 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/it_IT.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Consente di collegare le Philips Hue Light (lampadine Philips Hue) con SmartThings e di controllarle dall'area Things o dalla dashboard nell'applicazione mobile SmartThings. Aggiornate innanzitutto il bridge Hue, fuori dall'applicazione SmartThings, tramite l'applicazione Philips Hue. +'''Discovery Started!'''=Rilevamento avviato. +'''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.'''=Attendete mentre è in corso il rilevamento del bridge Hue. Tenete presente che occorre innanzitutto configurare il bridge e le lampadine Hue tramite l'applicazione Philips Hue. La procedura di rilevamento può richiede almeno cinque minuti, quindi sedetevi e rilassatevi! Selezionate il dispositivo in uso tra quelli riportati di seguito dopo il rilevamento. +'''Select Hue Bridge ({{numFound}} found)'''=Selezionate il bridge Hue ({{numFound}} trovati) +'''Bridge Discovery Failed!'''=Rilevamento bridge non riuscito. +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Impossibile rilevare i bridge Hue. Verificate che il bridge Hue sia connesso alla stessa rete dell'hub SmartThings e che sia collegato all'alimentazione. +'''Linking with your Hue'''=Collegamento con Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Il nome utente Hue corrente non è valido. Premete il pulsante sul bridge Hue per ripetere il collegamento. +'''Press the button on your Hue Bridge to setup a link.'''=Premete il pulsante sul bridge Hue per configurare un collegamento. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Non avete selezionato nessun bridge Hue. Premete “Done” (Fatto) e selezionatene uno prima di fare clic su Next (Avanti). +'''Success!'''=Operazione riuscita. +'''Linking to your hub was a success! Please click 'Next'!'''=Il collegamento all'hub è stato effettuato correttamente. Fate clic su “Next” (Avanti). +'''Find bridges'''=Cerca bridge +'''Light Discovery Failed!'''=Rilevamento lampadina non riuscito. +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Impossibile rilevare le lampadine. Riprovate più tardi. Fate clic su Done (Fatto) per uscire. +'''Select Hue Lights to add ({{numFound}} found)'''=Selezionate le Hue Light (lampadine Hue) da aggiungere ({{numFound}} trovate) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Hue Light (lampadine Hue) aggiunte in precedenza ({{existingLightsSize}} aggiunte) +'''Light Discovery Started!'''=Rilevamento lampadine avviato. +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Attendete mentre è in corso il rilevamento delle Hue Light (lampadine Hue). La procedura di rilevamento può richiede almeno cinque minuti, quindi sedetevi e rilassatevi! Selezionate il dispositivo in uso tra quelli riportati di seguito dopo il rilevamento. diff --git a/smartapps/smartthings/hue-connect.src/i18n/ko_KR.properties b/smartapps/smartthings/hue-connect.src/i18n/ko_KR.properties new file mode 100644 index 0000000..2f40e11 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/ko_KR.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Philips Hue 조명을 SmartThings와 연결하여 SmartThings 모바일 앱의 개별 기기 정보 영역이나 대시보드에서 조명을 조절할 수 있도록 지원합니다. SmartThings 앱을 빠져나와 Philips Hue 앱을 이용하여 먼저 Hue 브릿지를 업데이트하세요. +'''Discovery Started!'''=찾기 시작! +'''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.'''=Hue 브릿지 검색이 완료될 때까지 잠시 기다리세요. Philips Hue 앱을 이용하여 Hue 브릿지와 조명을 먼저 설정해야 합니다. 검색에는 5분 이상 걸릴 수 있으므로 편히 쉬면서 기다리세요! 검색이 완료되면 아래에서 기기를 선택하세요. +'''Select Hue Bridge ({{numFound}} found)'''=Hue 브릿지 선택 ({{numFound}}개 찾음) +'''Bridge Discovery Failed!'''=브릿지 찾기 실패! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Hue 브릿지를 찾지 못했습니다. Hue 브릿지가 SmartThings 허브와 같은 네트워크에 연결되어 있고 전원이 켜져 있는지 확인하세요. +'''Linking with your Hue'''=Hue와 연결 중 +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=현재 Hue 사용자 이름이 바르지 않습니다. Hue 브릿지의 버튼을 눌러 다시 연결하세요. +'''Press the button on your Hue Bridge to setup a link.'''=Hue 브릿지의 버튼을 눌러 다시 연결하세요. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=선택된 Hue 브릿지가 없습니다. [완료]를 누르고 Hue 브릿지를 선택한 후 [다음]을 클릭하세요. +'''Success!'''=성공! +'''Linking to your hub was a success! Please click 'Next'!'''=허브와 성공적으로 연결했습니다! [다음]을 클릭하세요. +'''Find bridges'''=브릿지 검색 +'''Light Discovery Failed!'''=조명 찾기 실패! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=조명을 찾지 못했습니다. 나중에 다시 시도하세요. 종료하려면 [완료]를 클릭하세요. +'''Select Hue Lights to add ({{numFound}} found)'''=추가할 Hue 조명 선택 ({{numFound}}개 찾음) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=이전에 추가한 Hue 조명 ({{existingLightsSize}} 추가됨) +'''Light Discovery Started!'''=조명 찾기 시작! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Hue 조명 검색이 완료될 때까지 잠시 기다리세요. 검색에는 5분 이상 걸릴 수 있으므로 편히 쉬면서 기다리세요! 검색이 완료되면 아래에서 기기를 선택하세요. diff --git a/smartapps/smartthings/hue-connect.src/i18n/nb_NO.properties b/smartapps/smartthings/hue-connect.src/i18n/nb_NO.properties new file mode 100644 index 0000000..ee833dc --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/nb_NO.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Lar deg koble Philips Hue Lights (lys) med SmartThings og kontrollere dem fra Things (Ting)-området eller dashbordet i SmartThings-mobilappen. Oppdater Hue Bridge (bro) først, utenfor SmartThings-appen, ved å bruke Philips Hue-appen. +'''Discovery Started!'''=Oppdagelse startet! +'''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.'''=Vent litt mens vi oppdager Hue Bridge (bro). Vær oppmerksom på at du må først sette opp Hue Bridge (bro) og Lights (lysene) ved å bruke Philips Hue-appen. Det kan ta fem minutter eller mer å oppdage den, så len deg tilbake og slapp av! Velg enheten nedenfor når den er oppdaget. +'''Select Hue Bridge ({{numFound}} found)'''=Velg Hue Bridge (bro) ({{numFound}} funnet) +'''Bridge Discovery Failed!'''=Oppdagelse av Bridge (bro) mislyktes! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Kunne ikke oppdage noen Hue Bridge (bro). Bekreft at Hue Bridge (bro) er koblet til det samme nettverket som SmartThings-huben, og at den har strøm. +'''Linking with your Hue'''=Kobler sammen med Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Det gjeldende Hue-brukernavnet er ugyldig. Trykk på knappen på Hue Bridge (bro) for å koble til igjen. +'''Press the button on your Hue Bridge to setup a link.'''=Trykk på knappen på Hue Bridge (bro) for å sette opp en kobling. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Du har ikke valgt en Hue Bridge (bro), trykk på “Done” (Utført), og velg en før du klikker på Next (Neste). +'''Success!'''=Suksess! +'''Linking to your hub was a success! Please click 'Next'!'''=Tilkobling til huben var vellykket! Klikk på 'Next' (Neste)! +'''Find bridges'''=Finn broer +'''Light Discovery Failed!'''=Lysoppdagelse mislyktes! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Kunne ikke oppdage noen lys, prøv igjen senere. Klikk på Done (Utført) for å avslutte. +'''Select Hue Lights to add ({{numFound}} found)'''=Velg Hue Ligths (lys) du vil legge til ({{numFound}} funnet) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Hue Lights (lys) tidligere lagt til ({{existingLightsSize}} lagt til) +'''Light Discovery Started!'''=Lysoppdagelse startet! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Vent litt mens vi oppdager Hue Lights (lys). Det kan ta fem minutter eller mer å oppdage den, så len deg tilbake og slapp av! Velg enheten nedenfor når den er oppdaget. diff --git a/smartapps/smartthings/hue-connect.src/i18n/nl_BE.properties b/smartapps/smartthings/hue-connect.src/i18n/nl_BE.properties new file mode 100644 index 0000000..cbf8841 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/nl_BE.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Hiermee kunt u uw Philips Hue lights (lampen) verbinden met SmartThings en ze bedienen via uw Things-gebied of het Dashboard in de SmartThings Mobiele app. Werk eerst met de Philips Hue-app uw Hue Bridge (brug) bij buiten de SmartThings-app. +'''Discovery Started!'''=Detectie gestart! +'''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.'''=Even geduld terwijl wij uw Hue Bridge (brug) detecteren. Houd er rekening mee dat u eerst uw Hue Bridge en Lights (lampen) moet configureren met de applicatie Philips Hue. Het detecteren kan wel vijf minuten of langer duren, dus even geduld! Selecteer uw apparaat hieronder na het detecteren. +'''Select Hue Bridge ({{numFound}} found)'''=Selecteer Hue Bridge (brug) ({{numFound}} gevonden) +'''Bridge Discovery Failed!'''=Detectie brug mislukt! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Kan geen Hue Bridges (bruggen) detecteren. Bevestig dat de Hue Bridge (brug) is verbonden met hetzelfde netwerk als uw SmartThings-hub en wordt voorzien van voeding. +'''Linking with your Hue'''=Koppelen met uw Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=De huidige Hue-gebruikersnaam is ongeldig. Druk op de knop op uw Hue Bridge (brug) om opnieuw te koppelen. +'''Press the button on your Hue Bridge to setup a link.'''=Druk op de knop op uw Hue Bridge (brug) om een koppeling in te stellen. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=U hebt geen Hue Bridge (brug) geselecteerd. Druk op “Done” (Gereed) en selecteer één brug voordat u op Next (Volgende) klikt. +'''Success!'''=Succes! +'''Linking to your hub was a success! Please click 'Next'!'''=De koppeling met uw hub is geslaagd! Klik op Next (Volgende)! +'''Find bridges'''=Bruggen zoeken +'''Light Discovery Failed!'''=Lampdetectie mislukt +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Kan geen lampen detecteren, probeer het later opnieuw. Klik op Done (Gereed) om af te sluiten. +'''Select Hue Lights to add ({{numFound}} found)'''=Selecteer Hue Lights (lampen) om toe te voegen ({{numFound}} gevonden) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Eerder toegevoegde Hue Lights (lampen) ({{existingLightsSize}} toegevoegd) +'''Light Discovery Started!'''=Lampdetectie gestart. +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Even geduld terwijl wij uw Hue Lights (lampen) detecteren. Het detecteren kan wel vijf minuten of langer duren, dus even geduld! Selecteer uw apparaat hieronder na het detecteren. diff --git a/smartapps/smartthings/hue-connect.src/i18n/nl_NL.properties b/smartapps/smartthings/hue-connect.src/i18n/nl_NL.properties new file mode 100644 index 0000000..cbf8841 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/nl_NL.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Hiermee kunt u uw Philips Hue lights (lampen) verbinden met SmartThings en ze bedienen via uw Things-gebied of het Dashboard in de SmartThings Mobiele app. Werk eerst met de Philips Hue-app uw Hue Bridge (brug) bij buiten de SmartThings-app. +'''Discovery Started!'''=Detectie gestart! +'''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.'''=Even geduld terwijl wij uw Hue Bridge (brug) detecteren. Houd er rekening mee dat u eerst uw Hue Bridge en Lights (lampen) moet configureren met de applicatie Philips Hue. Het detecteren kan wel vijf minuten of langer duren, dus even geduld! Selecteer uw apparaat hieronder na het detecteren. +'''Select Hue Bridge ({{numFound}} found)'''=Selecteer Hue Bridge (brug) ({{numFound}} gevonden) +'''Bridge Discovery Failed!'''=Detectie brug mislukt! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Kan geen Hue Bridges (bruggen) detecteren. Bevestig dat de Hue Bridge (brug) is verbonden met hetzelfde netwerk als uw SmartThings-hub en wordt voorzien van voeding. +'''Linking with your Hue'''=Koppelen met uw Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=De huidige Hue-gebruikersnaam is ongeldig. Druk op de knop op uw Hue Bridge (brug) om opnieuw te koppelen. +'''Press the button on your Hue Bridge to setup a link.'''=Druk op de knop op uw Hue Bridge (brug) om een koppeling in te stellen. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=U hebt geen Hue Bridge (brug) geselecteerd. Druk op “Done” (Gereed) en selecteer één brug voordat u op Next (Volgende) klikt. +'''Success!'''=Succes! +'''Linking to your hub was a success! Please click 'Next'!'''=De koppeling met uw hub is geslaagd! Klik op Next (Volgende)! +'''Find bridges'''=Bruggen zoeken +'''Light Discovery Failed!'''=Lampdetectie mislukt +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Kan geen lampen detecteren, probeer het later opnieuw. Klik op Done (Gereed) om af te sluiten. +'''Select Hue Lights to add ({{numFound}} found)'''=Selecteer Hue Lights (lampen) om toe te voegen ({{numFound}} gevonden) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Eerder toegevoegde Hue Lights (lampen) ({{existingLightsSize}} toegevoegd) +'''Light Discovery Started!'''=Lampdetectie gestart. +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Even geduld terwijl wij uw Hue Lights (lampen) detecteren. Het detecteren kan wel vijf minuten of langer duren, dus even geduld! Selecteer uw apparaat hieronder na het detecteren. diff --git a/smartapps/smartthings/hue-connect.src/i18n/pl_PL.properties b/smartapps/smartthings/hue-connect.src/i18n/pl_PL.properties new file mode 100644 index 0000000..eb51180 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/pl_PL.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Umożliwia łączenie Philips Hue Lights (lamp Philips Hue) z rozwiązaniem SmartThings oraz sterowanie nimi w obszarze Things (Rzeczy) lub na pulpicie nawigacyjnym w aplikacji mobilnej SmartThings. Najpierw zaktualizuj Hue Bridge (mostek Hue) poza aplikacją SmartThings, korzystając z aplikacji Philips Hue. +'''Discovery Started!'''=Rozpoczęto wykrywanie. +'''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.'''=Poczekaj na wykrycie Hue Bridge (mostka Hue). Pamiętaj, że najpierw musisz skonfigurować Hue Bridge (mostek Hue) i Hue Lights (lampy Hue) za pomocą aplikacji Philips Hue. Wykrywanie może potrwać co najmniej pięć minut, więc usiądź i zrelaksuj się. Po wykryciu Twojego urządzenia wybierz je poniżej. +'''Select Hue Bridge ({{numFound}} found)'''=Wybierz Hue Bridge (mostek Hue) (znaleziono {{numFound}}) +'''Bridge Discovery Failed!'''=Wykrywanie mostka nie powiodło się! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Wykrywanie Hue Bridges (mostków Hue) nie powiodło się. Potwierdź, że Hue Bridge (mostek Hue) został podłączony do tej samej sieci, co koncentrator SmartThings Hub, oraz że jego zasilanie działa. +'''Linking with your Hue'''=Łączenie z urządzeniem Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Bieżąca nazwa użytkownika urządzenia Hue jest nieprawidłowa. Naciśnij przycisk na Hue Bridge (mostku Hue), aby ponownie go podłączyć. +'''Press the button on your Hue Bridge to setup a link.'''=Naciśnij przycisk na Hue Bridge (mostku Hue), aby skonfigurować połączenie. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Nie wybrano Hue Bridge (mostka Hue), naciśnij opcję „Done” (Gotowe) i wybierz go przed kliknięciem opcji Next (Dalej). +'''Success!'''=Sukces! +'''Linking to your hub was a success! Please click 'Next'!'''=Łączenie z koncentratorem zakończyło się pomyślnie. Kliknij opcję „Next” (Dalej). +'''Find bridges'''=Wyszukaj mostki +'''Light Discovery Failed!'''=Wykrywanie lampy nie powiodło się. +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Nie można wykryć lamp, spróbuj ponownie później. Kliknij opcję Done (Gotowe), aby zakończyć. +'''Select Hue Lights to add ({{numFound}} found)'''=Wybierz Hue Lights (lampy Hue) do dodania (znaleziono {{numFound}}) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Poprzednio dodane Hue Lights (lampy Hue) (dodano {{existingLightsSize}}) +'''Light Discovery Started!'''=Rozpoczęto wykrywanie lamp. +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Poczekaj na wykrycie Hue Lights (lamp Hue). Wykrywanie może potrwać co najmniej pięć minut, więc usiądź i zrelaksuj się. Po wykryciu Twojego urządzenia wybierz je poniżej. diff --git a/smartapps/smartthings/hue-connect.src/i18n/pt_BR.properties b/smartapps/smartthings/hue-connect.src/i18n/pt_BR.properties new file mode 100644 index 0000000..81d8f13 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/pt_BR.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Permite conectar as luzes da Philips Hue com o SmartThings e controlá-las a partir da área "Things" (Coisas) ou do "Dashboard" (Painel) do aplicativo SmartThings Mobile. Primeiro atualize a ponte da Hue fora do aplicativo SmartThings, usando o aplicativo Philips Hue. +'''Discovery Started!'''=Detecção iniciada! +'''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.'''=Aguarde enquanto detectamos a ponte da Hue. Note que você deve primeiro configurar a ponte da Hue e as luzes usando o aplicativo Philips Hue. A detecção pode levar cinco minutos ou mais, portanto, sente-se e relaxe! Selecione abaixo o seu aparelho após a detecção. +'''Select Hue Bridge ({{numFound}} found)'''=Selecionar ponte da Hue ({{numFound}} encontrado(s)) +'''Bridge Discovery Failed!'''=Falha ao detectar a ponte! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Falha ao detectar pontes da Hue. Verifique se a ponte da Hue está conectada à mesma rede do seu SmartThings Hub e ligada na tomada. +'''Linking with your Hue'''=Vinculando com a Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=O nome de usuário da Hue atual é inválido. Pressione o botão na ponte da Hue para vincular novamente. +'''Press the button on your Hue Bridge to setup a link.'''=Pressione o botão na ponte da Hue para configurar a vinculação. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Você não selecionou uma ponte da Hue. Pressione 'Done' (Concluir) e selecione a ponte antes de clicar em Next (Avançar). +'''Success!'''=Sucesso! +'''Linking to your hub was a success! Please click 'Next'!'''=A vinculação com o hub foi concluída com êxito. Clique em "Next" (Avançar). +'''Find bridges'''=Encontrar pontes +'''Light Discovery Failed!'''=Falha ao detectar luz! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Falha ao detectar as luzes. Tente novamente mais tarde. Clique em \"Done\" (Concluir) para sair. +'''Select Hue Lights to add ({{numFound}} found)'''=Selecione as luzes da Hue a serem adicionadas ({{numFound}} encontrada(s)) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Luzes da Hue adicionadas anteriormente ({{existingLightsSize}} adicionada(s)) +'''Light Discovery Started!'''=Detecção de luz iniciada! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Aguarde enquanto detectamos as luzes da Hue. A detecção pode levar cinco minutos ou mais, portanto, sente-se e relaxe! Selecione abaixo o seu aparelho após a detecção. diff --git a/smartapps/smartthings/hue-connect.src/i18n/pt_PT.properties b/smartapps/smartthings/hue-connect.src/i18n/pt_PT.properties new file mode 100644 index 0000000..6298f90 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/pt_PT.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Permite-lhe ligar as luzes Philips Hue com o SmartThings e controlá-las a partir da sua área Things (Coisas) ou do Dashboard (Painel) na aplicação SmartThings Mobile. Actualize primeiro o seu Hue Bridge, fora da aplicação SmartThings, utilizando a aplicação Philips Hue. +'''Discovery Started!'''=Detecção Iniciada! +'''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.'''=Aguarde enquanto detectamos o seu Hue Bridge. Note que tem de configurar primeiro os seus Hue Bridge e Hue Lights (Luzes Hue) utilizando a aplicação Philips Hue. A detecção pode demorar cinco minutos ou mais, por isso, sente-se e relaxe! Seleccione o seu dispositivo abaixo depois de ter sido detectado. +'''Select Hue Bridge ({{numFound}} found)'''=Seleccionar Hue Bridge ({{numFound}} encontrado) +'''Bridge Discovery Failed!'''=Falha na Detecção de Bridge! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Falha ao detectar quaisquer Hue Bridges. Confirme se o Hue Bridge está ligado à mesma rede que o seu Hub SmartThings e que tem carga. +'''Linking with your Hue'''=Ligar com o Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=O nome de utilizador do Hue actual é inválido. Prima o botão no seu Hue Bridge para ligar novamente. +'''Press the button on your Hue Bridge to setup a link.'''=Prima o botão no Hue Bridge para configurar uma ligação. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Done' (Concluído) e seleccione um antes de clicar em Next (Seguinte). +'''Success!'''=Sucesso! +'''Linking to your hub was a success! Please click 'Next'!'''=A ligação ao seu Hub foi um sucesso! Clique em "Next" (Seguinte)! +'''Find bridges'''=Localizar bridges +'''Light Discovery Failed!'''=Falha na Detecção de Luzes! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Falha ao detectar quaisquer luzes, tente novamente mais tarde. Clique em \"Done\" (Concluído). +'''Select Hue Lights to add ({{numFound}} found)'''=Seleccione Hue Lights (Luzez Hue) para adicionar ({{numFound}} encontrado) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Hue Lights (Luzes Hue) anteriormente adicionado ({{existingLightsSize}} adicionado) +'''Light Discovery Started!'''=Detecção de Luzes Iniciada! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Aguarde enquanto detectamos o seu Hue Lights (Luzes Hue). A detecção pode demorar cinco minutos ou mais, por isso, sente-se e relaxe! Seleccione o seu dispositivo abaixo depois de ter sido detectado. diff --git a/smartapps/smartthings/hue-connect.src/i18n/ro_RO.properties b/smartapps/smartthings/hue-connect.src/i18n/ro_RO.properties new file mode 100644 index 0000000..02faf38 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/ro_RO.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Vă permite să conectați Philips Hue lights (luminile Philips Hue) cu SmartThings și să le controlați din zona Things sau Dashboard aflate în aplicația SmartThings Mobile. Actualizați mai întâi Hue Bridge, în afara aplicației SmartThings, utilizând aplicația Philips Hue. +'''Discovery Started!'''=Descoperire pornită! +'''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.'''=Așteptați până când descoperim dispozitivul Hue Bridge. Rețineți că trebuie să configurați mai întâi Hue Bridge și Hue Lights (lumini Hue) utilizând aplicația Philips Hue. Descoperirea poate dura aproximativ cinci sau mai multe minute; relaxați-vă și așteptați! Selectați dispozitivul mai jos după ce este descoperit. +'''Select Hue Bridge ({{numFound}} found)'''=Selectare Hue Bridge ({{numFound}} găsite) +'''Bridge Discovery Failed!'''=Descoperirea Hue Bridge nu a reușit! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Nu s-a descoperit niciun dispozitiv Hue Bridge. Confirmați că dispozitivul Hue Bridge este conectat la aceeași rețea ca și SmartThings Hub și că este alimentat. +'''Linking with your Hue'''=Asociere cu Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Numele de utilizator actual pentru Hue este nevalid. Apăsați butonul de pe Hue Bridge pentru a relua asocierea. +'''Press the button on your Hue Bridge to setup a link.'''=Apăsați butonul Hue Bridge pentru a configura o asociere. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Nu ați a selectat un dispozitive Hue Bridge; apăsați „Done” (Efectuat) și selectați unul, apoi faceți clic pe Next (Înainte). +'''Success!'''=Succes! +'''Linking to your hub was a success! Please click 'Next'!'''=Asocierea cu hubul dvs. a reușit! Faceți clic pe „Next” (Înainte)! +'''Find bridges'''=Găsire dispozitive bridge +'''Light Discovery Failed!'''=Descoperirea luminii nu a reușit! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Nu au fost găsită nicio lumină, încercați din nou mai târziu. Faceți clic pe Done (Efectuat) pentru a ieși. +'''Select Hue Lights to add ({{numFound}} found)'''=Selectați Hue Lights (lumini Hue) de adăugat ({{numFound}} găsite) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Hue Lights (lumini Hue) adăugate anterior ({{existingLightsSize}} adăugate) +'''Light Discovery Started!'''=Descoperire lumini pornită! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Așteptați până când descoperim Hue Lights (luminile Hue). Descoperirea poate dura aproximativ cinci sau mai multe minute; relaxați-vă și așteptați! Selectați dispozitivul mai jos după ce este descoperit. diff --git a/smartapps/smartthings/hue-connect.src/i18n/ru_RU.properties b/smartapps/smartthings/hue-connect.src/i18n/ru_RU.properties new file mode 100644 index 0000000..2a9880f --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/ru_RU.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Позволяет подключить лампы Philips Hue к концентратору SmartThings и управлять ими из области “Вещи” или с информационной панели в мобильном приложении SmartThings.\n\nПрежде чем перейти к настройке, обновите мост Hue при помощи приложения Philips Hue, вне приложения SmartThings. +'''Discovery Started!'''=Поиск начат! +'''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.'''=Идет поиск моста Hue. Обратите внимание, что сначала необходимо настроить мост и лампы Hue с помощью приложения Philips Hue. Пожалуйста, подождите. Поиск может занять больше 5 минут. В это время можно отдохнуть и расслабиться! Когда необходимое устройство будет обнаружено, выберите его из списка ниже. +'''Select Hue Bridge ({{numFound}} found)'''=Выберите мост Hue (найдено: {{numFound}}) +'''Bridge Discovery Failed!'''=Не удалось обнаружить мост Hue! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Не обнаружено ни одного моста Hue. Убедитесь, что мост Hue подключен к одной сети с концентратором SmartThings, а его питание — включено. +'''Linking with your Hue'''=Установка связи с Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Текущее имя пользователя Hue недопустимо. Нажмите кнопку на мосту Hue, чтобы установить связь повторно. +'''Press the button on your Hue Bridge to setup a link.'''=Нажмите кнопку на мосту Hue, чтобы установить связь. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Мост Hue не выбран. Прежде чем перейти к следующему шагу, нажмите “Готово” и выберите мост. +'''Success!'''=Успешно завершено! +'''Linking to your hub was a success! Please click 'Next'!'''=Связь с концентратором установлена! Нажмите “Далее”! +'''Find bridges'''=Поиск мостов +'''Light Discovery Failed!'''=Не удалось обнаружить лампу! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Не обнаружено ни одной лампы. Повторите попытку позже. Нажмите “Готово” для выхода. +'''Select Hue Lights to add ({{numFound}} found)'''=Выберите лампы Hue для добавления (найдено: {{numFound}}) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Уже добавленные лампы Hue (добавлено: {{existingLightsSize}}) +'''Light Discovery Started!'''=Поиск ламп начат! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Идет поиск ламп Hue. Пожалуйста, подождите. Поиск может занять больше 5 минут. В это время можно отдохнуть и расслабиться! Когда необходимое устройство будет обнаружено, выберите его из списка ниже. diff --git a/smartapps/smartthings/hue-connect.src/i18n/sk_SK.properties b/smartapps/smartthings/hue-connect.src/i18n/sk_SK.properties new file mode 100644 index 0000000..83d7776 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/sk_SK.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Umožňuje pripojiť svetlá Philips Hue pomocou centrály SmartThings a ovládať ich z oblasti Things (Veci) alebo z tabule v mobilnej aplikácii SmartThings. Najskôr aktualizujte sieťový most Hue mimo aplikácie SmartThings pomocou aplikácie Philips Hue. +'''Discovery Started!'''=Spustilo sa vyhľadávanie. +'''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.'''=Počkajte, kým sa nenájde sieťový most Hue. Najskôr musíte nakonfigurovať svetlá a sieťový most Hue pomocou aplikácie Philips Hue. Vyhľadávanie môže trvať aj päť minút alebo dlhšie, preto sa pokojne posaďte a počkajte. Po nájdení zariadenia ho nižšie vyberte. +'''Select Hue Bridge ({{numFound}} found)'''=Vyberte sieťový most Hue (nájdené: {{numFound}}) +'''Bridge Discovery Failed!'''=Vyhľadanie sieťového mostu zlyhalo. +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Nepodarilo sa nájsť žiadne sieťové mosty Hue. Skontrolujte, či je sieťový most Hue pripojený k rovnakej sieti ako sieťový most SmartThings a či je zapnutý. +'''Linking with your Hue'''=Prepojenie so zariadením Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Aktuálne meno používateľa zariadenia Hue je neplatné. Stlačením tlačidla na sieťovom moste Hue obnovte prepojenie. +'''Press the button on your Hue Bridge to setup a link.'''=Stlačením tlačidla na sieťovom moste Hue nastavte prepojenie. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Nevybrali ste žiadny sieťový most Hue. Stlačte tlačidlo „Done“ (Hotovo) a pred kliknutím na tlačidlo Next (Ďalej) nejaký vyberte. +'''Success!'''=Hotovo. +'''Linking to your hub was a success! Please click 'Next'!'''=Úspešne sa nadviazalo prepojenie s centrálou. Kliknite na tlačidlo Next (Ďalej). +'''Find bridges'''=Hľadať sieťové mosty +'''Light Discovery Failed!'''=Nepodarilo sa nájsť svetlo. +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Nepodarilo sa nájsť žiadne svetlá, skúste to znova neskôr. Kliknutím na tlačidlo Done (Hotovo) to ukončíte. +'''Select Hue Lights to add ({{numFound}} found)'''=Vyberte svetlá Hue, ktoré chcete pridať (nájdené: {{numFound}}) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Predtým pridané svetlá Hue (pridané: {{existingLightsSize}}) +'''Light Discovery Started!'''=Spustilo sa vyhľadávanie svetiel. +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Počkajte, kým sa nenájdu svetlá Hue. Vyhľadávanie môže trvať aj päť minút alebo dlhšie, preto sa pokojne posaďte a počkajte. Po nájdení zariadenia ho nižšie vyberte. diff --git a/smartapps/smartthings/hue-connect.src/i18n/sl_SI.properties b/smartapps/smartthings/hue-connect.src/i18n/sl_SI.properties new file mode 100644 index 0000000..05f1a48 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/sl_SI.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Omogoča povezavo Philips Hue lights (luči) s storitvijo SmartThings in njihovo upravljanje v razdelku Things (Stvari) ali na nadzorni plošči v mobilni aplikaciji SmartThings. Zunaj aplikacije SmartThings z aplikacijo Philips Hue najprej posodobite Hue Bridge (most). +'''Discovery Started!'''=Iskanje se je začelo! +'''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.'''=Počakajte, da poiščemo vaš Hue Bridge (most). Najprej morate z aplikacijo Philips Hue konfigurirati Hue Bridge (most) in Lights (luči). Iskanje lahko traja pet ali več minut, zato se udobno namestite in sprostite! Ko bo najdena, spodaj izberite svojo napravo. +'''Select Hue Bridge ({{numFound}} found)'''=Izberite Hue Bridge (most) (število najdenih: {{numFound}}) +'''Bridge Discovery Failed!'''=Iskanje mostu ni bilo uspešno! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Nobenega Hue Bridge (most) ni bilo mogoče najti. Preverite, ali je Hue Bridge (most) povezan z istim omrežjem kot zvezdišče SmartThings in priključen na napajanje. +'''Linking with your Hue'''=Povezovanje z izdelkom Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Trenutno uporabniško ime Hue ni veljavno. Za vnovično povezavo pritisnite gumb na Hue Bridge (most). +'''Press the button on your Hue Bridge to setup a link.'''=Za nastavitev povezave pritisnite gumb na Hue Bridge (most). +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Hue Bridge (most) niste izbrali. Pritisnite »Done« (Končano) in izberite most, preden kliknete Next (Naprej). +'''Success!'''=Uspeh! +'''Linking to your hub was a success! Please click 'Next'!'''=Povezava z zvezdiščem je bila uspešna! Kliknite »Next« (Naprej)! +'''Find bridges'''=Poišči mostove +'''Light Discovery Failed!'''=Iskanje luči ni bilo uspešno! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Nobene luči ni bilo mogoče najti, poskusite znova pozneje. Kliknite »Done« (Končano) za izhod. +'''Select Hue Lights to add ({{numFound}} found)'''=Izberite Hue Lights (luči), da jih dodate (število najdenih: {{numFound}}) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Predhodno dodane Hue Lights (luči) (dodano: {{existingLightsSize}}) +'''Light Discovery Started!'''=Iskanje luči se je začelo! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Počakajte, da poiščemo vaše Hue Lights (luči). Iskanje lahko traja pet ali več minut, zato se udobno namestite in sprostite! Ko bo najdena, spodaj izberite svojo napravo. diff --git a/smartapps/smartthings/hue-connect.src/i18n/sq_AL.properties b/smartapps/smartthings/hue-connect.src/i18n/sq_AL.properties new file mode 100644 index 0000000..499dde3 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/sq_AL.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Të lejon të lidhësh (dritat) Philips Hue lights me SmartThings dhe t’i kontrollosh që nga zona jote Things ose Paneli i drejtimit në App-in celular SmartThings. Përditëso (urën) Hue Bridge më parë, jashtë app-it SmartThings, me anë të app-it Philips Hue. +'''Discovery Started!'''=Zbulimi filloi! +'''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.'''=Prit pak sa të zbulojmë (urën) Hue Bridge. Mbaj parasysh se më parë duhet të konfigurosh (urën) Hue Bridge dhe Lights (dritat) me anë të aplikacionit Philips Hue. Zbulimi mund të kërkojë pesë minuta ose më shumë, prandaj bëj pak durim! Pasi të mbarojë zbulimi, përzgjidhe pajisjen tënde më poshtë. +'''Select Hue Bridge ({{numFound}} found)'''=Përzgjidh (urën) Hue Bridge ({{numFound}} u gjetën) +'''Bridge Discovery Failed!'''=Zbulimi i Bridge (urës) dështoi! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Dështova të zbuloj ndonjë (urë) Hue Bridge. Konfirmo që (ura) Hue Bridge është e lidhur me të njëjtin rrjet si Qendra SmartThings, dhe se ka energji. +'''Linking with your Hue'''=Për t’u lidhur me Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Emri i përdoruesit i tanishëm për Hue është i pavlefshëm. Shtyp butonin në (urën) Hue Bridge për t’u rilidhur. +'''Press the button on your Hue Bridge to setup a link.'''=Shtyp butonin në (urën) Hue Bridge për të konfiguruar lidhjen. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Nuk ke përzgjedhur ndonjë (urë) Hue Bridge, shtyp 'Done' (U krye) dhe përzgjidh një, para se të klikosh mbi Next (Tjetri). +'''Success!'''=Sukses! +'''Linking to your hub was a success! Please click 'Next'!'''=Lidhja me qendrën doli me sukses! Kliko mbi ‘Next’ (Tjetri)! +'''Find bridges'''=Gjej ura +'''Light Discovery Failed!'''=Zbulimi i dritës dështoi! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Dështova të zbuloj drita, provo sërish më vonë. Kliko mbi Done (U krye) për të dalë. +'''Select Hue Lights to add ({{numFound}} found)'''=Përzgjidh (dritat) Hue Lights për të shtuar ({{numFound}} u gjetën) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=(Dritat) Hue Lights të shtuara më parë ({{existingLightsSize}} u shtuan) +'''Light Discovery Started!'''=Zbulimi i dritave filloi! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Prit pak sa të zbulojmë (dritat) Hue Lights. Zbulimi mund të kërkojë pesë minuta ose më shumë, prandaj bëj pak durim! Pasi të mbarojë zbulimi, përzgjidhe pajisjen tënde më poshtë. diff --git a/smartapps/smartthings/hue-connect.src/i18n/sr_RS.properties b/smartapps/smartthings/hue-connect.src/i18n/sr_RS.properties new file mode 100644 index 0000000..033dbb0 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/sr_RS.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Omogućava vam da povežete Philips Hue svetla i SmartThings i da ih kontrolišete iz oblasti Things area (Oblast za stvari) ili sa Dashboard (Komandna tabla) u aplikaciji SmartThings Mobile. Prvo ažurirajte Hue Bridge, izvan aplikacije SmartThings, koristeći aplikaciju Philips Hue. +'''Discovery Started!'''=Otkrivanje je pokrenuto! +'''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.'''=Sačekajte da otkrijemo uređaj Hue Bridge. Imajte na umu da prvo morate da konfigurišete Hue Bridge (Hue most) i Hue Lights (Hue svetla) koristeći aplikaciju Philips Hue. Otkrivanje može da traje pet minuta ili duže i zato sedite i opustite se! Izaberite uređaj u nastavku kada bude otkriven. +'''Select Hue Bridge ({{numFound}} found)'''=Izaberite Hue Bridge ({{numFound}} pronađeno) +'''Bridge Discovery Failed!'''=Otkrivanje uređaja Bridge nije uspelo! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Nije otkriven nijedan Hue Bridge uređaj. Potvrdite da je uređaj Hue Bridge povezan na istu mrežu kao i SmartThings Hub i da je uključen. +'''Linking with your Hue'''=Povezivanje sa uređajem Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Trenutno korisničko ime za Hue je nevažeće. Pritisnite dugme na uređaju Hue Bridge da biste se ponovo povezali. +'''Press the button on your Hue Bridge to setup a link.'''=Pritisnite dugme na uređaju Hue Bridge da biste konfigurisali link. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Niste izabrali uređaj Hue Bridge, pritisnite „Done“ (Gotovo) i izaberite jedan pre nego što kliknete na sledeće. +'''Success!'''=Uspeh! +'''Linking to your hub was a success! Please click 'Next'!'''=Povezivanje na čvorište je bilo uspešno! Kliknite na „Next“ (Sledeće)! +'''Find bridges'''=Pronađi mostove +'''Light Discovery Failed!'''=Otkrivanje svetla nije uspelo! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Nije otkriveno nijedno svetlo, pokušajte ponovo kasnije. Kliknite na Done (Gotovo) radi izlaska. +'''Select Hue Lights to add ({{numFound}} found)'''=Izaberite svetla Hue Lights radi dodavanja (pronađeno: {{numFound}}) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Prethodno dodata svetla Hue Lights (dodato: {{existingLightsSize}}) +'''Light Discovery Started!'''=Otkrivanje svetla je pokrenuto! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Sačekajte da otkrijemo svetla Hue Lights. Otkrivanje može da traje pet minuta ili duže i zato sedite i opustite se! Izaberite uređaj u nastavku kada bude otkriven. diff --git a/smartapps/smartthings/hue-connect.src/i18n/sv_SE.properties b/smartapps/smartthings/hue-connect.src/i18n/sv_SE.properties new file mode 100644 index 0000000..e98192b --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/sv_SE.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Gör att du kan ansluta dina Philips Hue-lampor till SmartThings och styra dem från området Things (Saker) eller Dashboard (Instrumentpanelen) i programmet SmartThings Mobile. Uppdatera Hue-bryggan först, utanför programmet SmartThings, med programmet Philips Hue. +'''Discovery Started!'''=Identifieringen har startat! +'''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.'''=Vänta medan vi identifierar din Hue-brygga. Observera att du först måste konfigurera Hue-bryggan och lamporna med programmet Philips Hue. Identifieringen kan ta fem minuter eller mer, så ta det bara lugnt! Välj enheten nedan när den har identifierats. +'''Select Hue Bridge ({{numFound}} found)'''=Välj Hue-brygga ({{numFound}} hittades) +'''Bridge Discovery Failed!'''=Bryggidentifieringen misslyckades! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Det gick inte att identifiera några Hue-bryggor. Bekräfta att Hue-bryggan är ansluten till samma nätverk som SmartThings-hubben och att den är på. +'''Linking with your Hue'''=Länka till din Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Det nuvarande Hue-användarnamnet är ogiltigt. Tryck på knappen på Hue-bryggan för att göra om länkningen. +'''Press the button on your Hue Bridge to setup a link.'''=Tryck på knappen på Hue-bryggan för att konfigurera en länk. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Du har inte valt någon Hue-brygga. Tryck på ”Done” (Klart) och välj en innan du klickar på Next (Nästa). +'''Success!'''=Det lyckades! +'''Linking to your hub was a success! Please click 'Next'!'''=Det gick att länka till hubben! Klicka på Next (Nästa). +'''Find bridges'''=Hitta bryggor +'''Light Discovery Failed!'''=Lampidentifieringen misslyckades! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Det gick inte att identifiera några lampor. Försök igen senare. Avsluta genom att klicka på Done (Klart). +'''Select Hue Lights to add ({{numFound}} found)'''=Välj Hue-lampor att lägga till ({{numFound}} hittades) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Tidigare tillagda Hue-lampor ({{existingLightsSize}} tillagda) +'''Light Discovery Started!'''=Lampidentifieringen har startat! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Vänta medan vi identifierar dina Hue-lampor. Identifieringen kan ta fem minuter eller mer, så ta det bara lugnt! Välj enheten nedan när den har identifierats. diff --git a/smartapps/smartthings/hue-connect.src/i18n/th_TH.properties b/smartapps/smartthings/hue-connect.src/i18n/th_TH.properties new file mode 100644 index 0000000..281e714 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/th_TH.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=ช่วยให้คุณเชื่อมต่อไฟ Philips Hue ของคุณกับ SmartThings และทำการควบคุมไฟได้จากพื้นที่ Things หรือแดชบอร์ดของคุณในแอพมือถือ SmartThings โปรดอัพเดท Hue Bridge ของคุณก่อน ที่ด้านนอกแอพ SmartThings โดยใช้แอพ Philips Hue +'''Discovery Started!'''=การค้นหาเริ่มต้นแล้ว +'''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.'''=โปรดรอขณะเราค้นหา Hue Bridge ของคุณ ให้ทราบว่าคุณจะต้องกำหนดค่า Hue Bridge และไฟโดยใช้แอพพลิเคชั่น Phillips Hue ซึ่งขั้นตอนการค้นหาอาจใช้เวลาห้านาทีหรือมากกว่านั้น คุณสามารถนั่งรอได้โดยไม่ต้องกังวลใจ เลือกอุปกรณ์ของคุณที่ด้านล่างเมื่อถูกค้นพบ +'''Select Hue Bridge ({{numFound}} found)'''=เลือก Hue Bridge (พบ {{numFound}}) +'''Bridge Discovery Failed!'''=การค้นหา Bridge ล้มเหลว! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=ไม่พบ Hue Bridge ใดๆ โปรดยืนยันว่า Hue Bridge เชื่อมต่ออยู่กับเครือข่ายเดียวกันกับ SmartThings Hub ของคุณ และมีไฟเข้าอยู่ +'''Linking with your Hue'''=การเชื่อมโยงกับ Hue ของคุณ +'''The current Hue username is invalid. Please press the button on your Hue Bridge to relink.'''=ชื่อผู้ใช้ Hue ในปัจจุบันไม่ถูกต้อง โปรดกดปุ่มบน Hue Bridge ของคุณ เพื่อทำการเชื่อมโยงใหม่ +'''Press the button on your Hue Bridge to setup a link.'''=กดปุ่มบน Hue Bridge ของคุณเพื่อตั้งค่าลิงก์ +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=คุณยังไม่ได้เลือก Hue Bridge โปรดกด 'เรียบร้อย' และเลือกหนึ่งรายการก่อนคลิก ถัดไป +'''Success!'''=เสร็จสิ้น +'''Linking to your hub was a success! Please click 'Next'!'''=เชื่อมโยงกับ Hub ของคุณสำเร็จแล้ว โปรดคลิก 'ถัดไป' +'''Find bridges'''=พบ Bridge +'''Light Discovery Failed!'''=การค้นหาไฟล้มเหลว +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=ไม่พบไฟใดๆ โปรดลองอีกครั้งในภายหลัง คลิก เรียบร้อย เพื่อออก +'''Select Hue Lights to add ({{numFound}} found)'''=เลือกไฟ Hue เพื่อเพิ่ม (พบ {{numFound}}) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=ไฟ Hue ที่เพิ่มก่อนหน้านี้ ({{existingLightsSize}} ถูกเพิ่ม) +'''Light Discovery Started!'''=การค้นหาไฟเริ่มต้นแล้ว +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=โปรดรอขณะเราค้นหาไฟ Hue ของคุณ ขั้นตอนการค้นหาอาจใช้เวลาห้านาทีหรือมากกว่านั้น คุณสามารถนั่งรอได้โดยไม่ต้องกังวลใจ เลือกอุปกรณ์ของคุณที่ด้านล่างเมื่อถูกค้นพบ diff --git a/smartapps/smartthings/hue-connect.src/i18n/tr_TR.properties b/smartapps/smartthings/hue-connect.src/i18n/tr_TR.properties new file mode 100644 index 0000000..eba2abb --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/tr_TR.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=Philips Hue ışıklarınızı SmartThings'e bağlamanıza ve Things alanınız veya SmartThings uygulamasındaki Kontrol Paneli'nden kontrol etmenize olanak tanır. Lütfen önce SmartThings uygulamasının dışında Philips Hue uygulamasını kullanarak Hue Bridge'inizi güncelleyin. +'''Discovery Started!'''=Keşif Başladı! +'''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.'''=Hue Bridge'iniz keşfedilirken lütfen bekleyin. Hue Bridge ve Işıkları Philips Hue uygulamasını kullanarak yapılandırabileceğinizi lütfen unutmayın. Keşif beş dakika veya daha uzun sürebilir, biraz arkanıza yaslanıp rahatlayın! Keşfedildikten sonra aşağıda cihazınızı seçin. +'''Select Hue Bridge ({{numFound}} found)'''=Hue Bridge'i seçin ({{numFound}} bulundu) +'''Bridge Discovery Failed!'''=Bridge Keşfi Başarısız Oldu! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=Hiçbir Hue Bridge keşfedilemedi. Lütfen Hue Bridge'in SmartThings Hub'ınızla aynı ağa bağlı olduğunu ve gücünün olduğunu doğrulayın. +'''Linking with your Hue'''=Hue'nuzu bağlama +'''The current Hue username is invalid. Please press the button on your Hue Bridge to relink.'''=Mevcut Hue kullanıcı ismi geçersiz. Yeniden bağlamak için lütfen Hue Bridge'inizin üzerindeki tuşa basın. +'''Press the button on your Hue Bridge to setup a link.'''=Bağlantı kurmak için Hue Bridge'inizin üzerindeki tuşa basın. +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=Hue Bridge seçmediniz. İleri öğesine tıklamadan önce lütfen 'Bitti' öğesine basıp bir tane seçin. +'''Success!'''=Başarılı! +'''Linking to your hub was a success! Please click 'Next'!'''=Hub'ınız başarıyla bağlandı! Lütfen "İleri" öğesine tıklayın! +'''Find bridges'''=Bridge'leri bul +'''Light Discovery Failed!'''=Işık Keşfi Başarısız Oldu! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=Hiçbir ışık keşfedilemedi. Lütfen daha sonra tekrar deneyin. Çıkmak için Bitti öğesine tıklayın. +'''Select Hue Lights to add ({{numFound}} found)'''=Eklemek için Hue Işıklarını seçin ({{numFound}} bulundu) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=Önceden eklenen Hue Işıkları ({{existingLightsSize}} eklendi) +'''Light Discovery Started!'''=Işık Keşfi Başladı! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=Hue Işıklarınız keşfedilirken lütfen bekleyin. Keşif beş dakika veya daha uzun sürebilir, biraz arkanıza yaslanıp rahatlayın! Keşfedildikten sonra aşağıda cihazınızı seçin. diff --git a/smartapps/smartthings/hue-connect.src/i18n/zh_CN.properties b/smartapps/smartthings/hue-connect.src/i18n/zh_CN.properties new file mode 100644 index 0000000..92e7352 --- /dev/null +++ b/smartapps/smartthings/hue-connect.src/i18n/zh_CN.properties @@ -0,0 +1,19 @@ +'''Allows you to connect your Philips Hue lights with SmartThings and control them from your Things area or Dashboard in the SmartThings Mobile app. Please update your Hue Bridge first, outside of the SmartThings app, using the Philips Hue app.'''=可将 Philips Hue 灯连接到 SmartThings,并从 SmartThings 移动应用程序中的“设备”区域或仪表板控制它们。请首先使用 (SmartThings 应用程序以外的) Philips Hue 应用程序更新您的 Hue 桥接器。 +'''Discovery Started!'''=已开始查找! +'''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.'''=我们正在查找您的 Hue 桥接器,请稍候。请注意,首先您必须使用 Philips Hue 应用程序配置 Hue 桥接器。查找过程可能需要五分钟或更长时间,请耐心等待!找到之后,请在下方选择您的设备。 +'''Select Hue Bridge ({{numFound}} found)'''=选择 Hue 桥接器 (找到 {{numFound}} 个) +'''Bridge Discovery Failed!'''=桥接器查找失败! +'''Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.'''=未能找到任何 Hue 桥接器。请确认 Hue 桥接器连接到与 SmartThings Hub 相同的网络,并且该桥接器已接通电源。 +'''Linking with your Hue'''=正在连接您的 Hue +'''The current Hue username is invalid. Please press the button on your Hue Bridge to re-link.'''=Hue 当前用户名无效。请按 Hue 桥接器上的按钮重新链接。 +'''Press the button on your Hue Bridge to setup a link.'''=按 Hue 桥接器上的按钮以设置链接。 +'''You haven't selected a Hue Bridge, please Press 'Done' and select one before clicking next.'''=您尚未选择 Hue 桥接器,请按“完成”,选择一个桥接器,然后单击“下一步”。 +'''Success!'''=成功! +'''Linking to your hub was a success! Please click 'Next'!'''=成功链接到您的 Hub!请单击“下一步”! +'''Find bridges'''=查找桥接器 +'''Light Discovery Failed!'''=灯查找失败! +'''Failed to discover any lights, please try again later. Click 'Done' to exit.'''=未能找到任何灯,请稍候重试。单击“完成”以退出。 +'''Select Hue Lights to add ({{numFound}} found)'''=选择 Hue 灯进行添加 (找到 {{numFound}} 个) +'''Previously added Hue Lights ({{existingLightsSize}} added)'''=以前添加的 Hue 灯 (已添加 {{existingLightsSize}} 个) +'''Light Discovery Started!'''=已开始查找灯! +'''Please wait while we discover your Hue Lights. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.'''=我们正在查找您的 Hue 灯,请稍候。查找过程可能需要五分钟或更长时间,请耐心等待!找到之后,请在下方选择您的设备。 From fdd330abdf08058714716d7104dfdea6b4213c91 Mon Sep 17 00:00:00 2001 From: Lars Finander Date: Wed, 22 Mar 2017 16:14:17 -0700 Subject: [PATCH 10/16] DVCSMP-2453 HUE: add code to enable localization for Service Manager -Changed file names -ICP-462 --- .../hue-connect.src/i18n/{ar_AE.properties => ar-AE.properties} | 0 .../hue-connect.src/i18n/{bg_BG.properties => bg-BG.properties} | 0 .../hue-connect.src/i18n/{cs_CZ.properties => cs-CZ.properties} | 0 .../hue-connect.src/i18n/{da_DK.properties => da-DK.properties} | 0 .../hue-connect.src/i18n/{de_AT.properties => de-AT.properties} | 0 .../hue-connect.src/i18n/{de_CH.properties => de-CH.properties} | 0 .../hue-connect.src/i18n/{de_DE.properties => de-DE.properties} | 0 .../hue-connect.src/i18n/{el_GR.properties => el-GR.properties} | 0 .../hue-connect.src/i18n/{en_AU.properties => en-AU.properties} | 0 .../hue-connect.src/i18n/{en_CA.properties => en-CA.properties} | 0 .../hue-connect.src/i18n/{en_GB.properties => en-GB.properties} | 0 .../hue-connect.src/i18n/{en_IE.properties => en-IE.properties} | 0 .../hue-connect.src/i18n/{en_NZ.properties => en-NZ.properties} | 0 .../hue-connect.src/i18n/{en_PH.properties => en-PH.properties} | 0 .../hue-connect.src/i18n/{en_ZA.properties => en-ZA.properties} | 0 .../hue-connect.src/i18n/{es_ES.properties => es-ES.properties} | 0 .../hue-connect.src/i18n/{es_US.properties => es-US.properties} | 0 .../hue-connect.src/i18n/{et_EE.properties => et-EE.properties} | 0 .../hue-connect.src/i18n/{fi_FI.properties => fi-FI.properties} | 0 .../hue-connect.src/i18n/{fr_BE.properties => fr-BE.properties} | 0 .../hue-connect.src/i18n/{fr_CA.properties => fr-CA.properties} | 0 .../hue-connect.src/i18n/{fr_CH.properties => fr-CH.properties} | 0 .../hue-connect.src/i18n/{hr_HR.properties => hr-HR.properties} | 0 .../hue-connect.src/i18n/{hu_HU.properties => hu-HU.properties} | 0 .../hue-connect.src/i18n/{it_IT.properties => it-IT.properties} | 0 .../hue-connect.src/i18n/{ko_KR.properties => ko-KR.properties} | 0 .../hue-connect.src/i18n/{nb_NO.properties => nb-NO.properties} | 0 .../hue-connect.src/i18n/{nl_BE.properties => nl-BE.properties} | 0 .../hue-connect.src/i18n/{nl_NL.properties => nl-NL.properties} | 0 .../hue-connect.src/i18n/{pl_PL.properties => pl-PL.properties} | 0 .../hue-connect.src/i18n/{pt_BR.properties => pt-BR.properties} | 0 .../hue-connect.src/i18n/{pt_PT.properties => pt-PT.properties} | 0 .../hue-connect.src/i18n/{ro_RO.properties => ro-RO.properties} | 0 .../hue-connect.src/i18n/{ru_RU.properties => ru-RU.properties} | 0 .../hue-connect.src/i18n/{sk_SK.properties => sk-SK.properties} | 0 .../hue-connect.src/i18n/{sl_SI.properties => sl-SI.properties} | 0 .../hue-connect.src/i18n/{sq_AL.properties => sq-AL.properties} | 0 .../hue-connect.src/i18n/{sr_RS.properties => sr-RS.properties} | 0 .../hue-connect.src/i18n/{sv_SE.properties => sv-SE.properties} | 0 .../hue-connect.src/i18n/{th_TH.properties => th-TH.properties} | 0 .../hue-connect.src/i18n/{tr_TR.properties => tr-TR.properties} | 0 .../hue-connect.src/i18n/{zh_CN.properties => zh-CN.properties} | 0 42 files changed, 0 insertions(+), 0 deletions(-) rename smartapps/smartthings/hue-connect.src/i18n/{ar_AE.properties => ar-AE.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{bg_BG.properties => bg-BG.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{cs_CZ.properties => cs-CZ.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{da_DK.properties => da-DK.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{de_AT.properties => de-AT.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{de_CH.properties => de-CH.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{de_DE.properties => de-DE.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{el_GR.properties => el-GR.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{en_AU.properties => en-AU.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{en_CA.properties => en-CA.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{en_GB.properties => en-GB.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{en_IE.properties => en-IE.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{en_NZ.properties => en-NZ.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{en_PH.properties => en-PH.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{en_ZA.properties => en-ZA.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{es_ES.properties => es-ES.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{es_US.properties => es-US.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{et_EE.properties => et-EE.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{fi_FI.properties => fi-FI.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{fr_BE.properties => fr-BE.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{fr_CA.properties => fr-CA.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{fr_CH.properties => fr-CH.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{hr_HR.properties => hr-HR.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{hu_HU.properties => hu-HU.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{it_IT.properties => it-IT.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{ko_KR.properties => ko-KR.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{nb_NO.properties => nb-NO.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{nl_BE.properties => nl-BE.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{nl_NL.properties => nl-NL.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{pl_PL.properties => pl-PL.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{pt_BR.properties => pt-BR.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{pt_PT.properties => pt-PT.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{ro_RO.properties => ro-RO.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{ru_RU.properties => ru-RU.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{sk_SK.properties => sk-SK.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{sl_SI.properties => sl-SI.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{sq_AL.properties => sq-AL.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{sr_RS.properties => sr-RS.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{sv_SE.properties => sv-SE.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{th_TH.properties => th-TH.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{tr_TR.properties => tr-TR.properties} (100%) rename smartapps/smartthings/hue-connect.src/i18n/{zh_CN.properties => zh-CN.properties} (100%) diff --git a/smartapps/smartthings/hue-connect.src/i18n/ar_AE.properties b/smartapps/smartthings/hue-connect.src/i18n/ar-AE.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/ar_AE.properties rename to smartapps/smartthings/hue-connect.src/i18n/ar-AE.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/bg_BG.properties b/smartapps/smartthings/hue-connect.src/i18n/bg-BG.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/bg_BG.properties rename to smartapps/smartthings/hue-connect.src/i18n/bg-BG.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/cs_CZ.properties b/smartapps/smartthings/hue-connect.src/i18n/cs-CZ.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/cs_CZ.properties rename to smartapps/smartthings/hue-connect.src/i18n/cs-CZ.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/da_DK.properties b/smartapps/smartthings/hue-connect.src/i18n/da-DK.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/da_DK.properties rename to smartapps/smartthings/hue-connect.src/i18n/da-DK.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/de_AT.properties b/smartapps/smartthings/hue-connect.src/i18n/de-AT.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/de_AT.properties rename to smartapps/smartthings/hue-connect.src/i18n/de-AT.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/de_CH.properties b/smartapps/smartthings/hue-connect.src/i18n/de-CH.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/de_CH.properties rename to smartapps/smartthings/hue-connect.src/i18n/de-CH.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/de_DE.properties b/smartapps/smartthings/hue-connect.src/i18n/de-DE.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/de_DE.properties rename to smartapps/smartthings/hue-connect.src/i18n/de-DE.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/el_GR.properties b/smartapps/smartthings/hue-connect.src/i18n/el-GR.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/el_GR.properties rename to smartapps/smartthings/hue-connect.src/i18n/el-GR.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/en_AU.properties b/smartapps/smartthings/hue-connect.src/i18n/en-AU.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/en_AU.properties rename to smartapps/smartthings/hue-connect.src/i18n/en-AU.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/en_CA.properties b/smartapps/smartthings/hue-connect.src/i18n/en-CA.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/en_CA.properties rename to smartapps/smartthings/hue-connect.src/i18n/en-CA.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/en_GB.properties b/smartapps/smartthings/hue-connect.src/i18n/en-GB.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/en_GB.properties rename to smartapps/smartthings/hue-connect.src/i18n/en-GB.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/en_IE.properties b/smartapps/smartthings/hue-connect.src/i18n/en-IE.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/en_IE.properties rename to smartapps/smartthings/hue-connect.src/i18n/en-IE.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/en_NZ.properties b/smartapps/smartthings/hue-connect.src/i18n/en-NZ.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/en_NZ.properties rename to smartapps/smartthings/hue-connect.src/i18n/en-NZ.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/en_PH.properties b/smartapps/smartthings/hue-connect.src/i18n/en-PH.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/en_PH.properties rename to smartapps/smartthings/hue-connect.src/i18n/en-PH.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/en_ZA.properties b/smartapps/smartthings/hue-connect.src/i18n/en-ZA.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/en_ZA.properties rename to smartapps/smartthings/hue-connect.src/i18n/en-ZA.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/es_ES.properties b/smartapps/smartthings/hue-connect.src/i18n/es-ES.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/es_ES.properties rename to smartapps/smartthings/hue-connect.src/i18n/es-ES.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/es_US.properties b/smartapps/smartthings/hue-connect.src/i18n/es-US.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/es_US.properties rename to smartapps/smartthings/hue-connect.src/i18n/es-US.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/et_EE.properties b/smartapps/smartthings/hue-connect.src/i18n/et-EE.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/et_EE.properties rename to smartapps/smartthings/hue-connect.src/i18n/et-EE.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/fi_FI.properties b/smartapps/smartthings/hue-connect.src/i18n/fi-FI.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/fi_FI.properties rename to smartapps/smartthings/hue-connect.src/i18n/fi-FI.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/fr_BE.properties b/smartapps/smartthings/hue-connect.src/i18n/fr-BE.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/fr_BE.properties rename to smartapps/smartthings/hue-connect.src/i18n/fr-BE.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/fr_CA.properties b/smartapps/smartthings/hue-connect.src/i18n/fr-CA.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/fr_CA.properties rename to smartapps/smartthings/hue-connect.src/i18n/fr-CA.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/fr_CH.properties b/smartapps/smartthings/hue-connect.src/i18n/fr-CH.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/fr_CH.properties rename to smartapps/smartthings/hue-connect.src/i18n/fr-CH.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/hr_HR.properties b/smartapps/smartthings/hue-connect.src/i18n/hr-HR.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/hr_HR.properties rename to smartapps/smartthings/hue-connect.src/i18n/hr-HR.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/hu_HU.properties b/smartapps/smartthings/hue-connect.src/i18n/hu-HU.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/hu_HU.properties rename to smartapps/smartthings/hue-connect.src/i18n/hu-HU.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/it_IT.properties b/smartapps/smartthings/hue-connect.src/i18n/it-IT.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/it_IT.properties rename to smartapps/smartthings/hue-connect.src/i18n/it-IT.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/ko_KR.properties b/smartapps/smartthings/hue-connect.src/i18n/ko-KR.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/ko_KR.properties rename to smartapps/smartthings/hue-connect.src/i18n/ko-KR.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/nb_NO.properties b/smartapps/smartthings/hue-connect.src/i18n/nb-NO.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/nb_NO.properties rename to smartapps/smartthings/hue-connect.src/i18n/nb-NO.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/nl_BE.properties b/smartapps/smartthings/hue-connect.src/i18n/nl-BE.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/nl_BE.properties rename to smartapps/smartthings/hue-connect.src/i18n/nl-BE.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/nl_NL.properties b/smartapps/smartthings/hue-connect.src/i18n/nl-NL.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/nl_NL.properties rename to smartapps/smartthings/hue-connect.src/i18n/nl-NL.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/pl_PL.properties b/smartapps/smartthings/hue-connect.src/i18n/pl-PL.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/pl_PL.properties rename to smartapps/smartthings/hue-connect.src/i18n/pl-PL.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/pt_BR.properties b/smartapps/smartthings/hue-connect.src/i18n/pt-BR.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/pt_BR.properties rename to smartapps/smartthings/hue-connect.src/i18n/pt-BR.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/pt_PT.properties b/smartapps/smartthings/hue-connect.src/i18n/pt-PT.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/pt_PT.properties rename to smartapps/smartthings/hue-connect.src/i18n/pt-PT.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/ro_RO.properties b/smartapps/smartthings/hue-connect.src/i18n/ro-RO.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/ro_RO.properties rename to smartapps/smartthings/hue-connect.src/i18n/ro-RO.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/ru_RU.properties b/smartapps/smartthings/hue-connect.src/i18n/ru-RU.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/ru_RU.properties rename to smartapps/smartthings/hue-connect.src/i18n/ru-RU.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/sk_SK.properties b/smartapps/smartthings/hue-connect.src/i18n/sk-SK.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/sk_SK.properties rename to smartapps/smartthings/hue-connect.src/i18n/sk-SK.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/sl_SI.properties b/smartapps/smartthings/hue-connect.src/i18n/sl-SI.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/sl_SI.properties rename to smartapps/smartthings/hue-connect.src/i18n/sl-SI.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/sq_AL.properties b/smartapps/smartthings/hue-connect.src/i18n/sq-AL.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/sq_AL.properties rename to smartapps/smartthings/hue-connect.src/i18n/sq-AL.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/sr_RS.properties b/smartapps/smartthings/hue-connect.src/i18n/sr-RS.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/sr_RS.properties rename to smartapps/smartthings/hue-connect.src/i18n/sr-RS.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/sv_SE.properties b/smartapps/smartthings/hue-connect.src/i18n/sv-SE.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/sv_SE.properties rename to smartapps/smartthings/hue-connect.src/i18n/sv-SE.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/th_TH.properties b/smartapps/smartthings/hue-connect.src/i18n/th-TH.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/th_TH.properties rename to smartapps/smartthings/hue-connect.src/i18n/th-TH.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/tr_TR.properties b/smartapps/smartthings/hue-connect.src/i18n/tr-TR.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/tr_TR.properties rename to smartapps/smartthings/hue-connect.src/i18n/tr-TR.properties diff --git a/smartapps/smartthings/hue-connect.src/i18n/zh_CN.properties b/smartapps/smartthings/hue-connect.src/i18n/zh-CN.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/zh_CN.properties rename to smartapps/smartthings/hue-connect.src/i18n/zh-CN.properties From e6ca3d8ddf899300db621b3af10372ea6c618e24 Mon Sep 17 00:00:00 2001 From: Lars Finander Date: Wed, 22 Mar 2017 18:58:15 -0700 Subject: [PATCH 11/16] Hue: Renamed nb-NO to no-NO --- .../hue-connect.src/i18n/{nb-NO.properties => no-NO.properties} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename smartapps/smartthings/hue-connect.src/i18n/{nb-NO.properties => no-NO.properties} (100%) diff --git a/smartapps/smartthings/hue-connect.src/i18n/nb-NO.properties b/smartapps/smartthings/hue-connect.src/i18n/no-NO.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/nb-NO.properties rename to smartapps/smartthings/hue-connect.src/i18n/no-NO.properties From b1b356f370f0ef4e949dc4f59e2f26644575695e Mon Sep 17 00:00:00 2001 From: Lars Finander Date: Wed, 22 Mar 2017 19:35:36 -0700 Subject: [PATCH 12/16] Hue: Fixed fr-FR filename --- .../hue-connect.src/i18n/{fr_FR.properties => fr-FR.properties} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename smartapps/smartthings/hue-connect.src/i18n/{fr_FR.properties => fr-FR.properties} (100%) diff --git a/smartapps/smartthings/hue-connect.src/i18n/fr_FR.properties b/smartapps/smartthings/hue-connect.src/i18n/fr-FR.properties similarity index 100% rename from smartapps/smartthings/hue-connect.src/i18n/fr_FR.properties rename to smartapps/smartthings/hue-connect.src/i18n/fr-FR.properties From a2afb4cb1bb7715ff2188dee33de4539f8d08564 Mon Sep 17 00:00:00 2001 From: Donald Kirker Date: Thu, 23 Mar 2017 21:31:36 -0700 Subject: [PATCH 13/16] DVCSMP-2536 Update model and deviceJoinName values --- .../zll-white-color-temperature-bulb-5000k.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devicetypes/smartthings/zll-white-color-temperature-bulb-5000k.src/zll-white-color-temperature-bulb-5000k.groovy b/devicetypes/smartthings/zll-white-color-temperature-bulb-5000k.src/zll-white-color-temperature-bulb-5000k.groovy index 3c88380..a43c948 100644 --- a/devicetypes/smartthings/zll-white-color-temperature-bulb-5000k.src/zll-white-color-temperature-bulb-5000k.groovy +++ b/devicetypes/smartthings/zll-white-color-temperature-bulb-5000k.src/zll-white-color-temperature-bulb-5000k.groovy @@ -30,7 +30,7 @@ metadata { attribute "colorName", "string" command "setGenericName" - fingerprint profileId: "C05E", deviceId: "0220", inClusters: "0000, 0004, 0003, 0006, 0008, 0005, 0300", outClusters: "0019", manufacturer: "Eaton", model: "Halo_LT01", deviceJoinName: "Halo RL56 Wireless" + fingerprint profileId: "C05E", deviceId: "0220", inClusters: "0000, 0004, 0003, 0006, 0008, 0005, 0300", outClusters: "0019", manufacturer: "Eaton", model: "Halo_RL5601", deviceJoinName: "Halo RL56" } // UI tile definitions From 09e890091ac8991105ba0e9cb508cdc47c6fb85a Mon Sep 17 00:00:00 2001 From: sabersd Date: Mon, 27 Mar 2017 21:29:33 -0500 Subject: [PATCH 14/16] adding ocfDeviceType --- .../smartthings/smartalert-siren.src/smartalert-siren.groovy | 2 +- .../smartpower-dimming-outlet.groovy | 2 +- .../smartthings/smartpower-outlet.src/smartpower-outlet.groovy | 2 +- .../zigbee-dimmer-power.src/zigbee-dimmer-power.groovy | 2 +- .../zigbee-switch-power.src/zigbee-switch-power.groovy | 2 +- devicetypes/smartthings/zigbee-switch.src/zigbee-switch.groovy | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/devicetypes/smartthings/smartalert-siren.src/smartalert-siren.groovy b/devicetypes/smartthings/smartalert-siren.src/smartalert-siren.groovy index e46c42d..8c7a1c9 100644 --- a/devicetypes/smartthings/smartalert-siren.src/smartalert-siren.groovy +++ b/devicetypes/smartthings/smartalert-siren.src/smartalert-siren.groovy @@ -16,7 +16,7 @@ * Date: 2013-03-05 */ metadata { - definition (name: "SmartAlert Siren", namespace: "smartthings", author: "SmartThings") { + definition (name: "SmartAlert Siren", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "x.com.st.d.sensor.smoke") { capability "Actuator" capability "Switch" capability "Sensor" diff --git a/devicetypes/smartthings/smartpower-dimming-outlet.src/smartpower-dimming-outlet.groovy b/devicetypes/smartthings/smartpower-dimming-outlet.src/smartpower-dimming-outlet.groovy index fea3c37..fa5da7a 100644 --- a/devicetypes/smartthings/smartpower-dimming-outlet.src/smartpower-dimming-outlet.groovy +++ b/devicetypes/smartthings/smartpower-dimming-outlet.src/smartpower-dimming-outlet.groovy @@ -16,7 +16,7 @@ * Date: 2013-12-04 */ metadata { - definition (name: "SmartPower Dimming Outlet", namespace: "smartthings", author: "SmartThings") { + definition (name: "SmartPower Dimming Outlet", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.smartplug") { capability "Switch" capability "Switch Level" capability "Power Meter" diff --git a/devicetypes/smartthings/smartpower-outlet.src/smartpower-outlet.groovy b/devicetypes/smartthings/smartpower-outlet.src/smartpower-outlet.groovy index 76e0dc7..76a3dd0 100644 --- a/devicetypes/smartthings/smartpower-outlet.src/smartpower-outlet.groovy +++ b/devicetypes/smartthings/smartpower-outlet.src/smartpower-outlet.groovy @@ -15,7 +15,7 @@ */ metadata { // Automatically generated. Make future change here. - definition(name: "SmartPower Outlet", namespace: "smartthings", author: "SmartThings") { + definition(name: "SmartPower Outlet", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.smartplug") { capability "Actuator" capability "Switch" capability "Power Meter" diff --git a/devicetypes/smartthings/zigbee-dimmer-power.src/zigbee-dimmer-power.groovy b/devicetypes/smartthings/zigbee-dimmer-power.src/zigbee-dimmer-power.groovy index ceea649..c7130a3 100644 --- a/devicetypes/smartthings/zigbee-dimmer-power.src/zigbee-dimmer-power.groovy +++ b/devicetypes/smartthings/zigbee-dimmer-power.src/zigbee-dimmer-power.groovy @@ -13,7 +13,7 @@ */ metadata { - definition (name: "ZigBee Dimmer Power", namespace: "smartthings", author: "SmartThings") { + definition (name: "ZigBee Dimmer Power", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.switch") { capability "Actuator" capability "Configuration" capability "Refresh" diff --git a/devicetypes/smartthings/zigbee-switch-power.src/zigbee-switch-power.groovy b/devicetypes/smartthings/zigbee-switch-power.src/zigbee-switch-power.groovy index 9253465..28ea02d 100644 --- a/devicetypes/smartthings/zigbee-switch-power.src/zigbee-switch-power.groovy +++ b/devicetypes/smartthings/zigbee-switch-power.src/zigbee-switch-power.groovy @@ -13,7 +13,7 @@ */ metadata { - definition (name: "ZigBee Switch Power", namespace: "smartthings", author: "SmartThings") { + definition (name: "ZigBee Switch Power", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.switch") { capability "Actuator" capability "Configuration" capability "Refresh" diff --git a/devicetypes/smartthings/zigbee-switch.src/zigbee-switch.groovy b/devicetypes/smartthings/zigbee-switch.src/zigbee-switch.groovy index 34192de..52621a8 100644 --- a/devicetypes/smartthings/zigbee-switch.src/zigbee-switch.groovy +++ b/devicetypes/smartthings/zigbee-switch.src/zigbee-switch.groovy @@ -13,7 +13,7 @@ */ metadata { - definition (name: "ZigBee Switch", namespace: "smartthings", author: "SmartThings") { + definition (name: "ZigBee Switch", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.switch") { capability "Actuator" capability "Configuration" capability "Refresh" From 18343ae4b8adcce1201408a031a7e5422c4a6938 Mon Sep 17 00:00:00 2001 From: sabersd Date: Mon, 27 Mar 2017 21:46:25 -0500 Subject: [PATCH 15/16] fixing ocfDeviceType --- .../smartthings/smartalert-siren.src/smartalert-siren.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devicetypes/smartthings/smartalert-siren.src/smartalert-siren.groovy b/devicetypes/smartthings/smartalert-siren.src/smartalert-siren.groovy index 8c7a1c9..aaf2587 100644 --- a/devicetypes/smartthings/smartalert-siren.src/smartalert-siren.groovy +++ b/devicetypes/smartthings/smartalert-siren.src/smartalert-siren.groovy @@ -16,7 +16,7 @@ * Date: 2013-03-05 */ metadata { - definition (name: "SmartAlert Siren", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "x.com.st.d.sensor.smoke") { + definition (name: "SmartAlert Siren", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "x.com.st.smokedetector") { capability "Actuator" capability "Switch" capability "Sensor" From e3c1442278174fc2a833792e306ba8bf5e94832f Mon Sep 17 00:00:00 2001 From: "Donald C. Kirker" Date: Tue, 28 Mar 2017 11:31:04 -0700 Subject: [PATCH 16/16] MSA-1813 Spruce merge (#1841) * Hand merge changes from 379e70b3439544703323b544bbfcc3d3379b6126 into https://github.com/SmartThingsCommunity/SmartThingsPublic/pull/1737 * Spruce Scheduler from https://github.com/SmartThingsCommunity/SmartThingsPublic/pull/1737 --- .../spruce-controller.groovy | 656 ++-- .../spruce-scheduler.groovy | 3463 +++++++++++------ 2 files changed, 2629 insertions(+), 1490 deletions(-) diff --git a/devicetypes/plaidsystems/spruce-controller.src/spruce-controller.groovy b/devicetypes/plaidsystems/spruce-controller.src/spruce-controller.groovy index baf2f1a..df12e78 100644 --- a/devicetypes/plaidsystems/spruce-controller.src/spruce-controller.groovy +++ b/devicetypes/plaidsystems/spruce-controller.src/spruce-controller.groovy @@ -1,6 +1,5 @@ /** - * Spruce Controller - Pre Release V2 10/11/2015 - * + * Spruce Controller V2_4 Big Tiles * * Copyright 2015 Plaid Systems * * Author: NC @@ -21,82 +20,96 @@ */ metadata { - definition (name: "Spruce Controller", namespace: "plaidsystems", author: "NCauffman") { - capability "Switch" - capability "Configuration" - capability "Refresh" - capability "Actuator" - capability "Valve" + definition (name: 'Spruce Controller', namespace: 'plaidsystems', author: 'Plaid Systems') { + capability 'Switch' + capability 'Configuration' + capability 'Refresh' + capability 'Actuator' + capability 'Valve' - attribute "switch", "string" - attribute "switch1", "string" - attribute "switch2", "string" - attribute "switch8", "string" - attribute "switch5", "string" - attribute "switch3", "string" - attribute "switch4", "string" - attribute "switch6", "string" - attribute "switch7", "string" - attribute "switch9", "string" - attribute "switch10", "string" - attribute "switch11", "string" - attribute "switch12", "string" - attribute "switch13", "string" - attribute "switch14", "string" - attribute "switch15", "string" - attribute "switch16", "string" - attribute "status", "string" + attribute 'switch', 'string' + attribute 'switch1', 'string' + attribute 'switch2', 'string' + attribute 'switch8', 'string' + attribute 'switch5', 'string' + attribute 'switch3', 'string' + attribute 'switch4', 'string' + attribute 'switch6', 'string' + attribute 'switch7', 'string' + attribute 'switch9', 'string' + attribute 'switch10', 'string' + attribute 'switch11', 'string' + attribute 'switch12', 'string' + attribute 'switch13', 'string' + attribute 'switch14', 'string' + attribute 'switch15', 'string' + attribute 'switch16', 'string' + attribute 'rainsensor', 'string' + attribute 'status', 'string' + attribute 'tileMessage', 'string' + attribute 'minutes', 'string' + attribute 'VALUE_UP', 'string' + attribute 'VALUE_DOWN', 'string' - command "programOn" - command "programOff" - command "on" - command "off" - command "z1on" - command "z1off" - command "z2on" - command "z2off" - command "z3on" - command "z3off" - command "z4on" - command "z4off" - command "z5on" - command "z5off" - command "z6on" - command "z6off" - command "z7on" - command "z7off" - command "z8on" - command "z8off" - command "z9on" - command "z9off" - command "z10on" - command "z10off" - command "z11on" - command "z11off" - command "z12on" - command "z12off" - command "z13on" - command "z13off" - command "z14on" - command "z14off" - command "z15on" - command "z15off" - command "z16on" - command "z16off" - command "offtime" + command 'levelUp' + command 'levelDown' + command 'programOn' + command 'programOff' + command 'programWait' + command 'programEnd' - command "refresh" - command "rain" - command "manual" - command "setDisplay" + command 'on' + command 'off' + command 'zon' + command 'zoff' + command 'z1on' + command 'z1off' + command 'z2on' + command 'z2off' + command 'z3on' + command 'z3off' + command 'z4on' + command 'z4off' + command 'z5on' + command 'z5off' + command 'z6on' + command 'z6off' + command 'z7on' + command 'z7off' + command 'z8on' + command 'z8off' + command 'z9on' + command 'z9off' + command 'z10on' + command 'z10off' + command 'z11on' + command 'z11off' + command 'z12on' + command 'z12off' + command 'z13on' + command 'z13off' + command 'z14on' + command 'z14off' + command 'z15on' + command 'z15off' + command 'z16on' + command 'z16off' - command "settingsMap" - command "writeTime" - command "writeType" - command "notify" - command "updated" - - fingerprint endpointId: "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18", profileId: "0104", deviceId: "0002", deviceVersion: "00", inClusters: "0000,0003,0004,0005,0006,000F", outClusters: "0003, 0019", manufacturer: "PLAID SYSTEMS", model: "PS-SPRZ16-01" + command 'config' + command 'refresh' + command 'rain' + command 'manual' + command 'manualTime' + command 'settingsMap' + command 'writeTime' + command 'writeType' + command 'notify' + command 'updated' + + //ST release + //fingerprint endpointId: '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18', profileId: '0104', deviceId: '0002', deviceVersion: '00', inClusters: '0000,0003,0004,0005,0006,000F', outClusters: '0003, 0019', manufacturer: 'PLAID SYSTEMS', model: 'PS-SPRZ16-01' + //new release + fingerprint endpointId: "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18", profileId: "0104", deviceId: "0002", deviceVersion: "00", inClusters: "0000,0003,0004,0005,0006,0009,000A,000F", outClusters: "0003, 0019", manufacturer: "PLAID SYSTEMS", model: "PS-SPRZ16-01" } @@ -104,162 +117,230 @@ metadata { simulator { // status messages - // reply messages - + // reply messages } + preferences { - input description: "Press Configure button after making changes to these preferences", displayDuringSetup: true, type: "paragraph", element: "paragraph", title: "" - input "RainEnable", "bool", title: "Rain Sensor Attached?", required: false, displayDuringSetup: true - input "ManualTime", "number", title: "Automatic shutoff time when a zone is turned on manually?", required: false, displayDuringSetup: true - } + input description: 'If you have a rain sensor wired to the rain sensor input on the Spruce controller, turn it on here.', displayDuringSetup: true, type: 'paragraph', element: 'paragraph', title: 'Rain Sensor' + input description: 'The SYNC SETTINGS button must be pressed after making a change to the Rain sensor:', displayDuringSetup: false, type: 'paragraph', element: 'paragraph', title: '' + input 'RainEnable', 'bool', title: 'Rain Sensor Attached?', required: false, displayDuringSetup: true + input description: 'Adjust manual water time with arrows on main tile. The time indicated in the first small tile indicates the time the zone will water when manually switched on.', displayDuringSetup: false, type: 'paragraph', element: 'paragraph', title: '' + } // UI tile definitions tiles { - standardTile("status", "device.status") { - state "schedule", label: 'Schedule Set', icon: "http://www.plaidsystems.com/smartthings/st_spruce_leaf_225_t.png" - state "finished", label: 'Spruce Finished', icon: "st.Outdoor.outdoor5", backgroundColor: "#46c2e8" - state "raintoday", label: 'Rain Today', icon: "st.custom.wuk.nt_chancerain" - state "rainy", label: 'Previous Rain', icon: "st.custom.wuk.nt_chancerain" - state "raintom", label: 'Rain Tomorrow', icon: "st.custom.wuk.nt_chancerain" - state "donewweek", label: 'Spruce Finished', icon: "st.Outdoor.outdoor5", backgroundColor: "#00A0DC" - state "skipping", label: 'Skip Today', icon: "st.Outdoor.outdoor20", backgroundColor: "#36cfe3" - state "moisture", label: '', icon: "st.Weather.weather2", backgroundColor: "#36cfe3" - state "pause", label: 'PAUSE', icon: "st.contact.contact.open", backgroundColor: "#e86d13" - state "active", label: 'Active', icon: "st.Outdoor.outdoor12", backgroundColor: "#3DC72E" - state "season", label: 'Seasonal Adjustment', icon: "st.Outdoor.outdoor17", backgroundColor: "#ffb900" - state "disable", label: 'Disabled', icon: "st.secondary.off", backgroundColor: "#cccccc" - state "warning", label: '', icon: "st.categories.damageAndDanger", backgroundColor: "#ffff7f" - state "alarm", label: 'Alarm', icon: "st.categories.damageAndDanger", backgroundColor: "#f9240c" + multiAttributeTile(name:"switchall", type:"generic", width:6, height:4) { + tileAttribute('device.status', key: 'PRIMARY_CONTROL') { + attributeState 'schedule', label: 'Ready', icon: 'http://www.plaidsystems.com/smartthings/st_spruce_leaf_225_top.png' + attributeState 'finished', label: 'Finished', icon: 'st.Outdoor.outdoor5', backgroundColor: '#46c2e8' + attributeState 'raintoday', label: 'Rain Today', icon: 'http://www.plaidsystems.com/smartthings/st_rain.png', backgroundColor: '#d65fe3' + attributeState 'rainy', label: 'Rain', icon: 'http://www.plaidsystems.com/smartthings/st_rain.png', backgroundColor: '#d65fe3' + attributeState 'raintom', label: 'Rain Tomorrow', icon: 'http://www.plaidsystems.com/smartthings/st_rain.png', backgroundColor: '#d65fe3' + attributeState 'donewweek', label: 'Finished', icon: 'st.Outdoor.outdoor5', backgroundColor: '#00A0DC' + attributeState 'skipping', label: 'Skip', icon: 'st.Outdoor.outdoor20', backgroundColor: '#46c2e8' + attributeState 'moisture', label: 'Ready', icon: 'st.Weather.weather2', backgroundColor: '#46c2e8' + attributeState 'pause', label: 'PAUSE', icon: 'st.contact.contact.open', backgroundColor: '#e86d13' + attributeState 'delayed', label: 'Delayed', icon: 'st.contact.contact.open', backgroundColor: '#e86d13' + attributeState 'active', label: 'Active', icon: 'st.Outdoor.outdoor12', backgroundColor: '#3DC72E' + attributeState 'season', label: 'Adjust', icon: 'st.Outdoor.outdoor17', backgroundColor: '#ffb900' + attributeState 'disable', label: 'Off', icon: 'st.secondary.off', backgroundColor: '#cccccc' + attributeState 'warning', label: 'Warning', icon: 'http://www.plaidsystems.com/smartthings/st_spruce_leaf_225_top_yellow.png' + attributeState 'alarm', label: 'Alarm', icon: 'http://www.plaidsystems.com/smartthings/st_spruce_leaf_225_s_red.png', backgroundColor: '#e66565' + } + + tileAttribute("device.minutes", key: "VALUE_CONTROL") { + attributeState "VALUE_UP", action: "levelUp" + attributeState "VALUE_DOWN", action: "levelDown" + } + + tileAttribute("device.tileMessage", key: "SECONDARY_CONTROL") { + attributeState "tileMessage", label: '${currentValue}' + } + } - standardTile("switch", "device.switch") { - //state "programOff", label: 'Start Program', action: "programOn", icon: "st.sonos.play-icon", backgroundColor: "#a9a9a9" - state "off", label: 'Start Program', action: "programOn", icon: "st.sonos.play-icon", backgroundColor: "#a9a9a9" - state "programOn", label: 'Initialize Program', action: "programOff", icon: "st.contact.contact.open", backgroundColor: "#f6e10e" - state "on", label: 'Program Running', action: "off", icon: "st.Outdoor.outdoor12", backgroundColor: "#3DC72E" - } - standardTile("rainsensor", "device.rainsensor") { - state "rainSensrooff", label: 'Rain Sensor Clear', icon: "st.Weather.weather14", backgroundColor: "#a9a9a9" - state "rainSensoron", label: 'Rain Detected', icon: "st.Weather.weather10", backgroundColor: "#f6e10e" - } - standardTile("switch1", "device.switch1") { - state "z1off", label: '1', action: "z1on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z1on", label: '1', action: "z1off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" - } - standardTile("switch2", "device.switch2") { - state "z2off", label: '2', action: "z2on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z2on", label: '2', action: "z2off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" + valueTile('minutes', 'device.minutes'){ + state 'minutes', label: '${currentValue} min' + } + valueTile('dummy', 'device.minutes'){ + state 'minutes', label: '' + } + standardTile('switch', 'device.switch', width:2, height:2) { + state 'off', label: 'Start', action: 'programOn', icon: 'st.Outdoor.outdoor12', backgroundColor: '#a9a9a9' + state 'programOn', label: 'Wait', action: 'programOff', icon: 'st.contact.contact.open', backgroundColor: '#f6e10e' + state 'programWait', label: 'Wait', action: 'programEnd', icon: 'st.contact.contact.open', backgroundColor: '#f6e10e' + state 'on', label: 'Running', action: 'programEnd', icon: 'st.Outdoor.outdoor12', backgroundColor: '#3DC72E' } - standardTile("switch3", "device.switch3", inactiveLabel: false) { - state "z3off", label: '3', action: "z3on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z3on", label: '3', action: "z3off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" + standardTile("rainsensor", "device.rainsensor", decoration: 'flat') { + state "rainSensoroff", label: 'sensor', icon: 'http://www.plaidsystems.com/smartthings/st_drop_on.png' + state "rainSensoron", label: 'sensor', icon: 'http://www.plaidsystems.com/smartthings/st_drop_on_blue_small.png' + state "disable", label: 'sensor', icon: 'http://www.plaidsystems.com/smartthings/st_drop_x_small.png' + state "enable", label: 'sensor', icon: 'http://www.plaidsystems.com/smartthings/st_drop_on.png' } - standardTile("switch4", "device.switch4", inactiveLabel: false) { - state "z4off", label: '4', action: "z4on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z4on", label: '4', action: "z4off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" + standardTile('switch1', 'device.switch1', inactiveLabel: false) { + state 'z1off', label: '1', action: 'z1on', icon: 'st.valves.water.closed', backgroundColor: '#ffffff' + state 'z1on', label: '1', action: 'z1off', icon: 'st.valves.water.open', backgroundColor: '#00A0DC' } - standardTile("switch5", "device.switch5", inactiveLabel: false) { - state "z5off", label: '5', action: "z5on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z5on", label: '5', action: "z5off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" - } - standardTile("switch6", "device.switch6", inactiveLabel: false) { - state "z6off", label: '6', action: "z6on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z6on", label: '6', action: "z6off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" - } - standardTile("switch7", "device.switch7", inactiveLabel: false) { - state "z7off", label: '7', action: "z7on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z7on", label: '7', action: "z7off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" - } - standardTile("switch8", "device.switch8", inactiveLabel: false) { - state "z8off", label: '8', action: "z8on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z8on", label: '8', action: "z8off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" - } - standardTile("switch9", "device.switch9", inactiveLabel: false) { - state "z9off", label: '9', action: "z9on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z9on", label: '9', action: "z9off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" - } - standardTile("switch10", "device.switch10", inactiveLabel: false) { - state "z10off", label: '10', action: "z10on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z10on", label: '10', action: "z10off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" + standardTile('switch2', 'device.switch2', inactiveLabel: false) { + state 'z2off', label: '2', action: 'z2on', icon: 'st.valves.water.closed', backgroundColor: '#ffffff' + state 'z2on', label: '2', action: 'z2off', icon: 'st.valves.water.open', backgroundColor: '#00A0DC' } - standardTile("switch11", "device.switch11", inactiveLabel: false) { - state "z11off", label: '11', action: "z11on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z11on", label: '11', action: "z11off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" + standardTile('switch3', 'device.switch3', inactiveLabel: false) { + state 'z3off', label: '3', action: 'z3on', icon: 'st.valves.water.closed', backgroundColor: '#ffffff' + state 'z3on', label: '3', action: 'z3off', icon: 'st.valves.water.open', backgroundColor: '#00A0DC' } - standardTile("switch12", "device.switch12", inactiveLabel: false) { - state "z12off", label: '12', action: "z12on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z12on", label: '12', action: "z12off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" + standardTile('switch4', 'device.switch4', inactiveLabel: false) { + state 'z4off', label: '4', action: 'z4on', icon: 'st.valves.water.closed', backgroundColor: '#ffffff' + state 'z4on', label: '4', action: 'z4off', icon: 'st.valves.water.open', backgroundColor: '#00A0DC' } - standardTile("switch13", "device.switch13", inactiveLabel: false) { - state "z13off", label: '13', action: "z13on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z13on", label: '13', action: "z13off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" + standardTile('switch5', 'device.switch5', inactiveLabel: false) { + state 'z5off', label: '5', action: 'z5on', icon: 'st.valves.water.closed', backgroundColor: '#ffffff' + state 'z5on', label: '5', action: 'z5off', icon: 'st.valves.water.open', backgroundColor: '#00A0DC' } - standardTile("switch14", "device.switch14", inactiveLabel: false) { - state "z14off", label: '14', action: "z14on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z14on", label: '14', action: "z14off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" + standardTile('switch6', 'device.switch6', inactiveLabel: false) { + state 'z6off', label: '6', action: 'z6on', icon: 'st.valves.water.closed', backgroundColor: '#ffffff' + state 'z6on', label: '6', action: 'z6off', icon: 'st.valves.water.open', backgroundColor: '#00A0DC' } - standardTile("switch15", "device.switch15", inactiveLabel: false) { - state "z15off", label: '15', action: "z15on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z15on", label: '15', action: "z15off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" + standardTile('switch7', 'device.switch7', inactiveLabel: false) { + state 'z7off', label: '7', action: 'z7on', icon: 'st.valves.water.closed', backgroundColor: '#ffffff' + state 'z7on', label: '7', action: 'z7off', icon: 'st.valves.water.open', backgroundColor: '#00A0DC' + } + standardTile('switch8', 'device.switch8', inactiveLabel: false) { + state 'z8off', label: '8', action: 'z8on', icon: 'st.valves.water.closed', backgroundColor: '#ffffff' + state 'z8on', label: '8', action: 'z8off', icon: 'st.valves.water.open', backgroundColor: '#00A0DC' + } + standardTile('switch9', 'device.switch9', inactiveLabel: false) { + state 'z9off', label: '9', action: 'z9on', icon: 'st.valves.water.closed', backgroundColor: '#ffffff' + state 'z9on', label: '9', action: 'z9off', icon: 'st.valves.water.open', backgroundColor: '#00A0DC' + } + standardTile('switch10', 'device.switch10', inactiveLabel: false) { + state 'z10off', label: '10', action: 'z10on', icon: 'st.valves.water.closed', backgroundColor: '#ffffff' + state 'z10on', label: '10', action: 'z10off', icon: 'st.valves.water.open', backgroundColor: '#00A0DC' + } + standardTile('switch11', 'device.switch11', inactiveLabel: false) { + state 'z11off', label: '11', action: 'z11on', icon: 'st.valves.water.closed', backgroundColor: '#ffffff' + state 'z11on', label: '11', action: 'z11off', icon: 'st.valves.water.open', backgroundColor: '#00A0DC' + } + standardTile('switch12', 'device.switch12', inactiveLabel: false) { + state 'z12off', label: '12', action: 'z12on', icon: 'st.valves.water.closed', backgroundColor: '#ffffff' + state 'z12on', label: '12', action: 'z12off', icon: 'st.valves.water.open', backgroundColor: '#00A0DC' + } + standardTile('switch13', 'device.switch13', inactiveLabel: false) { + state 'z13off', label: '13', action: 'z13on', icon: 'st.valves.water.closed', backgroundColor: '#ffffff' + state 'z13on', label: '13', action: 'z13off', icon: 'st.valves.water.open', backgroundColor: '#00A0DC' + } + standardTile('switch14', 'device.switch14', inactiveLabel: false) { + state 'z14off', label: '14', action: 'z14on', icon: 'st.valves.water.closed', backgroundColor: '#ffffff' + state 'z14on', label: '14', action: 'z14off', icon: 'st.valves.water.open', backgroundColor: '#00A0DC' + } + standardTile('switch15', 'device.switch15', inactiveLabel: false) { + state 'z15off', label: '15', action: 'z15on', icon: 'st.valves.water.closed', backgroundColor: '#ffffff' + state 'z15on', label: '15', action: 'z15off', icon: 'st.valves.water.open', backgroundColor: '#00A0DC' } - standardTile("switch16", "device.switch16", inactiveLabel: false) { - state "z16off", label: '16', action: "z16on", icon: "st.valves.water.closed", backgroundColor: "#ffffff" - state "z16on", label: '16', action: "z16off", icon: "st.valves.water.open", backgroundColor: "#00A0DC" + standardTile('switch16', 'device.switch16', inactiveLabel: false) { + state 'z16off', label: '16', action: 'z16on', icon: 'st.valves.water.closed', backgroundColor: '#ffffff' + state 'z16on', label: '16', action: 'z16off', icon: 'st.valves.water.open', backgroundColor: '#00A0DC' } - standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") { - state "default", action: "refresh", icon:"st.secondary.refresh" + standardTile('refresh', 'device.switch', inactiveLabel: false, decoration: 'flat') { + state 'default', action: 'refresh', icon:'st.secondary.refresh'//-icon' } - standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat") { - state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure" - } + standardTile('configure', 'device.configure', inactiveLabel: false, decoration: 'flat') { + state 'configure', label:'', action:'configuration.configure', icon:'http://www.plaidsystems.com/smartthings/st_syncsettings.png'//sync_icon_small.png' + } - main (["status"]) - details(["status","rainsensor","switch","switch1","switch2","switch3","switch4","switch5","switch6","switch7","switch8","switch9","switch10","switch11","switch12","switch13","switch14","switch15","switch16","refresh","configure"]) - } + main (['switchall']) + details(['switchall','minutes','rainsensor','switch1','switch2','switch3','switch4','switch','switch5','switch6','switch7','switch8','switch9','switch10','switch11','switch12','refresh','configure','switch13','switch14','switch15','switch16']) + } } +//used for schedule def programOn(){ - sendEvent(name: "switch", value: "programOn", descriptionText: "Program turned on") + sendEvent(name: 'switch', value: 'programOn', descriptionText: 'Program turned on') + } + +def programWait(){ + sendEvent(name: 'switch', value: 'programWait', descriptionText: "Initializing Schedule") + } + +def programEnd(){ + //sets switch to off and tells schedule switch is off/schedule complete with manaual + sendEvent(name: 'switch', value: 'off', descriptionText: 'Program manually turned off') + zoff() } def programOff(){ - sendEvent(name: "switch", value: "off", descriptionText: "Program turned off") + sendEvent(name: 'switch', value: 'off', descriptionText: 'Program turned off') off() } - -def updated(){ - log.debug "updated" + +//set minutes +def levelUp(){ + def newvalue = 1 + if (device.latestValue('minutes') != null) newvalue = device.latestValue('minutes').toInteger()+1 + if (newvalue >= 60) newvalue = 60 + def value = newvalue.toString() + log.debug value + sendEvent(name: 'minutes', value: "${value}", descriptionText: "Manual Time set to ${value}", display: false) +} + +def levelDown(){ + def newvalue = device.latestValue('minutes').toInteger()-1 + if (newvalue <= 0) newvalue = 1 + def value = newvalue.toString() + log.debug value + sendEvent(name: 'minutes', value: "${value}", descriptionText: "Manual Time set to ${value}", display: false) } // Parse incoming device messages to generate events def parse(String description) { - //log.debug "Parse description $description" + log.debug "Parse description ${description}" def result = null def map = [:] - if (description?.startsWith("read attr -")) { + if (description?.startsWith('read attr -')) { def descMap = parseDescriptionAsMap(description) //log.debug "Desc Map: $descMap" //using 000F cluster instead of 0006 (switch) because ST does not differentiate between EPs and processes all as switch - if (descMap.cluster == "000F" && descMap.attrId == "0055") { - log.debug "Zone" + if (descMap.cluster == '000F' && descMap.attrId == '0055') { + log.debug 'Zone' map = getZone(descMap) } - else if (descMap.cluster == "0009" && descMap.attrId == "0000") { - log.debug "Alarm" + else if (descMap.cluster == '0009' && descMap.attrId == '0000') { + log.debug 'Alarm' map = getAlarm(descMap) } - } - - if (map) { - result = createEvent(map) } - log.debug "Parse returned $map $result" + else if (description?.startsWith('catchall: 0104 0009')){ + log.debug 'Sync settings to controller complete' + if (device.latestValue('status') != 'alarm'){ + def configEvt = createEvent(name: 'status', value: 'schedule', descriptionText: "Sync settings to controller complete") + def configMsg = createEvent(name: 'tileMessage', value: 'Sync settings to controller complete', descriptionText: "Sync settings to controller complete", displayed: false) + result = [configEvt, configMsg] + } + return result + } + + if (map) { + result = createEvent(map) + //configure after reboot + if (map.value == 'warning' || map.value == 'alarm'){ + def cmds = config() + def alarmEvt = createEvent(name: 'tileMessage', value: map.descriptionText, descriptionText: "${map.descriptionText}", displayed: false) + result = cmds?.collect { new physicalgraph.device.HubAction(it) } + createEvent(map) + alarmEvt + return result + } + else if (map.name == 'rainsensor'){ + def rainEvt = createEvent(name: 'tileMessage', value: map.descriptionText, descriptionText: "${map.descriptionText}", displayed: false) + result = [createEvent(map), rainEvt] + return result + } + } + if (map) log.debug "Parse returned ${map} ${result}" return result } def parseDescriptionAsMap(description) { - (description - "read attr - ").split(",").inject([:]) { map, param -> - def nameAndValue = param.split(":") + (description - 'read attr - ').split(',').inject([:]) { map, param -> + def nameAndValue = param.split(':') map += [(nameAndValue[0].trim()):nameAndValue[1].trim()] } } @@ -270,27 +351,28 @@ def getZone(descMap){ def EP = Integer.parseInt(descMap.endpoint.trim(), 16) String onoff - if(descMap.value == "00"){ - onoff = "off" + if(descMap.value == '00'){ + onoff = 'off' } - else onoff = "on" + else onoff = 'on' if (EP == 1){ - map.name = "switch" + map.name = 'switch' map.value = onoff - map.descriptionText = "${device.displayName} turned sprinkler program $onoff" + map.descriptionText = "${device.displayName} turned sprinkler program ${onoff}" } else if (EP == 18) { - map.name = "rainsensor" - map.value = "rainSensor" + onoff - map.descriptionText = "${device.displayName} rain sensor is $onoff" + map.name = 'rainsensor' + log.debug "Rain enable: ${RainEnable}, sensor: ${onoff}" + map.value = 'rainSensor' + onoff + map.descriptionText = "${device.displayName} rain sensor is ${onoff}" } else { EP -= 1 - map.name = "switch" + EP - map.value = "z" + EP + onoff - map.descriptionText = "${device.displayName} turned Zone $EP $onoff" + map.name = 'switch' + EP + map.value = 'z' + EP + onoff + map.descriptionText = "${device.displayName} turned Zone $EP ${onoff}" } map.isStateChange = true @@ -300,37 +382,59 @@ def getZone(descMap){ def getAlarm(descMap){ def map = [:] - map.name = "status" + map.name = 'status' def alarmID = Integer.parseInt(descMap.value.trim(), 16) log.debug "${alarmID}" - if(alarmID <= 0) map.descriptionText = "${device.displayName} has rebooted, no other alarms" - else map.descriptionText = "${device.displayName} rebooted, reported error on zone ${alarmID - 1}, please check zone is working correctly" - map.value = "alarm" - map.isStateChange = true + map.value = 'alarm' map.displayed = true + map.isStateChange = true + if(alarmID <= 0){ + map.descriptionText = "${device.displayName} reboot, no other alarms" + map.value = 'warning' + //map.isStateChange = false + } + else map.descriptionText = "${device.displayName} reboot, reported zone ${alarmID - 1} error, please check zone is working correctly, press SYNC SETTINGS button to clear" + return map } //status notify and change status -def notify(value, text){ - sendEvent(name:"status", value:"$value", descriptionText:"$text", isStateChange: true, display: false) +def notify(String val, String txt){ + sendEvent(name: 'status', value: val, descriptionText: txt, isStateChange: true, display: false) + + //String txtShort = txt.take(100) + sendEvent(name: 'tileMessage', value: txt, descriptionText: "", isStateChange: true, display: false) +} +def updated(){ + log.debug "updated" + } //prefrences - rain sensor, manual time def rain() { - log.debug "Rain $RainEnable" + log.debug "Rain sensor: ${RainEnable}" + if (RainEnable) sendEvent(name: 'rainsensor', value: 'enable', descriptionText: "${device.displayName} rain sensor is enabled", isStateChange: true) + else sendEvent(name: 'rainsensor', value: 'disable', descriptionText: "${device.displayName} rain sensor is disabled", isStateChange: true) + if (RainEnable) "st wattr 0x${device.deviceNetworkId} 18 0x0F 0x51 0x10 {01}" else "st wattr 0x${device.deviceNetworkId} 18 0x0F 0x51 0x10 {00}" } -def manual(){ - log.debug "Time $ManualTime" - def mTime = 10 - if (ManualTime) mTime = ManualTime - def manualTime = hex(mTime) - "st wattr 0x${device.deviceNetworkId} 1 6 0x4002 0x21 {00${manualTime}}" + +def manualTime(value){ + sendEvent(name: 'minutes', value: "${value}", descriptionText: "Manual Time set to ${value}", display: false) +} + +def manual(){ + def newManaul = 10 + if (device.latestValue('minutes')) newManaul = device.latestValue('minutes').toInteger() + log.debug "Manual Zone runtime ${newManaul} mins" + def manualTime = hex(newManaul) - } + def sendCmds = [] + sendCmds.push("st wattr 0x${device.deviceNetworkId} 1 6 0x4002 0x21 {00${manualTime}}") + return sendCmds +} //write switch time settings map def settingsMap(WriteTimes, attrType){ @@ -366,13 +470,20 @@ def writeTime(wEP, runTime){ //set reporting and binding def configure() { + + sendEvent(name: 'status', value: 'schedule', descriptionText: "Syncing settings to controller") + sendEvent(name: 'minutes', value: "10", descriptionText: "Manual Time set to 10 mins", display: false) + sendEvent(name: 'tileMessage', value: 'Syncing settings to controller', descriptionText: 'Syncing settings to controller') + config() +} + +def config(){ String zigbeeId = swapEndianHex(device.hub.zigbeeId) - log.debug "Confuguring Reporting and Bindings ${device.deviceNetworkId} ${device.zigbeeId}" - sendEvent(name: 'configuration',value: 100, descriptionText: "Configuration initialized") + log.debug "Configuring Reporting and Bindings ${device.deviceNetworkId} ${device.zigbeeId}" def configCmds = [ - //program on/off + //program on/off "zdo bind 0x${device.deviceNetworkId} 1 1 6 {${device.zigbeeId}} {}", "delay 1000", "zdo bind 0x${device.deviceNetworkId} 1 1 0x09 {${device.zigbeeId}} {}", "delay 1000", "zdo bind 0x${device.deviceNetworkId} 1 1 0x0F {${device.zigbeeId}} {}", "delay 1000", @@ -458,38 +569,16 @@ def configure() { "zcl global send-me-a-report 0x09 0x00 0x21 1 0 {00}", "delay 500", "send 0x${device.deviceNetworkId} 1 1", "delay 500" ] - return configCmds + rain() + manual() + return configCmds + rain() } - - -private hex(value) { - new BigInteger(Math.round(value).toString()).toString(16) -} - -private String swapEndianHex(String hex) { - reverseArray(hex.decodeHex()).encodeHex() -} - -private byte[] reverseArray(byte[] array) { - int i = 0; - int j = array.length - 1; - byte tmp; - while (j > i) { - tmp = array[j]; - array[j] = array[i]; - array[i] = tmp; - j--; - i++; - } - return array -} - def refresh() { - log.debug "refresh" - def refreshCmds = [ - + log.debug "refresh pressed" + sendEvent(name: 'tileMessage', value: 'Refresh', descriptionText: 'Refresh') + + def refreshCmds = [ + "st rattr 0x${device.deviceNetworkId} 1 0x0F 0x55", "delay 500", "st rattr 0x${device.deviceNetworkId} 2 0x0F 0x55", "delay 500", @@ -513,64 +602,96 @@ def refresh() { "st rattr 0x${device.deviceNetworkId} 18 0x0F 0x51","delay 500", ] - return refreshCmds + rain() + manual() + + return refreshCmds +} + +private hex(value) { + new BigInteger(Math.round(value).toString()).toString(16) +} + +private String swapEndianHex(String hex) { + reverseArray(hex.decodeHex()).encodeHex() +} + +private byte[] reverseArray(byte[] array) { + int i = 0; + int j = array.length - 1; + byte tmp; + while (j > i) { + tmp = array[j]; + array[j] = array[i]; + array[i] = tmp; + j--; + i++; + } + return array +} + +//on & off redefined for Alexa to start manual schedule +def on() { + log.debug 'Alexa on' + //schedule subscribes to programOn + sendEvent(name: 'switch', value: 'programOn', descriptionText: 'Alexa turned program on') +} +def off() { + log.debug 'Alexa off' + sendEvent(name: 'switch', value: 'off', descriptionText: 'Alexa turned program off') + zoff() } // Commands to device //zones on - 8 -def on() { - //sendEvent(name:"status", value:"active", descriptionText:"Program Running", isStateChange: true, display: false) - log.debug "on" - "st cmd 0x${device.deviceNetworkId} 1 6 1 {}" +def zon() { + "st cmd 0x${device.deviceNetworkId} 1 6 1 {}" } -def off() { - log.debug "off" - "st cmd 0x${device.deviceNetworkId} 1 6 0 {}" +def zoff() { + "st cmd 0x${device.deviceNetworkId} 1 6 0 {}" } def z1on() { - "st cmd 0x${device.deviceNetworkId} 2 6 1 {}" + return manual() + "st cmd 0x${device.deviceNetworkId} 2 6 1 {}" } def z1off() { "st cmd 0x${device.deviceNetworkId} 2 6 0 {}" } def z2on() { - "st cmd 0x${device.deviceNetworkId} 3 6 1 {}" + return manual() + "st cmd 0x${device.deviceNetworkId} 3 6 1 {}" } def z2off() { "st cmd 0x${device.deviceNetworkId} 3 6 0 {}" } def z3on() { - "st cmd 0x${device.deviceNetworkId} 4 6 1 {}" + return manual() + "st cmd 0x${device.deviceNetworkId} 4 6 1 {}" } def z3off() { "st cmd 0x${device.deviceNetworkId} 4 6 0 {}" } def z4on() { - "st cmd 0x${device.deviceNetworkId} 5 6 1 {}" + return manual() + "st cmd 0x${device.deviceNetworkId} 5 6 1 {}" } def z4off() { "st cmd 0x${device.deviceNetworkId} 5 6 0 {}" } def z5on() { - "st cmd 0x${device.deviceNetworkId} 6 6 1 {}" + return manual() + "st cmd 0x${device.deviceNetworkId} 6 6 1 {}" } def z5off() { "st cmd 0x${device.deviceNetworkId} 6 6 0 {}" } def z6on() { - "st cmd 0x${device.deviceNetworkId} 7 6 1 {}" + return manual() + "st cmd 0x${device.deviceNetworkId} 7 6 1 {}" } def z6off() { "st cmd 0x${device.deviceNetworkId} 7 6 0 {}" } def z7on() { - "st cmd 0x${device.deviceNetworkId} 8 6 1 {}" + return manual() + "st cmd 0x${device.deviceNetworkId} 8 6 1 {}" } def z7off() { "st cmd 0x${device.deviceNetworkId} 8 6 0 {}" } def z8on() { - "st cmd 0x${device.deviceNetworkId} 9 6 1 {}" + return manual() + "st cmd 0x${device.deviceNetworkId} 9 6 1 {}" } def z8off() { "st cmd 0x${device.deviceNetworkId} 9 6 0 {}" @@ -578,50 +699,51 @@ def z8off() { //zones 9 - 16 def z9on() { - "st cmd 0x${device.deviceNetworkId} 10 6 1 {}" + return manual() + "st cmd 0x${device.deviceNetworkId} 10 6 1 {}" } def z9off() { "st cmd 0x${device.deviceNetworkId} 10 6 0 {}" } def z10on() { - "st cmd 0x${device.deviceNetworkId} 11 6 1 {}" + return manual() + "st cmd 0x${device.deviceNetworkId} 11 6 1 {}" } def z10off() { "st cmd 0x${device.deviceNetworkId} 11 6 0 {}" } def z11on() { - "st cmd 0x${device.deviceNetworkId} 12 6 1 {}" + return manual() + "st cmd 0x${device.deviceNetworkId} 12 6 1 {}" } def z11off() { "st cmd 0x${device.deviceNetworkId} 12 6 0 {}" } def z12on() { - "st cmd 0x${device.deviceNetworkId} 13 6 1 {}" + return manual() + "st cmd 0x${device.deviceNetworkId} 13 6 1 {}" } def z12off() { "st cmd 0x${device.deviceNetworkId} 13 6 0 {}" } def z13on() { - "st cmd 0x${device.deviceNetworkId} 14 6 1 {}" + return manual() + "st cmd 0x${device.deviceNetworkId} 14 6 1 {}" } def z13off() { "st cmd 0x${device.deviceNetworkId} 14 6 0 {}" } def z14on() { - "st cmd 0x${device.deviceNetworkId} 15 6 1 {}" + return manual() + "st cmd 0x${device.deviceNetworkId} 15 6 1 {}" } def z14off() { "st cmd 0x${device.deviceNetworkId} 15 6 0 {}" } def z15on() { - "st cmd 0x${device.deviceNetworkId} 16 6 1 {}" + return manual() + "st cmd 0x${device.deviceNetworkId} 16 6 1 {}" } def z15off() { "st cmd 0x${device.deviceNetworkId} 16 6 0 {}" } def z16on() { - "st cmd 0x${device.deviceNetworkId} 17 6 1 {}" + return manual() + "st cmd 0x${device.deviceNetworkId} 17 6 1 {}" } def z16off() { "st cmd 0x${device.deviceNetworkId} 17 6 0 {}" -} \ No newline at end of file +} + diff --git a/smartapps/plaidsystems/spruce-scheduler.src/spruce-scheduler.groovy b/smartapps/plaidsystems/spruce-scheduler.src/spruce-scheduler.groovy index ff9d43a..54837a8 100644 --- a/smartapps/plaidsystems/spruce-scheduler.src/spruce-scheduler.groovy +++ b/smartapps/plaidsystems/spruce-scheduler.src/spruce-scheduler.groovy @@ -1,5 +1,5 @@ /** - * Spruce Scheduler Pre-release V2.5 12/22/2016 + * Spruce Scheduler Pre-release V2.53.1 - Updated 11/07/2016, BAB * * * Copyright 2015 Plaid Systems @@ -13,1200 +13,1955 @@ * 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. * - --------v2.51--------------------- - schedule function changed so runIn does not overwrite and cancel schedule - -ln 769 schedule cycleOn-> checkOn - -ln 841 checkOn function - -ln 863 state.run = false - --------Fixes - -changed weather from def to Map - -ln 968 if(runnowmap) -> pumpmap - --------Fixes V2.2------------- --History log messages condensed --Seasonal adjustment redefined -> weekly & daily --Learn mode redefined --No Learn redefined to operate any available days --ZoneSettings page redefined -> required to setup zones --Weather rain updated to fix error with some weather stations --Contact time delay added --new plants moisture and season redefined -* -* --------Fixes V2.1------------- --Many fixes, code cleanup by Jason C --open fields leading to unexpected errors --setting and summary improvements --multi controller support --Day to run mapping --Contact delays optimized --Warning notification added --manual start subscription added + +-------v2.53.1------------------- +-ln 210: enableManual string modified +-ln 496: added code for old ST app zoneNumber number to convert to enum for app update compatibility +-ln 854: unschedule if NOT running to clear/correct manual subscription +-ln 863: weather scheduled if rain OR seasonal enabled, both off is no weather check scheduled +-ln 1083: added sync check to manual start +-ln 1538: corrected contact delay minimum fro 5s to 10s + +-------v2.52--------------------- + -Major revision by BAB * */ definition( name: "Spruce Scheduler", namespace: "plaidsystems", - author: "NCauffman", - description: "Spruce automatic water scheduling app v2.5", + author: "Plaid Systems", + description: "Setup schedules for Spruce irrigation controller", category: "Green Living", iconUrl: "http://www.plaidsystems.com/smartthings/st_spruce_leaf_250f.png", iconX2Url: "http://www.plaidsystems.com/smartthings/st_spruce_leaf_250f.png", iconX3Url: "http://www.plaidsystems.com/smartthings/st_spruce_leaf_250f.png") preferences { - page(name: "startPage") - page(name: "autoPage") - page(name: "zipcodePage") - page(name: "weatherPage") - page(name: "globalPage") - page(name: "contactPage") - page(name: "delayPage") - page(name: "zonePage") + page(name: 'startPage') + page(name: 'autoPage') + page(name: 'zipcodePage') + page(name: 'weatherPage') + page(name: 'globalPage') + page(name: 'contactPage') + page(name: 'delayPage') + page(name: 'zonePage') - page(name: "zoneSettingsPage") - page(name: "zoneSetPage") - page(name: "plantSetPage") - page(name: "sprinklerSetPage") - page(name: "optionSetPage") - + page(name: 'zoneSettingsPage') + page(name: 'zoneSetPage') + page(name: 'plantSetPage') + page(name: 'sprinklerSetPage') + page(name: 'optionSetPage') + + //found at bottom - transition pages + page(name: 'zoneSetPage1') + page(name: 'zoneSetPage2') + page(name: 'zoneSetPage3') + page(name: 'zoneSetPage4') + page(name: 'zoneSetPage5') + page(name: 'zoneSetPage6') + page(name: 'zoneSetPage7') + page(name: 'zoneSetPage8') + page(name: 'zoneSetPage9') + page(name: 'zoneSetPage10') + page(name: 'zoneSetPage11') + page(name: 'zoneSetPage12') + page(name: 'zoneSetPage13') + page(name: 'zoneSetPage14') + page(name: 'zoneSetPage15') + page(name: 'zoneSetPage16') } def startPage(){ - dynamicPage(name: "startPage", title: "Spruce Smart Irrigation setup V2.51", install: true, uninstall: true) + dynamicPage(name: 'startPage', title: 'Spruce Smart Irrigation setup', install: true, uninstall: true) { - section(""){ - href(name: "globalPage", title: "Schedule settings", required: false, page: "globalPage", - image: "http://www.plaidsystems.com/smartthings/st_settings.png", - description: "Watering On: ${enableString()}\nWatering Time: ${startTimeString()}\nDays:${daysString()}\nNotifications:\n${notifyString()}") + section(''){ + href(name: 'globalPage', title: 'Schedule settings', required: false, page: 'globalPage', + image: 'http://www.plaidsystems.com/smartthings/st_settings.png', + description: "Schedule: ${enableString()}\nWatering Time: ${startTimeString()}\nDays:${daysString()}\nNotifications:${notifyString()}" + ) + } - } + section(''){ + href(name: 'weatherPage', title: 'Weather Settings', required: false, page: 'weatherPage', + image: 'http://www.plaidsystems.com/smartthings/st_rain_225_r.png', + description: "Weather from: ${zipString()}\nRain Delay: ${isRainString()}\nSeasonal Adjust: ${seasonalAdjString()}" + ) + } - section(""){ - href(name: "weatherPage", title: "Weather Settings", required: false, page: "weatherPage", - image: "http://www.plaidsystems.com/smartthings/st_rain_225_r.png", - description: "Weather from: ${zipString()}\nSeasonal Adjust: ${seasonalAdjString()}") - } + section(''){ + href(name: 'zonePage', title: 'Zone summary and setup', required: false, page: 'zonePage', + image: 'http://www.plaidsystems.com/smartthings/st_zone16_225.png', + description: "${getZoneSummary()}" + ) + } - section(""){ - href(name: "zonePage", title: "Zone summary and setup", required: false, page: "zonePage", - image: "http://www.plaidsystems.com/smartthings/st_zone16_225.png", - description: "${getZoneSummary()}") - } - - section(""){ - href(name: "delayPage", title: "Valve and Contact delays", required: false, page: "delayPage", - image: "http://www.plaidsystems.com/smartthings/st_timer.png", - description: "Valve Delay: ${pumpDelayString()} s\nContact Sensor: ${contactSensorString()}\nSchedule Sync: ${syncString()}") - } - section(""){ - href title: "Spruce Irrigation Knowledge Base", //page: "customPage", - description: "Explore our knowledge base for more information on Spruce and Spruce sensors. Contact from is also available here.", - required: false, style:"embedded", - image: "http://www.plaidsystems.com/smartthings/st_spruce_leaf_250f.png", - url: "http://support.spruceirrigation.com" - } - } -} - -def globalPage() { - dynamicPage(name: "globalPage", title: "") { - section("Spruce schedule Settings") { - label title: "Schedule Name:", description: "Name this schedule", required: false - input "switches", "capability.switch", title: "Spruce Irrigation Controller:", description: "Select a Spruce controller", required: true, multiple: false - } - - - section("Program Scheduling"){ - input "enable", "bool", title: "Enable watering:", defaultValue: 'true', metadata: [values: ['true', 'false']] - input "startTime", "time", title: "Watering start time", required: true - paragraph image: "http://www.plaidsystems.com/smartthings/st_calander.png", - title: "Selecting watering days", - "Selecting watering days is optional. Spruce will optimize your watering schedule automatically. If your area has water restrictions or you prefer set days, select the days to meet your requirements. " - input (name: "days", type: "enum", title: "Water only on these days...", required: false, multiple: true, - metadata: [values: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday', 'Even', 'Odd']]) - } - - section("Push Notifications") { - input (name: "notify", type: "enum", title: "Select what push notifications to receive.", required: false, multiple: true, - metadata: [values: ['Warnings', 'Daily', 'Weekly', 'Weather', 'Moisture']]) - } - + section(''){ + href(name: 'delayPage', title: 'Valve delays & Pause controls', required: false, page: 'delayPage', + image: 'http://www.plaidsystems.com/smartthings/st_timer.png', + description: "Valve Delay: ${pumpDelayString()} s\n${waterStoppersString()}\nSchedule Sync: ${syncString()}" + ) + } + + section(''){ + href(title: 'Spruce Irrigation Knowledge Base', //page: 'customPage', + description: 'Explore our knowledge base for more information on Spruce and Spruce sensors. Contact form is ' + + 'also available here.', + required: false, style:'embedded', + image: 'http://www.plaidsystems.com/smartthings/st_spruce_leaf_250f.png', + url: 'http://support.spruceirrigation.com' + ) + } } } - +def globalPage() { + dynamicPage(name: 'globalPage', title: '') { + section('Spruce schedule Settings') { + label title: 'Schedule Name:', description: 'Name this schedule', required: false + input 'switches', 'capability.switch', title: 'Spruce Irrigation Controller:', description: 'Select a Spruce controller', required: true, multiple: false + } + + section('Program Scheduling'){ + input 'enable', 'bool', title: 'Enable watering:', defaultValue: 'true', metadata: [values: ['true', 'false']] + input 'enableManual', 'bool', title: 'Enable this schedule for manual start, only 1 schedule should be enabled for manual start at a time!', defaultValue: 'true', metadata: [values: ['true', 'false']] + input 'startTime', 'time', title: 'Watering start time', required: true + paragraph(image: 'http://www.plaidsystems.com/smartthings/st_calander.png', + title: 'Selecting watering days', + 'Selecting watering days is optional. Spruce will optimize your watering schedule automatically. ' + + 'If your area has water restrictions or you prefer set days, select the days to meet your requirements. ') + input (name: 'days', type: 'enum', title: 'Water only on these days...', required: false, multiple: true, metadata: [values: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday', 'Even', 'Odd']]) + } + + section('Push Notifications') { + input(name: 'notify', type: 'enum', title: 'Select what push notifications to receive.', required: false, + multiple: true, metadata: [values: ['Daily', 'Delays', 'Warnings', 'Weather', 'Moisture', 'Events']]) + input('recipients', 'contact', title: 'Send push notifications to', required: false, multiple: true) + input(name: 'logAll', type: 'bool', title: 'Log all notices to Hello Home?', defaultValue: 'false', options: ['true', 'false']) + } + } +} + def weatherPage() { - dynamicPage(name: "weatherPage", title: "Weather settings") { - section("Location to get weather forecast and conditions:") { - href(name: "hrefWithImage", title: "${zipString()}", page: "zipcodePage", - description: "Set local weather station", - required: false, - image: "http://www.plaidsystems.com/smartthings/rain.png") - - input "rainDelay", "decimal", title: "inches of rain that will delay watering, default: 0.2", required: false - input "isSeason", "bool", title: "Enable Seasonal Weather Adjustment:", metadata: [values: ['true', 'false']] + dynamicPage(name: 'weatherPage', title: 'Weather settings') { + section('Location to get weather forecast and conditions:') { + href(name: 'hrefWithImage', title: "${zipString()}", page: 'zipcodePage', + description: 'Set local weather station', + required: false, + image: 'http://www.plaidsystems.com/smartthings/rain.png' + ) + input 'isRain', 'bool', title: 'Enable Rain check:', metadata: [values: ['true', 'false']] + input 'rainDelay', 'decimal', title: 'inches of rain that will delay watering, default: 0.2', required: false + input 'isSeason', 'bool', title: 'Enable Seasonal Weather Adjustment:', metadata: [values: ['true', 'false']] } } } def zipcodePage() { - return dynamicPage(name: "zipcodePage", title: "Spruce weather station setup") { - section(""){input "zipcode", "text", title: "Zipcode or WeatherUnderground station id. Default value is current location.", defaultValue: "${location.zipCode}", required: false, submitOnChange: true - } + return dynamicPage(name: 'zipcodePage', title: 'Spruce weather station setup') { + section(''){ + input(name: 'zipcode', type: 'text', title: 'Zipcode or WeatherUnderground station id. Default value is current Zip code', + defaultValue: getPWSID(), required: false, submitOnChange: true ) + } - section(""){href title: "Search WeatherUnderground.com for weather stations", - description: "After page loads, select Change Station for a list of weather stations. You will need to copy the station code into the zipcode field above", - required: false, style:"embedded", - image: "http://www.plaidsystems.com/smartthings/wu.png", - url: "http://www.wunderground.com/q/${location.zipCode}" - } - } -} - -private startTimeString() -{ - def newtime = "${settings["startTime"]}" - if ("${settings["startTime"]}" == "null") return "Please set!" - else return "${hhmm(newtime)}" -} - -def enableString() -{ - if(enable) return "${enable}" - return "False" -} - -def contactSensorString() -{ - if(contact) return "${contact} \n Delay: ${contactDelay} mins" - return "None" -} - -def seasonalAdjString() -{ - if(isSeason) return "${isSeason}" - return "False" -} -def syncString() -{ - if(sync) return "${sync}" - return "None" -} -def notifyString() -{ - def notifyString = "" - if("${settings["notify"]}" != "null") { - if (notify.contains('Weekly')) notifyString = "${notifyString} Weekly" - if (notify.contains('Daily')) notifyString = "${notifyString} Daily" - if (notify.contains('Weather')) notifyString = "${notifyString} Weather" - if (notify.contains('Warnings')) notifyString = "${notifyString} Warnings" - if (notify.contains('Moisture')) notifyString = "${notifyString} Moisture" - } - if(notifyString == "") - notifyString = " None" - return notifyString -} -def daysString() -{ - def daysString = "" - if ("${settings["days"]}" != "null") { - if(days.contains('Even') || days.contains('Odd')) { - if (days.contains('Even')) daysString = "${daysString} Even" - if (days.contains('Odd')) daysString = "${daysString} Odd" - } else { - if (days.contains('Monday')) daysString = "${daysString} M" - if (days.contains('Tuesday')) daysString = "${daysString} Tu" - if (days.contains('Wednesday')) daysString = "${daysString} W" - if (days.contains('Thursday')) daysString = "${daysString} Th" - if (days.contains('Friday')) daysString = "${daysString} F" - if (days.contains('Saturday')) daysString = "${daysString} Sa" - if (days.contains('Sunday')) daysString = "${daysString} Su" + section(''){ + paragraph(image: 'http://www.plaidsystems.com/smartthings/wu.png', title: 'WeatherUnderground Personal Weather Stations (PWS)', + required: false, + 'To automatically select the PWS nearest to your hub location, select the toggle below and clear the ' + + 'location field above') + input(name: 'nearestPWS', type: 'bool', title: 'Use nearest PWS', options: ['true', 'false'], + defaultValue: false, submitOnChange: true) + href(title: 'Or, Search WeatherUnderground.com for your desired PWS', + description: 'After page loads, select "Change Station" for a list of weather stations. ' + + 'You will need to copy the station code into the location field above', + required: false, style:'embedded', + url: (location.latitude && location.longitude)? "http://www.wunderground.com/cgi-bin/findweather/hdfForecast?query=${location.latitude}%2C${location.longitude}" : + "http://www.wunderground.com/q/${location.zipCode}") } } - if(daysString == "") - daysString = " Any" - return daysString +} + +private String getPWSID() { + String PWSID = location.zipCode + if (zipcode) PWSID = zipcode + if (nearestPWS && !zipcode) { + // find the nearest PWS to the hub's geo location + String geoLocation = location.zipCode + // use coordinates, if available + if (location.latitude && location.longitude) geoLocation = "${location.latitude}%2C${location.longitude}" + Map wdata = getWeatherFeature('geolookup', geoLocation) + if (wdata && wdata.response && !wdata.response.containsKey('error')) { // if we get good data + if (wdata.response.features.containsKey('geolookup') && (wdata.response.features.geolookup.toInteger() == 1) && wdata.location) { + PWSID = wdata.location.nearby_weather_stations.pws.station[0].id + } + else log.debug "bad response" + } + else log.debug "null or error" + } + log.debug "Nearest PWS ${PWSID}" + return PWSID } +private String startTimeString(){ + if (!startTime) return 'Please set!' else return hhmm(startTime) +} + +private String enableString(){ + if(enable && enableManual) return 'On & Manual Set' + else if (enable) return 'On & Manual Off' + else if (enableManual) return 'Off & Manual Set' + else return 'Off' +} + +private String waterStoppersString(){ + String stoppers = 'Contact Sensor' + if (settings.contacts) { + if (settings.contacts.size() != 1) stoppers += 's' + stoppers += ': ' + int i = 1 + settings.contacts.each { + if ( i > 1) stoppers += ', ' + stoppers += it.displayName + i++ + } + stoppers = "${stoppers}\nPause: When ${settings.contactStop}\n" + } + else { + stoppers += ': None\n' + } + stoppers += "Switch" + if (settings.toggles) { + if (settings.toggles.size() != 1) stoppers += 'es' + stoppers += ': ' + int i = 1 + settings.toggles.each { + if ( i > 1) stoppers += ', ' + stoppers += it.displayName + i++ + } + stoppers = "${stoppers}\nPause: When switched ${settings.toggleStop}\n" + } + else { + stoppers += ': None\n' + } + int cd = 10 + if (settings.contactDelay && settings.contactDelay > 10) cd = settings.contactDelay.toInteger() + stoppers += "Restart Delay: ${cd} secs" + return stoppers +} + +private String isRainString(){ + if (settings.isRain && !settings.rainDelay) return '0.2' as String + if (settings.isRain) return settings.rainDelay as String else return 'Off' +} -private hhmm(time, fmt = "h:mm a") -{ +private String seasonalAdjString(){ + if(settings.isSeason) return 'On' else return 'Off' +} + +private String syncString(){ + if (settings.sync) return "${settings.sync.displayName}" else return 'None' +} + +private String notifyString(){ + String notifyStr = '' + if(settings.notify) { + if (settings.notify.contains('Daily')) notifyStr += ' Daily' + //if (settings.notify.contains('Weekly')) notifyStr += ' Weekly' + if (settings.notify.contains('Delays')) notifyStr += ' Delays' + if (settings.notify.contains('Warnings')) notifyStr += ' Warnings' + if (settings.notify.contains('Weather')) notifyStr += ' Weather' + if (settings.notify.contains('Moisture')) notifyStr += ' Moisture' + if (settings.notify.contains('Events')) notifyStr += ' Events' + } + if (notifyStr == '') notifyStr = ' None' + if (settings.logAll) notifyStr += '\nSending all Notifications to Hello Home log' + + return notifyStr +} + +private String daysString(){ + String daysString = '' + if (days){ + if(days.contains('Even') || days.contains('Odd')) { + if (days.contains('Even')) daysString += ' Even' + if (days.contains('Odd')) daysString += ' Odd' + } + else { + if (days.contains('Monday')) daysString += ' M' + if (days.contains('Tuesday')) daysString += ' Tu' + if (days.contains('Wednesday')) daysString += ' W' + if (days.contains('Thursday')) daysString += ' Th' + if (days.contains('Friday')) daysString += ' F' + if (days.contains('Saturday')) daysString += ' Sa' + if (days.contains('Sunday')) daysString += ' Su' + } + } + if(daysString == '') return ' Any' + + else return daysString +} + +private String 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) + return f.format(t) } -def pumpDelayString() -{ - if ("${settings["pumpDelay"]}" == "null") return "5" - else return "${settings["pumpDelay"]}" +private String pumpDelayString(){ + if (!pumpDelay) return '0' else return pumpDelay as String + + } def delayPage() { - dynamicPage(name: "delayPage", title: "Additional Options") { - section(""){ - paragraph image: "http://www.plaidsystems.com/smartthings/st_timer.png", - title: "Pump and Master valve delay", + dynamicPage(name: 'delayPage', title: 'Additional Options') { + section(''){ + paragraph image: 'http://www.plaidsystems.com/smartthings/st_timer.png', + title: 'Pump and Master valve delay', required: false, - "Setting a delay is optional. If you have master valves or a pump suppling water then you can set a delay here. The delay is the time between the valve or pump turning on and the water valves opening. This is also the delay between valves opening" + 'Setting a delay is optional, default is 0. If you have a pump that feeds water directly into your valves, ' + + 'set this to 0. To fill a tank or build pressure, you may increase the delay.\n\nStart->Pump On->delay->Valve ' + + 'On->Valve Off->delay->...' + input name: 'pumpDelay', type: 'number', title: 'Set a delay in seconds?', defaultValue: '0', required: false } - section("") { - input "pumpDelay", "number", title: "Set a delay in seconds?", defaultValue: '5', required: false - } - section(""){ - paragraph image: "http://www.plaidsystems.com/smartthings/st_pause.png", - title: "Contact delays", + + section(''){ + paragraph(image: 'http://www.plaidsystems.com/smartthings/st_pause.png', + title: 'Pause Control Contacts & Switches', required: false, - "Selecting contacts is optional. When a selected contact sensor is opened, water immediately stops and will not resume until closed. Caution: if a contact is set and left open, the watering program will never run." + 'Selecting contacts or control switches is optional. When a selected contact sensor is opened or switch is ' + + 'toggled, water immediately stops and will not resume until all of the contact sensors are closed and all of ' + + 'the switches are reset.\n\nCaution: if all contacts or switches are left in the stop state, the dependent ' + + 'schedule(s) will never run.') + input(name: 'contacts', title: 'Select water delay contact sensors', type: 'capability.contactSensor', multiple: true, + required: false, submitOnChange: true) + // if (settings.contact) settings.contact = null // 'contact' has been deprecated + if (contacts) + input(name: 'contactStop', title: 'Stop watering when sensors are...', type: 'enum', required: (settings.contacts != null), + options: ['open', 'closed'], defaultValue: 'open') + input(name: 'toggles', title: 'Select water delay switches', type: 'capability.switch', multiple: true, required: false, + submitOnChange: true) + if (toggles) + input(name: 'toggleStop', title: 'Stop watering when switches are...', type: 'enum', + required: (settings.toggles != null), options: ['on', 'off'], defaultValue: 'off') + input(name: 'contactDelay', type: 'number', title: 'Restart watering how many seconds after all contacts and switches ' + + 'are reset? (minimum 10s)', defaultValue: '10', required: false) } - section("") { - input name: "contact", title: "Select water delay contacts", type: "capability.contactSensor", multiple: true, required: false - - input "contactDelay", "number", title: "How many minutes delay after contact is closed?", defaultValue: '1', required: false - } - section(""){ - paragraph image: "http://www.plaidsystems.com/smartthings/st_spruce_controller_250.png", - title: "Controller Sync", - required: false, - "For multiple controllers only. This schedule will wait for the selected controller to finish." - input "sync", "capability.switch", title: "Select Master Controller", description: "Select Spruce Controller to sync", required: false, multiple: false + + section(''){ + paragraph image: 'http://www.plaidsystems.com/smartthings/st_spruce_controller_250.png', + title: 'Controller Sync', + required: false, + 'For multiple controllers only. This schedule will wait for the selected controller to finish before ' + + 'starting. Do not set with a single controller!' + input name: 'sync', type: 'capability.switch', title: 'Select Master Controller', description: 'Only use this setting with multiple controllers', required: false, multiple: false } } } -def zonePage() { - def z1Par=[zoneP:"1"], z2Par=[zoneP:"2"], z3Par=[zoneP:"3"], z4Par=[zoneP:"4"], z5Par=[zoneP:"5"], z6Par=[zoneP:"6"], z7Par=[zoneP:"7"], - z8Par=[zoneP:"8"],z9Par = [zoneP:"9"], z10Par = [zoneP:"10"], z11Par = [zoneP:"11"], z12Par = [zoneP:"12"], z13Par = [zoneP:"13"], - z14Par = [zoneP:"14"], z15Par = [zoneP:"15"], z16Par = [zoneP:"16"] - - dynamicPage(name: "zonePage", title: "Zone setup", install: false, uninstall: false) { - section("") { - href(name: "hrefWithImage", title: "Zone configuration", page: "zoneSettingsPage", +def zonePage() { + dynamicPage(name: 'zonePage', title: 'Zone setup', install: false, uninstall: false) { + section('') { + href(name: 'hrefWithImage', title: 'Zone configuration', page: 'zoneSettingsPage', description: "${zoneString()}", required: false, - image: "http://www.plaidsystems.com/smartthings/st_spruce_leaf_250f.png") + image: 'http://www.plaidsystems.com/smartthings/st_spruce_leaf_250f.png') } - if (zoneNumber >= 1){ - section(""){ - href(name: "z1Page", title: "1: ${getname("1")}", required: false, page: "zoneSetPage", - image: "${getimage("1")}", - params: z1Par, + if (zoneActive('1')){ + section(''){ + href(name: 'z1Page', title: "1: ${getname("1")}", required: false, page: 'zoneSetPage1', + image: "${getimage("1")}", description: "${display("1")}" ) } } - if (zoneNumber >= 2){ - section(""){ - href(name: "z2Page", title: "2: ${getname("2")}", required: false, page: "zoneSetPage", + if (zoneActive('2')){ + section(''){ + href(name: 'z2Page', title: "2: ${getname("2")}", required: false, page: 'zoneSetPage2', image: "${getimage("2")}", - params: z2Par, description: "${display("2")}" ) } } - if (zoneNumber >= 3){ - section(""){ - href(name: "z3Page", title: "3: ${getname("3")}", required: false, page: "zoneSetPage", + if (zoneActive('3')){ + section(''){ + href(name: 'z3Page', title: "3: ${getname("3")}", required: false, page: 'zoneSetPage3', image: "${getimage("3")}", - params: z3Par, description: "${display("3")}" ) } } - if (zoneNumber >= 4){ - section(""){ - href(name: "z4Page", title: "4: ${getname("4")}", required: false, page: "zoneSetPage", + if (zoneActive('4')){ + section(''){ + href(name: 'z4Page', title: "4: ${getname("4")}", required: false, page: 'zoneSetPage4', image: "${getimage("4")}", - params: z4Par, description: "${display("4")}" ) } } - if (zoneNumber >= 5){ - section(""){ - href(name: "z5Page", title: "5: ${getname("5")}", required: false, page: "zoneSetPage", + if (zoneActive('5')){ + section(''){ + href(name: 'z5Page', title: "5: ${getname("5")}", required: false, page: 'zoneSetPage5', image: "${getimage("5")}", - params: z5Par, description: "${display("5")}" ) } } - if (zoneNumber >= 6){ - section(""){ - href(name: "z6Page", title: "6: ${getname("6")}", required: false, page: "zoneSetPage", + if (zoneActive('6')){ + section(''){ + href(name: 'z6Page', title: "6: ${getname("6")}", required: false, page: 'zoneSetPage6', image: "${getimage("6")}", - params: z6Par, description: "${display("6")}" ) } } - if (zoneNumber >= 7){ - section(""){ - href(name: "z7Page", title: "7: ${getname("7")}", required: false, page: "zoneSetPage", + if (zoneActive('7')){ + section(''){ + href(name: 'z7Page', title: "7: ${getname("7")}", required: false, page: 'zoneSetPage7', image: "${getimage("7")}", - params: z7Par, description: "${display("7")}" ) } } - if (zoneNumber >= 8){ - section(""){ - href(name: "z8Page", title: "8: ${getname("8")}", required: false, page: "zoneSetPage", + if (zoneActive('8')){ + section(''){ + href(name: 'z8Page', title: "8: ${getname("8")}", required: false, page: 'zoneSetPage8', image: "${getimage("8")}", - params: z8Par, description: "${display("8")}" ) } } - if (zoneNumber >= 9){ - section(""){ - href(name: "z9Page", title: "9: ${getname("9")}", required: false, page: "zoneSetPage", + if (zoneActive('9')){ + section(''){ + href(name: 'z9Page', title: "9: ${getname("9")}", required: false, page: 'zoneSetPage9', image: "${getimage("9")}", - params: z9Par, description: "${display("9")}" ) } } - if (zoneNumber >= 10){ - section(""){ - href(name: "z10Page", title: "10: ${getname("10")}", required: false, page: "zoneSetPage", + if (zoneActive('10')){ + section(''){ + href(name: 'z10Page', title: "10: ${getname("10")}", required: false, page: 'zoneSetPage10', image: "${getimage("10")}", - params: z10Par, description: "${display("10")}" ) } } - if (zoneNumber >= 11){ - section(""){ - href(name: "z11Page", title: "11: ${getname("11")}", required: false, page: "zoneSetPage", + if (zoneActive('11')){ + section(''){ + href(name: 'z11Page', title: "11: ${getname("11")}", required: false, page: 'zoneSetPage11', image: "${getimage("11")}", - params: z11Par, description: "${display("11")}" ) } } - if (zoneNumber >= 12){ - section(""){ - href(name: "z12Page", title: "12: ${getname("12")}", required: false, page: "zoneSetPage", + if (zoneActive('12')){ + section(''){ + href(name: 'z12Page', title: "12: ${getname("12")}", required: false, page: 'zoneSetPage12', image: "${getimage("12")}", - params: z12Par, description: "${display("12")}" ) } } - if (zoneNumber >= 13){ - section(""){ - href(name: "z13Page", title: "13: ${getname("13")}", required: false, page: "zoneSetPage", + if (zoneActive('13')){ + section(''){ + href(name: 'z13Page', title: "13: ${getname("13")}", required: false, page: 'zoneSetPage13', image: "${getimage("13")}", - params: z13Par, description: "${display("13")}" ) } } - if (zoneNumber >= 14){ - section(""){ - href(name: "z14Page", title: "14: ${getname("14")}", required: false, page: "zoneSetPage", + if (zoneActive('14')){ + section(''){ + href(name: 'z14Page', title: "14: ${getname("14")}", required: false, page: 'zoneSetPage14', image: "${getimage("14")}", - params: z14Par, description: "${display("14")}" ) } } - if (zoneNumber >= 15){ - section(""){ - href(name: "z15Page", title: "15: ${getname("15")}", required: false, page: "zoneSetPage", + if (zoneActive('15')){ + section(''){ + href(name: 'z15Page', title: "15: ${getname("15")}", required: false, page: 'zoneSetPage15', image: "${getimage("15")}", - params: z15Par, description: "${display("15")}" ) } } - if (zoneNumber >= 16){ - section(""){ - href(name: "z16Page", title: "16: ${getname("16")}", required: false, page: "zoneSetPage", + if (zoneActive('16')){ + section(''){ + href(name: 'z16Page', title: "16: ${getname("16")}", required: false, page: 'zoneSetPage16', image: "${getimage("16")}", - params: z16Par, description: "${display("16")}" ) } } - - } } - -def zoneString(){ - def numberString = "Add zones to setup" - if (zoneNumber) numberString = "Setup: " + "${zoneNumber}" + " zones" - if (learn) numberString += "\nLearn: enabled" - else numberString += "\nLearn: disabled" + +// Verify whether a zone is active +/*//Code for fresh install +private boolean zoneActive(String zoneStr){ + if (!zoneNumber) return false + if (zoneNumber.contains(zoneStr)) return true // don't display zones that are not selected + return false +} +*/ +//code change for ST update file -> change input to zoneNumberEnum +private boolean zoneActive(z){ + if (!zoneNumberEnum && zoneNumber && zoneNumber >= z.toInteger()) return true + else if (!zoneNumberEnum && zoneNumber && zoneNumber != z.toInteger()) return false + else if (zoneNumberEnum && zoneNumberEnum.contains(z)) return true + return false +} + + +private String zoneString() { + String numberString = 'Add zones to setup' + if (zoneNumber) numberString = "Zones enabled: ${zoneNumber}" + if (learn) numberString = "${numberString}\nSensor mode: Adaptive" + else numberString = "${numberString}\nSensor mode: Delay" return numberString - } - -def zoneSettingsPage() { - dynamicPage(name: "zoneSettingsPage", title: "Zone Configuration") { - section(""){ - input (name: "zoneNumber", type: "number", title: "Enter number of zones to configure?",description: "How many valves do you have? 1-16", required: true)//, defaultValue: 16) - input "gain", "number", title: "Increase or decrease all water times by this %, enter a negative or positive value, Default: 0", required: false - paragraph image: "http://www.plaidsystems.com/smartthings/st_sensor_200_r.png", - title: "Moisture sensor learn mode", - "Learn mode: Watering times will be adjusted based on the assigned moisture sensor and watering will follow a schedule.\n\nNo Learn mode: Zones with moisture sensors will water on any available days when the low moisture setpoint has been reached." - input "learn", "bool", title: "Enable learning (with moisture sensors)", metadata: [values: ['true', 'false']] - } - } } -def zoneSetPage(params){ - dynamicPage(name: "zoneSetPage", title: "Zone ${setPage("${params?.zoneP}")} Setup") { - section(""){ +def zoneSettingsPage() { + dynamicPage(name: 'zoneSettingsPage', title: 'Zone Configuration') { + section(''){ + //input (name: "zoneNumber", type: "number", title: "Enter number of zones to configure?",description: "How many valves do you have? 1-16", required: true)//, defaultValue: 16) + input 'zoneNumberEnum', 'enum', title: 'Select zones to configure', multiple: true, metadata: [values: ['1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16']] + input 'gain', 'number', title: 'Increase or decrease all water times by this %, enter a negative or positive value, Default: 0', required: false, range: '-99..99' + paragraph image: 'http://www.plaidsystems.com/smartthings/st_sensor_200_r.png', + title: 'Moisture sensor adapt mode', + 'Adaptive mode enabled: Watering times will be adjusted based on the assigned moisture sensor.\n\nAdaptive mode ' + + 'disabled (Delay): Zones with moisture sensors will water on any available days when the low moisture setpoint has ' + + 'been reached.' + input 'learn', 'bool', title: 'Enable Adaptive Moisture Control (with moisture sensors)', metadata: [values: ['true', 'false']] + } + } +} + +def zoneSetPage() { + dynamicPage(name: 'zoneSetPage', title: "Zone ${state.app} Setup") { + section(''){ paragraph image: "http://www.plaidsystems.com/smartthings/st_${state.app}.png", - title: "Current Settings", + title: 'Current Settings', "${display("${state.app}")}" - } - section(""){ - input "name${state.app}", "text", title: "Zone name?", required: false, defaultValue: "Zone ${state.app}" - } - section(""){ - href(name: "tosprinklerSetPage", title: "Sprinkler type: ${setString("zone")}", required: false, page: "sprinklerSetPage", - image: "${getimage("${settings["zone${state.app}"]}")}", - description: "Set sprinkler nozzle type or turn zone off") - } - section(""){ - href(name: "toplantSetPage", title: "Landscape Select: ${setString("plant")}", required: false, page: "plantSetPage", + } + + section(''){ + input "name${state.app}", 'text', title: 'Zone name?', required: false, defaultValue: "Zone ${state.app}" + } + + section(''){ + href(name: 'tosprinklerSetPage', title: "Sprinkler type: ${setString('zone')}", required: false, page: 'sprinklerSetPage', + image: "${getimage("${settings."zone${state.app}"}")}", + //description: "Set sprinkler nozzle type or turn zone off") + description: 'Sprinkler type descriptions') + input "zone${state.app}", 'enum', title: 'Sprinkler Type', multiple: false, required: false, defaultValue: 'Off', submitOnChange: true, metadata: [values: ['Off', 'Spray', 'Rotor', 'Drip', 'Master Valve', 'Pump']] + } + + section(''){ + href(name: 'toplantSetPage', title: "Landscape Select: ${setString('plant')}", required: false, page: 'plantSetPage', image: "${getimage("${settings["plant${state.app}"]}")}", - description: "Set landscape type") + //description: "Set landscape type") + description: 'Landscape type descriptions') + input "plant${state.app}", 'enum', title: 'Landscape', multiple: false, required: false, submitOnChange: true, metadata: [values: ['Lawn', 'Garden', 'Flowers', 'Shrubs', 'Trees', 'Xeriscape', 'New Plants']] } - section(""){ - href(name: "tooptionSetPage", title: "Options: ${setString("option")}", required: false, page: "optionSetPage", + section(''){ + href(name: 'tooptionSetPage', title: "Options: ${setString('option')}", required: false, page: 'optionSetPage', image: "${getimage("${settings["option${state.app}"]}")}", - description: "Set watering options") - } - section(""){ - paragraph image: "http://www.plaidsystems.com/smartthings/st_sensor_200_r.png", - title: "Moisture sensor settings", - "Select a soil moisture sensor to monitor and control watering. The soil moisture target value is optional and is the target low value. Spruce will use a default value based on settings, however you may override this setting to modify soil moisture threshold" - - input "sensor${state.app}", "capability.relativeHumidityMeasurement", title: "Select moisture sensor?", required: false, multiple: false - - input "sensorSp${state.app}", "number", title: "Minimum moisture sensor target value, Setpoint: ${getDrySp("${state.app}")}", required: false + //description: "Set watering options") + description: 'Watering option descriptions') + input "option${state.app}", 'enum', title: 'Options', multiple: false, required: false, defaultValue: 'Cycle 2x', submitOnChange: true,metadata: [values: ['Slope', 'Sand', 'Clay', 'No Cycle', 'Cycle 2x', 'Cycle 3x']] } - section(""){ - paragraph image: "http://www.plaidsystems.com/smartthings/st_timer.png", - title: "Enter total watering time per week or ", "" - - input "minWeek${state.app}", "number", title: "Water time per week (minutes). Default: 0 = autoadjust", required: false - - input "perDay${state.app}", "number", title: "Guideline value for dividing minutes per week into watering days, a high value means more water per day. Default: 20", defaultValue: '20', required: false + + section(''){ + paragraph image: 'http://www.plaidsystems.com/smartthings/st_sensor_200_r.png', + title: 'Moisture sensor settings', + 'Select a soil moisture sensor to monitor and control watering. The soil moisture target value is set to a default value but can be adjusted to tune watering' + input "sensor${state.app}", 'capability.relativeHumidityMeasurement', title: 'Select moisture sensor?', required: false, multiple: false + input "sensorSp${state.app}", 'number', title: "Minimum moisture sensor target value, Setpoint: ${getDrySp(state.app)}", required: false + } + + section(''){ + paragraph image: 'http://www.plaidsystems.com/smartthings/st_timer.png', + title: 'Optional: Enter total watering time per week', + 'This value will replace the calculated time from other settings' + input "minWeek${state.app}", 'number', title: 'Minimum water time per week.\nDefault: 0 = autoadjust', description: 'minutes per week', required: false + input "perDay${state.app}", 'number', title: 'Guideline value for time per day, this divides minutes per week into watering days. Default: 20', defaultValue: '20', required: false } - } } -def setString(i){ - if (i == "zone"){ - if (settings["zone${state.app}"] != null) return "${settings["zone${state.app}"]}" - else return "Not Set" - } - if (i == "plant"){ - if (settings["plant${state.app}"] != null) return "${settings["plant${state.app}"]}" - else return "Not Set" - } - if (i == "option"){ - if (settings["option${state.app}"] != null) return "${settings["option${state.app}"]}" - else return "Not Set" - } +private String setString(String type) { + switch (type) { + case 'zone': + if (settings."zone${state.app}") return settings."zone${state.app}" else return 'Not Set' + break + case 'plant': + if (settings."plant${state.app}") return settings."plant${state.app}" else return 'Not Set' + break + case 'option': + if (settings."option${state.app}") return settings."option${state.app}" else return 'Not Set' + break + default: + return '????' + } } -def plantSetPage(){ - dynamicPage(name: "plantSetPage", title: "${settings["name${state.app}"]} Landscape Select") { - section(""){ - paragraph image: "http://www.plaidsystems.com/img/st_${state.app}.png", +def plantSetPage() { + dynamicPage(name: 'plantSetPage', title: "${settings["name${state.app}"]} Landscape Select") { + section(''){ + paragraph image: 'http://www.plaidsystems.com/img/st_${state.app}.png', title: "${settings["name${state.app}"]}", "Current settings ${display("${state.app}")}" - - input "plant${state.app}", "enum", title: "Landscape", multiple: false, required: false, submitOnChange: true, metadata: [values: ['Lawn', 'Garden', 'Flowers', 'Shrubs', 'Trees', 'Xeriscape', 'New Plants']] - } - section(""){ - paragraph image: "http://www.plaidsystems.com/smartthings/st_lawn_200_r.png", - title: "Lawn", - "Select Lawn for typical grass applications" - - paragraph image: "http://www.plaidsystems.com/smartthings/st_garden_225_r.png", - title: "Garden", - "Select Garden for vegetable gardens" + //input "plant${state.app}", "enum", title: "Landscape", multiple: false, required: false, submitOnChange: true, metadata: [values: ['Lawn', 'Garden', 'Flowers', 'Shrubs', 'Trees', 'Xeriscape', 'New Plants']] + } + section(''){ + paragraph image: 'http://www.plaidsystems.com/smartthings/st_lawn_200_r.png', + title: 'Lawn', + 'Select Lawn for typical grass applications' + + paragraph image: 'http://www.plaidsystems.com/smartthings/st_garden_225_r.png', + title: 'Garden', + 'Select Garden for vegetable gardens' - paragraph image: "http://www.plaidsystems.com/smartthings/st_flowers_225_r.png", - title: "Flowers", - "Select Lawn for typical grass applications" + paragraph image: 'http://www.plaidsystems.com/smartthings/st_flowers_225_r.png', + title: 'Flowers', + 'Select Flowers for beds with smaller seasonal plants' - paragraph image: "http://www.plaidsystems.com/smartthings/st_shrubs_225_r.png", - title: "Shrubs", - "Select Garden for vegetable gardens" + paragraph image: 'http://www.plaidsystems.com/smartthings/st_shrubs_225_r.png', + title: 'Shrubs', + 'Select Shrubs for beds with larger established plants' - paragraph image: "http://www.plaidsystems.com/smartthings/st_trees_225_r.png", - title: "Trees", - "Select Lawn for typical grass applications" + paragraph image: 'http://www.plaidsystems.com/smartthings/st_trees_225_r.png', + title: 'Trees', + 'Select Trees for deep rooted areas without other plants' - paragraph image: "http://www.plaidsystems.com/smartthings/st_xeriscape_225_r.png", - title: "Xeriscape", - "Reduces water for native or drought tolorent plants" + paragraph image: 'http://www.plaidsystems.com/smartthings/st_xeriscape_225_r.png', + title: 'Xeriscape', + 'Reduces water for native or drought tolorent plants' - paragraph image: "http://www.plaidsystems.com/smartthings/st_newplants_225_r.png", - title: "New Plants", - "Increases watering time per week and reduces automatic adjustments to help establish new plants. No weekly seasonal adjustment and moisture setpoint set to 40." - } - } + paragraph image: 'http://www.plaidsystems.com/smartthings/st_newplants_225_r.png', + title: 'New Plants', + 'Increases watering time per week and reduces automatic adjustments to help establish new plants. No weekly seasonal adjustment and moisture setpoint set to 40.' + } + } } def sprinklerSetPage(){ - dynamicPage(name: "sprinklerSetPage", title: "${settings["name${state.app}"]} Sprinkler Select") { - section(""){ + dynamicPage(name: 'sprinklerSetPage', title: "${settings["name${state.app}"]} Sprinkler Select") { + section(''){ paragraph image: "http://www.plaidsystems.com/img/st_${state.app}.png", title: "${settings["name${state.app}"]}", "Current settings ${display("${state.app}")}" - input "zone${state.app}", "enum", title: "Sprinkler Type", multiple: false, required: false, defaultValue: 'Off', metadata: [values: ['Off', 'Spray', 'Rotor', 'Drip', 'Master Valve', 'Pump']] - + //input "zone${state.app}", "enum", title: "Sprinkler Type", multiple: false, required: false, defaultValue: 'Off', metadata: [values: ['Off', 'Spray', 'Rotor', 'Drip', 'Master Valve', 'Pump']] } - section(""){ - paragraph image: "http://www.plaidsystems.com/smartthings/st_spray_225_r.png", - title: "Spray", - "Spray sprinkler heads spray a fan of water over the lawn. The water is applied evenly and can be turned on for a shorter duration of time." + section(''){ + paragraph image: 'http://www.plaidsystems.com/smartthings/st_spray_225_r.png', + title: 'Spray', + 'Spray sprinkler heads spray a fan of water over the lawn. The water is applied evenly and can be turned on for a shorter duration of time.' - paragraph image: "http://www.plaidsystems.com/smartthings/st_rotor_225_r.png", - title: "Rotor", - "Rotor sprinkler heads rotate, spraying a stream over the lawn. Because they move back and forth across the lawn, they require a longer water period." + paragraph image: 'http://www.plaidsystems.com/smartthings/st_rotor_225_r.png', + title: 'Rotor', + 'Rotor sprinkler heads rotate, spraying a stream over the lawn. Because they move back and forth across the lawn, they require a longer water period.' - paragraph image: "http://www.plaidsystems.com/smartthings/st_drip_225_r.png", - title: "Drip", - "Drip lines or low flow emitters water slowely to minimize evaporation, because they are low flow, they require longer watering periods." + paragraph image: 'http://www.plaidsystems.com/smartthings/st_drip_225_r.png', + title: 'Drip', + 'Drip lines or low flow emitters water slowely to minimize evaporation, because they are low flow, they require longer watering periods.' - paragraph image: "http://www.plaidsystems.com/smartthings/st_master_225_r.png", - title: "Master", - "Master valves will open before watering begins. Set the delay between master opening and watering in delay settings." + paragraph image: 'http://www.plaidsystems.com/smartthings/st_master_225_r.png', + title: 'Master', + 'Master valves will open before watering begins. Set the delay between master opening and watering in delay settings.' - paragraph image: "http://www.plaidsystems.com/smartthings/st_pump_225_r.png", - title: "Pump", - "Attach a pump relay to this zone and the pump will turn on before watering begins. Set the delay between pump start and watering in delay settings." - } + paragraph image: 'http://www.plaidsystems.com/smartthings/st_pump_225_r.png', + title: 'Pump', + 'Attach a pump relay to this zone and the pump will turn on before watering begins. Set the delay between pump start and watering in delay settings.' } + } } def optionSetPage(){ - dynamicPage(name: "optionSetPage", title: "${settings["name${state.app}"]} Options") { - section(""){ + dynamicPage(name: 'optionSetPage', title: "${settings["name${state.app}"]} Options") { + section(''){ paragraph image: "http://www.plaidsystems.com/img/st_${state.app}.png", title: "${settings["name${state.app}"]}", "Current settings ${display("${state.app}")}" - input "option${state.app}", "enum", title: "Options", multiple: false, required: false, defaultValue: 'Cycle 2x', metadata: [values: ['Slope', 'Sand', 'Clay', 'No Cycle', 'Cycle 2x', 'Cycle 3x']] + //input "option${state.app}", "enum", title: "Options", multiple: false, required: false, defaultValue: 'Cycle 2x', metadata: [values: ['Slope', 'Sand', 'Clay', 'No Cycle', 'Cycle 2x', 'Cycle 3x']] } - section(""){ - paragraph image: "http://www.plaidsystems.com/smartthings/st_slope_225_r.png", - title: "Slope", - "Slope sets the sprinklers to cycle 3x, each with a short duration to minimize runoff" + section(''){ + paragraph image: 'http://www.plaidsystems.com/smartthings/st_slope_225_r.png', + title: 'Slope', + 'Slope sets the sprinklers to cycle 3x, each with a short duration to minimize runoff' - paragraph image: "http://www.plaidsystems.com/smartthings/st_sand_225_r.png", - title: "Sand", - "Sandy soil drains quickly and requires more frequent but shorter intervals of water." + paragraph image: 'http://www.plaidsystems.com/smartthings/st_sand_225_r.png', + title: 'Sand', + 'Sandy soil drains quickly and requires more frequent but shorter intervals of water' - paragraph image: "http://www.plaidsystems.com/smartthings/st_clay_225_r.png", - title: "Clay", - "Clay sets the sprinklers to cycle 2x, each with a short duration to maximize absorption" + paragraph image: 'http://www.plaidsystems.com/smartthings/st_clay_225_r.png', + title: 'Clay', + 'Clay sets the sprinklers to cycle 2x, each with a short duration to maximize absorption' - paragraph image: "http://www.plaidsystems.com/smartthings/st_cycle1x_225_r.png", - title: "No Cycle", - "The sprinklers will run for 1 long duration" + paragraph image: 'http://www.plaidsystems.com/smartthings/st_cycle1x_225_r.png', + title: 'No Cycle', + 'The sprinklers will run for 1 long duration' - paragraph image: "http://www.plaidsystems.com/smartthings/st_cycle2x_225_r.png", - title: "Cycle 2x", - "Cycle 2x will break the water period up into 2 shorter cycles to help minimize runoff and maximize adsorption" + paragraph image: 'http://www.plaidsystems.com/smartthings/st_cycle2x_225_r.png', + title: 'Cycle 2x', + 'Cycle 2x will break the water period up into 2 shorter cycles to help minimize runoff and maximize adsorption' - paragraph image: "http://www.plaidsystems.com/smartthings/st_cycle3x_225_r.png", - title: "Cycle 3x", - "Cycle 3x will break the water period up into 3 shorter cycles to help minimize runoff and maximize adsorption" - } + paragraph image: 'http://www.plaidsystems.com/smartthings/st_cycle3x_225_r.png', + title: 'Cycle 3x', + 'Cycle 3x will break the water period up into 3 shorter cycles to help minimize runoff and maximize adsorption' } + } } def setPage(i){ - if (i != "null") state.app = i + if (i) state.app = i return state.app } -def getaZoneSummary(zone) -{ - def daysString = "" - def dpw = initDPW(zone) - def runTime = calcRunTime(initTPW(zone), dpw) - if ( !learn && (settings["sensor${zone}"] != null) ) { - daysString = "if Moisture is low on: " - dpw = daysAvailable() - } - if (days && (days.contains('Even') || days.contains('Odd'))) { - if(dpw == 1) daysString = "Every 8 days" - if(dpw == 2) daysString = "Every 4 days" - if(dpw == 4) daysString = "Every 2 days" - if(days.contains('Even') && days.contains('Odd')) daysString = "any day" - } - else { - def int[] dpwMap = [0,0,0,0,0,0,0] - dpwMap = getDPWDays(dpw) - daysString += getRunDays(dpwMap) - } - return "${zone}: ${runTime} minutes, ${daysString}" +private String getaZoneSummary(int zone){ + if (!settings."zone${zone}" || (settings."zone${zone}" == 'Off')) return "${zone}: Off" + + String daysString = '' + int tpw = initTPW(zone) + int dpw = initDPW(zone) + int runTime = calcRunTime(tpw, dpw) + + if ( !learn && (settings."sensor${zone}")) { + daysString = 'if Moisture is low on: ' + dpw = daysAvailable() + } + if (days && (days.contains('Even') || days.contains('Odd'))) { + if (dpw == 1) daysString = 'Every 8 days' + if (dpw == 2) daysString = 'Every 4 days' + if (dpw == 4) daysString = 'Every 2 days' + if (days.contains('Even') && days.contains('Odd')) daysString = 'any day' + } + else { + def int[] dpwMap = [0,0,0,0,0,0,0] + dpwMap = getDPWDays(dpw) + daysString += getRunDays(dpwMap) + } + return "${zone}: ${runTime} min, ${daysString}" } -def getZoneSummary() -{ - def summary = "" - if (learn) summary = "Moisture Learning enabled" - else summary = "Moisture Learning disabled" - def zone = 1 +private String getZoneSummary(){ + String summary = '' + if (learn) summary = 'Moisture Learning enabled' else summary = 'Moisture Learning disabled' + + int zone = 1 createDPWMap() while(zone <= 16) { - def zoneSum = getaZoneSummary(zone) - if (nozzle(zone) == 4) summary = "${summary}\n${zone}: ${settings["zone${zone}"]}" - else if ("${runTime}" != "0" && "${initDPW(zone)}" != "0") summary = "${summary}\n${zoneSum}" - zone++ + if (nozzle(zone) == 4) summary = "${summary}\n${zone}: ${settings."zone${zone}"}" + else if ( (initDPW(zone) != 0) && zoneActive(zone.toString())) summary = "${summary}\n${getaZoneSummary(zone)}" + zone++ } - if(summary == "") return zoneString() //"Setup all 16 zones" - - return summary + if (summary) return summary else return zoneString() //"Setup all 16 zones" } -def display(i) -{ - def displayString = "" - def dpw = initDPW(i) - def runTime = calcRunTime(initTPW(i), dpw) - if ("${settings["zone${i}"]}" != "null") displayString += "${settings["zone${i}"]} : " - if ("${settings["plant${i}"]}" != "null") displayString += "${settings["plant${i}"]} : " - if ("${settings["option${i}"]}" != "null") displayString += "${settings["option${i}"]} : " - if ("${settings["sensor${i}"]}" != "null") displayString += "${settings["sensor${i}"]} : " - if ("${runTime}" != "0" && "${dpw}" != "0") displayString += "${runTime} minutes, ${dpw} days per week" - return "${displayString}" +private String display(String i){ + //log.trace "display(${i})" + String displayString = '' + int tpw = initTPW(i.toInteger()) + int dpw = initDPW(i.toInteger()) + int runTime = calcRunTime(tpw, dpw) + if (settings."zone${i}") displayString += settings."zone${i}" + ' : ' + if (settings."plant${i}") displayString += settings."plant${i}" + ' : ' + if (settings."option${i}") displayString += settings."option${i}" + ' : ' + int j = i.toInteger() + if (settings."sensor${i}") { + displayString += settings."sensor${i}" + displayString += "=${getDrySp(j)}% : " + } + if ((runTime != 0) && (dpw != 0)) displayString = "${displayString}${runTime} minutes, ${dpw} days per week" + return displayString } -def getimage(i){ - if ("${settings["zone${i}"]}" == "Off") return "http://www.plaidsystems.com/smartthings/off2.png" - else if ("${settings["zone${i}"]}" == "Master Valve") return "http://www.plaidsystems.com/smartthings/master.png" - else if ("${settings["zone${i}"]}" == "Pump") return "http://www.plaidsystems.com/smartthings/pump.png" - else if ("${settings["plant${i}"]}" != "null" && "${settings["zone${i}"]}" != "null")// && "${settings["option${i}"]}" != "null") - i = "${settings["plant${i}"]}" - - switch("${i}"){ +private String getimage(String image){ + String imageStr = image + if (image.isNumber()) { + String zoneStr = settings."zone${image}" + if (zoneStr) { + if (zoneStr == 'Off') return 'http://www.plaidsystems.com/smartthings/off2.png' + if (zoneStr == 'Master Valve') return 'http://www.plaidsystems.com/smartthings/master.png' + if (zoneStr == 'Pump') return 'http://www.plaidsystems.com/smartthings/pump.png' + + if (settings."plant${image}") imageStr = settings."plant${image}" // default assume asking for the plant image + } + } + // OK, lookup the requested image + switch (imageStr) { case "null": - return "http://www.plaidsystems.com/smartthings/off2.png" - case "Off": - return "http://www.plaidsystems.com/smartthings/off2.png" - case "Lawn": - return "http://www.plaidsystems.com/smartthings/st_lawn_200_r.png" - case "Garden": - return "http://www.plaidsystems.com/smartthings/st_garden_225_r.png" - case "Flowers": - return "http://www.plaidsystems.com/smartthings/st_flowers_225_r.png" - case "Shrubs": - return "http://www.plaidsystems.com/smartthings/st_shrubs_225_r.png" - case "Trees": - return "http://www.plaidsystems.com/smartthings/st_trees_225_r.png" - case "Xeriscape": - return "http://www.plaidsystems.com/smartthings/st_xeriscape_225_r.png" - case "New Plants": - return "http://www.plaidsystems.com/smartthings/st_newplants_225_r.png" - case "Spray": - return "http://www.plaidsystems.com/smartthings/st_spray_225_r.png" - case "Rotor": - return "http://www.plaidsystems.com/smartthings/st_rotor_225_r.png" - case "Drip": - return "http://www.plaidsystems.com/smartthings/st_drip_225_r.png" - case "Master Valve": + case null: + return 'http://www.plaidsystems.com/smartthings/off2.png' + case 'Off': + return 'http://www.plaidsystems.com/smartthings/off2.png' + case 'Lawn': + return 'http://www.plaidsystems.com/smartthings/st_lawn_200_r.png' + case 'Garden': + return 'http://www.plaidsystems.com/smartthings/st_garden_225_r.png' + case 'Flowers': + return 'http://www.plaidsystems.com/smartthings/st_flowers_225_r.png' + case 'Shrubs': + return 'http://www.plaidsystems.com/smartthings/st_shrubs_225_r.png' + case 'Trees': + return 'http://www.plaidsystems.com/smartthings/st_trees_225_r.png' + case 'Xeriscape': + return 'http://www.plaidsystems.com/smartthings/st_xeriscape_225_r.png' + case 'New Plants': + return 'http://www.plaidsystems.com/smartthings/st_newplants_225_r.png' + case 'Spray': + return 'http://www.plaidsystems.com/smartthings/st_spray_225_r.png' + case 'Rotor': + return 'http://www.plaidsystems.com/smartthings/st_rotor_225_r.png' + case 'Drip': + return 'http://www.plaidsystems.com/smartthings/st_drip_225_r.png' + case 'Master Valve': return "http://www.plaidsystems.com/smartthings/st_master_225_r.png" - case "Pump": - return "http://www.plaidsystems.com/smartthings/st_pump_225_r.png" - case "Slope": - return "http://www.plaidsystems.com/smartthings/st_slope_225_r.png" - case "Sand": - return "http://www.plaidsystems.com/smartthings/st_sand_225_r.png" - case "Clay": - return "http://www.plaidsystems.com/smartthings/st_clay_225_r.png" - case "No Cycle": - return "http://www.plaidsystems.com/smartthings/st_cycle1x_225_r.png" - case "Cycle 2x": - return "http://www.plaidsystems.com/smartthings/st_cycle2x_225_r.png" + case 'Pump': + return 'http://www.plaidsystems.com/smartthings/st_pump_225_r.png' + case 'Slope': + return 'http://www.plaidsystems.com/smartthings/st_slope_225_r.png' + case 'Sand': + return 'http://www.plaidsystems.com/smartthings/st_sand_225_r.png' + case 'Clay': + return 'http://www.plaidsystems.com/smartthings/st_clay_225_r.png' + case 'No Cycle': + return 'http://www.plaidsystems.com/smartthings/st_cycle1x_225_r.png' + case 'Cycle 2x': + return 'http://www.plaidsystems.com/smartthings/st_cycle2x_225_r.png' case "Cycle 3x": - return "http://www.plaidsystems.com/smartthings/st_cycle3x_225_r.png" + return 'http://www.plaidsystems.com/smartthings/st_cycle3x_225_r.png' default: - return "http://www.plaidsystems.com/smartthings/off2.png" - } + return 'http://www.plaidsystems.com/smartthings/off2.png' } +} -def getname(i) { - if ("${settings["name${i}"]}" != "null") return "${settings["name${i}"]}" - else return "Zone $i" +private String getname(String i) { + if (settings."name${i}") return settings."name${i}" else return "Zone ${i}" } -def zipString() { - if (!zipcode) return "${location.zipCode}" +private String zipString() { + if (!settings.zipcode) return "${location.zipCode}" //add pws for correct weatherunderground lookup - if (!zipcode.isNumber()) return "pws:${zipcode}" - else return "${zipcode}" + if (!settings.zipcode.isNumber()) return "pws:${settings.zipcode}" + else return settings.zipcode } //app install def installed() { - state.dpwMap = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] - state.tpwMap = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] - state.Rain = [0,0,0,0,0,0,0] - state.fail = 0 - state.seasonAdj = 0 - state.weekseasonAdj = 0 + state.dpwMap = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + state.tpwMap = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + state.Rain = [0,0,0,0,0,0,0] + state.daycount = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + atomicState.run = false // must be atomic - used to recover from crashes + state.pauseTime = null + atomicState.startTime = null + atomicState.finishTime = null // must be atomic - used to recover from crashes + log.debug "Installed with settings: ${settings}" installSchedule() } -def updated() { - unsubscribe() - unschedule() - log.debug "Installed with settings: ${settings}" +def updated() { + log.debug "Updated with settings: ${settings}" installSchedule() } -def installSchedule(){ - if(switches && startTime) { - def runTime = timeToday(startTime, location.timeZone) - def checktime = timeToday(startTime, location.timeZone).getTime() - 120000 - log.debug "checktime: $checktime runtime: $runTime" - if(enable) { - subscribe switches, "switch.programOn", manualStart - schedule(checktime, Check) - schedule(runTime, checkOn) - note("schedule", "Schedule set to start at ${startTimeString()}", "w") +def installSchedule(){ + if (!state.seasonAdj) state.seasonAdj = 100.0 + if (!state.weekseasonAdj) state.weekseasonAdj = 0 + if (state.daysAvailable != 0) state.daysAvailable = 0 // force daysAvailable to be initialized by daysAvailable() + state.daysAvailable = daysAvailable() // every time we save the schedule + + if (atomicState.run) { + attemptRecovery() // clean up if we crashed earlier + } + else { + unsubscribe() //added back in to reset manual subscription + resetEverything() + } + subscribe(app, appTouch) // enable the "play" button for this schedule + Random rand = new Random() + long randomOffset = 0 + + // always collect rainfall + int randomSeconds = rand.nextInt(59) + if (settings.isRain || settings.isSeason) schedule("${randomSeconds} 57 23 1/1 * ? *", getRainToday) // capture today's rainfall just before midnight + + if (settings.switches && settings.startTime && settings.enable){ + + randomOffset = rand.nextInt(60000) + 20000 + def checktime = timeToday(settings.startTime, location.timeZone).getTime() + randomOffset + //log.debug "randomOffset ${randomOffset} checktime ${checktime}" + schedule(checktime, preCheck) //check weather & Days writeSettings() - } - else note("disable", "Automatic watering turned off, set active in app to resume scheduled watering.", "w") + note('schedule', "${app.label}: Starts at ${startTimeString()}", 'i') + } + else { + unschedule( preCheck ) + note('disable', "${app.label}: Automatic watering disabled or setup is incomplete", 'a') + } +} + +// Called to find and repair after crashes - called by installSchedule() and busy() +private boolean attemptRecovery() { + if (!atomicState.run) { + return false // only clean up if we think we are still running + } + else { // Hmmm...seems we were running before... + def csw = settings.switches.currentSwitch + def cst = settings.switches.currentStatus + switch (csw) { + case 'on': // looks like this schedule is running the controller at the moment + if (!atomicState.startTime) { // cycleLoop cleared the startTime, but cycleOn() didn't set it + log.debug "${app.label}: crashed in cycleLoop(), cycleOn() never started, cst is ${cst} - resetting" + resetEverything() // reset and try again...it's probably not us running the controller, though + return false + } + // We have a startTime... + if (!atomicState.finishTime) { // started, but we don't think we're done yet..so it's probably us! + runIn(15, cycleOn) // goose the cycle, just in case + note('active', "${app.label}: schedule is apparently already running", 'i') + return true + } + + // hmmm...switch is on and we think we're finished...probably somebody else is running...let busy figure it out + resetEverything() + return false + break + + case 'off': // switch is off - did we finish? + if (atomicState.finishTime) { // off and finished, let's just reset things + resetEverything() + return false + } + + if (switches.currentStatus != 'pause') { // off and not paused - probably another schedule, let's clean up + resetEverything() + return false + } + + // off and not finished, and paused, we apparently crashed while paused + runIn(15, cycleOn) + return true + break + + case 'programOn': // died while manual program running? + case 'programWait': // looks like died previously before we got started, let's try to clean things up + resetEverything() + if (atomicState.finishTime) atomicState.finishTime = null + if ((cst == 'active') || atomicState.startTime) { // if we announced we were in preCheck, or made it all the way to cycleOn before it crashed + settings.switches.programOff() // only if we think we actually started (cycleOn() started) + // probably kills manual cycles too, but we'll let that go for now + } + if (atomicState.startTime) atomicState.startTime = null + note ('schedule', "Looks like ${app.label} crashed recently...cleaning up", c) + return false + break + + default: + log.debug "attemptRecovery(): atomicState.run == true, and I've nothing left to do" + return true + } + } +} + +// reset everything to the initial (not running) state +private def resetEverything() { + if (atomicState.run) atomicState.run = false // we're not running the controller any more + unsubAllBut() // release manual, switches, sync, contacts & toggles + + // take care not to unschedule preCheck() or getRainToday() + unschedule(cycleOn) + unschedule(checkRunMap) + unschedule(writeCycles) + unschedule(subOff) + + if (settings.enableManual) subscribe(settings.switches, 'switch.programOn', manualStart) +} + +// unsubscribe from ALL events EXCEPT app.touch +private def unsubAllBut() { + unsubscribe(settings.switches) + unsubWaterStoppers() + if (settings.sync) unsubscribe(settings.sync) + +} + +// enable the "Play" button in SmartApp list +def appTouch(evt) { + + log.debug "appTouch(): atomicState.run = ${atomicState.run}" + + runIn(2, preCheck) // run it off a schedule, so we can see how long it takes in the app.state +} + +// true if one of the stoppers is in Stop state +private boolean isWaterStopped() { + if (settings.contacts && settings.contacts.currentContact.contains(settings.contactStop)) return true + + if (settings.toggles && settings.toggles.currentSwitch.contains(settings.toggleStop)) return true + + return false +} + +// watch for water stoppers +private def subWaterStop() { + if (settings.contacts) { + unsubscribe(settings.contacts) + subscribe(settings.contacts, "contact.${settings.contactStop}", waterStop) + } + if (settings.toggles) { + unsubscribe(settings.toggles) + subscribe(settings.toggles, "switch.${settings.toggleStop}", waterStop) + } +} + +// watch for water starters +private def subWaterStart() { + if (settings.contacts) { + unsubscribe(settings.contacts) + def cond = (settings.contactStop == 'open') ? 'closed' : 'open' + subscribe(settings.contacts, "contact.${cond}", waterStart) + } + if (settings.toggles) { + unsubscribe(settings.toggles) + def cond = (settings.toggleStop == 'on') ? 'off' : 'on' + subscribe(settings.toggles, "switch.${cond}", waterStart) + } +} + +// stop watching water stoppers and starters +private def unsubWaterStoppers() { + if (settings.contacts) unsubscribe(settings.contacts) + if (settings.toggles) unsubscribe(settings.toggles) +} + +// which of the stoppers are in stop mode? +private String getWaterStopList() { + String deviceList = '' + int i = 1 + if (settings.contacts) { + settings.contacts.each { + if (it.currentContact == settings.contactStop) { + if (i > 1) deviceList += ', ' + deviceList = "${deviceList}${it.displayName} is ${settings.contactStop}" + i++ + } + } + } + if (settings.toggles) { + settings.toggles.each { + if (it.currentSwitch == settings.toggleStop) { + if (i > 1) deviceList += ', ' + deviceList = "${deviceList}${it.displayName} is ${settings.toggleStop}" + i++ + } + } + } + return deviceList +} + +//write initial zone settings to device at install/update +def writeSettings(){ + if (!state.tpwMap) state.tpwMap = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + if (!state.dpwMap) state.dpwMap = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + if (state.setMoisture) state.setMoisture = null // not using any more + if (!state.seasonAdj) state.seasonAdj = 100.0 + if (!state.weekseasonAdj) state.weekseasonAdj = 0 + setSeason() +} + +//get day of week integer +int getWeekDay(day) +{ + def weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] + def mapDay = [Monday:1, Tuesday:2, Wednesday:3, Thursday:4, Friday:5, Saturday:6, Sunday:7] + if(day && weekdays.contains(day)) { + return mapDay.get(day).toInteger() + } + def today = new Date().format('EEEE', location.timeZone) + return mapDay.get(today).toInteger() +} + +// Get string of run days from dpwMap +private String getRunDays(day1,day2,day3,day4,day5,day6,day7) +{ + String str = '' + if(day1) str += 'M' + if(day2) str += 'T' + if(day3) str += 'W' + if(day4) str += 'Th' + if(day5) str += 'F' + if(day6) str += 'Sa' + if(day7) str += 'Su' + if(str == '') str = '0 Days/week' + return str +} + +//start manual schedule +def manualStart(evt){ + boolean running = attemptRecovery() // clean up if prior run crashed + + if (settings.enableManual && !running && (settings.switches.currentStatus != 'pause')){ + if (settings.sync && ( (settings.sync.currentSwitch != 'off') || settings.sync.currentStatus == 'pause') ) { + note('skipping', "${app.label}: Manual run aborted, ${settings.sync.displayName} appears to be busy", 'a') + } + else { + def runNowMap = [] + runNowMap = cycleLoop(0) + + if (runNowMap) { + atomicState.run = true + settings.switches.programWait() + subscribe(settings.switches, 'switch.off', cycleOff) + + runIn(60, cycleOn) // start water program + + // note that manual DOES abide by waterStoppers (if configured) + String newString = '' + int tt = state.totalTime + if (tt) { + int hours = tt / 60 // DON'T Math.round this one + int mins = tt - (hours * 60) + String hourString = '' + String s = '' + if (hours > 1) s = 's' + if (hours > 0) hourString = "${hours} hour${s} & " + s = 's' + if (mins == 1) s = '' + newString = "run time: ${hourString}${mins} minute${s}:\n" + } + + note('active', "${app.label}: Manual run, watering in 1 minute: ${newString}${runNowMap}", 'd') + } + else note('skipping', "${app.label}: Manual run failed, check configuration", 'a') + } + } + else note('skipping', "${app.label}: Manual run aborted, ${settings.switches.displayName} appears to be busy", 'a') +} + +//true if another schedule is running +boolean busy(){ + // Check if we are already running, crashed or somebody changed the schedule time while this schedule is running + if (atomicState.run){ + if (!attemptRecovery()) { // recovery will clean out any prior crashes and correct state of atomicState.run + return false // (atomicState.run = false) + } + else { + // don't change the current status, in case the currently running schedule is in off/paused mode + note(settings.switches.currentStatus, "${app.label}: Already running, skipping additional start", 'i') + return true + } + } + // Not already running... + + // Moved from cycleOn() - don't even start pre-check until the other controller completes its cycle + if (settings.sync) { + if ((settings.sync.currentSwitch != 'off') || settings.sync.currentStatus == 'pause') { + subscribe(settings.sync, 'switch.off', syncOn) + + note('delayed', "${app.label}: Waiting for ${settings.sync.displayName} to complete before starting", 'c') + return true + } + } + + // Check that the controller isn't paused while running some other schedule + def csw = settings.switches.currentSwitch + def cst = settings.switches.currentStatus + + if ((csw == 'off') && (cst != 'pause')) { // off && !paused: controller is NOT in use + log.debug "switches ${csw}, status ${cst} (1st)" + resetEverything() // get back to the start state + return false + } + + if (isDay()) { // Yup, we need to run today, so wait for the other schedule to finish + log.debug "switches ${csw}, status ${cst} (3rd)" + resetEverything() + subscribe(settings.switches, 'switch.off', busyOff) + note('delayed', "${app.label}: Waiting for currently running schedule to complete before starting", 'c') + return true + } + + // Somthing is running, but we don't need to run today anyway - don't need to do busyOff() + // (Probably should never get here, because preCheck() should check isDay() before calling busy() + log.debug "Another schedule is running, but ${app.label} is not scheduled for today anyway" + return true +} + +def busyOff(evt){ + def cst = settings.switches.currentStatus + if ((settings.switches.currentSwitch == 'off') && (cst != 'pause')) { // double check that prior schedule is done + unsubscribe(switches) // we don't want any more button pushes until preCheck runs + Random rand = new Random() // just in case there are multiple schedules waiting on the same controller + int randomSeconds = rand.nextInt(120) + 15 + runIn(randomSeconds, preCheck) // no message so we don't clog the system + note('active', "${app.label}: ${settings.switches} finished, starting in ${randomSeconds} seconds", 'i') + } +} + +//run check every day +def preCheck() { + + if (!isDay()) { + log.debug "preCheck() Skipping: ${app.label} is not scheduled for today" // silent - no note + //if (!atomicState.run && enableManual) subscribe(switches, 'switch.programOn', manualStart) // only if we aren't running already + return + } + + if (!busy()) { + atomicState.run = true // set true before doing anything, atomic in case we crash (busy() set it false if !busy) + settings.switches.programWait() // take over the controller so other schedules don't mess with us + runIn(45, checkRunMap) // schedule checkRunMap() before doing weather check, gives isWeather 45s to complete + // because that seems to be a little more than the max that the ST platform allows + unsubAllBut() // unsubscribe to everything except appTouch() + subscribe(settings.switches, 'switch.off', cycleOff) // and start setting up for today's cycle + def start = now() + note('active', "${app.label}: Starting...", 'd') // + def end = now() + log.debug "preCheck note active ${end - start}ms" + + if (isWeather()) { // set adjustments and check if we shold skip because of rain + resetEverything() // if so, clean up our subscriptions + switches.programOff() // and release the controller + } + else { + log.debug 'preCheck(): running checkRunMap in 2 seconds' //COOL! We finished before timing out, and we're supposed to water today + runIn(2, checkRunMap) // jack the schedule so it runs sooner! + } + } +} + +//start water program +def cycleOn(){ + if (atomicState.run) { // block if manually stopped during precheck which goes to cycleOff + + if (!isWaterStopped()) { // make sure ALL the contacts and toggles aren't paused + // All clear, let's start running! + subscribe(settings.switches, 'switch.off', cycleOff) + subWaterStop() // subscribe to all the pause contacts and toggles + resume() + + // send the notification AFTER we start the controller (in case note() causes us to run over our execution time limit) + String newString = "${app.label}: Starting..." + if (!atomicState.startTime) { + atomicState.startTime = now() // if we haven't already started + if (atomicState.startTime) atomicState.finishTime = null // so recovery in busy() knows we didn't finish + if (state.pauseTime) state.pauseTime = null + if (state.totalTime) { + String finishTime = new Date(now() + (60000 * state.totalTime).toLong()).format('EE @ h:mm a', location.timeZone) + newString = "${app.label}: Starting - ETC: ${finishTime}" + } + } + else if (state.pauseTime) { // resuming after a pause + + def elapsedTime = Math.round((now() - state.pauseTime) / 60000) // convert ms to minutes + int tt = state.totalTime + elapsedTime + 1 + state.totalTime = tt // keep track of the pauses, and the 1 minute delay above + String finishTime = new Date(atomicState.startTime + (60000 * tt).toLong()).format('EE @ h:mm a', location.timeZone) + state.pauseTime = null + newString = "${app.label}: Resuming - New ETC: ${finishTime}" + } + note('active', newString, 'd') + } + else { + // Ready to run, but one of the control contacts is still open, so we wait + subWaterStart() // one of them is paused, let's wait until the are all clear! + note('pause', "${app.label}: Watering paused, ${getWaterStopList()}", 'c') + } } } - -//write initial zone settings to device at install/update -def writeSettings() + +//when switch reports off, watering program is finished +def cycleOff(evt){ + + if (atomicState.run) { + def ft = new Date() + atomicState.finishTime = ft // this is important to reset the schedule after failures in busy() + String finishTime = ft.format('h:mm a', location.timeZone) + note('finished', "${app.label}: Finished watering at ${finishTime}", 'd') + } + else { + log.debug "${settings.switches} turned off" // is this a manual off? perhaps we should send a note? + } + resetEverything() // all done here, back to starting state +} + +//run check each day at scheduled time +def checkRunMap(){ + + //check if isWeather returned true or false before checking + if (atomicState.run) { + + //get & set watering times for today + def runNowMap = [] + runNowMap = cycleLoop(1) // build the map + + if (runNowMap) { + runIn(60, cycleOn) // start water + subscribe(settings.switches, 'switch.off', cycleOff) // allow manual off before cycleOn() starts + if (atomicState.startTime) atomicState.startTime = null // these were already cleared in cycleLoop() above + if (state.pauseTime) state.pauseTime = null // ditto + // leave atomicState.finishTime alone so that recovery in busy() knows we never started if cycleOn() doesn't clear it + + String newString = '' + int tt = state.totalTime + if (tt) { + int hours = tt / 60 // DON'T Math.round this one + int mins = tt - (hours * 60) + String hourString = '' + String s = '' + if (hours > 1) s = 's' + if (hours > 0) hourString = "${hours} hour${s} & " + s = 's' + if (mins == 1) s = '' + newString = "run time: ${hourString}${mins} minute${s}:\n" + } + note('active', "${app.label}: Watering in 1 minute, ${newString}${runNowMap}", 'd') + } + else { + unsubscribe(settings.switches) + unsubWaterStoppers() + switches.programOff() + if (enableManual) subscribe(settings.switches, 'switch.programOn', manualStart) + note('skipping', "${app.label}: No watering today", 'd') + if (atomicState.run) atomicState.run = false // do this last, so that the above note gets sent to the controller + } + } + else { + log.debug 'checkRunMap(): atomicState.run = false' // isWeather cancelled us out before we got started + } +} + +//get todays schedule +def cycleLoop(int i) { - def cyclesMap = [:] - if(!state.tpwMap) state.tpwMap = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] - if(!state.dpwMap) state.dpwMap = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] - if(!state.seasonAdj) state.seasonAdj = 0 - if(!state.weekseasonAdj) state.weekseasonAdj = 0 - setSeason() - //add pumpdelay @ 1 + boolean isDebug = false + if (isDebug) log.debug "cycleLoop(${i})" + + int zone = 1 + int dpw = 0 + int tpw = 0 + int cyc = 0 + int rtime = 0 + def timeMap = [:] + def pumpMap = "" + def runNowMap = "" + String soilString = '' + int totalCycles = 0 + int totalTime = 0 + if (atomicState.startTime) atomicState.startTime = null // haven't started yet + + while(zone <= 16) + { + rtime = 0 + def setZ = settings."zone${zone}" + if ((setZ && (setZ != 'Off')) && (nozzle(zone) != 4) && zoneActive(zone.toString())) { + + // First check if we run this zone today, use either dpwMap or even/odd date + dpw = getDPW(zone) + int runToday = 0 + // if manual, or every day allowed, or zone uses a sensor, then we assume we can today + // - preCheck() has already verified that today isDay() + if ((i == 0) || (state.daysAvailable == 7) || (settings."sensor${zone}")) { + runToday = 1 + } + else { + + dpw = getDPW(zone) // figure out if we need to run (if we don't already know we do) + if (settings.days && (settings.days.contains('Even') || settings.days.contains('Odd'))) { + def daynum = new Date().format('dd', location.timeZone) + int dayint = Integer.parseInt(daynum) + if (settings.days.contains('Odd') && (((dayint +1) % Math.round(31 / (dpw * 4))) == 0)) runToday = 1 + else if (settings.days.contains('Even') && ((dayint % Math.round(31 / (dpw * 4))) == 0)) runToday = 1 + } + else { + int weekDay = getWeekDay()-1 + def dpwMap = getDPWDays(dpw) + runToday = dpwMap[weekDay] //1 or 0 + if (isDebug) log.debug "Zone: ${zone} dpw: ${dpw} weekDay: ${weekDay} dpwMap: ${dpwMap} runToday: ${runToday}" + + } + } + + // OK, we're supposed to run (or at least adjust the sensors) + if (runToday == 1) + { + def soil + if (i == 0) soil = moisture(0) // manual + else soil = moisture(zone) // moisture check + soilString = "${soilString}${soil[1]}" + + // Run this zone if soil moisture needed + if ( soil[0] == 1 ) + { + cyc = cycles(zone) + tpw = getTPW(zone) + dpw = getDPW(zone) // moisture() may have changed DPW + + rtime = calcRunTime(tpw, dpw) + //daily weather adjust if no sensor + if(settings.isSeason && (!settings.learn || !settings."sensor${zone}")) { + + + rtime = Math.round(((rtime / cyc) * (state.seasonAdj / 100.0)) + 0.4) + } + else { + rtime = Math.round((rtime / cyc) + 0.4) // let moisture handle the seasonAdjust for Adaptive (learn) zones + } + totalCycles += cyc + totalTime += (rtime * cyc) + runNowMap += "${settings."name${zone}"}: ${cyc} x ${rtime} min\n" + if (isDebug) log.debug "Zone ${zone} Map: ${cyc} x ${rtime} min - totalTime: ${totalTime}" + } + } + } + if (nozzle(zone) == 4) pumpMap += "${settings."name${zone}"}: ${settings."zone${zone}"} on\n" + timeMap."${zone+1}" = "${rtime}" + zone++ + } + + if (soilString) { + String seasonStr = '' + String plus = '' + float sa = state.seasonAdj + if (settings.isSeason && (sa != 100.0) && (sa != 0.0)) { + float sadj = sa - 100.0 + if (sadj > 0.0) plus = '+' //display once in cycleLoop() + int iadj = Math.round(sadj) + if (iadj != 0) seasonStr = "Adjusting ${plus}${iadj}% for weather forecast\n" + } + note('moisture', "${app.label} Sensor status:\n${seasonStr}${soilString}" /* + seasonStr + soilString */,'m') + } + + if (!runNowMap) { + return runNowMap // nothing to run today + } + + //send settings to Spruce Controller + switches.settingsMap(timeMap,4002) + runIn(30, writeCycles) + + // meanwhile, calculate our total run time + int pDelay = 0 + if (settings.pumpDelay && settings.pumpDelay.isNumber()) pDelay = settings.pumpDelay.toInteger() + totalTime += Math.round(((pDelay * (totalCycles-1)) / 60.0)) // add in the pump startup and inter-zone delays + state.totalTime = totalTime + + if (state.pauseTime) state.pauseTime = null // and we haven't paused yet + // but let cycleOn() reset finishTime + return (runNowMap + pumpMap) +} + +//send cycle settings +def writeCycles(){ + //log.trace "writeCycles()" + def cyclesMap = [:] + //add pumpdelay @ 1 cyclesMap."1" = pumpDelayString() - def zone = 1 - def cycle = 0 + int zone = 1 + int cycle = 0 while(zone <= 17) { if(nozzle(zone) == 4) cycle = 4 else cycle = cycles(zone) //offset by 1, due to pumpdelay @ 1 cyclesMap."${zone+1}" = "${cycle}" - if (zone <= 16) { - state.tpwMap.putAt(zone-1, initTPW(zone)) - state.dpwMap.putAt(zone-1, initDPW(zone)) - } zone++ } - switches.settingsMap(cyclesMap, 4001) -} - -//get day of week integer -def getWeekDay(day) -{ - def weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] - def mapDay = [Monday:1, Tuesday:2, Wednesday:3, Thursday:4, Friday:5, Saturday:6, Sunday:7] - if(day && weekdays.contains(day)) { - return mapDay.get(day) - } - def today = new Date().format("EEEE", location.timeZone) - return mapDay.get(today) + switches.settingsMap(cyclesMap, 4001) } -// Get string of run days from dpwMap -def getRunDays(day1,day2,day3,day4,day5,day6,day7) -{ - def str = "" - if(day1) - str += "M" - if(day2) - str += "T" - if(day3) - str += "W" - if(day4) - str += "Th" - if(day5) - str += "F" - if(day6) - str += "Sa" - if(day7) - str += "Su" - if(string == "") - str = "0 Days/week" - return str +def resume(){ + log.debug 'resume()' + settings.switches.zon() } -def checkOn(){ - cycleOn() -} - -//start water program -def cycleOn(){ - if (state.run == true){ - subscribe switches, "switch.off", cycleOff - if (sync != null) subscribe sync, "status.finished", syncOn - if (contact != null){ - subscribe contact, "contact.open", doorOpen - subscribe contact, "contact.closed", doorClosed - } - if (sync != null && !sync.currentValue('status').contains('finished')) note("pause", "waiting for $sync to complete before starting schedule", "w") - else if (contact == null || !contact.currentValue('contact').contains('open')) resume() //runIn(15, resume) //15 second delay to allow writesettings to finish resume -> switches.on - else note("pause", "$contact opened $switches paused watering", "w") - } -} - -//when switch reports off, watering program is finished -def cycleOff(evt){ - state.run = false - if (contact == null || !contact.currentValue('contact').contains('open')){ - note("finished", "finished watering for today", "d") - unsubscribe(contact) - } +def syncOn(evt){ + // double check that the switch is actually finished and not just paused + if ((settings.sync.currentSwitch == 'off') && (settings.sync.currentStatus != 'pause')) { + resetEverything() // back to our known state + Random rand = new Random() // just in case there are multiple schedules waiting on the same controller + int randomSeconds = rand.nextInt(120) + 15 + runIn(randomSeconds, preCheck) // no message so we don't clog the system + note('schedule', "${app.label}: ${settings.sync} finished, starting in ${randomSeconds} seconds", 'c') + } // else, it is just pausing...keep waiting for the next "off" } -//start check -def manualStart(evt){ +// handle start of pause session +def waterStop(evt){ + log.debug "waterStop: ${evt.displayName}" - def runNowMap = [] - runNowMap = cycleLoop() - if (runNowMap) - { - state.run = true - runNowMap = "Water will begin in 1 minute:\n" + runNowMap - note("active", "${runNowMap}", "d") - runIn(60, cycleOn) //start water program - } - - else { - switches.programOff() - state.run = false - note("skipping", "No watering scheduled for today.", "d") - } - -} - - -//run check each day at scheduled time -def Check(){ - state.run = true - // Create weekly water summary, if requested, on Sunday - if(notify && notify.contains('Weekly') && (getWeekDay() == 7)) - { - def zone = 1 - def zoneSummary = "" - while(zone <= 16) { - if(settings["zone${zone}"] != null && settings["zone${zone}"] != 'Off' && nozzle(zone) != 4) { - def sum = getaZoneSummary(zone) - zoneSummary = "${zoneSummary} ${sum}" - } - zone++ - } - log.debug "Weekly water summary: ${zoneSummary}" - sendPush "Weekly water summary: ${zoneSummary}" - } - - def runNowMap = [] - if (isDay() == false){ - switches.programOff() - state.run = false - note("skipping", "No watering allowed today.", "d") - } - else if (isWeather() == false) - { - //get & set watering times for today - runNowMap = cycleLoop() - if (runNowMap) - { - state.run = true - runNowMap = "Water will begin in 2 minutes:\n" + runNowMap - note("active", "${runNowMap}", "d") - //cycleOn() //start water program - } - else { - switches.programOff() - state.run = false - note("skipping", "No watering scheduled for today.", "d") - } - } - else { - switches.programOff() - state.run = false - } -} - -//get todays schedule -def cycleLoop() -{ - def zone = 1 - def cyc = 0 - def rtime = 0 - def timeMap = [:] - def pumpMap = "" - def runNowMap = "" - def soilString = "" - - while(zone <= 16) - { - rtime = 0 - //change to tpw(?) - if(settings["zone${zone}"] != null && settings["zone${zone}"] != 'Off' && nozzle(zone) != 4) - { - // First check if we run this zone today, use either dpwMap or even/odd date - def dpw = getDPW(zone) - def runToday = 0 - if (days && (days.contains('Even') || days.contains('Odd'))) { - def daynum = new Date().format("dd", location.timeZone) - int dayint = Integer.parseInt(daynum) - if(days.contains('Odd') && (dayint +1) % Math.round(31 / (dpw * 4)) == 0) runToday = 1 - if(days.contains('Even') && dayint % Math.round(31 / (dpw * 4)) == 0) runToday = 1 - } else { - def weekDay = getWeekDay()-1 - def dpwMap = getDPWDays(dpw) - def today = dpwMap[weekDay] - log.debug "Zone: ${zone} dpw: ${dpw} weekDay: ${weekDay} dpwMap: ${dpwMap} today: ${today}" - runToday = dpwMap[weekDay] //1 or 0 - } - //if no learn check moisture sensors on available days - if (!learn && (settings["sensor${zone}"] != null) ) runToday = 1 - - if(runToday) - { - def soil = moisture(zone) - soilString += "${soil[1]}" - - // Run this zone if soil moisture needed or if it is a weekly - // We run at least once a week and let moisture lower the time if needed - if ( (soil[0] == 1 ) || (learn && dpw == 1) ) - { - cyc = cycles(zone) - dpw = getDPW(zone) - rtime = calcRunTime(getTPW(zone), dpw) - //daily weather adjust if no sensor - if(isSeason && settings["sensor${zone}"] == null) rtime = Math.round(rtime / cyc * state.seasonAdj / 100) - // runTime is total run time devided by num cycles - else rtime = Math.round(rtime / cyc) - runNowMap += "${settings["name${zone}"]}: ${cyc} x ${rtime} min\n" - log.debug"Zone ${zone} Map: ${cyc} x ${rtime} min" - } - } + unschedule(cycleOn) // in case we got stopped again before cycleOn starts from the restart + unsubscribe(settings.switches) + subWaterStart() + + if (!state.pauseTime) { // only need to do this for the first event if multiple contacts + state.pauseTime = now() + + String cond = evt.value + switch (cond) { + case 'open': + cond = 'opened' + break + case 'on': + cond = 'switched on' + break + case 'off': + cond = 'switched off' + break + //case 'closed': + // cond = 'closed' + // break + case null: + cond = '????' + break + default: + break } - if (nozzle(zone) == 4) pumpMap += "${settings["name${zone}"]}: ${settings["zone${zone}"]} on\n" - timeMap."${zone+1}" = "${rtime}" - zone++ - } - if (soilString) { - soilString = "Moisture Sensors:\n" + soilString - note("moisture", "${soilString}","m") - } - //send settings to Spruce Controller - switches.settingsMap(timeMap,4002) - if (runNowMap) return runNowMap += pumpMap - return runNowMap + note('pause', "${app.label}: Watering paused - ${evt.displayName} ${cond}", 'c') // set to Paused + } + if (settings.switches.currentSwitch != 'off') { + runIn(30, subOff) + settings.switches.off() // stop the water + } + else + subscribe(settings.switches, 'switch.off', cycleOff) +} + +// This is a hack to work around the delay in response from the controller to the above programOff command... +// We frequently see the off notification coming a long time after the command is issued, so we try to catch that so that +// we don't prematurely exit the cycle. +def subOff() { + subscribe(settings.switches, 'switch.off', offPauseCheck) +} + +def offPauseCheck( evt ) { + unsubscribe(settings.switches) + subscribe(settings.switches, 'switch.off', cycleOff) + if (/*(switches.currentSwitch != 'off') && */ (settings.switches.currentStatus != 'pause')) { // eat the first off while paused + cycleOff(evt) + } +} + +// handle end of pause session +def waterStart(evt){ + if (!isWaterStopped()){ // only if ALL of the selected contacts are not open + def cDelay = 10 + if (settings.contactDelay > 10) cDelay = settings.contactDelay + runIn(cDelay, cycleOn) + + unsubscribe(settings.switches) + subWaterStop() // allow stopping again while we wait for cycleOn to start + + log.debug "waterStart(): enabling device is ${evt.device} ${evt.value}" + + String cond = evt.value + switch (cond) { + case 'open': + cond = 'opened' + break + case 'on': + cond = 'switched on' + break + case 'off': + cond = 'switched off' + break + //case 'closed': + // cond = 'closed' + // break + case null: + cond = '????' + break + default: + break + } + // let cycleOn() change the status to Active - keep us paused until then + + note('pause', "${app.label}: ${evt.displayName} ${cond}, watering in ${cDelay} seconds", 'c') + } + else { + log.debug "waterStart(): one down - ${evt.displayName}" + } } //Initialize Days per week, based on TPW, perDay and daysAvailable settings -def initDPW(i){ - if(initTPW(i) > 0) { - def dpw - def perDay = 20 - if(settings["perDay${i}"]) perDay = settings["perDay${i}"].toInteger() - dpw = Math.round(initTPW(i) / perDay) - if(dpw <= 1) return 1 +int initDPW(int zone){ + //log.debug "initDPW(${zone})" + if(!state.dpwMap) state.dpwMap = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + + int tpw = getTPW(zone) // was getTPW -does not update times in scheduler without initTPW + int dpw = 0 + + if(tpw > 0) { + float perDay = 20.0 + if(settings."perDay${zone}") perDay = settings."perDay${zone}".toFloat() + + dpw = Math.round(tpw.toFloat() / perDay) + if(dpw <= 1) dpw = 1 // 3 days per week not allowed for even or odd day selection if(dpw == 3 && days && (days.contains('Even') || days.contains('Odd')) && !(days.contains('Even') && days.contains('Odd'))) - if(initTPW(i) / perDay < 3.0) return 2 - else return 4 - if(daysAvailable() < dpw) return daysAvailable() - return dpw + if((tpw.toFloat() / perDay) < 3.0) dpw = 2 else dpw = 4 + int daycheck = daysAvailable() // initialize & optimize daysAvailable + if (daycheck < dpw) dpw = daycheck } - return 0 + state.dpwMap[zone-1] = dpw + return dpw } // Get current days per week value, calls init if not defined -def getDPW(zone) -{ - def i = zone.toInteger() - if(state.dpwMap) return state.dpwMap.get(i-1) - return initDPW(i) +int getDPW(int zone) { + if (state.dpwMap) return state.dpwMap[zone-1] else return initDPW(zone) } //Initialize Time per Week -def initTPW(i){ - if("${settings["zone${i}"]}" == null || nozzle(i) == 0 || nozzle(i) == 4 || plant(i) == 0) return 0 +int initTPW(int zone) { + //log.trace "initTPW(${zone})" + if (!state.tpwMap) state.tpwMap = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + + int n = nozzle(zone) + def zn = settings."zone${zone}" + if (!zn || (zn == 'Off') || (n == 0) || (n == 4) || (plant(zone) == 0) || !zoneActive(zone.toString())) return 0 // apply gain adjustment - def gainAdjust = 100 - if (gain && gain != 0) gainAdjust += gain + float gainAdjust = 100.0 + if (settings.gain && settings.gain != 0) gainAdjust += settings.gain - // apply seasonal adjustment is enabled and not set to new plants - def seasonAdjust = 100 - if (state.weekseasonAdj && isSeason && settings["plant${i}"] != "New Plants") seasonAdjust = state.weekseasonAdj + // apply seasonal adjustment if enabled and not set to new plants + float seasonAdjust = 100.0 + def wsa = state.weekseasonAdj + if (wsa && isSeason && (settings."plant${zone}" != 'New Plants')) seasonAdjust = wsa - def zone = i.toInteger() - def tpw = 0 + int tpw = 0 + // Use learned, previous tpw if it is available + if ( settings."sensor${zone}" ) { + seasonAdjust = 100.0 // no weekly seasonAdjust if this zone uses a sensor + if(state.tpwMap && settings.learn) tpw = state.tpwMap[zone-1] + } - // Use learned, previous tpw if it is available - if(state.tpwMap) tpw = state.tpwMap.get(zone-1) - // set user time with season adjust - if(settings["minWeek${i}"] != null && settings["minWeek${i}"] != 0) tpw = Math.round(("${settings["minWeek${i}"]}").toInteger() * seasonAdjust / 100) - - // initial tpw calculation - if (tpw == null || tpw == 0) tpw = Math.round(plant(i) * nozzle(i) * gainAdjust / 100 * seasonAdjust / 100) - // apply gain to all zones --obsolete with learn implementation-- - //else if (gainAdjust != 100) twp = Math.round(tpw * gainAdjust / 100) - - //if (tpw <= 3) tpw = 3 + // set user-specified minimum time with seasonal adjust + int minWeek = 0 + def mw = settings."minWeek${zone}" + if (mw) minWeek = mw.toInteger() + if (minWeek != 0) { + tpw = Math.round(minWeek * (seasonAdjust / 100.0)) + } + else if (!tpw || (tpw == 0)) { // use calculated tpw + tpw = Math.round((plant(zone) * nozzle(zone) * (gainAdjust / 100.0) * (seasonAdjust / 100.0))) + } + state.tpwMap[zone-1] = tpw return tpw } // Get the current time per week, calls init if not defined -def getTPW(zone) +int getTPW(int zone) { - def i = zone.toInteger() - if(state.tpwMap) return state.tpwMap.get(i-1) - return initTPW(i) + if (state.tpwMap) return state.tpwMap[zone-1] else return initTPW(zone) } // Calculate daily run time based on tpw and dpw -def calcRunTime(tpw, dpw) +int calcRunTime(int tpw, int dpw) { - def duration = 0 - if(tpw > 0 && dpw > 0) { - duration = Math.round(tpw / dpw) - } + int duration = 0 + if ((tpw > 0) && (dpw > 0)) duration = Math.round(tpw.toFloat() / dpw.toFloat()) return duration } // Check the moisture level of a zone returning dry (1) or wet (0) and adjust tpw if overly dry/wet -def moisture(i) +def moisture(int i) { - // No Sensor on this zone - if(settings["sensor${i}"] == null) { - return [1,""] + boolean isDebug = false + if (isDebug) log.debug "moisture(${i})" + + def endMsecs = 0 + // No Sensor on this zone or manual start skips moisture checking altogether + if ((i == 0) || !settings."sensor${i}") { + return [1,''] } - // Check if sensor is reporting 6-> 12 hours - def sixHours = new Date(now() - (1000 * 60 * 60 * 12).toLong()) - def recentActivity = (settings["sensor${i}"].eventsSince(sixHours)?.findAll { it.name == "temperature" }) - if (recentActivity == []) { - //change to seperate warning note? - note("warning", "Please check ${settings["sensor${i}"]}, no activity in the last 12 hours", "w") - return [1, "Please check ${settings["sensor${i}"]}, no activity in the last 12 hours\n"] //change to 1 + // Ensure that the sensor has reported within last 48 hours + int spHum = getDrySp(i) + int hours = 48 + def yesterday = new Date(now() - (/* 1000 * 60 * 60 */ 3600000 * hours).toLong()) + float latestHum = settings."sensor${i}".latestValue('humidity').toFloat() // state = 29, value = 29.13 + def lastHumDate = settings."sensor${i}".latestState('humidity').date + if (lastHumDate < yesterday) { + note('warning', "${app.label}: Please check sensor ${settings."sensor${i}"}, no humidity reports in the last ${hours} hours", 'a') + + if (latestHum < spHum) + latestHum = spHum - 1.0 // amke sure we water and do seasonal adjustments, but not tpw adjustments + else + latestHum = spHum + 0.99 // make sure we don't water, do seasonal adjustments, but not tpw adjustments } - - def latestHum = settings["sensor${i}"].latestValue("humidity") - def spHum = getDrySp(i).toInteger() - //def moistureList = [] - if (!learn) + + if (!settings.learn) { - // no learn mode, only looks at target moisture level - if(latestHum <= spHum) { + // in Delay mode, only looks at target moisture level, doesn't try to adjust tpw + // (Temporary) seasonal adjustment WILL be applied in cycleLoop(), as if we didn't have a sensor + if (latestHum <= spHum.toFloat()) { //dry soil - return [1,"${settings["name${i}"]}, Watering ${settings["sensor${i}"]} reads ${latestHum}%, SP is ${spHum}%\n"] - } else { - //wet soil - return [0,"${settings["name${i}"]}, Skipping ${settings["sensor${i}"]} reads ${latestHum}%, SP is ${spHum}%\n"] + return [1,"${settings."name${i}"}, Watering: ${settings."sensor${i}"} reads ${latestHum}%, SP is ${spHum}%\n"] + } + else { + //wet soil + return [0,"${settings."name${i}"}, Skipping: ${settings."sensor${i}"} reads ${latestHum}%, SP is ${spHum}%\n"] } } - def tpw = getTPW(i) - def tpwAdjust = Math.round((spHum - latestHum) * getDPW(i)) - // Only adjust tpw if outside of 1 percent, otherwise rounding will keep it the same anyways - if (tpwAdjust >= -1 && tpwAdjust <= 1) { - tpwAdjust = 0 + //in Adaptive mode + int tpw = getTPW(i) + int dpw = getDPW(i) + int cpd = cycles(i) + + + + + if (isDebug) log.debug "moisture(${i}): tpw: ${tpw}, dpw: ${dpw}, cycles: ${cpd} (before adjustment)" + + float diffHum = 0.0 + if (latestHum > 0.0) diffHum = (spHum - latestHum) / 100.0 + else { + diffHum = 0.02 // Safety valve in case sensor is reporting 0% humidity (e.g., somebody pulled it out of the ground or flower pot) + note('warning', "${app.label}: Please check sensor ${settings."sensor${i}"}, it is currently reading 0%", 'a') + } + + int daysA = state.daysAvailable + int minimum = cpd * dpw // minimum of 1 minute per scheduled days per week (note - can be 1*1=1) + if (minimum < daysA) minimum = daysA // but at least 1 minute per available day + int tpwAdjust = 0 + + if (diffHum > 0.01) { // only adjust tpw if more than 1% of target SP + tpwAdjust = Math.round(((tpw * diffHum) + 0.5) * dpw * cpd) // Compute adjustment as a function of the current tpw + float adjFactor = 2.0 / daysA // Limit adjustments to 200% per week - spread over available days + if (tpwAdjust > (tpw * adjFactor)) tpwAdjust = Math.round((tpw * adjFactor) + 0.5) // limit fast rise + if (tpwAdjust < minimum) tpwAdjust = minimum // but we need to move at least 1 minute per cycle per day to actually increase the watering time + } else if (diffHum < -0.01) { + if (diffHum < -0.05) diffHum = -0.05 // try not to over-compensate for a heavy rainstorm... + tpwAdjust = Math.round(((tpw * diffHum) - 0.5) * dpw * cpd) + float adjFactor = -0.6667 / daysA // Limit adjustments to 66% per week + if (tpwAdjust < (tpw * adjFactor)) tpwAdjust = Math.round((tpw * adjFactor) - 0.5) // limit slow decay + if (tpwAdjust > (-1 * minimum)) tpwAdjust = -1 * minimum // but we need to move at least 1 minute per cycle per day to actually increase the watering time } - def moistureSum = "" - if(tpwAdjust != 0) { - def newTPW = Math.round(tpw + (tpw * tpwAdjust / 100)) - if (newTPW <= 5) note("warning", "Please check ${settings["sensor${i}"]}, Zone ${i} time per week is very low: ${newTPW} mins/week","w") - if (newTPW >= 150) note("warning", "Please check ${settings["sensor${i}"]}, Zone ${i} time per week is very high: ${newTPW} mins/week","w") - state.tpwMap.putAt(i-1, newTPW) - state.dpwMap.putAt(i-1, initDPW(i)) - moistureSum = "Zone ${i}: ${settings["sensor${i}"]} moisture is: ${latestHum}%, SP is ${spHum}% time adjusted by ${tpwAdjust}% to ${newTPW} mins/week\n" - } else { - moistureSum = "Zone ${i}: ${settings["sensor${i}"]} moisture is: ${latestHum}%, SP is ${spHum}% no time adjustment\n" + int seasonAdjust = 0 + if (isSeason) { + float sa = state.seasonAdj + if ((sa != 100.0) && (sa != 0.0)) { + float sadj = sa - 100.0 + if (sa > 0.0) + seasonAdjust = Math.round(((sadj / 100.0) * tpw) + 0.5) + else + seasonAdjust = Math.round(((sadj / 100.0) * tpw) - 0.5) + } } - //note("moisture", "${moistureSum}","m") - return [1, "${moistureSum}"] + if (isDebug) log.debug "moisture(${i}): diffHum: ${diffHum}, tpwAdjust: ${tpwAdjust} seasonAdjust: ${seasonAdjust}" + + // Now, adjust the tpw. + // With seasonal adjustments enabled, tpw can go up or down independent of the difference in the sensor vs SP + int newTPW = tpw + tpwAdjust + seasonAdjust + + int perDay = 20 + def perD = settings."perDay${i}" + if (perD) perDay = perD.toInteger() + if (perDay == 0) perDay = daysA * cpd // at least 1 minute per cycle per available day + if (newTPW < perDay) newTPW = perDay // make sure we have always have enough for 1 day of minimum water + + int adjusted = 0 + if ((tpwAdjust + seasonAdjust) > 0) { // needs more water + int maxTPW = daysA * 120 // arbitrary maximum of 2 hours per available watering day per week + if (newTPW > maxTPW) newTPW = maxTPW // initDPW() below may spread this across more days + if (newTPW > (maxTPW * 0.75)) note('warning', "${app.label}: Please check ${settings["sensor${i}"]}, ${settings."name${i}"} time per week seems high: ${newTPW} mins/week",'a') + if (state.tpwMap[i-1] != newTPW) { // are we changing the tpw? + state.tpwMap[i-1] = newTPW + dpw = initDPW(i) // need to recalculate days per week since tpw changed - initDPW() stores the value into dpwMap + adjusted = newTPW - tpw // so that the adjustment note is accurate + } + } + else if ((tpwAdjust + seasonAdjust) < 0) { // Needs less water + // Find the minimum tpw + minimum = cpd * daysA // at least 1 minute per cycle per available day + int minLimit = 0 + def minL = settings."minWeek${i}" + if (minL) minLimit = minL.toInteger() // unless otherwise specified in configuration + if (minLimit > 0) { + if (newTPW < minLimit) newTPW = minLimit // use configured minutes per week as the minimum + } else if (newTPW < minimum) { + newTPW = minimum // else at least 1 minute per cycle per available day + note('warning', "${app.label}: Please check ${settings."sensor${i}"}, ${settings."name${i}"} time per week is very low: ${newTPW} mins/week",'a') + } + if (state.tpwMap[i-1] != newTPW) { // are we changing the tpw? + state.tpwMap[i-1] = newTPW // store the new tpw + dpw = initDPW(i) // may need to reclac days per week - initDPW() now stores the value into state.dpwMap - avoid doing that twice + adjusted = newTPW - tpw // so that the adjustment note is accurate + } + } + // else no adjustments, or adjustments cancelled each other out. + + String moistureSum = '' + String adjStr = '' + String plus = '' + if (adjusted > 0) plus = '+' + if (adjusted != 0) adjStr = ", ${plus}${adjusted} min" + if (Math.abs(adjusted) > 1) adjStr = "${adjStr}s" + if (diffHum >= 0.0) { // water only if ground is drier than SP + moistureSum = "> ${settings."name${i}"}, Water: ${settings."sensor${i}"} @ ${latestHum}% (${spHum}%)${adjStr} (${newTPW} min/wk)\n" + return [1, moistureSum] + } + else { // not watering + moistureSum = "> ${settings."name${i}"}, Skip: ${settings."sensor${i}"} @ ${latestHum}% (${spHum}%)${adjStr} (${newTPW} min/wk)\n" + return [0, moistureSum] + } + return [0, moistureSum] } - + +//get moisture SP +int getDrySp(int i){ + if (settings."sensorSp${i}") return settings."sensorSp${i}".toInteger() // configured SP + + + if (settings."plant${i}" == 'New Plants') return 40 // New Plants get special care + + + switch (settings."option${i}") { // else, defaults based off of soil type + case 'Sand': + return 22 + case 'Clay': + return 38 + default: + return 28 + } +} + //notifications to device, pushed if requested -def note(status, message, type){ - log.debug "${status}: ${message}" - switches.notify("${status}", "${message}") - if(notify) - { - if (notify.contains('Daily') && type == "d"){ - sendPush "${message}" - } - if (notify.contains('Weather') && type == "f"){ - sendPush "${message}" - } - if (notify.contains('Warnings') && type == "w"){ - sendPush "${message}" - } - if (notify.contains('Moisture') && type == "m"){ - sendPush "${message}" - } +def note(String statStr, String msg, String msgType) { + + // send to debug first (near-zero cost) + log.debug "${statStr}: ${msg}" + + // notify user second (small cost) + boolean notifyController = true + if(settings.notify || settings.logAll) { + String spruceMsg = "Spruce ${msg}" + switch(msgType) { + case 'd': + if (settings.notify && settings.notify.contains('Daily')) { // always log the daily events to the controller + sendIt(spruceMsg) + } + else if (settings.logAll) { + sendNotificationEvent(spruceMsg) + } + break + case 'c': + if (settings.notify && settings.notify.contains('Delays')) { + sendIt(spruceMsg) + } + else if (settings.logAll) { + sendNotificationEvent(spruceMsg) + } + break + case 'i': + if (settings.notify && settings.notify.contains('Events')) { + sendIt(spruceMsg) + //notifyController = false // no need to notify controller unless we don't notify the user + } + else if (settings.logAll) { + sendNotificationEvent(spruceMsg) + } + break + case 'f': + notifyController = false // no need to notify the controller, ever + if (settings.notify && settings.notify.contains('Weather')) { + sendIt(spruceMsg) + } + else if (settings.logAll) { + sendNotificationEvent(spruceMsg) + } + break + case 'a': + notifyController = false // no need to notify the controller, ever + if (settings.notify && settings.notify.contains('Warnings')) { + sendIt(spruceMsg) + } else + sendNotificationEvent(spruceMsg) // Special case - make sure this goes into the Hello Home log, if not notifying + break + case 'm': + if (settings.notify && settings.notify.contains('Moisture')) { + sendIt(spruceMsg) + //notifyController = false // no need to notify controller unless we don't notify the user + } + else if (settings.logAll) { + sendNotificationEvent(spruceMsg) + } + break + default: + break + } + } + // finally, send to controller DTH, to change the state and to log important stuff in the event log + if (notifyController) { // do we really need to send these to the controller? + // only send status updates to the controller if WE are running, or nobody else is + if (atomicState.run || ((settings.switches.currentSwitch == 'off') && (settings.switches.currentStatus != 'pause'))) { + settings.switches.notify(statStr, msg) + + } + else { // we aren't running, so we don't want to change the status of the controller + // send the event using the current status of the switch, so we don't change it + //log.debug "note - direct sendEvent()" + settings.switches.notify(settings.switches.currentStatus, msg) + + } + } +} + +def sendIt(String msg) { + if (location.contactBookEnabled && settings.recipients) { + sendNotificationToContacts(msg, settings.recipients, [event: true]) + } + else { + sendPush( msg ) } } //days available -def daysAvailable(){ - int dayCount = 0 - if("${settings["days"]}" == "null") dayCount = 7 - else if(days){ - if (days.contains('Even') || days.contains('Odd')) { - dayCount = 4 - if(days.contains('Even') && days.contains('Odd')) dayCount = 7 - } else { - if (days.contains('Monday')) dayCount += 1 - if (days.contains('Tuesday')) dayCount += 1 - if (days.contains('Wednesday')) dayCount += 1 - if (days.contains('Thursday')) dayCount += 1 - if (days.contains('Friday')) dayCount += 1 - if (days.contains('Saturday')) dayCount += 1 - if (days.contains('Sunday')) dayCount += 1 - } - } +int daysAvailable(){ + + // Calculate days available for watering and save in state variable for future use + def daysA = state.daysAvailable + if (daysA && (daysA > 0)) { // state.daysAvailable has already calculated and stored in state.daysAvailable + return daysA + } + + if (!settings.days) { // settings.days = "" --> every day is available + state.daysAvailable = 7 + return 7 // every day is allowed + } + + int dayCount = 0 // settings.days specified, need to calculate state.davsAvailable (once) + if (settings.days.contains('Even') || settings.days.contains('Odd')) { + dayCount = 4 + if(settings.days.contains('Even') && settings.days.contains('Odd')) dayCount = 7 + } + else { + if (settings.days.contains('Monday')) dayCount += 1 + if (settings.days.contains('Tuesday')) dayCount += 1 + if (settings.days.contains('Wednesday')) dayCount += 1 + if (settings.days.contains('Thursday')) dayCount += 1 + if (settings.days.contains('Friday')) dayCount += 1 + if (settings.days.contains('Saturday')) dayCount += 1 + if (settings.days.contains('Sunday')) dayCount += 1 + } + + state.daysAvailable = dayCount return dayCount } -//get moisture SP -def getDrySp(i){ - if ("${settings["sensorSp${i}"]}" != "null") return "${settings["sensorSp${i}"]}" - else if (settings["plant${i}"] == "New Plants") return 40 - else{ - switch (settings["option${i}"]) { - case "Sand": - return 15 - case "Clay": - return 35 - default: - return 20 - } - } -} - //zone: ['Off', 'Spray', 'rotor', 'Drip', 'Master Valve', 'Pump'] -def nozzle(i){ - def getT = settings["zone${i}"] +int nozzle(int i){ + String getT = settings."zone${i}" if (!getT) return 0 + switch(getT) { - case "Spray": + case 'Spray': return 1 - case "Rotor": + case 'Rotor': return 1.4 - case "Drip": + case 'Drip': return 2.4 - case "Master Valve": + case 'Master Valve': return 4 - case "Pump": + case 'Pump': return 4 default: return 0 @@ -1214,23 +1969,24 @@ def nozzle(i){ } //plant: ['Lawn', 'Garden', 'Flowers', 'Shrubs', 'Trees', 'Xeriscape', 'New Plants'] -def plant(i){ - def getP = settings["plant${i}"] +int plant(int i){ + String getP = settings."plant${i}" if(!getP) return 0 + switch(getP) { - case "Lawn": + case 'Lawn': return 60 - case "Garden": + case 'Garden': return 50 - case "Flowers": + case 'Flowers': return 40 - case "Shrubs": + case 'Shrubs': return 30 - case "Trees": + case 'Trees': return 20 - case "Xeriscape": + case 'Xeriscape': return 30 - case "New Plants": + case 'New Plants': return 80 default: return 0 @@ -1238,21 +1994,22 @@ def plant(i){ } //option: ['Slope', 'Sand', 'Clay', 'No Cycle', 'Cycle 2x', 'Cycle 3x'] -def cycles(i){ - def getC = settings["option${i}"] +int cycles(int i){ + String getC = settings."option${i}" if(!getC) return 2 + switch(getC) { - case "Slope": + case 'Slope': return 3 - case "Sand": + case 'Sand': return 1 - case "Clay": + case 'Clay': return 2 - case "No Cycle": + case 'No Cycle': return 1 - case "Cycle 2x": + case 'Cycle 2x': return 2 - case "Cycle 3x": + case 'Cycle 3x': return 3 default: return 2 @@ -1260,188 +2017,374 @@ def cycles(i){ } //check if day is allowed -def isDay() { - if ("${settings["days"]}" == "null") return true +boolean isDay() { + + if (daysAvailable() == 7) return true // every day is allowed - def today = new Date().format("EEEE", location.timeZone) - def daynum = new Date().format("dd", location.timeZone) - int dayint = Integer.parseInt(daynum) - - log.debug "today: ${today} ${dayint}, days: ${days}" - - if (days.contains(today)) return true - if (days.contains("Even") && (dayint % 2 == 0)) return true - if (days.contains("Odd") && (dayint % 2 != 0)) return true + def daynow = new Date() + String today = daynow.format('EEEE', location.timeZone) + if (settings.days.contains(today)) return true + def daynum = daynow.format('dd', location.timeZone) + int dayint = Integer.parseInt(daynum) + if (settings.days.contains('Even') && (dayint % 2 == 0)) return true + if (settings.days.contains('Odd') && (dayint % 2 != 0)) return true return false } //set season adjustment & remove season adjustment def setSeason() { - - def zone = 1 - while(zone <= 16) { - if ( !learn || (settings["sensor${zone}"] == null) ) { - state.tpwMap.putAt(zone-1, 0) - def tpw = initTPW(zone) - //def newTPW = Math.round(tpw * tpwAdjust / 100) - state.tpwMap.putAt(zone-1, tpw) - state.dpwMap.putAt(zone-1, initDPW(zone)) - log.debug "Zone ${zone}: seasonaly adjusted by ${state.weekseasonAdj-100}% to ${tpw}" - } - - zone++ - } + boolean isDebug = false + if (isDebug) log.debug 'setSeason()' + + int zone = 1 + while(zone <= 16) { + if ( !settings.learn || !settings."sensor${zone}" || state.tpwMap[zone-1] == 0) { + + int tpw = initTPW(zone) // now updates state.tpwMap + int dpw = initDPW(zone) // now updates state.dpwMap + if (isDebug) { + if (!settings.learn && (tpw != 0) && (state.weekseasonAdj != 0)) { + log.debug "Zone ${zone}: seasonally adjusted by ${state.weekseasonAdj-100}% to ${tpw}" + } + } + } + zone++ + } } -//check weather -def isWeather(){ - def wzipcode = "${zipString()}" - - // Forecast rain - Map sdata = getWeatherFeature("forecast10day", wzipcode) - - log.debug sdata.response - if(sdata.response.containsKey('error') || sdata == null) { - note("season", "Weather API error, skipping weather check" , "f") - return false +//capture today's total rainfall - scheduled for just before midnight each day +def getRainToday() { + def wzipcode = zipString() + Map wdata = getWeatherFeature('conditions', wzipcode) + if (!wdata) { + + note('warning', "${app.label}: Please check Zipcode/PWS setting, error: null", 'a') + } + else { + if (!wdata.response || wdata.response.containsKey('error')) { + log.debug wdata.response + note('warning', "${app.label}: Please check Zipcode/PWS setting, error:\n${wdata.response.error.type}: ${wdata.response.error.description}" , 'a') + } + else { + float TRain = 0.0 + if (wdata.current_observation.precip_today_in.isNumber()) { // WU can return "t" for "Trace" - we'll assume that means 0.0 + TRain = wdata.current_observation.precip_today_in.toFloat() + if (TRain > 25.0) TRain = 25.0 + else if (TRain < 0.0) TRain = 0.0 // WU sometimes returns -999 for "estimated" locations + log.debug "getRainToday(): ${wdata.current_observation.precip_today_in} / ${TRain}" + } + int day = getWeekDay() // what day is it today? + if (day == 7) day = 0 // adjust: state.Rain order is Su,Mo,Tu,We,Th,Fr,Sa + state.Rain[day] = TRain as Float // store today's total rainfall + } } - def qpf = sdata.forecast.simpleforecast.forecastday.qpf_allday.mm - def qpfTodayIn = 0 - if (qpf.get(0).isNumber()) qpfTodayIn = Math.round(qpf.get(0).toInteger() /25.4 * 100) /100 - log.debug "qpfTodayIn ${qpfTodayIn}" - def qpfTomIn = 0 - if (qpf.get(1).isNumber()) qpfTomIn = Math.round(qpf.get(1).toInteger() /25.4 * 100) /100 - log.debug "qpfTomIn ${qpfTomIn}" - // current conditions - Map cond = getWeatherFeature("conditions", wzipcode) - - def TRain = 0 - if (cond.current_observation.precip_today_metric.isNumber()) TRain = Math.round(cond.current_observation.precip_today_metric.toInteger() /25.4 * 100) /100 - log.debug "TRain ${TRain}" - // reported rain - Map yCond = getWeatherFeature("yesterday", wzipcode) - def YRain = 0 - if (yCond.history.dailysummary.precipi.get(0).isNumber()) YRain = yCond.history.dailysummary.precipi.get(0) - - if(TRain > qpfTodayIn) qpfTodayIn = TRain - log.debug "TRain ${TRain} qpfTodayIn ${qpfTodayIn}" - //state.Rain = [S,M,T,W,T,F,S] - //state.Rain = [0,0.43,3,0,0,0,0] - def day = getWeekDay() - state.Rain.putAt(day - 1, YRain) - def i = 0 - def weeklyRain = 0 - while (i <= 6){ - def factor = 0 - if ((day - i) > 0) factor = day - i - else factor = day + 7 - i - def getrain = state.Rain.get(i) - weeklyRain += Math.round(getrain.toFloat() / factor * 100)/100 - i++ - } - log.debug "weeklyRain ${weeklyRain}" - //note("season", "weeklyRain ${weeklyRain} ${state.Rain}", "d") - +} + +//check weather, set seasonal adjustment factors, skip today if rainy +boolean isWeather(){ + def startMsecs = 0 + def endMsecs = 0 + boolean isDebug = false + if (isDebug) log.debug 'isWeather()' + + if (!settings.isRain && !settings.isSeason) return false // no need to do any of this + + String wzipcode = zipString() + if (isDebug) log.debug "isWeather(): ${wzipcode}" + + // get only the data we need + // Moved geolookup to installSchedule() + String featureString = 'forecast/conditions' + if (settings.isSeason) featureString = "${featureString}/astronomy" + if (isDebug) startMsecs= now() + Map wdata = getWeatherFeature(featureString, wzipcode) + if (isDebug) { + endMsecs = now() + log.debug "isWeather() getWeatherFeature elapsed time: ${endMsecs - startMsecs}ms" + } + if (wdata && wdata.response) { + if (isDebug) log.debug wdata.response + if (wdata.response.containsKey('error')) { + if (wdata.response.error.type != 'invalidfeature') { + note('warning', "${app.label}: Please check Zipcode/PWS setting, error:\n${wdata.response.error.type}: ${wdata.response.error.description}" , 'a') + return false + } + else { + // Will find out which one(s) weren't reported later (probably never happens now that we don't ask for history) + log.debug 'Rate limited...one or more WU features unavailable at this time.' + } + } + } + else { + if (isDebug) log.debug 'wdata is null' + note('warning', "${app.label}: Please check Zipcode/PWS setting, error: null" , 'a') + return false + } + + String city = wzipcode + + + + if (wdata.current_observation) { + if (wdata.current_observation.observation_location.city != '') city = wdata.current_observation.observation_location.city + else if (wdata.current_observation.observation_location.full != '') city = wdata.current_observation.display_location.full + + if (wdata.current_observation.estimated.estimated) city = "${city} (est)" + } + + // OK, we have good data, let's start the analysis + float qpfTodayIn = 0.0 + float qpfTomIn = 0.0 + float popToday = 50.0 + float popTom = 50.0 + float TRain = 0.0 + float YRain = 0.0 + float weeklyRain = 0.0 + + if (settings.isRain) { + if (isDebug) log.debug 'isWeather(): isRain' + + // Get forecasted rain for today and tomorrow + + if (!wdata.forecast) { + log.debug 'isWeather(): Unable to get weather forecast.' + return false + } + if (wdata.forecast.simpleforecast.forecastday[0].qpf_allday.in.isNumber()) qpfTodayIn = wdata.forecast.simpleforecast.forecastday[0].qpf_allday.in.toFloat() + if (wdata.forecast.simpleforecast.forecastday[0].pop.isNumber()) popToday = wdata.forecast.simpleforecast.forecastday[0].pop.toFloat() + if (wdata.forecast.simpleforecast.forecastday[1].qpf_allday.in.isNumber()) qpfTomIn = wdata.forecast.simpleforecast.forecastday[1].qpf_allday.in.toFloat() + if (wdata.forecast.simpleforecast.forecastday[1].pop.isNumber()) popTom = wdata.forecast.simpleforecast.forecastday[1].pop.toFloat() + if (qpfTodayIn > 25.0) qpfTodayIn = 25.0 + else if (qpfTodayIn < 0.0) qpfTodayIn = 0.0 + if (qpfTomIn > 25.0) qpfTomIn = 25.0 + else if (qpfTomIn < 0.0) qpfTomIn = 0.0 + + // Get rainfall so far today + + if (!wdata.current_observation) { + log.debug 'isWeather(): Unable to get current weather conditions.' + return false + } + if (wdata.current_observation.precip_today_in.isNumber()) { + TRain = wdata.current_observation.precip_today_in.toFloat() + if (TRain > 25.0) TRain = 25.0 // Ignore runaway weather + else if (TRain < 0.0) TRain = 0.0 // WU can return -999 for estimated locations + } + if (TRain > (qpfTodayIn * (popToday / 100.0))) { // Not really what PoP means, but use as an adjustment factor of sorts + qpfTodayIn = TRain // already have more rain than was forecast for today, so use that instead + popToday = 100 // we KNOW this rain happened + } + + // Get yesterday's rainfall + int day = getWeekDay() + YRain = state.Rain[day - 1] + + if (isDebug) log.debug "TRain ${TRain} qpfTodayIn ${qpfTodayIn} @ ${popToday}%, YRain ${YRain}" + + int i = 0 + while (i <= 6){ // calculate (un)weighted average (only heavy rainstorms matter) + int factor = 0 + if ((day - i) > 0) factor = day - i else factor = day + 7 - i + float getrain = state.Rain[i] + if (factor != 0) weeklyRain += (getrain / factor) + i++ + } + + if (isDebug) log.debug "isWeather(): weeklyRain ${weeklyRain}" + } + + if (isDebug) log.debug 'isWeather(): build report' + //get highs - def getHigh = sdata.forecast.simpleforecast.forecastday.high.fahrenheit - def avgHigh = Math.round((getHigh.get(0).toInteger() + getHigh.get(1).toInteger() + getHigh.get(2).toInteger() + getHigh.get(3).toInteger() + getHigh.get(4).toInteger())/5) + int highToday = 0 + int highTom = 0 + if (wdata.forecast.simpleforecast.forecastday[0].high.fahrenheit.isNumber()) highToday = wdata.forecast.simpleforecast.forecastday[0].high.fahrenheit.toInteger() + if (wdata.forecast.simpleforecast.forecastday[1].high.fahrenheit.isNumber()) highTom = wdata.forecast.simpleforecast.forecastday[1].high.fahrenheit.toInteger() + + String weatherString = "${app.label}: ${city} weather:\n TDA: ${highToday}F" + if (settings.isRain) weatherString = "${weatherString}, ${qpfTodayIn}in rain (${Math.round(popToday)}% PoP)" + weatherString = "${weatherString}\n TMW: ${highTom}F" + if (settings.isRain) weatherString = "${weatherString}, ${qpfTomIn}in rain (${Math.round(popTom)}% PoP)\n YDA: ${YRain}in rain" - Map citydata = getWeatherFeature("geolookup", wzipcode) - def weatherString = "${citydata.location.city} weather\n Today: ${getHigh.get(0)}F, ${qpfTodayIn}in rain\n Tomorrow: ${getHigh.get(1)}F, ${qpfTomIn}in rain\n Yesterday: ${YRain}in rain " - - if (isSeason) - { - //daily adjust - state.seasonAdj = Math.round(getHigh.get(0).toInteger()/avgHigh *100) - weatherString += "\n Adjusted ${state.seasonAdj - 100}% for Today" + if (settings.isSeason) + { + if (!settings.isRain) { // we need to verify we have good data first if we didn't do it above + + if (!wdata.forecast) { + log.debug 'Unable to get weather forecast' + return false + } + } + + // is the temp going up or down for the next few days? + float heatAdjust = 100.0 + float avgHigh = highToday.toFloat() + if (highToday != 0) { + // is the temp going up or down for the next few days? + int totalHigh = highToday + int j = 1 + int highs = 1 + while (j < 4) { // get forecasted high for next 3 days + if (wdata.forecast.simpleforecast.forecastday[j].high.fahrenheit.isNumber()) { + totalHigh += wdata.forecast.simpleforecast.forecastday[j].high.fahrenheit.toInteger() + highs++ + } + j++ + } + if ( highs > 0 ) avgHigh = (totalHigh / highs) + heatAdjust = avgHigh / highToday + } + if (isDebug) log.debug "highToday ${highToday}, avgHigh ${avgHigh}, heatAdjust ${heatAdjust}" + + //get humidity + int humToday = 0 + if (wdata.forecast.simpleforecast.forecastday[0].avehumidity.isNumber()) + humToday = wdata.forecast.simpleforecast.forecastday[0].avehumidity.toInteger() + + float humAdjust = 100.0 + float avgHum = humToday.toFloat() + if (humToday != 0) { + int j = 1 + int highs = 1 + int totalHum = humToday + while (j < 4) { // get forcasted humitidty for today and the next 3 days + if (wdata.forecast.simpleforecast.forecastday[j].avehumidity.isNumber()) { + totalHum += wdata.forecast.simpleforecast.forecastday[j].avehumidity.toInteger() + highs++ + } + j++ + } + if (highs > 1) avgHum = totalHum / highs + humAdjust = 1.5 - ((0.5 * avgHum) / humToday) // basically, half of the delta % between today and today+3 days + } + if (isDebug) log.debug "humToday ${humToday}, avgHum ${avgHum}, humAdjust ${humAdjust}" + + //daily adjustment - average of heat and humidity factors + //hotter over next 3 days, more water + //cooler over next 3 days, less water + //drier over next 3 days, more water + //wetter over next 3 days, less water + // + //Note: these should never get to be very large, and work best if allowed to cumulate over time (watering amount will change marginally + // as days get warmer/cooler and drier/wetter) + def sa = ((heatAdjust + humAdjust) / 2) * 100.0 + state.seasonAdj = sa + sa = sa - 100.0 + String plus = '' + if (sa > 0) plus = '+' + weatherString = "${weatherString}\n Adjusting ${plus}${Math.round(sa)}% for weather forecast" // Apply seasonal adjustment on Monday each week or at install - if(getWeekDay() == 1 || state.weekseasonAdj == 0) { - - //get humidity - def gethum = sdata.forecast.simpleforecast.forecastday.avehumidity - def humWeek = Math.round((gethum.get(0).toInteger() + gethum.get(1).toInteger() + gethum.get(2).toInteger() + gethum.get(3).toInteger() + gethum.get(4).toInteger())/5) - + if ((getWeekDay() == 1) || (state.weekseasonAdj == 0)) { //get daylight - Map astro = getWeatherFeature("astronomy", wzipcode) - def getsunRH = astro.moon_phase.sunrise.hour - def getsunRM = astro.moon_phase.sunrise.minute - def getsunSH = astro.moon_phase.sunset.hour - def getsunSM = astro.moon_phase.sunset.minute - def daylight = ((getsunSH.toInteger() * 60) + getsunSM.toInteger())-((getsunRH.toInteger() * 60) + getsunRM.toInteger()) - //set seasonal adjustment - state.weekseasonAdj = Math.round((daylight/700 * avgHigh/75) * ((1-(humWeek/100)) * avgHigh/75)*100) + if (wdata.sun_phase) { + int getsunRH = 0 + int getsunRM = 0 + int getsunSH = 0 + int getsunSM = 0 + + if (wdata.sun_phase.sunrise.hour.isNumber()) getsunRH = wdata.sun_phase.sunrise.hour.toInteger() + if (wdata.sun_phase.sunrise.minute.isNumber()) getsunRM = wdata.sun_phase.sunrise.minute.toInteger() + if (wdata.sun_phase.sunset.hour.isNumber()) getsunSH = wdata.sun_phase.sunset.hour.toInteger() + if (wdata.sun_phase.sunset.minute.isNumber()) getsunSM = wdata.sun_phase.sunset.minute.toInteger() - //apply seasonal time adjustment - weatherString += "\n Applying seasonal adjustment of ${state.weekseasonAdj-100}% this week" - //note("season", "Applying seasonal adjustment of ${state.weekseasonAdj-100}% this week", "f") - setSeason() + int daylight = ((getsunSH * 60) + getsunSM)-((getsunRH * 60) + getsunRM) + if (daylight >= 850) daylight = 850 + + //set seasonal adjustment + //seasonal q (fudge) factor + float qFact = 75.0 + + // (Daylight / 11.66 hours) * ( Average of ((Avg Temp / 70F) + ((1/2 of Average Humidity) / 65.46))) * calibration quotient + // Longer days = more water (day length constant = approx USA day length at fall equinox) + // Higher temps = more water + // Lower humidity = more water (humidity constant = USA National Average humidity in July) + float wa = ((daylight / 700.0) * (((avgHigh / 70.0) + (1.5-((avgHum * 0.5) / 65.46))) / 2.0) * qFact) + state.weekseasonAdj = wa + + //apply seasonal time adjustment + plus = '' + if (wa != 0) { + if (wa > 100.0) plus = '+' + String waStr = String.format('%.2f', (wa - 100.0)) + weatherString = "${weatherString}\n Seasonal adjustment of ${waStr}% for the week" + } + setSeason() + } + else { + log.debug 'isWeather(): Unable to get sunrise/set info for today.' + } } } + note('season', weatherString , 'f') + + // if only doing seasonal adjustments, we are done + if (!settings.isRain) return false - note("season", weatherString , "f") - - def setrainDelay = "0.2" - if (rainDelay) setrainDelay = rainDelay - if (switches.latestValue("rainsensor") == "rainsensoron"){ - note("raintoday", "is skipping watering, rain sensor is on.", "d") - return true - } - else if (qpfTodayIn > setrainDelay.toFloat()){ - note("raintoday", "is skipping watering, ${qpfTodayIn}in rain today.", "d") - return true - } - else if (qpfTomIn > setrainDelay.toFloat()){ - note("raintom", "is skipping watering, ${qpfTomIn}in rain expected tomorrow.", "d") - return true - } - else if (weeklyRain > setrainDelay.toFloat()){ - note("rainy", "is skipping watering, ${weeklyRain}in average rain over the past week.", "d") - return true - } - return false - -} - -def doorOpen(evt){ - note("pause", "$contact opened $switches paused watering", "w") - switches.off() -} - -def doorClosed(evt){ - note("active", "$contact closed $switches will resume watering in $contactDelay minutes", "w") - runIn(contactDelay * 60, resume) + float setrainDelay = 0.2 + if (settings.rainDelay) setrainDelay = settings.rainDelay.toFloat() + + // if we have no sensors, rain causes us to skip watering for the day + if (!anySensors()) { + if (settings.switches.latestValue('rainsensor') == 'rainsensoron'){ + note('raintoday', "${app.label}: skipping, rain sensor is on", 'd') + return true + } + float popRain = qpfTodayIn * (popToday / 100.0) + if (popRain > setrainDelay){ + String rainStr = String.format('%.2f', popRain) + note('raintoday', "${app.label}: skipping, ${rainStr}in of rain is probable today", 'd') + return true + } + popRain += qpfTomIn * (popTom / 100.0) + if (popRain > setrainDelay){ + String rainStr = String.format('%.2f', popRain) + note('raintom', "${app.label}: skipping, ${rainStr}in of rain is probable today + tomorrow", 'd') + return true + } + if (weeklyRain > setrainDelay){ + String rainStr = String.format('%.2f', weeklyRain) + note('rainy', "${app.label}: skipping, ${rainStr}in weighted average rain over the past week", 'd') + return true + } + } + else { // we have at least one sensor in the schedule + // Ignore rain sensor & historical rain - only skip if more than setrainDelay is expected before midnight tomorrow + float popRain = (qpfTodayIn * (popToday / 100.0)) - TRain // ignore rain that has already fallen so far today - sensors should already reflect that + if (popRain > setrainDelay){ + String rainStr = String.format('%.2f', popRain) + note('raintoday', "${app.label}: skipping, at least ${rainStr}in of rain is probable later today", 'd') + return true + } + popRain += qpfTomIn * (popTom / 100.0) + if (popRain > setrainDelay){ + String rainStr = String.format('%.2f', popRain) + note('raintom', "${app.label}: skipping, at least ${rainStr}in of rain is probable later today + tomorrow", 'd') + return true + } + } + if (isDebug) log.debug "isWeather() ends" + return false } -def resume(){ - switches.on() - state.fail = 10 +// true if ANY of this schedule's zones are on and using sensors +private boolean anySensors() { + int zone=1 + while (zone <= 16) { + def zoneStr = settings."zone${zone}" + if (zoneStr && (zoneStr != 'Off') && settings."sensor${zone}") return true + zone++ + } + return false } -def syncOn(evt){ - note("active", "$sync complete, starting scheduled program", "w") - cycleOn() -} - -def getDPWDays(dpw) -{ - if(dpw == 1) - return state.DPWDays1 - if(dpw == 2) - return state.DPWDays2 - if(dpw == 3) - return state.DPWDays3 - if(dpw == 4) - return state.DPWDays4 - if(dpw == 5) - return state.DPWDays5 - if(dpw == 6) - return state.DPWDays6 - if(dpw == 7) - return state.DPWDays7 - return [0,0,0,0,0,0,0] +def getDPWDays(int dpw){ + if (dpw && (dpw.isNumber()) && (dpw >= 1) && (dpw <= 7)) { + return state."DPWDays${dpw}" + } else + return [0,0,0,0,0,0,0] } // Create a map of what days each possible DPW value will run on @@ -1458,152 +2401,159 @@ def createDPWMap() { state.DPWDays5 = [] state.DPWDays6 = [] state.DPWDays7 = [] - def NDAYS = 7 + //def NDAYS = 7 // day Distance[NDAYS][NDAYS], easier to just define than calculate everytime def int[][] dayDistance = [[0,1,2,3,3,2,1],[1,0,1,2,3,3,2],[2,1,0,1,2,3,3],[3,2,1,0,1,2,3],[3,3,2,1,0,1,2],[2,3,3,2,1,0,1],[1,2,3,3,2,1,0]] def ndaysAvailable = daysAvailable() - def i = 0 - def int[] daysAvailable = [0,1,2,3,4,5,6] - if(days) - { - if (days.contains('Even') || days.contains('Odd')) { - return - } - if (days.contains('Monday')) { - daysAvailable[i] = 0 - i++ - } - if (days.contains('Tuesday')) { - daysAvailable[i] = 1 - i++ - } - if (days.contains('Wednesday')) { - daysAvailable[i] = 2 - i++ - } - if (days.contains('Thursday')) { - daysAvailable[i] = 3 - i++ - } - if (days.contains('Friday')) { - daysAvailable[i] = 4 - i++ - } - if (days.contains('Saturday')) { - daysAvailable[i] = 5 - i++ - } - if (days.contains('Sunday')) { - daysAvailable[i] = 6 - i++ - } - - if(i != ndaysAvailable) { - log.debug "ERROR: days and daysAvailable do not match." - log.debug "${i} ${ndaysAvailable}" - } + int i = 0 + + // def int[] daysAvailable = [0,1,2,3,4,5,6] + def int[] daysAvailable = [0,0,0,0,0,0,0] + + if(settings.days) { + if (settings.days.contains('Even') || settings.days.contains('Odd')) { + return + } + if (settings.days.contains('Monday')) { + daysAvailable[i] = 0 + i++ + } + if (settings.days.contains('Tuesday')) { + daysAvailable[i] = 1 + i++ + } + if (settings.days.contains('Wednesday')) { + daysAvailable[i] = 2 + i++ + } + if (settings.days.contains('Thursday')) { + daysAvailable[i] = 3 + i++ + } + if (settings.days.contains('Friday')) { + daysAvailable[i] = 4 + i++ + } + if (settings.days.contains('Saturday')) { + daysAvailable[i] = 5 + i++ + } + if (settings.days.contains('Sunday')) { + daysAvailable[i] = 6 + i++ + } + if(i != ndaysAvailable) { + log.debug 'ERROR: days and daysAvailable do not match in setup - overriding' + log.debug "${i} ${ndaysAvailable}" + ndaysAvailable = i // override incorrect setup execution + state.daysAvailable = i + } + } + else { // all days are available if settings.days == "" + daysAvailable = [0,1,2,3,4,5,6] } //log.debug "Ndays: ${ndaysAvailable} Available Days: ${daysAvailable}" def maxday = -1 def max = -1 - def days = new int[7] + def dDays = new int[7] def int[][] runDays = [[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]] + for(def a=0; a < ndaysAvailable; a++) { - - // Figure out next day using the dayDistance map, getting the farthest away day (max value) - if(a > 0 && ndaysAvailable >= 2 && a != ndaysAvailable-1) { - if(a == 1) { - for(def c=1; c < ndaysAvailable; c++) { - def d = dayDistance[daysAvailable[0]][daysAvailable[c]] - if(d > max) { - max = d - maxday = daysAvailable[c] - } - } - //log.debug "max: ${max} maxday: ${maxday}" - days[0] = maxday - } + // Figure out next day using the dayDistance map, getting the farthest away day (max value) + if(a > 0 && ndaysAvailable >= 2 && a != ndaysAvailable-1) { + if(a == 1) { + for(def c=1; c < ndaysAvailable; c++) { + def d = dayDistance[daysAvailable[0]][daysAvailable[c]] + if(d > max) { + max = d + maxday = daysAvailable[c] + } + } + //log.debug "max: ${max} maxday: ${maxday}" + dDays[0] = maxday + } - // Find successive maxes for the following days - if(a > 1) { - def lmax = max - def lmaxday = maxday - max = -1 - for(def c = 1; c < ndaysAvailable; c++) { - def d = dayDistance[daysAvailable[0]][daysAvailable[c]] - def t = d > max - if(a % 2 == 0) - t = d >= max - if(d < lmax && d >= max) { - if(d == max) { - d = dayDistance[lmaxday][daysAvailable[c]] - if(d > dayDistance[lmaxday][maxday]) { - max = d - maxday = daysAvailable[c] - } - } else { - max = d - maxday = daysAvailable[c] - } - } - } - lmax = 5 - while(max == -1) { - lmax = lmax -1 - for(def c = 1; c < ndaysAvailable; c++) { - def d = dayDistance[daysAvailable[0]][daysAvailable[c]] - if(d < lmax && d >= max) { - if(d == max) { - d = dayDistance[lmaxday][daysAvailable[c]] - if(d > dayDistance[lmaxday][maxday]) { - max = d - maxday = daysAvailable[c] - } - } else { - max = d - maxday = daysAvailable[c] - } - } - } - for(def d=0; d< a-2; d++) - if(maxday == days[d]) - max = -1 - } - //log.debug"max: ${max} maxday: ${maxday}" - days[a-1] = maxday - } - } + // Find successive maxes for the following days + if(a > 1) { + def lmax = max + def lmaxday = maxday + max = -1 + for(int c = 1; c < ndaysAvailable; c++) { + def d = dayDistance[daysAvailable[0]][daysAvailable[c]] + def t = d > max + if (a % 2 == 0) t = d >= max + if(d < lmax && d >= max) { + if(d == max) { + d = dayDistance[lmaxday][daysAvailable[c]] + if(d > dayDistance[lmaxday][maxday]) { + max = d + maxday = daysAvailable[c] + } + } + else { + max = d + maxday = daysAvailable[c] + } + } + } + lmax = 5 + while(max == -1) { + lmax = lmax -1 + for(int c = 1; c < ndaysAvailable; c++) { + def d = dayDistance[daysAvailable[0]][daysAvailable[c]] + if(d < lmax && d >= max) { + if(d == max) { + d = dayDistance[lmaxday][daysAvailable[c]] + if(d > dayDistance[lmaxday][maxday]) { + max = d + maxday = daysAvailable[c] + } + } + else { + max = d + maxday = daysAvailable[c] + } + } + } + for (def d=0; d< a-2; d++) { + if(maxday == dDays[d]) max = -1 + } + } + //log.debug "max: ${max} maxday: ${maxday}" + dDays[a-1] = maxday + } + } - // Set the runDays map using the calculated maxdays - for(def b=0; b < 7; b++) - { - // Runs every day available - if(a == ndaysAvailable-1) { - runDays[a][b] = 0 - for(def c=0; c < ndaysAvailable; c++) - if(b == daysAvailable[c]) - runDays[a][b] = 1 - - } else - // runs weekly, use first available day - if(a == 0) - if(b == daysAvailable[0]) - runDays[a][b] = 1 - else - runDays[a][b] = 0 - else { - // Otherwise, start with first available day - if(b == daysAvailable[0]) - runDays[a][b] = 1 - else { - runDays[a][b] = 0 - for(def c=0; c < a; c++) - if(b == days[c]) - runDays[a][b] = 1 - } - } - } - + // Set the runDays map using the calculated maxdays + for(int b=0; b < 7; b++) { + // Runs every day available + if(a == ndaysAvailable-1) { + runDays[a][b] = 0 + for (def c=0; c < ndaysAvailable; c++) { + if(b == daysAvailable[c]) runDays[a][b] = 1 + } + } + else { + // runs weekly, use first available day + if(a == 0) { + if(b == daysAvailable[0]) + runDays[a][b] = 1 + else + runDays[a][b] = 0 + } + else { + // Otherwise, start with first available day + if(b == daysAvailable[0]) + runDays[a][b] = 1 + else { + runDays[a][b] = 0 + for(def c=0; c < a; c++) + if(b == dDays[c]) + runDays[a][b] = 1 + } + } + } + } } //log.debug "DPW: ${runDays}" @@ -1615,3 +2565,70 @@ def createDPWMap() { state.DPWDays6 = runDays[5] state.DPWDays7 = runDays[6] } + +//transition page to populate app state - this is a fix for WP param +def zoneSetPage1(){ + state.app = 1 + zoneSetPage() + } +def zoneSetPage2(){ + state.app = 2 + zoneSetPage() + } +def zoneSetPage3(){ + state.app = 3 + zoneSetPage() + } +def zoneSetPage4(){ + state.app = 4 + zoneSetPage() + } +def zoneSetPage5(){ + state.app = 5 + zoneSetPage() + } +def zoneSetPage6(){ + state.app = 6 + zoneSetPage() + } +def zoneSetPage7(){ + state.app = 7 + zoneSetPage() + } +def zoneSetPage8(){ + state.app = 8 + zoneSetPage() + } +def zoneSetPage9(i){ + state.app = 9 + zoneSetPage() + } +def zoneSetPage10(){ + state.app = 10 + zoneSetPage() + } +def zoneSetPage11(){ + state.app = 11 + zoneSetPage() + } +def zoneSetPage12(){ + state.app = 12 + zoneSetPage() + } +def zoneSetPage13(){ + state.app = 13 + zoneSetPage() + } +def zoneSetPage14(){ + state.app = 14 + zoneSetPage() + } +def zoneSetPage15(){ + state.app = 15 + zoneSetPage() + } +def zoneSetPage16(){ + state.app = 16 + zoneSetPage() + } +