Created
July 12, 2016 22:57
-
-
Save paulwalko/baee2e94acd0b0835d87305308af4383 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Initial State Event Streamer (non-buffered) | |
* | |
* Copyright 2016 David Sulpy | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except | |
* in compliance with the License. You may obtain a copy of the License at: | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed | |
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License | |
* for the specific language governing permissions and limitations under the License. | |
* | |
* SmartThings data is sent from this SmartApp to Initial State. This is event data only for | |
* devices for which the user has authorized. Likewise, Initial State's services call this | |
* SmartApp on the user's behalf to configure Initial State specific parameters. The ToS and | |
* Privacy Policy for Initial State can be found here: https://www.initialstate.com/terms | |
*/ | |
definition( | |
name: "DIY Initial State Event Streamer 10", | |
namespace: "initialstate.events", | |
author: "David Sulpy", | |
description: "A SmartThings SmartApp to allow SmartThings events to be viewable inside an Initial State Event Bucket in your https://www.initialstate.com account.", | |
category: "SmartThings Labs", | |
iconUrl: "https://s3.amazonaws.com/initialstate-web-cdn/IS-wordmark-vertica_small.png", | |
iconX2Url: "https://s3.amazonaws.com/initialstate-web-cdn/IS-wordmark-vertical.png", | |
iconX3Url: "https://s3.amazonaws.com/initialstate-web-cdn/IS-wordmark-vertical.png", | |
oauth: [displayName: "Initial State", displayLink: "https://www.initialstate.com"]) | |
import groovy.json.JsonSlurper | |
preferences { | |
section("Choose which devices to monitor...") { | |
input "accelerometers", "capability.accelerationSensor", title: "Accelerometers", multiple: true, required: false | |
input "alarms", "capability.alarm", title: "Alarms", multiple: true, required: false | |
input "batteries", "capability.battery", title: "Batteries", multiple: true, required: false | |
input "beacons", "capability.beacon", title: "Beacons", multiple: true, required: false | |
input "cos", "capability.carbonMonoxideDetector", title: "Carbon Monoxide Detectors", multiple: true, required: false | |
input "colors", "capability.colorControl", title: "Color Controllers", multiple: true, required: false | |
input "contacts", "capability.contactSensor", title: "Contact Sensors", multiple: true, required: false | |
input "doorsControllers", "capability.doorControl", title: "Door Controllers", multiple: true, required: false | |
input "energyMeters", "capability.energyMeter", title: "Energy Meters", multiple: true, required: false | |
input "illuminances", "capability.illuminanceMeasurement", title: "Illuminance Meters", multiple: true, required: false | |
input "locks", "capability.lock", title: "Locks", multiple: true, required: false | |
input "motions", "capability.motionSensor", title: "Motion Sensors", multiple: true, required: false | |
input "musicPlayers", "capability.musicPlayer", title: "Music Players", multiple: true, required: false | |
input "powerMeters", "capability.powerMeter", title: "Power Meters", multiple: true, required: false | |
input "presences", "capability.presenceSensor", title: "Presence Sensors", multiple: true, required: false | |
input "humidities", "capability.relativeHumidityMeasurement", title: "Humidity Meters", multiple: true, required: false | |
input "relaySwitches", "capability.relaySwitch", title: "Relay Switches", multiple: true, required: false | |
input "sleepSensors", "capability.sleepSensor", title: "Sleep Sensors", multiple: true, required: false | |
input "smokeDetectors", "capability.smokeDetector", title: "Smoke Detectors", multiple: true, required: false | |
input "peds", "capability.stepSensor", title: "Pedometers", multiple: true, required: false | |
input "switches", "capability.switch", title: "Switches", multiple: true, required: false | |
input "switchLevels", "capability.switchLevel", title: "Switch Levels", multiple: true, required: false | |
input "temperatures", "capability.temperatureMeasurement", title: "Temperature Sensors", multiple: true, required: false | |
input "thermostats", "capability.thermostat", title: "Thermostats", multiple: true, required: false | |
input "valves", "capability.valve", title: "Valves", multiple: true, required: false | |
input "waterSensors", "capability.waterSensor", title: "Water Sensors", multiple: true, required: false | |
input "arduino", "capability.windowShade", title: "Arduino", multiple: true, required: false | |
} | |
} | |
def subscribeToEvents() { | |
if (accelerometers != null) { | |
subscribe(accelerometers, "acceleration", genericHandler) | |
} | |
if (alarms != null) { | |
subscribe(alarms, "alarm", genericHandler) | |
} | |
if (batteries != null) { | |
subscribe(batteries, "battery", genericHandler) | |
} | |
if (beacons != null) { | |
subscribe(beacons, "presence", genericHandler) | |
} | |
if (cos != null) { | |
subscribe(cos, "carbonMonoxide", genericHandler) | |
} | |
if (colors != null) { | |
subscribe(colors, "hue", genericHandler) | |
subscribe(colors, "saturation", genericHandler) | |
subscribe(colors, "color", genericHandler) | |
} | |
if (contacts != null) { | |
subscribe(contacts, "contact", genericHandler) | |
subscribe(contacts, "valve", genericHandler) | |
subscribe(contacts, "heat1", genericHandler) | |
subscribe(contacts, "heat2", genericHandler) | |
subscribe(contacts, "compressor", genericHandler) | |
subscribe(contacts, "fan", genericHandler) | |
} | |
if (energyMeters != null) { | |
subscribe(energyMeters, "energy", genericHandler) | |
} | |
if (illuminances != null) { | |
subscribe(illuminances, "illuminance", genericHandler) | |
} | |
if (locks != null) { | |
subscribe(locks, "lock", genericHandler) | |
} | |
if (motions != null) { | |
subscribe(motions, "motion", genericHandler) | |
} | |
if (musicPlayers != null) { | |
subscribe(musicPlayers, "status", genericHandler) | |
subscribe(musicPlayers, "level", genericHandler) | |
subscribe(musicPlayers, "trackDescription", genericHandler) | |
subscribe(musicPlayers, "trackData", genericHandler) | |
subscribe(musicPlayers, "mute", genericHandler) | |
} | |
if (powerMeters != null) { | |
subscribe(powerMeters, "power", genericHandler) | |
} | |
if (presences != null) { | |
subscribe(presences, "presence", genericHandler) | |
} | |
if (humidities != null) { | |
subscribe(humidities, "humidity", genericHandler) | |
} | |
if (relaySwitches != null) { | |
subscribe(relaySwitches, "switch", genericHandler) | |
} | |
if (sleepSensors != null) { | |
subscribe(sleepSensors, "sleeping", genericHandler) | |
} | |
if (smokeDetectors != null) { | |
subscribe(smokeDetectors, "smoke", genericHandler) | |
} | |
if (peds != null) { | |
subscribe(peds, "steps", genericHandler) | |
subscribe(peds, "goal", genericHandler) | |
} | |
if (switches != null) { | |
subscribe(switches, "switch", genericHandler) | |
} | |
if (switchLevels != null) { | |
subscribe(switchLevels, "level", genericHandler) | |
} | |
if (temperatures != null) { | |
subscribe(temperatures, "temperature", genericHandler) | |
} | |
if (thermostats != null) { | |
subscribe(thermostats, "temperature", genericHandler) | |
subscribe(thermostats, "heatingSetpoint", genericHandler) | |
subscribe(thermostats, "coolingSetpoint", genericHandler) | |
subscribe(thermostats, "thermostatSetpoint", genericHandler) | |
subscribe(thermostats, "thermostatMode", genericHandler) | |
subscribe(thermostats, "thermostatFanMode", genericHandler) | |
subscribe(thermostats, "thermostatOperatingState", genericHandler) | |
} | |
if (valves != null) { | |
subscribe(valves, "contact", genericHandler) | |
} | |
if (waterSensors != null) { | |
subscribe(waterSensors, "water", genericHandler) | |
} | |
if (arduino != null) { | |
subscribe(arduino, "pressure", genericHandler) | |
subscribe(arduino, "supply", genericHandler) | |
subscribe(arduino, "suction", genericHandler) | |
subscribe(arduino, "return", genericHandler) | |
subscribe(arduino, "freonDelta", genericHandler) | |
subscribe(arduino, "airDelta", genericHandler) | |
subscribe(arduino, "valve", genericHandler) | |
subscribe(arduino, "heat stage 1", genericHandler) | |
subscribe(arduino, "heat stage 2", genericHandler) | |
subscribe(arduino, "compressor", genericHandler) | |
subscribe(arduino, "fan", genericHandler) | |
subscribe(arduino, "water", genericHandler) | |
} | |
} | |
def installed() { | |
atomicState.version = "1.0.18 (unbuffered)" | |
atomicState.bucketName = "SmartThings" //change if needed | |
atomicState.bucketKey = "<PRIVATE>" //change if wanted | |
atomicState.accessKey = "<PRIVATE>" //MUST CHANGE | |
subscribeToEvents() | |
atomicState.isBucketCreated = false | |
atomicState.grokerSubdomain = "groker" | |
log.debug "installed (version $atomicState.version)" | |
} | |
def updated() { | |
atomicState.version = "1.0.18 (unbuffered)" | |
unsubscribe() | |
if (atomicState.bucketKey != null && atomicState.accessKey != null) { | |
atomicState.isBucketCreated = false | |
} | |
if (atomicState.grokerSubdomain == null || atomicState.grokerSubdomain == "") { | |
atomicState.grokerSubdomain = "groker" | |
} | |
subscribeToEvents() | |
log.debug "updated (version $atomicState.version)" | |
} | |
def uninstalled() { | |
log.debug "uninstalled (version $atomicState.version)" | |
} | |
def tryCreateBucket() { | |
// can't ship events if there is no grokerSubdomain | |
if (atomicState.grokerSubdomain == null || atomicState.grokerSubdomain == "") { | |
log.error "streaming url is currently null" | |
return | |
} | |
// if the bucket has already been created, no need to continue | |
if (atomicState.isBucketCreated) { | |
return | |
} | |
if (!atomicState.bucketName) { | |
atomicState.bucketName = atomicState.bucketKey | |
} | |
if (!atomicState.accessKey) { | |
return | |
} | |
def bucketName = "${atomicState.bucketName}" | |
def bucketKey = "${atomicState.bucketKey}" | |
def accessKey = "${atomicState.accessKey}" | |
def bucketCreateBody = new JsonSlurper().parseText("{\"bucketKey\": \"$bucketKey\", \"bucketName\": \"$bucketName\"}") | |
def bucketCreatePost = [ | |
uri: "https://${atomicState.grokerSubdomain}.initialstate.com/api/buckets", | |
headers: [ | |
"Content-Type": "application/json", | |
"X-IS-AccessKey": accessKey | |
], | |
body: bucketCreateBody | |
] | |
log.debug bucketCreatePost | |
try { | |
// Create a bucket on Initial State so the data has a logical grouping | |
httpPostJson(bucketCreatePost) { resp -> | |
log.debug "bucket posted" | |
if (resp.status >= 400) { | |
log.error "bucket not created successfully" | |
} else { | |
atomicState.isBucketCreated = true | |
} | |
} | |
} catch (e) { | |
log.error "bucket creation error: $e" | |
} | |
} | |
def genericHandler(evt) { | |
log.trace "$evt.displayName($evt.name:$evt.unit) $evt.value" | |
def key = "$evt.displayName($evt.name)" | |
if (evt.unit != null) { | |
key = "$evt.displayName(${evt.name}_$evt.unit)" | |
} | |
def value = "$evt.value" | |
tryCreateBucket() | |
eventHandler(key, value) | |
} | |
def eventHandler(name, value) { | |
def epoch = now() / 1000 | |
def event = new JsonSlurper().parseText("{\"key\": \"$name\", \"value\": \"$value\", \"epoch\": \"$epoch\"}") | |
tryShipEvents(event) | |
log.debug "Shipped Event: " + event | |
} | |
def tryShipEvents(event) { | |
def grokerSubdomain = atomicState.grokerSubdomain | |
// can't ship events if there is no grokerSubdomain | |
if (grokerSubdomain == null || grokerSubdomain == "") { | |
log.error "streaming url is currently null" | |
return | |
} | |
def accessKey = atomicState.accessKey | |
def bucketKey = atomicState.bucketKey | |
// can't ship if access key and bucket key are null, so finish trying | |
if (accessKey == null || bucketKey == null) { | |
return | |
} | |
def eventPost = [ | |
uri: "https://${grokerSubdomain}.initialstate.com/api/events", | |
headers: [ | |
"Content-Type": "application/json", | |
"X-IS-BucketKey": "${bucketKey}", | |
"X-IS-AccessKey": "${accessKey}", | |
"Accept-Version": "0.0.2" | |
], | |
body: event | |
] | |
try { | |
// post the events to initial state | |
httpPostJson(eventPost) { resp -> | |
log.debug "shipped events and got ${resp.status}" | |
if (resp.status >= 400) { | |
log.error "shipping failed... ${resp.data}" | |
} | |
} | |
} catch (e) { | |
log.error "shipping events failed: $e" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment