Compare commits

..

93 Commits

Author SHA1 Message Date
Vinay Rao
e373b6f92e Merge pull request #1272 from SmartThingsCommunity/staging
Rolling up staging to production for deployment
2016-09-20 11:53:36 -07:00
Vinay Rao
43a1ae6371 Merge pull request #1271 from SmartThingsCommunity/production
Rolling down production hotfix to staging
2016-09-20 11:52:40 -07:00
Vinay Rao
a441b94a33 Merge pull request #1264 from posborne/bugfix/fix-hue-connect-http-headers
PROB-1373: hue: fix HTTP request headers
2016-09-20 08:43:01 -07:00
Vinay Rao
2a58d7ff62 Merge pull request #1266 from jimmyjames/revert-async-ecobee
Revert "[DVCSMP-1979] Use async http for polling and refresh tokens."
2016-09-19 15:22:20 -07:00
Juan Pablo Risso
260917d515 MKTP-829 - Moving disclaimer to first page (#1261) 2016-09-19 14:01:33 -04:00
Paul Osborne
c1478d3e96 hue: fix HTTP request headers
Previously, the whitespace characters from the file were used for
newlines in HTTP headers.  In order for the HTTP headers sent to
the hue to be valid, line separators must always be \r\n.  Oddly, the
hue seemed to accept and respond to requests with the invalid header
that was being sent but it would cause increased latency for all
other API clients.

In addition to the missing carriage returns, the GET request was also
missing the required blank line which marks the end of the request
headers.

https://smartthings.atlassian.net/browse/PROB-1366
http://status.smartthings.com/incidents/13j8g8g2w7ly
https://community.smartthings.com/t/new-hue-delay/57569
2016-09-19 11:01:52 -05:00
Jim Anderson
8b9bff15dc Revert "[DVCSMP-1979] Use async http for polling and refresh tokens."
This reverts commit 826993cc45.
2016-09-19 09:38:33 -05:00
Lars Finander
75c1ede16c Merge pull request #1260 from larsfinander/SSVD-2737_philips_hue_color_handling_staging
SSVD-2736 Philips Hue: Color Coordinator does not work
2016-09-16 11:33:14 -06:00
Lars Finander
a7acc384a2 SSVD-2736 Philips Hue: Color Coordinator does not work
-SSVD-2631 Double color events
-SSVD-2601 Color picker control does not show the current color
-Changed color model for Philips Hue to use hue/sat instead of x/y
-Added color events in hex
-Added HSV color conversion algorithms
2016-09-16 11:16:31 -06:00
Vinay Rao
c6998e5f1d Merge pull request #1249 from jackchi/healthcheck-12min-checkin
[CHF-363] Set HealthCheck interval to 12 min
2016-09-14 14:37:02 -07:00
jackchi
f95e906d6e [CHF-363] Set HealthCheck interval to 12 min 2016-09-14 13:46:54 -07:00
Jack Chi
4891e3b947 Merge pull request #1245 from jackchi/healthcheck-5min-reporting
[CHF-353] Cree Bulb polling fix; reads status every 5 minutes
2016-09-13 17:03:19 -07:00
jackchi
ae91f9bff5 [CHF-353] Cree Bulb polling fix; reads status every 5 minutes 2016-09-13 17:01:19 -07:00
Vinay Rao
bb87ad2cf0 Merge pull request #1196 from juano2310/disclaimer
MKTP-829 - Adding disclaimer
2016-09-13 15:13:43 -07:00
Vinay Rao
5dff03fb69 Merge pull request #1244 from SmartThingsCommunity/master
Rolling up master to staging for next week's deploy
2016-09-13 13:46:05 -07:00
Vinay Rao
629d768575 Merge pull request #1243 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-09-13 13:44:38 -07:00
Vinay Rao
dd7c6b90d5 Merge pull request #1241 from SmartThingsCommunity/staging
Rolling up staging to prod for deploy
2016-09-13 12:28:13 -07:00
Andrew Bresee
4523498dab Add parens to unsubscribe method (#1231) 2016-09-13 13:23:55 -04:00
Jason Terhune
e89e45e000 Another circle fix: dependencies task needs artifactory creds too. 2016-09-13 08:47:22 -05:00
Jason Terhune
78ec280e83 Fix circle build. 2016-09-13 08:37:20 -05:00
Jason Terhune-Wold
1f144d36e4 Merge pull request #1221 from jterhune/gradle-compile
Configure gradle to compile devicetypes and smartapps.
2016-09-13 08:30:57 -05:00
Vinay Rao
f5bd580c9e Merge pull request #1240 from juano2310/staging
SSVD-2733 -  Typo fix
2016-09-12 18:00:11 -07:00
juano2310
d5329dbde3 SSVD-2733 - Typo fix 2016-09-12 20:58:36 -04:00
Vinay Rao
48818cfb06 Merge pull request #1239 from larsfinander/CHF-348_philips_hue_staging
CHF-348 Philips Hue: Change offline time to 16 min
2016-09-12 16:23:41 -07:00
Lars Finander
079919260b CHF-348 Philips Hue: Change offline time to 16 min 2016-09-12 17:19:14 -06:00
Vinay Rao
570922e2ac Merge pull request #1238 from jackchi/healthcheck-5min-reporting
[CHF-348] Set 10 VD required devices to report in at 5 minutes
2016-09-12 15:52:29 -07:00
Lars Finander
53ed9b4d2b Merge pull request #1237 from larsfinander/add_hue_offline_events_staging
Add offline events to Philips Hue
2016-09-12 16:49:57 -06:00
jackchi
7149a81c85 [CHF-348] Set 10 VD required devices to report in at 5 minutes 2016-09-12 14:51:57 -07:00
Vinay Rao
30274f0cd7 Merge pull request #914 from jazzslider/motion-labels
Newer Fibaro motion sensor handler needs motion state labels
2016-09-12 13:26:28 -07:00
Jack Chi
8869cd3af0 Merge pull request #1232 from jackchi/healthcheck-all
[CHF-201] Removing DTH workaround now that all events go to Kafka
2016-09-12 10:46:12 -07:00
Jack Chi
fb0caa6446 Merge pull request #1233 from jackchi/healthcheck-removehack
[CHF-201] Removing DTH workaround now that all events go to Kafka
2016-09-12 08:24:10 -07:00
Lars Finander
3d05d42cb8 Add offline events to Philips Hue
-Handles case when bridge goes offline
-Handles case when indiviudual lights go offline
2016-09-11 22:56:24 -06:00
Vinay Rao
3184615e87 Merge pull request #1235 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-09-09 16:50:50 -07:00
Vinay Rao
0f70362e0a Merge pull request #1234 from larsfinander/DVCSMP-2024_OSRAM_Hue_incorrect_staging
DVCSMP-2024 OSRAM: Hue is incorrectly set to be 0-360
2016-09-09 16:49:31 -07:00
Lars Finander
bc817f8530 DVCSMP-2024 OSRAM: Hue is incorrectly set to be 0-360
-Hue changed to handle 0-100 according to SmartThings API
2016-09-09 17:41:46 -06:00
jackchi
01b8399893 [CHF-201] Removing DTH workaround now that all events go to Kafka 2016-09-09 14:58:03 -07:00
jackchi
81318bafac [CHF-201] Removing DTH workaround now that all events go to Kafka 2016-09-09 14:48:19 -07:00
Lars Finander
60c2006bfc Merge pull request #1230 from larsfinander/SSVD-2798_Philips_Hue_discovery_issue
SSVD-2798 Philips Hue: Light discovery UI issue
2016-09-09 11:01:40 -06:00
Lars Finander
1e4f1223e7 SSVD-2798 Philips Hue: Light discovery UI issue
-Keep checked lights in "lights to add list" when page refreshes
2016-09-09 10:50:23 -06:00
Jason Terhune
b78bce55b2 Configure gradle to compile devicetypes and smartapps. 2016-09-09 09:41:11 -05:00
Vinay Rao
01593c3973 Merge pull request #1229 from SmartThingsCommunity/staging
Rolling down hotfix to master
2016-09-08 19:34:52 -07:00
Vinay Rao
6862785d6c Merge pull request #1228 from SmartThingsCommunity/production
Rolling down hotfix to staging
2016-09-08 19:33:26 -07:00
Amol Mundayoor
763d7411e2 Merge pull request #1227 from munds/netatmo
Removing debug logs for netatmo
2016-09-08 11:22:42 -07:00
Amol Mundayoor
c703543f36 Commenting out log.debug instead of removing them 2016-09-08 11:20:27 -07:00
dsainteclaire
5db6ecda3e Merge pull request #1226 from dsainteclaire/DVCSMP-1959-remove-logging-of-phone-numbers
DVCSMP-1959 removed logging of device and phone information due to security concerns
2016-09-08 11:10:22 -07:00
Amol Mundayoor
43b836f413 Removing debug logs for netatmo 2016-09-08 11:07:31 -07:00
David Sainte-Claire
006b5e7bea removed logging of device and phone information due to security concerns 2016-09-08 10:54:04 -07:00
Rohan Desai
62c8c19805 Merge pull request #1225 from rohandesai/dynamic-execution-fix
DVCSMP-1959: fixes for dynamic execution (Curb-control)
2016-09-08 10:47:55 -07:00
Rohan Desai
48e9a4bd6a removed semi colons 2016-09-08 10:46:40 -07:00
dsainteclaire
07a4c0decc Merge pull request #1223 from dsainteclaire/DVCSMP-1959-remove-sensitive-information-withings
DVCSMP-1959 removed logging of sensitive access tokens from smartapp
2016-09-08 10:41:56 -07:00
Andrew Bresee
6aa09bb052 Change log statement to not log personal phone number (#1224) 2016-09-08 13:40:35 -04:00
Rohan Desai
2f889de11a fixes for dynamic execution 2016-09-08 10:36:28 -07:00
David Sainte-Claire
5584020e96 removed logging of sensitive access tokens from smartapp 2016-09-08 10:31:24 -07:00
Jim Anderson
4ef2e694c2 Merge pull request #1180 from jimmyjames/ecobee-async-http-polling
[DVCSMP-1979] Use async http for polling and refresh tokens.
2016-09-08 12:13:53 -05:00
Jim Anderson
826993cc45 [DVCSMP-1979] Use async http for polling and refresh tokens. 2016-09-08 12:11:21 -05:00
Luke Bredeson
ae3306928b Merge pull request #1220 from lbredeso/fix-smart-security
DVCSMP-2020: smart-security app contains invalid code
2016-09-08 10:14:01 -05:00
Luke Bredeson
8777ec5f6d DVCSMP-2020: smart-security app contains invalid code 2016-09-08 10:06:38 -05:00
Andrew Bresee
91eb59a10d DVCSMP-1959: Replace log logging personal phone number (#1217)
* Replace log logging personal phone number

* Removed commented out log
2016-09-08 07:45:30 -04:00
Andrew Bresee
324ac13afb DVCSMP-1959: Unsubscribe from a pointless method (#1215)
* Unsubscribe from a pointless method

* Remove subscription to pointless method
2016-09-07 18:07:01 -04:00
Andrew Bresee
878eb66b8b Remove log logging personal information about a device (#1214) 2016-09-07 16:30:35 -04:00
Rohan Desai
8dfc270c2d Merge pull request #1213 from rohandesai/log-security-fixes
DVCSMP-1959 security fixes for SAs
2016-09-07 12:58:25 -07:00
Rohan Desai
614573a15c security fixes for SAs 2016-09-07 11:28:08 -07:00
dsainteclaire
9c7b0875ba Merge pull request #1211 from dsainteclaire/DVCSMP-1959-remove-sensitive-information-bon-voyage
DVCSMP-1959 removed log messages from smartapp that may print sensitive information
2016-09-07 11:24:22 -07:00
Andrew Bresee
7568cbf781 DVCSMP-1959: Security review - removing potentially confidential log statements (#1210)
* Commented out log statement logging users access token

* Commented out log.info logging potentially confidential device information

* Remove log logging potentially confidential information on the app
2016-09-07 14:11:20 -04:00
Vinay Rao
1858c280a5 Merge pull request #1212 from workingmonk/bug/negative_battery_1
SSVD-2771 fix to avoid negative values
2016-09-07 11:09:02 -07:00
Vinay Rao
6b7d0968f6 chaning min battery percentage to 1 2016-09-07 11:07:30 -07:00
David Sainte-Claire
159d3acf4f removed log messages from smartapp that may print sensitive information 2016-09-07 10:56:25 -07:00
Vinay Rao
e8101630a3 Merge pull request #1209 from workingmonk/bug/negative_battery
SSVD-2771 fix to avoid negative values
2016-09-07 10:49:40 -07:00
Vinay Rao
f5ba78b221 fix to avoid negative values 2016-09-07 10:46:12 -07:00
tslagle13
19b8a7eeb9 Merge pull request #1167 from CosmicPuppy/CosmicPuppy-Netatmo-CapabilitySensor
MSA-1468 - To Netatmo DTHs, added Capability "Sensor"
2016-09-07 10:15:42 -07:00
twack
1b37d649a5 Merge pull request #1207 from twack/20160907_update_its_too_hot
(DVCSMP-1959) 20160907_update_its_to_hot_for_security
2016-09-07 09:22:09 -07:00
twack
dedb0f8465 Update its-too-hot.groovy 2016-09-07 09:20:13 -07:00
Juan Pablo Risso
06acc13575 DVCSMP-1959 - Remove sensitive information from logs (#1206) 2016-09-07 12:14:58 -04:00
twack
c051d719cc 20160907_update_its_to_hot_for_security 2016-09-07 09:14:19 -07:00
Vinay Rao
1e54b93b0c Merge pull request #1203 from SmartThingsCommunity/master
Rolling up master to staging
2016-09-06 17:15:57 -07:00
Vinay Rao
bac37f9ca2 Merge pull request #1202 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-09-06 17:08:39 -07:00
Vinay Rao
f0ecb65c09 Merge pull request #1201 from SmartThingsCommunity/revert-1197-revert_WWST-40_staging
Revert "Revert "WWST-40 Philips Hue: Implement device watch""
2016-09-06 17:07:33 -07:00
Vinay Rao
1c0ddd2571 Revert "Revert "WWST-40 Philips Hue: Implement device watch"" 2016-09-06 17:07:14 -07:00
Vinay Rao
b7e0cbda09 Merge pull request #1200 from SmartThingsCommunity/revert-1194-revert-latest-ecobee-changes
Revert "revert changes for DVCSMP-1980 and SSVD-2534 on staging"
2016-09-06 17:07:06 -07:00
Vinay Rao
f80e094bd9 Revert "revert changes for DVCSMP-1980 and SSVD-2534 on staging" 2016-09-06 17:06:38 -07:00
Vinay Rao
ce9ac624d0 Merge pull request #1199 from SmartThingsCommunity/staging
Rolling up staging to production for deploy
2016-09-06 16:41:19 -07:00
Juan Pablo Risso
f3f5cc42c9 CREX-5826 - Missing braces (#1198) 2016-09-06 17:38:45 -04:00
Vinay Rao
313fe8b734 Merge pull request #1197 from larsfinander/revert_WWST-40_staging
Revert "WWST-40 Philips Hue: Implement device watch"
2016-09-06 12:33:51 -07:00
Vinay Rao
0d693386d1 Merge pull request #1194 from jimmyjames/revert-latest-ecobee-changes
revert changes for DVCSMP-1980 and SSVD-2534 on staging
2016-09-06 12:01:30 -07:00
Lars Finander
d1aee1e874 Revert "WWST-40 Philips Hue: Implement device watch"
This reverts commit bacd335991.
2016-09-06 12:42:11 -06:00
Lars Finander
3528e7da51 Merge pull request #1195 from larsfinander/DVCSMP-2004_Philips_Hue_Nullpointer_in_bridge_staging
DVCSMP-2004 Philips Hue: Nullpointer in bridge
2016-09-06 12:40:02 -06:00
juano2310
fe2fbc3b97 MKTP-829 - Adding disclaimer 2016-09-06 14:01:20 -04:00
Lars Finander
5c2e06c98d DVCSMP-2004 Philips Hue: Nullpointer in bridge 2016-09-06 10:43:03 -06:00
Jim Anderson
26df619b4f revert changes for DVCSMP-1980 and SSVD-2534 on staging 2016-09-06 11:22:06 -05:00
Juan Pablo Risso
af2ea04442 CREX-5826 - 2 SMS bug fix (#1193)
options.method = 'none' & variable name update

Revert variable name
2016-09-06 12:04:26 -04:00
Juan Pablo Risso
383f72580a SSVD-2738 - SSVD-2734 - SSVD-2733 (#1187)
* SSVD-2738 - Count Down Bug

* SSVD-2734 - Copy text

* SSVD-2733 - Add Unit
2016-09-06 11:39:18 -04:00
CosmicPuppy
5e6b4f74e0 To Netatmo DTHs, added Capability "Sensor" per http://docs.smartthings.com/en/latest/device-type-developers-guide/overview.html?highlight=sensor%20actuator#actuator-and-sensor.
There are some SmartApps out there using the "Actuator" and "Sensor" Capabilities and this Device doesn't show up for them (e.g., SmartTiles V6).
2016-08-29 13:55:19 -07:00
Adam Jensen
22185c5440 Added labels to the motion attribute in the main multiattributetile 2016-05-24 08:18:51 -05:00
54 changed files with 490 additions and 450 deletions

View File

@@ -19,7 +19,7 @@ buildscript {
username smartThingsArtifactoryUserName
password smartThingsArtifactoryPassword
}
url "http://artifactory.smartthings.com/libs-release-local"
url "https://artifactory.smartthings.com/libs-release-local"
}
}
}
@@ -27,9 +27,37 @@ buildscript {
repositories {
mavenLocal()
jcenter()
maven {
credentials {
username smartThingsArtifactoryUserName
password smartThingsArtifactoryPassword
}
url "https://artifactory.smartthings.com/libs-release-local"
}
}
sourceSets {
devicetypes {
groovy {
srcDirs = ['devicetypes']
}
}
smartapps {
groovy {
srcDirs = ['smartapps']
}
}
}
dependencies {
devicetypesCompile 'org.codehaus.groovy:groovy-all:2.4.7'
devicetypesCompile 'smartthings:appengine-z-wave:0.1.2'
devicetypesCompile 'smartthings:appengine-zigbee:0.1.11'
smartappsCompile 'org.codehaus.groovy:groovy-all:2.4.7'
smartappsCompile 'smartthings:appengine-common:0.1.8'
smartappsCompile 'org.codehaus.groovy.modules.http-builder:http-builder:0.7.1'
smartappsCompile 'org.grails:grails-web:2.3.11'
smartappsCompile 'org.json:json:20140107'
}
slackSendMessage {

View File

@@ -5,7 +5,9 @@ machine:
dependencies:
override:
- echo "Nothing to do."
- ./gradlew dependencies -PsmartThingsArtifactoryUserName="$ARTIFACTORY_USERNAME" -PsmartThingsArtifactoryPassword="$ARTIFACTORY_PASSWORD"
post:
- ./gradlew compileSmartappsGroovy compileDevicetypesGroovy -PsmartThingsArtifactoryUserName="$ARTIFACTORY_USERNAME" -PsmartThingsArtifactoryPassword="$ARTIFACTORY_PASSWORD"
test:
override:

View File

@@ -15,6 +15,7 @@
*/
metadata {
definition (name: "Netatmo Additional Module", namespace: "dianoga", author: "Brian Steere") {
capability "Sensor"
capability "Relative Humidity Measurement"
capability "Temperature Measurement"

View File

@@ -15,6 +15,7 @@
*/
metadata {
definition (name: "Netatmo Basestation", namespace: "dianoga", author: "Brian Steere") {
capability "Sensor"
capability "Relative Humidity Measurement"
capability "Temperature Measurement"

View File

@@ -15,6 +15,7 @@
*/
metadata {
definition (name: "Netatmo Outdoor Module", namespace: "dianoga", author: "Brian Steere") {
capability "Sensor"
capability "Relative Humidity Measurement"
capability "Temperature Measurement"
}

View File

@@ -15,6 +15,8 @@
*/
metadata {
definition (name: "Netatmo Rain", namespace: "dianoga", author: "Brian Steere") {
capability "Sensor"
attribute "rain", "number"
attribute "rainSumHour", "number"
attribute "rainSumDay", "number"

View File

@@ -33,8 +33,8 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name:"FGMS", type:"lighting", width:6, height:4) {//with generic type secondary control text is not displayed in Android app
tileAttribute("device.motion", key:"PRIMARY_CONTROL") {
attributeState("inactive", icon:"st.motion.motion.inactive", backgroundColor:"#79b821")
attributeState("active", icon:"st.motion.motion.active", backgroundColor:"#ffa81e")
attributeState("inactive", label:"no motion", icon:"st.motion.motion.inactive", backgroundColor:"#79b821")
attributeState("active", label:"motion", icon:"st.motion.motion.active", backgroundColor:"#ffa81e")
}
tileAttribute("device.tamper", key:"SECONDARY_CONTROL") {
@@ -278,4 +278,4 @@ private encap(physicalgraph.zwave.Command cmd) {
} else {
crc16(cmd)
}
}
}

View File

@@ -19,7 +19,6 @@ metadata {
capability "Actuator"
capability "Configuration"
capability "Polling"
capability "Refresh"
capability "Switch"
capability "Switch Level"
@@ -67,12 +66,6 @@ def parse(String description) {
def resultMap = zigbee.getEvent(description)
if (resultMap) {
sendEvent(resultMap)
// Temporary fix for the case when Device is OFFLINE and is connected again
if (state.lastActivity == null){
state.lastActivity = now()
sendEvent(name: "deviceWatch-lastActivity", value: state.lastActivity, description: "Last Activity is on ${new Date((long)state.lastActivity)}", displayed: false, isStateChange: true)
}
state.lastActivity = now()
}
else {
log.debug "DID NOT PARSE MESSAGE for description : $description"
@@ -96,27 +89,24 @@ def setLevel(value) {
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
if (state.lastActivity < (now() - (1000 * device.currentValue("checkInterval"))) ){
log.info "ping, alive=no, lastActivity=${state.lastActivity}"
state.lastActivity = null
return zigbee.levelRefresh()
} else {
log.info "ping, alive=yes, lastActivity=${state.lastActivity}"
sendEvent(name: "deviceWatch-lastActivity", value: state.lastActivity, description: "Last Activity is on ${new Date((long)state.lastActivity)}", displayed: false, isStateChange: true)
}
return zigbee.levelRefresh()
}
def refresh() {
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.onOffConfig() + zigbee.levelConfig()
}
def poll() {
zigbee.onOffRefresh() + zigbee.levelRefresh()
def healthPoll() {
def cmds = zigbee.onOffRefresh() + zigbee.levelRefresh()
cmds.each{ sendHubCommand(new physicalgraph.device.HubAction(it))}
}
def configure() {
unschedule()
schedule("0 0/5 * * * ? *", "healthPoll")
log.debug "Configuring Reporting and Bindings."
sendEvent(name: "checkInterval", value: 1200, displayed: false, data: [protocol: "zigbee"])
zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh()
// Device-Watch allows 2 check-in misses from device
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee"])
// minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh()
}

View File

@@ -57,7 +57,7 @@ metadata {
}
void installed() {
sendEvent(name: "checkInterval", value: 60 * 30, data: [protocol: "lan"], displayed: false)
sendEvent(name: "checkInterval", value: 60 * 12, data: [protocol: "lan"], displayed: false)
}
// parse events into attributes

View File

@@ -62,7 +62,7 @@ def parse(description) {
log.trace "HUE BRIDGE, GENERATING EVENT: $map.name: $map.value"
results << createEvent(name: "${map.name}", value: "${map.value}")
} else {
log.trace "Parsing description"
log.trace "Parsing description"
def msg = parseLanMessage(description)
if (msg.body) {
def contentType = msg.headers["Content-Type"]
@@ -72,13 +72,13 @@ def parse(description) {
log.info "Bridge response: $msg.body"
} else {
// Sending Bulbs List to parent"
if (parent.state.inBulbDiscovery)
log.info parent.bulbListHandler(device.hub.id, msg.body)
if (parent.isInBulbDiscovery())
log.info parent.bulbListHandler(device.hub.id, msg.body)
}
}
else if (contentType?.contains("xml")) {
log.debug "HUE BRIDGE ALREADY PRESENT"
parent.hubVerification(device.hub.id, msg.body)
parent.hubVerification(device.hub.id, msg.body)
}
}
}

View File

@@ -66,7 +66,7 @@ metadata {
}
void installed() {
sendEvent(name: "checkInterval", value: 60 * 30, data: [protocol: "lan"], displayed: false)
sendEvent(name: "checkInterval", value: 60 * 12, data: [protocol: "lan"], displayed: false)
}
// parse events into attributes

View File

@@ -50,7 +50,7 @@ metadata {
}
void installed() {
sendEvent(name: "checkInterval", value: 60 * 30, data: [protocol: "lan"], displayed: false)
sendEvent(name: "checkInterval", value: 60 * 12, data: [protocol: "lan"], displayed: false)
}
// parse events into attributes

View File

@@ -55,7 +55,7 @@ metadata {
}
void installed() {
sendEvent(name: "checkInterval", value: 60 * 30, data: [protocol: "lan"], displayed: false)
sendEvent(name: "checkInterval", value: 60 * 12, data: [protocol: "lan"], displayed: false)
}
// parse events into attributes

View File

@@ -91,7 +91,7 @@ def parse(String description) {
if (descMap.cluster == "0300") {
if(descMap.attrId == "0000"){ //Hue Attribute
def hueValue = Math.round(convertHexToInt(descMap.value) / 255 * 360)
def hueValue = Math.round(convertHexToInt(descMap.value) / 255 * 100)
log.debug "Hue value returned is $hueValue"
sendEvent(name: "hue", value: hueValue, displayed:false)
}
@@ -203,7 +203,7 @@ def setLevel(value) {
//input Hue Integer values; returns color name for saturation 100%
private getColorName(hueValue){
if(hueValue>360 || hueValue<0)
if(hueValue>100 || hueValue<0)
return
hueValue = Math.round(hueValue / 100 * 360)

View File

@@ -1,4 +1,4 @@
/*
/*
Osram Flex RGBW Light Strip
Osram bulbs have a firmware issue causing it to forget its dimming level when turned off (via commands). Handling
@@ -8,7 +8,7 @@
metadata {
definition (name: "OSRAM LIGHTIFY LED Flexible Strip RGBW", namespace: "smartthings", author: "SmartThings") {
capability "Color Temperature"
capability "Actuator"
capability "Switch"
@@ -18,7 +18,7 @@ metadata {
capability "Refresh"
capability "Sensor"
capability "Color Control"
attribute "colorName", "string"
command "setAdjustedColor"
@@ -49,7 +49,7 @@ metadata {
standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") {
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
}
controlTile("colorTempSliderControl", "device.colorTemperature", "slider", height: 1, width: 2, inactiveLabel: false, range:"(2700..6500)") {
state "colorTemperature", action:"color temperature.setColorTemperature"
}
@@ -118,7 +118,7 @@ def parse(String description) {
}
}
else if(descMap.attrId == "0000"){ //Hue Attribute
def hueValue = Math.round(convertHexToInt(descMap.value) / 255 * 360)
def hueValue = Math.round(convertHexToInt(descMap.value) / 255 * 100)
log.debug "Hue value returned is $hueValue"
sendEvent(name: "hue", value: hueValue, displayed:false)
}
@@ -274,7 +274,7 @@ private getGenericName(value){
//input Hue Integer values; returns color name for saturation 100%
private getColorName(hueValue){
if(hueValue>360 || hueValue<0)
if(hueValue>100 || hueValue<0)
return
hueValue = Math.round(hueValue / 100 * 360)
@@ -449,7 +449,7 @@ def setColor(value){
def level = hex(value.level * 255 / 100)
cmd << zigbeeSetLevel(level)
}
if (value.switch == "off") {
cmd << "delay 150"
cmd << off()

View File

@@ -101,12 +101,6 @@ def parse(String description) {
else {
def descriptionText = finalResult.value == "on" ? '{{ device.displayName }} is On' : '{{ device.displayName }} is Off'
sendEvent(name: finalResult.type, value: finalResult.value, descriptionText: descriptionText, translatable: true)
// Temporary fix for the case when Device is OFFLINE and is connected again
if (state.lastActivity == null){
state.lastActivity = now()
sendEvent(name: "deviceWatch-lastActivity", value: state.lastActivity, description: "Last Activity is on ${new Date((long)state.lastActivity)}", displayed: false, isStateChange: true)
}
state.lastActivity = now()
}
}
else {
@@ -126,15 +120,7 @@ def on() {
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
if (state.lastActivity < (now() - (1000 * device.currentValue("checkInterval"))) ){
log.info "ping, alive=no, lastActivity=${state.lastActivity}"
state.lastActivity = null
return zigbee.onOffRefresh()
} else {
log.info "ping, alive=yes, lastActivity=${state.lastActivity}"
sendEvent(name: "deviceWatch-lastActivity", value: state.lastActivity, description: "Last Activity is on ${new Date((long)state.lastActivity)}", displayed: false, isStateChange: true)
}
return zigbee.onOffRefresh()
}
def refresh() {
@@ -142,8 +128,10 @@ def refresh() {
}
def configure() {
sendEvent(name: "checkInterval", value: 1200, displayed: false, data: [protocol: "zigbee"])
zigbee.onOffConfig() + powerConfig() + refresh()
// Device-Watch allows 2 check-in misses from device
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee"])
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
zigbee.onOffConfig(0, 300) + powerConfig() + refresh()
}
//power config for devices with min reporting interval as 1 seconds and reporting interval if no activity as 10min (600s)

View File

@@ -101,13 +101,6 @@ def parse(String description) {
map = parseIasMessage(description)
}
// Temporary fix for the case when Device is OFFLINE and is connected again
if (state.lastActivity == null){
state.lastActivity = now()
sendEvent(name: "deviceWatch-lastActivity", value: state.lastActivity, description: "Last Activity is on ${new Date((long)state.lastActivity)}", displayed: false, isStateChange: true)
}
state.lastActivity = now()
log.debug "Parse returned $map"
def result = map ? createEvent(map) : null
@@ -233,6 +226,8 @@ private Map getBatteryResult(rawValue) {
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
def roundedPct = Math.round(pct * 100)
if (roundedPct <= 0)
roundedPct = 1
result.value = Math.min(100, roundedPct)
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
}
@@ -283,15 +278,7 @@ private Map getMoistureResult(value) {
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
if (state.lastActivity < (now() - (1000 * device.currentValue("checkInterval"))) ){
log.info "ping, alive=no, lastActivity=${state.lastActivity}"
state.lastActivity = null
return zigbee.readAttribute(0x001, 0x0020) // Read the Battery Level
} else {
log.info "ping, alive=yes, lastActivity=${state.lastActivity}"
sendEvent(name: "deviceWatch-lastActivity", value: state.lastActivity, description: "Last Activity is on ${new Date((long)state.lastActivity)}", displayed: false, isStateChange: true)
}
return zigbee.readAttribute(0x001, 0x0020) // Read the Battery Level
}
def refresh() {
@@ -305,23 +292,19 @@ def refresh() {
}
def configure() {
sendEvent(name: "checkInterval", value: 14400, displayed: false, data: [protocol: "zigbee"])
// Device-Watch allows 2 check-in misses from device
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee"])
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "Configuring Reporting, IAS CIE, and Bindings."
def configCmds = [
def enrollCmds = [
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
"zdo bind 0x${device.deviceNetworkId} ${endpointId} 1 1 {${device.zigbeeId}} {}", "delay 500",
"zcl global send-me-a-report 1 0x20 0x20 30 21600 {01}", //checkin time 6 hrs
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
"zdo bind 0x${device.deviceNetworkId} ${endpointId} 1 0x402 {${device.zigbeeId}} {}", "delay 500",
"zcl global send-me-a-report 0x402 0 0x29 30 3600 {6400}",
"send 0x${device.deviceNetworkId} 1 1", "delay 500"
]
return configCmds + refresh() // send refresh cmds as part of config
// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity
// battery minReport 30 seconds, maxReportTime 6 hrs by default
return enrollCmds + zigbee.batteryConfig() + zigbee.temperatureConfig(30, 300) + refresh() // send refresh cmds as part of config
}
def enrollResponse() {

View File

@@ -105,13 +105,6 @@ def parse(String description) {
map = parseIasMessage(description)
}
// Temporary fix for the case when Device is OFFLINE and is connected again
if (state.lastActivity == null){
state.lastActivity = now()
sendEvent(name: "deviceWatch-lastActivity", value: state.lastActivity, description: "Last Activity is on ${new Date((long)state.lastActivity)}", displayed: false, isStateChange: true)
}
state.lastActivity = now()
log.debug "Parse returned $map"
def result = map ? createEvent(map) : null
@@ -248,6 +241,8 @@ private Map getBatteryResult(rawValue) {
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
def roundedPct = Math.round(pct * 100)
if (roundedPct <= 0)
roundedPct = 1
result.value = Math.min(100, roundedPct)
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
}
@@ -294,15 +289,7 @@ private Map getMotionResult(value) {
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
if (state.lastActivity < (now() - (1000 * device.currentValue("checkInterval"))) ){
log.info "ping, alive=no, lastActivity=${state.lastActivity}"
state.lastActivity = null
return zigbee.readAttribute(0x001, 0x0020) // Read the Battery Level
} else {
log.info "ping, alive=yes, lastActivity=${state.lastActivity}"
sendEvent(name: "deviceWatch-lastActivity", value: state.lastActivity, description: "Last Activity is on ${new Date((long)state.lastActivity)}", displayed: false, isStateChange: true)
}
return zigbee.readAttribute(0x001, 0x0020) // Read the Battery Level
}
def refresh() {
@@ -316,24 +303,19 @@ def refresh() {
}
def configure() {
sendEvent(name: "checkInterval", value: 14400, displayed: false, data: [protocol: "zigbee"])
// Device-Watch allows 2 check-in misses from device
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee"])
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "Configuring Reporting, IAS CIE, and Bindings."
def configCmds = [
def enrollCmds = [
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
"zdo bind 0x${device.deviceNetworkId} ${endpointId} 1 1 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 1 0x20 0x20 30 21600 {01}", //checkin time 6 hrs
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
"zdo bind 0x${device.deviceNetworkId} ${endpointId} 1 0x402 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 0x402 0 0x29 300 3600 {6400}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500"
]
return configCmds + refresh() // send refresh cmds as part of config
// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity
// battery minReport 30 seconds, maxReportTime 6 hrs by default
return enrollCmds + zigbee.batteryConfig() + zigbee.temperatureConfig(30, 300) + refresh() // send refresh cmds as part of config
}
def enrollResponse() {

View File

@@ -206,6 +206,8 @@ private Map getBatteryResult(rawValue) {
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
def roundedPct = Math.round(pct * 100)
if (roundedPct <= 0)
roundedPct = 1
result.value = Math.min(100, roundedPct)
result.descriptionText = "${linkText} battery was ${result.value}%"
}

View File

@@ -127,13 +127,6 @@ def parse(String description) {
map = parseIasMessage(description)
}
// Temporary fix for the case when Device is OFFLINE and is connected again
if (state.lastActivity == null){
state.lastActivity = now()
sendEvent(name: "deviceWatch-lastActivity", value: state.lastActivity, description: "Last Activity is on ${new Date((long)state.lastActivity)}", displayed: false, isStateChange: true)
}
state.lastActivity = now()
def result = map ? createEvent(map) : null
if (description?.startsWith('enroll request')) {
@@ -313,6 +306,8 @@ private Map getBatteryResult(rawValue) {
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
def roundedPct = Math.round(pct * 100)
if (roundedPct <= 0)
roundedPct = 1
result.value = Math.min(100, roundedPct)
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
}
@@ -376,15 +371,7 @@ private getAccelerationResult(numValue) {
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
if (state.lastActivity < (now() - (1000 * device.currentValue("checkInterval"))) ){
log.info "ping, alive=no, lastActivity=${state.lastActivity}"
state.lastActivity = null
return zigbee.readAttribute(0x001, 0x0020) // Read the Battery Level
} else {
log.info "ping, alive=yes, lastActivity=${state.lastActivity}"
sendEvent(name: "deviceWatch-lastActivity", value: state.lastActivity, description: "Last Activity is on ${new Date((long)state.lastActivity)}", displayed: false, isStateChange: true)
}
return zigbee.readAttribute(0x001, 0x0020) // Read the Battery Level
}
def refresh() {
@@ -414,13 +401,16 @@ def refresh() {
}
def configure() {
sendEvent(name: "checkInterval", value: 14400, displayed: false, data: [protocol: "zigbee"])
// Device-Watch allows 2 check-in misses from device
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee"])
log.debug "Configuring Reporting"
// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity
// battery minReport 30 seconds, maxReportTime 6 hrs by default
def configCmds = enrollResponse() +
zigbee.batteryConfig() +
zigbee.temperatureConfig() +
zigbee.temperatureConfig(30, 300) +
zigbee.configureReporting(0xFC02, 0x0010, 0x18, 10, 3600, 0x01, [mfgCode: manufacturerCode]) +
zigbee.configureReporting(0xFC02, 0x0012, 0x29, 1, 3600, 0x0001, [mfgCode: manufacturerCode]) +
zigbee.configureReporting(0xFC02, 0x0013, 0x29, 1, 3600, 0x0001, [mfgCode: manufacturerCode]) +

View File

@@ -206,6 +206,8 @@ def getTemperature(value) {
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
def roundedPct = Math.round(pct * 100)
if (roundedPct <= 0)
roundedPct = 1
result.value = Math.min(100, roundedPct)
result.descriptionText = "${linkText} battery was ${result.value}%"
}

View File

@@ -92,13 +92,6 @@ def parse(String description) {
map = parseIasMessage(description)
}
// Temporary fix for the case when Device is OFFLINE and is connected again
if (state.lastActivity == null){
state.lastActivity = now()
sendEvent(name: "deviceWatch-lastActivity", value: state.lastActivity, description: "Last Activity is on ${new Date((long)state.lastActivity)}", displayed: false, isStateChange: true)
}
state.lastActivity = now()
log.debug "Parse returned $map"
def result = map ? createEvent(map) : null
@@ -207,6 +200,8 @@ private Map getBatteryResult(rawValue) {
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
def roundedPct = Math.round(pct * 100)
if (roundedPct <= 0)
roundedPct = 1
result.value = Math.min(100, roundedPct)
result.descriptionText = "${linkText} battery was ${result.value}%"
}
@@ -246,15 +241,7 @@ private Map getContactResult(value) {
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
if (state.lastActivity < (now() - (1000 * device.currentValue("checkInterval"))) ){
log.info "ping, alive=no, lastActivity=${state.lastActivity}"
state.lastActivity = null
return zigbee.readAttribute(0x001, 0x0020) // Read the Battery Level
} else {
log.info "ping, alive=yes, lastActivity=${state.lastActivity}"
sendEvent(name: "deviceWatch-lastActivity", value: state.lastActivity, description: "Last Activity is on ${new Date((long)state.lastActivity)}", displayed: false, isStateChange: true)
}
return zigbee.readAttribute(0x001, 0x0020) // Read the Battery Level
}
def refresh() {
@@ -268,23 +255,19 @@ def refresh() {
}
def configure() {
sendEvent(name: "checkInterval", value: 14400, displayed: false, data: [protocol: "zigbee"])
// Device-Watch allows 2 check-in misses from device
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee"])
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "Configuring Reporting, IAS CIE, and Bindings."
def configCmds = [
def enrollCmds = [
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
"zdo bind 0x${device.deviceNetworkId} ${endpointId} 1 1 {${device.zigbeeId}} {}", "delay 500",
"zcl global send-me-a-report 1 0x20 0x20 30 21600 {01}", //checkin time 6 hrs
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
"zdo bind 0x${device.deviceNetworkId} ${endpointId} 1 0x402 {${device.zigbeeId}} {}", "delay 500",
"zcl global send-me-a-report 0x402 0 0x29 30 3600 {6400}",
"send 0x${device.deviceNetworkId} 1 1", "delay 500"
]
return configCmds + refresh() // send refresh cmds as part of config
// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity
// battery minReport 30 seconds, maxReportTime 6 hrs by default
return enrollCmds + zigbee.batteryConfig() + zigbee.temperatureConfig(30, 300) + refresh() // send refresh cmds as part of config
}
def enrollResponse() {

View File

@@ -83,13 +83,6 @@ def parse(String description) {
map = parseCustomMessage(description)
}
// Temporary fix for the case when Device is OFFLINE and is connected again
if (state.lastActivity == null){
state.lastActivity = now()
sendEvent(name: "deviceWatch-lastActivity", value: state.lastActivity, description: "Last Activity is on ${new Date((long)state.lastActivity)}", displayed: false, isStateChange: true)
}
state.lastActivity = now()
log.debug "Parse returned $map"
return map ? createEvent(map) : null
}
@@ -214,6 +207,8 @@ private Map getBatteryResult(rawValue) {
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
def roundedPct = Math.round(pct * 100)
if (roundedPct <= 0)
roundedPct = 1
result.value = Math.min(100, roundedPct)
result.descriptionText = "${linkText} battery was ${result.value}%"
}
@@ -251,14 +246,7 @@ private Map getHumidityResult(value) {
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
if (state.lastActivity < (now() - (1000 * device.currentValue("checkInterval"))) ){
log.info "ping, alive=no, lastActivity=${state.lastActivity}"
state.lastActivity = null
return zigbee.readAttribute(0x001, 0x0020) // Read the Battery Level
} else {
log.info "ping, alive=yes, lastActivity=${state.lastActivity}"
sendEvent(name: "deviceWatch-lastActivity", value: state.lastActivity, description: "Last Activity is on ${new Date((long)state.lastActivity)}", displayed: false, isStateChange: true)
}
return zigbee.readAttribute(0x001, 0x0020) // Read the Battery Level
}
def refresh()
@@ -276,23 +264,19 @@ def refresh()
}
def configure() {
sendEvent(name: "checkInterval", value: 14400, displayed: false, data: [protocol: "zigbee"])
// Device-Watch allows 2 check-in misses from device
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee"])
log.debug "Configuring Reporting and Bindings."
def configCmds = [
"zdo bind 0x${device.deviceNetworkId} 1 1 1 {${device.zigbeeId}} {}", "delay 500",
"zcl global send-me-a-report 1 0x20 0x20 30 21600 {01}", //checkin time 6 hrs
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
"zdo bind 0x${device.deviceNetworkId} 1 1 0x402 {${device.zigbeeId}} {}", "delay 500",
"zcl global send-me-a-report 0x402 0 0x29 30 3600 {6400}",
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
def humidityConfigCmds = [
"zdo bind 0x${device.deviceNetworkId} 1 1 0xFC45 {${device.zigbeeId}} {}", "delay 500",
"zcl global send-me-a-report 0xFC45 0 0x29 30 3600 {6400}",
"send 0x${device.deviceNetworkId} 1 1", "delay 500"
]
return configCmds + refresh() // send refresh cmds as part of config
// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity
// battery minReport 30 seconds, maxReportTime 6 hrs by default
return humidityConfigCmds + zigbee.batteryConfig() + zigbee.temperatureConfig(30, 300) + refresh() // send refresh cmds as part of config
}
private hex(value) {

View File

@@ -54,12 +54,6 @@ def parse(String description) {
def event = zigbee.getEvent(description)
if (event) {
// Temporary fix for the case when Device is OFFLINE and is connected again
if (state.lastActivity == null){
state.lastActivity = now()
sendEvent(name: "deviceWatch-lastActivity", value: state.lastActivity, description: "Last Activity is on ${new Date((long)state.lastActivity)}", displayed: false, isStateChange: true)
}
state.lastActivity = now()
if (event.name=="level" && event.value==0) {}
else {
sendEvent(event)
@@ -86,15 +80,7 @@ def setLevel(value) {
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
if (state.lastActivity < (now() - (1000 * device.currentValue("checkInterval"))) ){
log.info "ping, alive=no, lastActivity=${state.lastActivity}"
state.lastActivity = null
return zigbee.onOffRefresh()
} else {
log.info "ping, alive=yes, lastActivity=${state.lastActivity}"
sendEvent(name: "deviceWatch-lastActivity", value: state.lastActivity, description: "Last Activity is on ${new Date((long)state.lastActivity)}", displayed: false, isStateChange: true)
}
return zigbee.onOffRefresh()
}
def refresh() {
@@ -103,7 +89,8 @@ def refresh() {
def configure() {
log.debug "Configuring Reporting and Bindings."
// Enrolls device to Device-Watch with 3 x Reporting interval 30min
sendEvent(name: "checkInterval", value: 1800, displayed: false, data: [protocol: "zigbee"])
zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh()
// Device-Watch allows 2 check-in misses from device
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee"])
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh()
}

View File

@@ -85,12 +85,6 @@ def parse(String description) {
def event = zigbee.getEvent(description)
if (event) {
log.debug event
// Temporary fix for the case when Device is OFFLINE and is connected again
if (state.lastActivity == null){
state.lastActivity = now()
sendEvent(name: "deviceWatch-lastActivity", value: state.lastActivity, description: "Last Activity is on ${new Date((long)state.lastActivity)}", displayed: false, isStateChange: true)
}
state.lastActivity = now()
if (event.name=="level" && event.value==0) {}
else {
if (event.name=="colorTemperature") {
@@ -105,7 +99,7 @@ def parse(String description) {
if (zigbeeMap?.clusterInt == COLOR_CONTROL_CLUSTER) {
if(zigbeeMap.attrInt == ATTRIBUTE_HUE){ //Hue Attribute
def hueValue = Math.round(zigbee.convertHexToInt(zigbeeMap.value) / 255 * 360)
def hueValue = Math.round(zigbee.convertHexToInt(zigbeeMap.value) / 255 * 100)
sendEvent(name: "hue", value: hueValue, descriptionText: "Color has changed")
}
else if(zigbeeMap.attrInt == ATTRIBUTE_SATURATION){ //Saturation Attribute
@@ -130,15 +124,7 @@ def off() {
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
if (state.lastActivity < (now() - (1000 * device.currentValue("checkInterval"))) ){
log.info "ping, alive=no, lastActivity=${state.lastActivity}"
state.lastActivity = null
return zigbee.onOffRefresh()
} else {
log.info "ping, alive=yes, lastActivity=${state.lastActivity}"
sendEvent(name: "deviceWatch-lastActivity", value: state.lastActivity, description: "Last Activity is on ${new Date((long)state.lastActivity)}", displayed: false, isStateChange: true)
}
return zigbee.onOffRefresh()
}
def refresh() {
@@ -147,9 +133,10 @@ def refresh() {
def configure() {
log.debug "Configuring Reporting and Bindings."
// Enrolls device to Device-Watch with 3 x Reporting interval 30min
sendEvent(name: "checkInterval", value: 1800, displayed: false, data: [protocol: "zigbee"])
zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01) + zigbee.readAttribute(0x0006, 0x00) + zigbee.readAttribute(0x0008, 0x00) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, 0x00) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_COLOR_TEMPERATURE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION)
// Device-Watch allows 2 check-in misses from device
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee"])
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01) + zigbee.readAttribute(0x0006, 0x00) + zigbee.readAttribute(0x0008, 0x00) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, 0x00) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_COLOR_TEMPERATURE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION)
}
def setColorTemperature(value) {

View File

@@ -74,12 +74,6 @@ def parse(String description) {
log.debug "description is $description"
def event = zigbee.getEvent(description)
if (event) {
// Temporary fix for the case when Device is OFFLINE and is connected again
if (state.lastActivity == null){
state.lastActivity = now()
sendEvent(name: "deviceWatch-lastActivity", value: state.lastActivity, description: "Last Activity is on ${new Date((long)state.lastActivity)}", displayed: false, isStateChange: true)
}
state.lastActivity = now()
if (event.name=="level" && event.value==0) {}
else {
if (event.name=="colorTemperature") {
@@ -110,15 +104,7 @@ def setLevel(value) {
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
if (state.lastActivity < (now() - (1000 * device.currentValue("checkInterval"))) ){
log.info "ping, alive=no, lastActivity=${state.lastActivity}"
state.lastActivity = null
return zigbee.onOffRefresh()
} else {
log.info "ping, alive=yes, lastActivity=${state.lastActivity}"
sendEvent(name: "deviceWatch-lastActivity", value: state.lastActivity, description: "Last Activity is on ${new Date((long)state.lastActivity)}", displayed: false, isStateChange: true)
}
return zigbee.onOffRefresh()
}
def refresh() {
@@ -127,9 +113,10 @@ def refresh() {
def configure() {
log.debug "Configuring Reporting and Bindings."
// Enrolls device to Device-Watch with 3 x Reporting interval 30min
sendEvent(name: "checkInterval", value: 1800, displayed: false, data: [protocol: "zigbee"])
zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh()
// Device-Watch allows 2 check-in misses from device
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee"])
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh()
}
def setColorTemperature(value) {

View File

@@ -65,7 +65,16 @@ void updateSwitch() {
private void updateAll(devices) {
def command = request.JSON?.command
if (command) {
devices."$command"()
switch(command) {
case "on":
devices.on()
break
case "off":
devices.off()
break
default:
httpError(403, "Access denied. This command is not supported by current capability.")
}
}
}
@@ -77,7 +86,16 @@ private void update(devices) {
if (!device) {
httpError(404, "Device not found")
} else {
device."$command"()
switch(command) {
case "on":
device.on()
break
case "off":
device.off()
break
default:
httpError(403, "Access denied. This command is not supported by current capability.")
}
}
}
}

View File

@@ -58,7 +58,7 @@ def authPage() {
if (canInstallLabs()) {
def redirectUrl = getBuildRedirectUrl()
log.debug "Redirect url = ${redirectUrl}"
// log.debug "Redirect url = ${redirectUrl}"
if (state.authToken) {
description = "Tap 'Next' to proceed"
@@ -113,13 +113,13 @@ def oauthInitUrl() {
scope: "read_station"
]
log.debug "REDIRECT URL: ${getVendorAuthPath() + toQueryString(oauthParams)}"
// log.debug "REDIRECT URL: ${getVendorAuthPath() + toQueryString(oauthParams)}"
redirect (location: getVendorAuthPath() + toQueryString(oauthParams))
}
def callback() {
log.debug "callback()>> params: $params, params.code ${params.code}"
// log.debug "callback()>> params: $params, params.code ${params.code}"
def code = params.code
def oauthState = params.state
@@ -135,7 +135,7 @@ def callback() {
scope: "read_station"
]
log.debug "TOKEN URL: ${getVendorTokenPath() + toQueryString(tokenParams)}"
// log.debug "TOKEN URL: ${getVendorTokenPath() + toQueryString(tokenParams)}"
def tokenUrl = getVendorTokenPath()
def params = [
@@ -144,7 +144,7 @@ def callback() {
body: tokenParams
]
log.debug "PARAMS: ${params}"
// log.debug "PARAMS: ${params}"
httpPost(params) { resp ->
@@ -156,7 +156,7 @@ def callback() {
state.refreshToken = data.refresh_token
state.authToken = data.access_token
state.tokenExpires = now() + (data.expires_in * 1000)
log.debug "swapped token: $resp.data"
// log.debug "swapped token: $resp.data"
}
}
@@ -292,7 +292,7 @@ def refreshToken() {
response.data.each {key, value ->
def data = slurper.parseText(key);
log.debug "Data: $data"
// log.debug "Data: $data"
state.refreshToken = data.refresh_token
state.accessToken = data.access_token

View File

@@ -28,7 +28,7 @@ mappings {
path("/receivedToken") { action: [ POST: "receivedToken", GET: "receivedToken"] }
path("/receiveToken") { action: [ POST: "receiveToken", GET: "receiveToken"] }
path("/hookCallback") { action: [ POST: "hookEventHandler", GET: "hookEventHandler"] }
path("/oauth/initialize") {action: [GET: "oauthInitUrl"]}
path("/oauth/initialize") {action: [GET: "oauthInitUrl"]}
path("/oauth/callback") { action: [ GET: "callback" ] }
}
@@ -44,7 +44,7 @@ def callback() {
} else {
log.warn "No authQueryString"
}
if (state.JawboneAccessToken) {
log.debug "Access token already exists"
setup()
@@ -73,7 +73,7 @@ def callback() {
def authPage() {
log.debug "authPage"
def description = null
def description = null
if (state.JawboneAccessToken == null) {
if (!state.accessToken) {
log.debug "About to create access token"
@@ -82,12 +82,13 @@ def authPage() {
description = "Click to enter Jawbone Credentials"
def redirectUrl = buildRedirectUrl
log.debug "RedirectURL = ${redirectUrl}"
def donebutton= state.JawboneAccessToken != null
def donebutton= state.JawboneAccessToken != null
return dynamicPage(name: "Credentials", title: "Jawbone UP", nextPage: null, uninstall: true, install: donebutton) {
section { paragraph title: "Note:", "This device has not been officially tested and certified to “Work with SmartThings”. You can connect it to your SmartThings home but performance may vary and we will not be able to provide support or assistance." }
section { href url:redirectUrl, style:"embedded", required:true, title:"Jawbone UP", state: hast ,description:description }
}
} else {
description = "Jawbone Credentials Already Entered."
description = "Jawbone Credentials Already Entered."
return dynamicPage(name: "Credentials", title: "Jawbone UP", uninstall: true, install:true) {
section { href url: buildRedirectUrl("receivedToken"), style:"embedded", state: "complete", title:"Jawbone UP", description:description }
}
@@ -107,7 +108,7 @@ def receiveToken(redirectUrl = null) {
def params = [
uri: "https://jawbone.com/auth/oauth2/token?${toQueryString(oauthParams)}",
]
httpGet(params) { response ->
httpGet(params) { response ->
log.debug "${response.data}"
log.debug "Setting access token to ${response.data.access_token}, refresh token to ${response.data.refresh_token}"
state.JawboneAccessToken = response.data.access_token
@@ -149,7 +150,7 @@ def connectionStatus(message, redirectUrl = null) {
<meta http-equiv="refresh" content="3; url=${redirectUrl}" />
"""
}
def html = """
<!DOCTYPE html>
<html>
@@ -229,12 +230,12 @@ def validateCurrentToken() {
log.debug "validateCurrentToken"
def url = "https://jawbone.com/nudge/api/v.1.1/users/@me/refreshToken"
def requestBody = "secret=${appSettings.clientSecret}"
try {
httpPost(uri: url, headers: ["Authorization": "Bearer ${state.JawboneAccessToken}" ], body: requestBody) {response ->
if (response.status == 200) {
log.debug "${response.data}"
log.debug "Setting refresh token to ${response.data.data.refresh_token}"
log.debug "Setting refresh token"
state.refreshToken = response.data.data.refresh_token
}
}
@@ -258,7 +259,7 @@ def validateCurrentToken() {
state.remove("refreshToken")
}
} else {
log.debug "Setting access token to ${data.access_token}, refresh token to ${data.refresh_token}"
log.debug "Setting access token"
state.JawboneAccessToken = data.access_token
state.refreshToken = data.refresh_token
}
@@ -271,10 +272,10 @@ def validateCurrentToken() {
}
def initialize() {
log.debug "Callback URL - Webhook"
def localServerUrl = getApiServerUrl()
log.debug "Callback URL - Webhook"
def localServerUrl = getApiServerUrl()
def hookUrl = "${localServerUrl}/api/token/${state.accessToken}/smartapps/installations/${app.id}/hookCallback"
def webhook = "https://jawbone.com/nudge/api/v.1.1/users/@me/pubsub?webhook=$hookUrl"
def webhook = "https://jawbone.com/nudge/api/v.1.1/users/@me/pubsub?webhook=$hookUrl"
httpPost(uri: webhook, headers: ["Authorization": "Bearer ${state.JawboneAccessToken}" ])
}
@@ -284,16 +285,16 @@ def setup() {
if (state.JawboneAccessToken) {
def urlmember = "https://jawbone.com/nudge/api/users/@me/"
def member = null
httpGet(uri: urlmember, headers: ["Authorization": "Bearer ${state.JawboneAccessToken}" ]) {response ->
def member = null
httpGet(uri: urlmember, headers: ["Authorization": "Bearer ${state.JawboneAccessToken}" ]) {response ->
member = response.data.data
}
if (member) {
state.member = member
def externalId = "${app.id}.${member.xid}"
// find the appropriate child device based on my app id and the device network id
// find the appropriate child device based on my app id and the device network id
def deviceWrapper = getChildDevice("${externalId}")
// invoke the generatePresenceEvent method on the child device
@@ -312,7 +313,7 @@ def setup() {
}
def installed() {
if (!state.accessToken) {
log.debug "About to create access token"
createAccessToken()
@@ -324,7 +325,7 @@ def installed() {
}
def updated() {
if (!state.accessToken) {
log.debug "About to create access token"
createAccessToken()
@@ -348,29 +349,29 @@ def uninstalled() {
}
def pollChild(childDevice) {
def member = state.member
generatePollingEvents (member, childDevice)
def member = state.member
generatePollingEvents (member, childDevice)
}
def generatePollingEvents (member, childDevice) {
// lets figure out if the member is currently "home" (At the place)
def urlgoals = "https://jawbone.com/nudge/api/users/@me/goals"
def urlmoves = "https://jawbone.com/nudge/api/users/@me/moves"
def urlsleeps = "https://jawbone.com/nudge/api/users/@me/sleeps"
def urlgoals = "https://jawbone.com/nudge/api/users/@me/goals"
def urlmoves = "https://jawbone.com/nudge/api/users/@me/moves"
def urlsleeps = "https://jawbone.com/nudge/api/users/@me/sleeps"
def goals = null
def moves = null
def sleeps = null
httpGet(uri: urlgoals, headers: ["Authorization": "Bearer ${state.JawboneAccessToken}" ]) {response ->
def sleeps = null
httpGet(uri: urlgoals, headers: ["Authorization": "Bearer ${state.JawboneAccessToken}" ]) {response ->
goals = response.data.data
}
httpGet(uri: urlmoves, headers: ["Authorization": "Bearer ${state.JawboneAccessToken}" ]) {response ->
}
httpGet(uri: urlmoves, headers: ["Authorization": "Bearer ${state.JawboneAccessToken}" ]) {response ->
moves = response.data.data.items[0]
}
}
try { // we are going to just ignore any errors
log.debug "Member = ${member.first}"
log.debug "Moves Goal = ${goals.move_steps} Steps"
log.debug "Moves = ${moves.details.steps} Steps"
log.debug "Moves = ${moves.details.steps} Steps"
childDevice?.sendEvent(name:"steps", value: moves.details.steps)
childDevice?.sendEvent(name:"goal", value: goals.move_steps)
@@ -378,29 +379,29 @@ def generatePollingEvents (member, childDevice) {
}
catch (e) {
// eat it
}
}
}
def generateInitialEvent (member, childDevice) {
// lets figure out if the member is currently "home" (At the place)
def urlgoals = "https://jawbone.com/nudge/api/users/@me/goals"
def urlmoves = "https://jawbone.com/nudge/api/users/@me/moves"
def urlsleeps = "https://jawbone.com/nudge/api/users/@me/sleeps"
def urlgoals = "https://jawbone.com/nudge/api/users/@me/goals"
def urlmoves = "https://jawbone.com/nudge/api/users/@me/moves"
def urlsleeps = "https://jawbone.com/nudge/api/users/@me/sleeps"
def goals = null
def moves = null
def sleeps = null
httpGet(uri: urlgoals, headers: ["Authorization": "Bearer ${state.JawboneAccessToken}" ]) {response ->
def sleeps = null
httpGet(uri: urlgoals, headers: ["Authorization": "Bearer ${state.JawboneAccessToken}" ]) {response ->
goals = response.data.data
}
httpGet(uri: urlmoves, headers: ["Authorization": "Bearer ${state.JawboneAccessToken}" ]) {response ->
}
httpGet(uri: urlmoves, headers: ["Authorization": "Bearer ${state.JawboneAccessToken}" ]) {response ->
moves = response.data.data.items[0]
}
}
try { // we are going to just ignore any errors
log.debug "Member = ${member.first}"
log.debug "Moves Goal = ${goals.move_steps} Steps"
log.debug "Moves = ${moves.details.steps} Steps"
log.debug "Sleeping state = false"
log.debug "Sleeping state = false"
childDevice?.generateSleepingEvent(false)
childDevice?.sendEvent(name:"steps", value: moves.details.steps)
childDevice?.sendEvent(name:"goal", value: goals.move_steps)
@@ -408,27 +409,27 @@ def generateInitialEvent (member, childDevice) {
}
catch (e) {
// eat it
}
}
}
def setColor (steps,goal,childDevice) {
def result = steps * 100 / goal
if (result < 25)
if (result < 25)
childDevice?.sendEvent(name:"steps", value: "steps", label: steps)
else if ((result >= 25) && (result < 50))
else if ((result >= 25) && (result < 50))
childDevice?.sendEvent(name:"steps", value: "steps1", label: steps)
else if ((result >= 50) && (result < 75))
else if ((result >= 50) && (result < 75))
childDevice?.sendEvent(name:"steps", value: "steps1", label: steps)
else if (result >= 75)
childDevice?.sendEvent(name:"steps", value: "stepsgoal", label: steps)
else if (result >= 75)
childDevice?.sendEvent(name:"steps", value: "stepsgoal", label: steps)
}
def hookEventHandler() {
// log.debug "In hookEventHandler method."
log.debug "request = ${request}"
def json = request.JSON
def json = request.JSON
// get some stuff we need
def userId = json.events.user_xid[0]
def json_type = json.events.type[0]
@@ -437,39 +438,39 @@ def hookEventHandler() {
//log.debug json
log.debug "Userid = ${userId}"
log.debug "Notification Type: " + json_type
log.debug "Notification Action: " + json_action
log.debug "Notification Action: " + json_action
// find the appropriate child device based on my app id and the device network id
def externalId = "${app.id}.${userId}"
def childDevice = getChildDevice("${externalId}")
if (childDevice) {
switch (json_action) {
case "enter_sleep_mode":
childDevice?.generateSleepingEvent(true)
break
case "exit_sleep_mode":
childDevice?.generateSleepingEvent(false)
break
case "creation":
switch (json_action) {
case "enter_sleep_mode":
childDevice?.generateSleepingEvent(true)
break
case "exit_sleep_mode":
childDevice?.generateSleepingEvent(false)
break
case "creation":
childDevice?.sendEvent(name:"steps", value: 0)
break
case "updation":
def urlgoals = "https://jawbone.com/nudge/api/users/@me/goals"
def urlmoves = "https://jawbone.com/nudge/api/users/@me/moves"
def urlgoals = "https://jawbone.com/nudge/api/users/@me/goals"
def urlmoves = "https://jawbone.com/nudge/api/users/@me/moves"
def goals = null
def moves = null
httpGet(uri: urlgoals, headers: ["Authorization": "Bearer ${state.JawboneAccessToken}" ]) {response ->
def moves = null
httpGet(uri: urlgoals, headers: ["Authorization": "Bearer ${state.JawboneAccessToken}" ]) {response ->
goals = response.data.data
}
httpGet(uri: urlmoves, headers: ["Authorization": "Bearer ${state.JawboneAccessToken}" ]) {response ->
}
httpGet(uri: urlmoves, headers: ["Authorization": "Bearer ${state.JawboneAccessToken}" ]) {response ->
moves = response.data.data.items[0]
}
}
log.debug "Goal = ${goals.move_steps} Steps"
log.debug "Steps = ${moves.details.steps} Steps"
log.debug "Steps = ${moves.details.steps} Steps"
childDevice?.sendEvent(name:"steps", value: moves.details.steps)
childDevice?.sendEvent(name:"goal", value: goals.move_steps)
//setColor(moves.details.steps,goals.move_steps,childDevice)
childDevice?.sendEvent(name:"goal", value: goals.move_steps)
//setColor(moves.details.steps,goals.move_steps,childDevice)
break
case "deletion":
app.delete()

View File

@@ -14,7 +14,7 @@
* for the specific language governing permissions and limitations under the License.
*
*/
definition(
name: "Smart Home Ventilation",
namespace: "MichaelStruck",
@@ -164,7 +164,7 @@ def installed() {
def updated() {
unschedule()
turnOffSwitch() //Turn off all switches if the schedules are changed while in mid-schedule
unsubscribe
unsubscribe()
log.debug "Updated with settings: ${settings}"
init()
}
@@ -174,12 +174,12 @@ def init() {
schedule (midnightTime, midNight)
subscribe(location, "mode", locationHandler)
startProcess()
}
}
// Common methods
def startProcess () {
createDayArray()
createDayArray()
state.dayCount=state.data.size()
if (state.dayCount){
state.counter = 0
@@ -190,7 +190,7 @@ def startProcess () {
def startDay() {
def start = convertEpoch(state.data[state.counter].start)
def stop = convertEpoch(state.data[state.counter].stop)
runOnce(start, turnOnSwitch, [overwrite: true])
runOnce(stop, incDay, [overwrite: true])
}
@@ -218,7 +218,7 @@ def locationHandler(evt) {
}
if (!result) {
startProcess()
}
}
}
def midNight(){
@@ -238,7 +238,7 @@ def turnOffSwitch() {
}
log.debug "Home ventilation switches are off."
}
def schedDesc(on1, off1, on2, off2, on3, off3, on4, off4, modeList, dayList) {
def title = ""
def dayListClean = "On "
@@ -252,7 +252,7 @@ def schedDesc(on1, off1, on2, off2, on3, off3, on4, off4, modeList, dayList) {
dayListClean = "${dayListClean}, "
}
}
}
}
else {
dayListClean = "Every day"
}
@@ -272,7 +272,7 @@ def schedDesc(on1, off1, on2, off2, on3, off3, on4, off4, modeList, dayList) {
modeListClean = "${modeListClean} ${modePrefix}"
}
}
}
}
else {
modeListClean = "${modeListClean}all modes"
}
@@ -283,16 +283,16 @@ def schedDesc(on1, off1, on2, off2, on3, off3, on4, off4, modeList, dayList) {
title += "\nSchedule 2: ${humanReadableTime(on2)} to ${humanReadableTime(off2)}"
}
if (on3 && off3) {
title += "\nSchedule 3: ${humanReadableTime(on3)} to ${humanReadableTime(off3)}"
title += "\nSchedule 3: ${humanReadableTime(on3)} to ${humanReadableTime(off3)}"
}
if (on4 && off4) {
title += "\nSchedule 4: ${humanReadableTime(on4)} to ${humanReadableTime(off4)}"
title += "\nSchedule 4: ${humanReadableTime(on4)} to ${humanReadableTime(off4)}"
}
if (on1 || on2 || on3 || on4) {
title += "\n$modeListClean"
title += "\n$dayListClean"
title += "\n$dayListClean"
}
if (!on1 && !on2 && !on3 && !on4) {
title="Click to configure scenario"
}
@@ -374,7 +374,7 @@ def createDayArray() {
timeOk(timeOnD1, timeOffD1)
timeOk(timeOnD2, timeOffD2)
timeOk(timeOnD3, timeOffD3)
timeOk(timeOnD4, timeOffD4)
timeOk(timeOnD4, timeOffD4)
}
}
state.data.sort{it.start}
@@ -384,7 +384,7 @@ def createDayArray() {
private def textAppName() {
def text = "Smart Home Ventilation"
}
}
private def textVersion() {
def text = "Version 2.1.2 (05/31/2015)"
@@ -416,4 +416,4 @@ private def textHelp() {
"that each scenario does not overlap and run in separate modes (i.e. Home, Out of town, etc). Also note that you should " +
"avoid scheduling the ventilation fan at exactly midnight; the app resets itself at that time. It is suggested to start any new schedule " +
"at 12:15 am or later."
}
}

View File

@@ -17,7 +17,7 @@ definition(
name: "Monitor on Sense",
namespace: "resteele",
author: "Rachel Steele",
description: "Turn on Monitor when vibration is sensed",
description: "Turn on switch when vibration is sensed",
category: "My Apps",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
@@ -25,10 +25,10 @@ definition(
preferences {
section("When the keyboard is used...") {
section("When vibration is sensed...") {
input "accelerationSensor", "capability.accelerationSensor", title: "Which Sensor?"
}
section("Turn on/off a light...") {
section("Turn on switch...") {
input "switch1", "capability.switch"
}
}
@@ -47,5 +47,3 @@ def updated() {
def accelerationActiveHandler(evt) {
switch1.on()
}

View File

@@ -114,13 +114,16 @@ def beaconHandler(evt) {
if (allOk) {
def data = new groovy.json.JsonSlurper().parseText(evt.data)
log.debug "<beacon-control> data: $data - phones: " + phones*.deviceNetworkId
// removed logging of device names. can be added back for debugging
//log.debug "<beacon-control> data: $data - phones: " + phones*.deviceNetworkId
def beaconName = getBeaconName(evt)
log.debug "<beacon-control> beaconName: $beaconName"
// removed logging of device names. can be added back for debugging
//log.debug "<beacon-control> beaconName: $beaconName"
def phoneName = getPhoneName(data)
log.debug "<beacon-control> phoneName: $phoneName"
// removed logging of device names. can be added back for debugging
//log.debug "<beacon-control> phoneName: $phoneName"
if (phoneName != null) {
def action = data.presence == "1" ? "arrived" : "left"
def msg = "$phoneName has $action ${action == 'arrived' ? 'at ' : ''}the $beaconName"

View File

@@ -49,13 +49,15 @@ preferences {
def installed() {
log.debug "Installed with settings: ${settings}"
log.debug "Current mode = ${location.mode}, people = ${people.collect{it.label + ': ' + it.currentPresence}}"
// commented out log statement because presence sensor label could contain user's name
//log.debug "Current mode = ${location.mode}, people = ${people.collect{it.label + ': ' + it.currentPresence}}"
subscribe(people, "presence", presence)
}
def updated() {
log.debug "Updated with settings: ${settings}"
log.debug "Current mode = ${location.mode}, people = ${people.collect{it.label + ': ' + it.currentPresence}}"
// commented out log statement because presence sensor label could contain user's name
//log.debug "Current mode = ${location.mode}, people = ${people.collect{it.label + ': ' + it.currentPresence}}"
unsubscribe()
subscribe(people, "presence", presence)
}

View File

@@ -64,10 +64,12 @@ def meterHandler(evt) {
def lastValue = atomicState.lastValue as double
atomicState.lastValue = meterValue
def dUnit = evt.unit ?: "Watts"
def aboveThresholdValue = aboveThreshold as int
if (meterValue > aboveThresholdValue) {
if (lastValue < aboveThresholdValue) { // only send notifications when crossing the threshold
def msg = "${meter} reported ${evt.value} ${evt.unit} which is above your threshold of ${aboveThreshold}."
def msg = "${meter} reported ${evt.value} ${dUnit} which is above your threshold of ${aboveThreshold}."
sendMessage(msg)
} else {
// log.debug "not sending notification for ${evt.description} because the threshold (${aboveThreshold}) has already been crossed"
@@ -78,7 +80,7 @@ def meterHandler(evt) {
def belowThresholdValue = belowThreshold as int
if (meterValue < belowThresholdValue) {
if (lastValue > belowThresholdValue) { // only send notifications when crossing the threshold
def msg = "${meter} reported ${evt.value} ${evt.unit} which is below your threshold of ${belowThreshold}."
def msg = "${meter} reported ${evt.value} ${dUnit} which is below your threshold of ${belowThreshold}."
sendMessage(msg)
} else {
// log.debug "not sending notification for ${evt.description} because the threshold (${belowThreshold}) has already been crossed"

View File

@@ -54,10 +54,10 @@ def waterWetHandler(evt) {
def alreadySentSms = recentEvents.count { it.value && it.value == "wet" } > 1
if (alreadySentSms) {
log.debug "SMS already sent to $phone within the last $deltaSeconds seconds"
log.debug "SMS already sent within the last $deltaSeconds seconds"
} else {
def msg = "${alarm.displayName} is wet!"
log.debug "$alarm is wet, texting $phone"
log.debug "$alarm is wet, texting phone number"
if (location.contactBookEnabled) {
sendNotificationToContacts(msg, recipients)

View File

@@ -90,7 +90,7 @@ def takeAction(){
}
def sendTextMessage() {
log.debug "$multisensor was open too long, texting $phone"
log.debug "$multisensor was open too long, texting phone"
updateSmsHistory()
def openMinutes = maxOpenTime * (state.smsHistory?.size() ?: 1)

View File

@@ -761,7 +761,7 @@ String displayableTime(timeRemaining) {
return "${minutes}:00"
}
def fraction = "0.${parts[1]}" as double
def seconds = "${60 * fraction as int}".padRight(2, "0")
def seconds = "${60 * fraction as int}".padLeft(2, "0")
return "${minutes}:${seconds}"
}
@@ -1101,4 +1101,4 @@ def hasStartLevel() {
def hasEndLevel() {
return (endLevel != null && endLevel != "")
}
}

View File

@@ -47,13 +47,13 @@ preferences {
def installed() {
log.debug "Installed with settings: ${settings}"
log.debug "Current mode = ${location.mode}, people = ${people.collect{it.label + ': ' + it.currentPresence}}"
// log.debug "Current mode = ${location.mode}, people = ${people.collect{it.label + ': ' + it.currentPresence}}"
subscribe(people, "presence", presence)
}
def updated() {
log.debug "Updated with settings: ${settings}"
log.debug "Current mode = ${location.mode}, people = ${people.collect{it.label + ': ' + it.currentPresence}}"
// log.debug "Current mode = ${location.mode}, people = ${people.collect{it.label + ': ' + it.currentPresence}}"
unsubscribe()
subscribe(people, "presence", presence)
}
@@ -71,11 +71,10 @@ def presence(evt)
def person = getPerson(evt)
def recentNotPresent = person.statesSince("presence", t0).find{it.value == "not present"}
if (recentNotPresent) {
log.debug "skipping notification of arrival of ${person.displayName} because last departure was only ${now() - recentNotPresent.date.time} msec ago"
log.debug "skipping notification of arrival of Person because last departure was only ${now() - recentNotPresent.date.time} msec ago"
}
else {
def message = "${person.displayName} arrived at home, changing mode to '${newMode}'"
log.info message
send(message)
setLocationMode(newMode)
}
@@ -106,6 +105,4 @@ private send(msg) {
sendSms(phone, msg)
}
}
log.debug msg
}

View File

@@ -57,12 +57,11 @@ def scheduleCheck()
def message = message1 ?: "SmartThings - Habit Helper Reminder!"
if (location.contactBookEnabled) {
log.debug "Texting reminder: ($message) to contacts:${recipients?.size()}"
log.debug "Texting reminder to contacts:${recipients?.size()}"
sendNotificationToContacts(message, recipients)
}
else {
log.debug "Texting reminder: ($message) to $phone1"
log.debug "Texting reminder"
sendSms(phone1, message)
}
}

View File

@@ -170,7 +170,7 @@ def bulbDiscovery() {
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, options:newLights
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
}
section {
@@ -724,13 +724,13 @@ private void updateBridgeStatus(childDevice) {
}
/**
* Check if all Hue bridges have been heard from in the last 16 minutes, if not an Offline event will be sent
* for the bridge. Also, set ID number on bridge if not done previously.
* Check if all Hue bridges have been heard from in the last 11 minutes, if not an Offline event will be sent
* for the bridge and all connected lights. Also, set ID number on bridge if not done previously.
*/
private void checkBridgeStatus() {
def bridges = getHueBridges()
// Check if each bridge has been heard from within the last 16 minutes (3 poll intervals times 5 minutes plus buffer)
def time = now() - (1000 * 60 * 30)
// Check if each bridge has been heard from within the last 11 minutes (2 poll intervals times 5 minutes plus buffer)
def time = now() - (1000 * 60 * 11)
bridges.each {
def d = getChildDevice(it.value.mac)
if(d) {
@@ -740,16 +740,21 @@ private void checkBridgeStatus() {
d.sendEvent(name: "idNumber", value: it.value.idNumber)
}
if (it.value.lastActivity < time) { // it.value.lastActivity != null &&
log.warn "Bridge $it.key is Offline"
d.sendEvent(name: "status", value: "Offline")
// set all lights to offline since bridge is not reachable
state.bulbs?.each {it.value.online = false}
} else {
if (it.value.lastActivity < time) { // it.value.lastActivity != null &&
log.warn "Bridge $it.key is Offline"
d.sendEvent(name: "status", value: "Offline")
state.bulbs?.each {
it.value.online = false
}
getChildDevices().each {
it.sendEvent(name: "DeviceWatch-DeviceOffline", value: "offline", isStateChange: true, displayed: false)
}
} else {
d.sendEvent(name: "status", value: "Online")//setOnline(false)
}
}
}
}
}
}
}
def isValidSource(macAddress) {
@@ -757,6 +762,10 @@ def isValidSource(macAddress) {
return (vbridges?.find {"${it.value.mac}" == macAddress}) != null
}
def isInBulbDiscovery() {
return state.inBulbDiscovery
}
/////////////////////////////////////
//CHILD DEVICE METHODS
/////////////////////////////////////
@@ -792,10 +801,12 @@ def parse(childDevice, description) {
}
// Philips Hue priority for color is xy > ct > hs
// For SmartThings, try to always send hue, sat and hex
private sendColorEvents(device, xy, hue, sat, ct, colormode = null) {
if (device == null || (xy == null && hue == null && sat == null && ct == null))
return
def events = [:]
// For now, only care about changing color temperature if requested by user
if (ct != null && (colormode == "ct" || (xy == null && hue == null && sat == null))) {
// for some reason setting Hue to their specified minimum off 153 yields 154, dealt with below
@@ -809,13 +820,13 @@ private sendColorEvents(device, xy, hue, sat, ct, colormode = null) {
if (hue != null) {
// 0-65535
def value = Math.min(Math.round(hue * 100 / 65535), 65535) as int
device.sendEvent([name: "hue", value: value, descriptionText: "Color has changed"])
events["hue"] = [name: "hue", value: value, descriptionText: "Color has changed", displayed: false]
}
if (sat != null) {
// 0-254
def value = Math.round(sat * 100 / 254) as int
device.sendEvent([name: "saturation", value: value, descriptionText: "Color has changed"])
events["saturation"] = [name: "saturation", value: value, descriptionText: "Color has changed", displayed: false]
}
// Following is used to decide what to base hex calculations on since it is preferred to return a colorchange in hex
@@ -827,17 +838,28 @@ private sendColorEvents(device, xy, hue, sat, ct, colormode = null) {
def model = state.bulbs[id]?.modelid
def hex = colorFromXY(xy, model)
// TODO Disabled until a solution for the jumping color picker can be figured out
//device.sendEvent([name: "color", value: hex.toUpperCase(), descriptionText: "Color has changed", displayed: false])
// Create Hue and Saturation events if not previously existing
def hsv = hexToHsv(hex)
if (events["hue"] == null)
events["hue"] = [name: "hue", value: hsv[0], descriptionText: "Color has changed", displayed: false]
if (events["saturation"] == null)
events["saturation"] = [name: "saturation", value: hsv[1], descriptionText: "Color has changed", displayed: false]
events["color"] = [name: "color", value: hex.toUpperCase(), descriptionText: "Color has changed", displayed: true]
} else if (colormode == "hs" || colormode == null) {
// colormode is "hs" or "xy" is missing, default to follow hue/sat which is already handled above
def hueValue = (hue != null) ? events["hue"].value : Integer.parseInt("$device.currentHue")
def satValue = (sat != null) ? events["saturation"].value : Integer.parseInt("$device.currentSaturation")
// TODO Disabled until the standard behavior of lights is defined (hue and sat events are sent above)
//def hex = colorUtil.hslToHex((int) device.currentHue, (int) device.currentSaturation)
// device.sendEvent([name: "color", value: hex.toUpperCase(), descriptionText: "Color has changed"])
def hex = hsvToHex(hueValue, satValue)
events["color"] = [name: "color", value: hex.toUpperCase(), descriptionText: "Color has changed", displayed: true]
}
return debug
boolean sendColorChanged = false
events.each {
device.sendEvent(it.value)
}
}
private sendBasicEvents(device, param, value) {
@@ -878,8 +900,6 @@ private handleCommandResponse(body) {
def updates = [:]
body.each { payload ->
log.debug $payload
if (payload?.success) {
def childDeviceNetworkId = app.id + "/"
def eventType
@@ -951,6 +971,7 @@ private handlePoll(body) {
} else {
state.bulbs[bulb.key]?.online = false
log.warn "$device is not reachable by Hue bridge"
device.sendEvent(name: "DeviceWatch-DeviceOffline", value: "offline", displayed: false, isStateChange: true)
}
}
}
@@ -1091,26 +1112,22 @@ def setColor(childDevice, huesettings) {
def sat = null
def xy = null
// For now ignore model to get a consistent color if same color is set across multiple devices
// def model = state.bulbs[getId(childDevice)]?.modelid
if (huesettings.hex != null) {
// Prefer hue/sat over hex to make sure it works with the majority of the smartapps
if (huesettings.hue != null || huesettings.sat != null) {
// If both hex and hue/sat are set, send all values to bridge to get hue/sat in response from bridge to
// generate hue/sat events even though bridge will prioritize XY when setting color
if (huesettings.hue != null)
value.hue = Math.min(Math.round(huesettings.hue * 65535 / 100), 65535)
if (huesettings.saturation != null)
value.sat = Math.min(Math.round(huesettings.saturation * 254 / 100), 254)
} else if (huesettings.hex != null && false) {
// For now ignore model to get a consistent color if same color is set across multiple devices
// def model = state.bulbs[getId(childDevice)]?.modelid
// value.xy = calculateXY(huesettings.hex, model)
// Once groups, or scenes are introduced it might be a good idea to use unique models again
value.xy = calculateXY(huesettings.hex)
}
// If both hex and hue/sat are set, send all values to bridge to get hue/sat in response from bridge to
// generate hue/sat events even though bridge will prioritize XY when setting color
if (huesettings.hue != null)
value.hue = Math.min(Math.round(huesettings.hue * 65535 / 100), 65535)
else
value.hue = Math.min(Math.round(childDevice.device?.currentValue("hue") * 65535 / 100), 65535)
if (huesettings.saturation != null)
value.sat = Math.min(Math.round(huesettings.saturation * 254 / 100), 254)
else
value.sat = Math.min(Math.round(childDevice.device?.currentValue("saturation") * 254 / 100), 254)
/* Disabled for now due to bad behavior via Lightning Wizard
if (!value.xy) {
// Below will translate values to hex->XY to take into account the color support of the different hue types
@@ -1165,9 +1182,8 @@ private poll() {
def host = getBridgeIP()
def uri = "/api/${state.username}/lights/"
log.debug "GET: $host$uri"
sendHubCommand(new physicalgraph.device.HubAction("""GET ${uri} HTTP/1.1
HOST: ${host}
""", physicalgraph.device.Protocol.LAN, selectedHue))
sendHubCommand(new physicalgraph.device.HubAction("GET ${uri} HTTP/1.1\r\n" +
"HOST: ${host}\r\n\r\n", physicalgraph.device.Protocol.LAN, selectedHue))
}
private isOnline(id) {
@@ -1183,13 +1199,11 @@ private put(path, body) {
log.debug "PUT: $host$uri"
log.debug "BODY: ${bodyJSON}"
sendHubCommand(new physicalgraph.device.HubAction("""PUT $uri HTTP/1.1
HOST: ${host}
Content-Length: ${length}
${bodyJSON}
""", physicalgraph.device.Protocol.LAN, "${selectedHue}"))
sendHubCommand(new physicalgraph.device.HubAction("PUT $uri HTTP/1.1\r\n" +
"HOST: ${host}\r\n" +
"Content-Length: ${length}\r\n" +
"\r\n" +
"${bodyJSON}", physicalgraph.device.Protocol.LAN, "${selectedHue}"))
}
/*
@@ -1647,3 +1661,101 @@ private boolean checkPointInLampsReach(p, colorPoints) {
return false;
}
}
/**
* Converts an RGB color in hex to HSV.
* Algorithm based on http://en.wikipedia.org/wiki/HSV_color_space.
*
* @param colorStr color value in hex (#ff03d3)
*
* @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 max = Math.max(Math.max(r, g), b)
def min = Math.min(Math.min(r, g), b)
def h, s, v = max;
def d = max - min;
s = max == 0 ? 0 : d / max;
if(max == min){
h = 0;
}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;
}
h /= 6;
}
return [(h * 100).round(), (s * 100).round(), (v * 100).round()];
}
/**
* Converts HSV 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)
* @return the color in hex (#ff03d3)
*/
def hsvToHex(hue, sat, value = 100){
def r, g, b;
def h = hue / 100
def s = sat / 100
def v = value / 100
def i = Math.floor(h * 6);
def f = h * 6 - i;
def p = v * (1 - s);
def q = v * (1 - f * s);
def t = v * (1 - (1 - f) * s);
switch (i % 6) {
case 0:
r = v
g = t
b = p
break
case 1:
r = q
g = v
b = p
break
case 2:
r = p
g = v
b = t
break
case 3:
r = p
g = q
b = v
break
case 4:
r = t
g = p
b = v
break
case 5:
r = v
g = p
b = q
break
}
// Converting float components to int components.
def r1 = String.format("%02X", (int) (r * 255.0f));
def g1 = String.format("%02X", (int) (g * 255.0f));
def b1 = String.format("%02X", (int) (b * 255.0f));
return "#$r1$g1$b1"
}

View File

@@ -53,14 +53,14 @@ def accelerationActiveHandler(evt) {
def alreadySentSms = recentEvents.count { it.value && it.value == "active" } > 1
if (alreadySentSms) {
log.debug "SMS already sent to $phone1 within the last $deltaSeconds seconds"
log.debug "SMS already sent within the last $deltaSeconds seconds"
} else {
if (location.contactBookEnabled) {
log.debug "$accelerationSensor has moved, texting contacts: ${recipients?.size()}"
log.debug "accelerationSensor has moved, texting contacts: ${recipients?.size()}"
sendNotificationToContacts("${accelerationSensor.label ?: accelerationSensor.name} moved", recipients)
}
else {
log.debug "$accelerationSensor has moved, texting $phone1"
log.debug "accelerationSensor has moved, sending text message"
sendSms(phone1, "${accelerationSensor.label ?: accelerationSensor.name} moved")
}
}

View File

@@ -69,10 +69,10 @@ def temperatureHandler(evt) {
def alreadySentSms = recentEvents.count { it.doubleValue >= tooHot } > 1
if (alreadySentSms) {
log.debug "SMS already sent to $phone1 within the last $deltaMinutes minutes"
log.debug "SMS already sent within the last $deltaMinutes minutes"
// TODO: Send "Temperature back to normal" SMS, turn switch off
} else {
log.debug "Temperature rose above $tooHot: sending SMS to $phone1 and activating $mySwitch"
log.debug "Temperature rose above $tooHot: sending SMS and activating $mySwitch"
def tempScale = location.temperatureScale ?: "F"
send("${temperatureSensor1.displayName} is too hot, reporting a temperature of ${evt.value}${evt.unit?:tempScale}")
switch1?.on()

View File

@@ -50,9 +50,9 @@ def authPage() {
}
def description = "Tap to enter LIFX credentials"
def redirectUrl = "${serverUrl}/oauth/initialize?appId=${app.id}&access_token=${state.accessToken}&apiServerUrl=${apiServerUrl}" // this triggers oauthInit() below
// def redirectUrl = "${apiServerUrl}"
log.debug "app id: ${app.id}"
log.debug "redirect url: ${redirectUrl}"
// def redirectUrl = "${apiServerUrl}"
// log.debug "app id: ${app.id}"
// log.debug "redirect url: ${redirectUrl}"s
return dynamicPage(name: "Credentials", title: "Connect to LIFX", nextPage: null, uninstall: true, install:true) {
section {
href(url:redirectUrl, required:true, title:"Connect to LIFX", description:"Tap here to connect your LIFX account")
@@ -372,7 +372,7 @@ def updateDevices() {
def childDevice = getChildDevice(device.id)
selectors.add("${device.id}")
if (!childDevice) {
log.info("Adding device ${device.id}: ${device.product}")
// log.info("Adding device ${device.id}: ${device.product}")
def data = [
label: device.label,
level: Math.round((device.brightness ?: 1) * 100),

View File

@@ -51,7 +51,7 @@ definition(
}
preferences(oauthPage: "deviceAuthorization") {
page(name: "Credentials", title: "Connect to your Logitech Harmony device", content: "authPage", install: false, nextPage: "deviceAuthorization")
page(name: "Credentials", title: "Connect to your Logitech Harmony device", content: "authPage", install: false, nextPage: "deviceAuthorization")
page(name: "deviceAuthorization", title: "Logitech Harmony device authorization", install: true) {
section("Allow Logitech Harmony to control these things...") {
input "switches", "capability.switch", title: "Which Switches?", multiple: true, required: false
@@ -102,7 +102,8 @@ def authPage() {
description = "Click to enter Harmony Credentials"
def redirectUrl = buildRedirectUrl
return dynamicPage(name: "Credentials", title: "Harmony", nextPage: null, uninstall: true, install:false) {
section { href url:redirectUrl, style:"embedded", required:true, title:"Harmony", description:description }
section { paragraph title: "Note:", "This device has not been officially tested and certified to “Work with SmartThings”. You can connect it to your SmartThings home but performance may vary and we will not be able to provide support or assistance." }
section { href url:redirectUrl, style:"embedded", required:true, title:"Harmony", description:description }
}
} else {
//device discovery request every 5 //25 seconds
@@ -314,8 +315,6 @@ def installed() {
}
def updated() {
unsubscribe()
unschedule()
if (!state.accessToken) {
log.debug "About to create access token"
createAccessToken()

View File

@@ -111,16 +111,23 @@ private sendMessage(evt) {
if (location.contactBookEnabled) {
sendNotificationToContacts(msg, recipients, options)
} else {
if (pushAndPhone != 'No') {
log.debug 'sending push'
options.method = 'push'
sendNotification(msg, options)
}
if (phone) {
options.phone = phone
log.debug 'sending SMS'
sendNotification(msg, options)
if (pushAndPhone != 'No') {
log.debug 'Sending push and SMS'
options.method = 'both'
} else {
log.debug 'Sending SMS'
options.method = 'phone'
}
} else if (pushAndPhone != 'No') {
log.debug 'Sending push'
options.method = 'push'
} else {
log.debug 'Sending nothing'
options.method = 'none'
}
sendNotification(msg, options)
}
if (frequency) {
state[evt.deviceId] = now()

View File

@@ -41,10 +41,10 @@ def updated() {
def presenceHandler(evt) {
if (evt.value == "present") {
log.debug "${presence.label ?: presence.name} has arrived at the ${location}"
// log.debug "${presence.label ?: presence.name} has arrived at the ${location}"
sendPush("${presence.label ?: presence.name} has arrived at the ${location}")
} else if (evt.value == "not present") {
log.debug "${presence.label ?: presence.name} has left the ${location}"
// log.debug "${presence.label ?: presence.name} has left the ${location}"
sendPush("${presence.label ?: presence.name} has left the ${location}")
}
}

View File

@@ -47,7 +47,7 @@ def updated() {
def presenceHandler(evt) {
if (evt.value == "present") {
log.debug "${presence.label ?: presence.name} has arrived at the ${location}"
// log.debug "${presence.label ?: presence.name} has arrived at the ${location}"
if (location.contactBookEnabled) {
sendNotificationToContacts("${presence.label ?: presence.name} has arrived at the ${location}", recipients)
@@ -56,7 +56,7 @@ def presenceHandler(evt) {
sendSms(phone1, "${presence.label ?: presence.name} has arrived at the ${location}")
}
} else if (evt.value == "not present") {
log.debug "${presence.label ?: presence.name} has left the ${location}"
// log.debug "${presence.label ?: presence.name} has left the ${location}"
if (location.contactBookEnabled) {
sendNotificationToContacts("${presence.label ?: presence.name} has left the ${location}", recipients)

View File

@@ -67,7 +67,7 @@ def updated() {
}
def subscribe() {
log.debug "present: ${cars.collect{it.displayName + ': ' + it.currentPresence}}"
// log.debug "present: ${cars.collect{it.displayName + ': ' + it.currentPresence}}"
subscribe(doorSensor, "contact", garageDoorContact)
subscribe(cars, "presence", carPresence)

View File

@@ -71,7 +71,7 @@ def updated() {
private subscribeToEvents()
{
subscribe intrusionMotions, "motion", intruderMotion
subscribe residentMotions, "motion", residentMotion
// subscribe residentMotions, "motion", residentMotion
subscribe intrusionContacts, "contact", contact
subscribe alarms, "alarm", alarm
subscribe(app, appTouch)
@@ -156,6 +156,7 @@ def residentMotion(evt)
// startReArmSequence()
// }
//}
unsubscribe(residentMotions)
}
def contact(evt)
@@ -214,7 +215,7 @@ def checkForReArm()
}
else {
log.warn "checkForReArm: lastIntruderMotion was null, unable to check for re-arming intrusion detection"
}
}
}
private startAlarmSequence()

View File

@@ -48,7 +48,7 @@ def updated()
def contactOpenHandler(evt) {
log.trace "$evt.value: $evt, $settings"
log.debug "$contact1 was opened, texting $phone1"
log.debug "$contact1 was opened, sending text"
if (location.contactBookEnabled) {
sendNotificationToContacts("Your ${contact1.label ?: contact1.name} was opened", recipients)
}

View File

@@ -50,7 +50,7 @@ def updated() {
def motionActiveHandler(evt) {
log.trace "$evt.value: $evt, $settings"
if (presence1.latestValue("presence") == "not present") {
// Don't send a continuous stream of text messages
def deltaSeconds = 10
@@ -60,14 +60,14 @@ def motionActiveHandler(evt) {
def alreadySentSms = recentEvents.count { it.value && it.value == "active" } > 1
if (alreadySentSms) {
log.debug "SMS already sent to $phone1 within the last $deltaSeconds seconds"
log.debug "SMS already sent within the last $deltaSeconds seconds"
} else {
if (location.contactBookEnabled) {
log.debug "$motion1 has moved while you were out, sending notifications to: ${recipients?.size()}"
sendNotificationToContacts("${motion1.label} ${motion1.name} moved while you were out", recipients)
}
else {
log.debug "$motion1 has moved while you were out, texting $phone1"
log.debug "$motion1 has moved while you were out, sending text"
sendSms(phone1, "${motion1.label} ${motion1.name} moved while you were out")
}
}

View File

@@ -53,13 +53,13 @@ def accelerationActiveHandler(evt) {
def alreadySentSms = recentEvents.count { it.value && it.value == "active" } > 1
if (alreadySentSms) {
log.debug "SMS already sent to $phone1 within the last $deltaSeconds seconds"
log.debug "SMS already sent to phone within the last $deltaSeconds seconds"
} else {
if (location.contactBookEnabled) {
sendNotificationToContacts("Gun case has moved!", recipients)
}
else {
log.debug "$accelerationSensor has moved, texting $phone1"
log.debug "$accelerationSensor has moved, texting phone"
sendSms(phone1, "Gun case has moved!")
}
}

View File

@@ -86,6 +86,7 @@ def firstPage()
def lightSwitchesDiscovered = lightSwitchesDiscovered()
return dynamicPage(name:"firstPage", title:"Discovery Started!", nextPage:"", refreshInterval: refreshInterval, install:true, uninstall: true) {
section { paragraph title: "Note:", "This device has not been officially tested and certified to “Work with SmartThings”. You can connect it to your SmartThings home but performance may vary and we will not be able to provide support or assistance." }
section("Select a device...") {
input "selectedSwitches", "enum", required:false, title:"Select Wemo Switches \n(${switchesDiscovered.size() ?: 0} found)", multiple:true, options:switchesDiscovered
input "selectedMotions", "enum", required:false, title:"Select Wemo Motions \n(${motionsDiscovered.size() ?: 0} found)", multiple:true, options:motionsDiscovered
@@ -681,4 +682,4 @@ private Boolean hasAllHubsOver(String desiredFirmware) {
private List getRealHubFirmwareVersions() {
return location.hubs*.firmwareVersionString.findAll { it }
}
}

View File

@@ -60,7 +60,7 @@ def authPage() {
def oauthInitUrl() {
def token = getToken()
log.debug "initiateOauth got token: $token"
//log.debug "initiateOauth got token: $token"
// store these for validate after the user takes the oauth journey
state.oauth_request_token = token.oauth_token
@@ -76,7 +76,7 @@ def getToken() {
]
def requestTokenBaseUrl = "https://oauth.withings.com/account/request_token"
def url = buildSignedUrl(requestTokenBaseUrl, params)
log.debug "getToken - url: $url"
//log.debug "getToken - url: $url"
return getJsonFromUrl(url)
}
@@ -182,7 +182,7 @@ def exchangeToken() {
def requestTokenBaseUrl = "https://oauth.withings.com/account/access_token"
def url = buildSignedUrl(requestTokenBaseUrl, params, tokenSecret)
log.debug "signed url: $url with secret $tokenSecret"
//log.debug "signed url: $url with secret $tokenSecret"
def token = getJsonFromUrl(url)
@@ -198,8 +198,8 @@ def exchangeToken() {
def load() {
def json = get(getMeasurement(new Date() - 30))
log.debug "swapped, then received: $json"
// removed logging of actual json payload. Can be put back for debugging
log.debug "swapped, then received json"
parse(data:json)
def html = """