mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-22 13:20:53 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e21a8673ed | ||
|
|
3b89368d45 | ||
|
|
12f6039de5 | ||
|
|
65c9da32e7 | ||
|
|
7147770e2d |
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Author: Fidure
|
* Author: Fidure
|
||||||
* Date: 2014-12-13
|
* Date: 2014-12-13
|
||||||
* Updated: 2015-08-26
|
* Updated: 2016-1-29
|
||||||
*/
|
*/
|
||||||
metadata {
|
metadata {
|
||||||
// Automatically generated. Make future change here.
|
// Automatically generated. Make future change here.
|
||||||
@@ -207,7 +207,8 @@ def parse(String description) {
|
|||||||
case "0000":
|
case "0000":
|
||||||
map.name = "temperature"
|
map.name = "temperature"
|
||||||
map.value = getTemperature(atMap.value)
|
map.value = getTemperature(atMap.value)
|
||||||
result += createEvent("name":"displayTemperature", "value": getDisplayTemperature(atMap.value))
|
result += createEvent("name":"displayTemperature", "value":
|
||||||
|
getDisplayTemperature(atMap.value))
|
||||||
break;
|
break;
|
||||||
case "0005":
|
case "0005":
|
||||||
//log.debug "hex time: ${descMap.value}"
|
//log.debug "hex time: ${descMap.value}"
|
||||||
@@ -227,7 +228,7 @@ def parse(String description) {
|
|||||||
case "0012":
|
case "0012":
|
||||||
map.name = "heatingSetpoint"
|
map.name = "heatingSetpoint"
|
||||||
map.value = getDisplayTemperature(atMap.value)
|
map.value = getDisplayTemperature(atMap.value)
|
||||||
updateSetpoint(map.name,map.value)
|
updateSetpoint(map.name,map.value)
|
||||||
break;
|
break;
|
||||||
case "001c":
|
case "001c":
|
||||||
map.name = "thermostatMode"
|
map.name = "thermostatMode"
|
||||||
@@ -298,7 +299,7 @@ def parseDescriptionAsMap(description) {
|
|||||||
def size = Long.parseLong(''+ map.get('size'), 16)
|
def size = Long.parseLong(''+ map.get('size'), 16)
|
||||||
def index = 12;
|
def index = 12;
|
||||||
def len
|
def len
|
||||||
|
|
||||||
//log.trace "processing multi attributes"
|
//log.trace "processing multi attributes"
|
||||||
while((index-12) < size) {
|
while((index-12) < size) {
|
||||||
attrId = flipHexStringEndianness(raw[index..(index+3)])
|
attrId = flipHexStringEndianness(raw[index..(index+3)])
|
||||||
@@ -313,9 +314,9 @@ def parseDescriptionAsMap(description) {
|
|||||||
list += ['attrId': "$attrId", 'encoding':"$encoding", 'value': "$value"]
|
list += ['attrId': "$attrId", 'encoding':"$encoding", 'value': "$value"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
list += ['attrId': "$attrId", 'encoding': "$encoding", 'value': "$value"]
|
list += ['attrId': "$attrId", 'encoding': "$encoding", 'value': "$value"]
|
||||||
|
|
||||||
map.remove('value')
|
map.remove('value')
|
||||||
map.remove('encoding')
|
map.remove('encoding')
|
||||||
map.remove('attrId')
|
map.remove('attrId')
|
||||||
@@ -339,8 +340,9 @@ def getDataLengthByType(t)
|
|||||||
"2a":3, "2b":4, "2c":5, "2d":6, "2e":7, "2f":8, "30":1, "31":2, "38":2, "39":4, "40":8, "e0":4, "e1":4, "e2":4,
|
"2a":3, "2b":4, "2c":5, "2d":6, "2e":7, "2f":8, "30":1, "31":2, "38":2, "39":4, "40":8, "e0":4, "e1":4, "e2":4,
|
||||||
"e8":2, "e9":2, "ea":4, "f0":8, "f1":16]
|
"e8":2, "e9":2, "ea":4, "f0":8, "f1":16]
|
||||||
|
|
||||||
// return number of hex chars
|
// return number of hex chars if the type is not in the map,
|
||||||
return map.get(t) * 2
|
// then it's likely a malformed msg and should not be parsed
|
||||||
|
return (map.get(t) ?: 256) * 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -377,15 +379,13 @@ def updateSetpoint(attrib, val)
|
|||||||
|
|
||||||
def value = '--';
|
def value = '--';
|
||||||
|
|
||||||
|
if (("heat" == mode && heat != null) ||
|
||||||
|
("auto" == mode && runningMode == "heat" && heat != null))
|
||||||
|
value = (attrib == "heatingSetpoint")? val : heat;
|
||||||
|
else if (("cool" == mode && cool != null) || ("auto" == mode && runningMode == "cool" && cool != null))
|
||||||
|
value = (attrib == "coolingSetpoint")? val : cool;
|
||||||
|
|
||||||
|
|
||||||
if ("heat" == mode && heat != null)
|
|
||||||
value = heat;
|
|
||||||
else if ("cool" == mode && cool != null)
|
|
||||||
value = cool;
|
|
||||||
else if ("auto" == mode && runningMode == "cool" && cool != null)
|
|
||||||
value = cool;
|
|
||||||
else if ("auto" == mode && runningMode == "heat" && heat != null)
|
|
||||||
value = heat;
|
|
||||||
|
|
||||||
sendEvent("name":"displaySetpoint", "value": value)
|
sendEvent("name":"displaySetpoint", "value": value)
|
||||||
}
|
}
|
||||||
@@ -565,7 +565,7 @@ def convertToTime(data)
|
|||||||
def time = Integer.parseInt("$data", 16) as long;
|
def time = Integer.parseInt("$data", 16) as long;
|
||||||
time *= 1000;
|
time *= 1000;
|
||||||
time += 946684800000; // 481418694
|
time += 946684800000; // 481418694
|
||||||
time -= location.timeZone.getRawOffset() + location.timeZone.getDSTSavings();
|
time -= location.timeZone.getOffset(date.getTime());
|
||||||
|
|
||||||
def d = new Date(time);
|
def d = new Date(time);
|
||||||
|
|
||||||
@@ -611,12 +611,14 @@ def checkLastTimeSync(delay)
|
|||||||
if (!lastSync)
|
if (!lastSync)
|
||||||
lastSync = "${new Date(0)}"
|
lastSync = "${new Date(0)}"
|
||||||
|
|
||||||
if (settings.sync_clock ?: false && lastSync != new Date(0))
|
if (!settings.sync_clock)
|
||||||
{
|
{
|
||||||
sendEvent("name":"lastTimeSync", "value":"${new Date(0)}")
|
if (lastSync != new Date(0))
|
||||||
}
|
{
|
||||||
|
sendEvent("name":"lastTimeSync", "value":"${new Date(0)}")
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
long duration = (new Date()).getTime() - (new Date(lastSync)).getTime()
|
long duration = (new Date()).getTime() - (new Date(lastSync)).getTime()
|
||||||
|
|
||||||
@@ -649,7 +651,7 @@ def refresh()
|
|||||||
{
|
{
|
||||||
log.debug "refresh called"
|
log.debug "refresh called"
|
||||||
// log.trace "list: " + readAttributesCommand(0x201, [0x1C,0x1E,0x23])
|
// log.trace "list: " + readAttributesCommand(0x201, [0x1C,0x1E,0x23])
|
||||||
|
|
||||||
readAttributesCommand(0x201, [0x00,0x11,0x12]) +
|
readAttributesCommand(0x201, [0x00,0x11,0x12]) +
|
||||||
readAttributesCommand(0x201, [0x1C,0x1E,0x23]) +
|
readAttributesCommand(0x201, [0x1C,0x1E,0x23]) +
|
||||||
readAttributesCommand(0x201, [0x24,0x25,0x29]) +
|
readAttributesCommand(0x201, [0x24,0x25,0x29]) +
|
||||||
@@ -731,7 +733,7 @@ def setThermostatMode(String next) {
|
|||||||
def val = (getModeMap().find { it.value == next }?.key)?: "00"
|
def val = (getModeMap().find { it.value == next }?.key)?: "00"
|
||||||
|
|
||||||
// log.trace "mode changing to $next sending value: $val"
|
// log.trace "mode changing to $next sending value: $val"
|
||||||
|
|
||||||
sendEvent("name":"thermostatMode", "value":"$next")
|
sendEvent("name":"thermostatMode", "value":"$next")
|
||||||
["st wattr 0x${device.deviceNetworkId} 1 0x201 0x1C 0x30 {$val}"] +
|
["st wattr 0x${device.deviceNetworkId} 1 0x201 0x1C 0x30 {$val}"] +
|
||||||
refresh()
|
refresh()
|
||||||
@@ -805,32 +807,31 @@ def lock()
|
|||||||
//log.debug "current lock is: ${val}"
|
//log.debug "current lock is: ${val}"
|
||||||
|
|
||||||
if (val == "00")
|
if (val == "00")
|
||||||
val = getLockMap().find { it.value == (settings.lock_level ?: "Full") }?.key
|
val = getLockMap().find { it.value == (settings.lock_level ?: "Unlocked") }?.key
|
||||||
else
|
else
|
||||||
val = "00"
|
val = "00"
|
||||||
|
|
||||||
"st rattr 0x${device.deviceNetworkId} 1 0x204 0x01"
|
["st wattr 0x${device.deviceNetworkId} 1 0x204 1 0x30 {${val}}",
|
||||||
|
"st rattr 0x${device.deviceNetworkId} 1 0x204 0x01", "delay 500"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def setThermostatTime()
|
def setThermostatTime()
|
||||||
{
|
{
|
||||||
|
|
||||||
if ((settings.sync_clock ?: false))
|
if (false == (settings.sync_clock ?: false))
|
||||||
{
|
{
|
||||||
log.debug "sync time is disabled, leaving"
|
log.debug "sync time is disabled, leaving"
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Date date = new Date();
|
Date date = new Date();
|
||||||
String zone = location.timeZone.getRawOffset() + " DST " + location.timeZone.getDSTSavings();
|
String zone = location.timeZone.getRawOffset() + " DST " + location.timeZone.getDSTSavings();
|
||||||
|
|
||||||
long millis = date.getTime(); // Millis since Unix epoch
|
long millis = date.getTime(); // Millis since Unix epoch
|
||||||
millis -= 946684800000; // adjust for ZigBee EPOCH
|
millis -= 946684800000; // adjust for ZigBee EPOCH
|
||||||
// adjust for time zone and DST offset
|
// adjust for time zone and DST offset
|
||||||
millis += location.timeZone.getRawOffset() + location.timeZone.getDSTSavings();
|
millis += location.timeZone.getOffset(date.getTime());
|
||||||
//convert to seconds
|
//convert to seconds
|
||||||
millis /= 1000;
|
millis /= 1000;
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ metadata {
|
|||||||
capability "Switch"
|
capability "Switch"
|
||||||
capability "Sensor"
|
capability "Sensor"
|
||||||
|
|
||||||
fingerprint profileId: "0104", inClusters: "0000,0003,0006", outClusters: "0019"
|
fingerprint profileId: "0104", inClusters: "0006, 0004, 0003, 0000, 0005", outClusters: "0019", manufacturer: "Compacta International, Ltd", model: "ZBMPlug15", deviceJoinName: "SmartPower Outlet V1"
|
||||||
}
|
}
|
||||||
|
|
||||||
// simulator metadata
|
// simulator metadata
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Initial State Event Streamer
|
* Initial State Event Streamer
|
||||||
*
|
*
|
||||||
* Copyright 2015 David Sulpy
|
* Copyright 2016 David Sulpy
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
* 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:
|
* in compliance with the License. You may obtain a copy of the License at:
|
||||||
@@ -77,6 +77,62 @@ mappings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def getAccessKey() {
|
||||||
|
log.trace "get access key"
|
||||||
|
if (atomicState.accessKey == null) {
|
||||||
|
httpError(404, "Access Key Not Found")
|
||||||
|
} else {
|
||||||
|
[
|
||||||
|
accessKey: atomicState.accessKey
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def getBucketKey() {
|
||||||
|
log.trace "get bucket key"
|
||||||
|
if (atomicState.bucketKey == null) {
|
||||||
|
httpError(404, "Bucket key Not Found")
|
||||||
|
} else {
|
||||||
|
[
|
||||||
|
bucketKey: atomicState.bucketKey,
|
||||||
|
bucketName: atomicState.bucketName
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def setBucketKey() {
|
||||||
|
log.trace "set bucket key"
|
||||||
|
def newBucketKey = request.JSON?.bucketKey
|
||||||
|
def newBucketName = request.JSON?.bucketName
|
||||||
|
|
||||||
|
log.debug "bucket name: $newBucketName"
|
||||||
|
log.debug "bucket key: $newBucketKey"
|
||||||
|
|
||||||
|
if (newBucketKey && (newBucketKey != atomicState.bucketKey || newBucketName != atomicState.bucketName)) {
|
||||||
|
atomicState.bucketKey = "$newBucketKey"
|
||||||
|
atomicState.bucketName = "$newBucketName"
|
||||||
|
atomicState.isBucketCreated = false
|
||||||
|
}
|
||||||
|
|
||||||
|
tryCreateBucket()
|
||||||
|
}
|
||||||
|
|
||||||
|
def setAccessKey() {
|
||||||
|
log.trace "set access key"
|
||||||
|
def newAccessKey = request.JSON?.accessKey
|
||||||
|
def newGrokerSubdomain = request.JSON?.grokerSubdomain
|
||||||
|
|
||||||
|
if (newGrokerSubdomain && newGrokerSubdomain != "" && newGrokerSubdomain != atomicState.grokerSubdomain) {
|
||||||
|
atomicState.grokerSubdomain = "$newGrokerSubdomain"
|
||||||
|
atomicState.isBucketCreated = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newAccessKey && newAccessKey != atomicState.accessKey) {
|
||||||
|
atomicState.accessKey = "$newAccessKey"
|
||||||
|
atomicState.isBucketCreated = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def subscribeToEvents() {
|
def subscribeToEvents() {
|
||||||
if (accelerometers != null) {
|
if (accelerometers != null) {
|
||||||
subscribe(accelerometers, "acceleration", genericHandler)
|
subscribe(accelerometers, "acceleration", genericHandler)
|
||||||
@@ -169,85 +225,27 @@ def subscribeToEvents() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def getAccessKey() {
|
|
||||||
log.trace "get access key"
|
|
||||||
if (atomicState.accessKey == null) {
|
|
||||||
httpError(404, "Access Key Not Found")
|
|
||||||
} else {
|
|
||||||
[
|
|
||||||
accessKey: atomicState.accessKey
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def getBucketKey() {
|
|
||||||
log.trace "get bucket key"
|
|
||||||
if (atomicState.bucketKey == null) {
|
|
||||||
httpError(404, "Bucket key Not Found")
|
|
||||||
} else {
|
|
||||||
[
|
|
||||||
bucketKey: atomicState.bucketKey,
|
|
||||||
bucketName: atomicState.bucketName
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def setBucketKey() {
|
|
||||||
log.trace "set bucket key"
|
|
||||||
def newBucketKey = request.JSON?.bucketKey
|
|
||||||
def newBucketName = request.JSON?.bucketName
|
|
||||||
|
|
||||||
log.debug "bucket name: $newBucketName"
|
|
||||||
log.debug "bucket key: $newBucketKey"
|
|
||||||
|
|
||||||
if (newBucketKey && (newBucketKey != atomicState.bucketKey || newBucketName != atomicState.bucketName)) {
|
|
||||||
atomicState.bucketKey = "$newBucketKey"
|
|
||||||
atomicState.bucketName = "$newBucketName"
|
|
||||||
atomicState.isBucketCreated = false
|
|
||||||
}
|
|
||||||
|
|
||||||
tryCreateBucket()
|
|
||||||
}
|
|
||||||
|
|
||||||
def setAccessKey() {
|
|
||||||
log.trace "set access key"
|
|
||||||
def newAccessKey = request.JSON?.accessKey
|
|
||||||
def newGrokerSubdomain = request.JSON?.grokerSubdomain
|
|
||||||
|
|
||||||
if (newGrokerSubdomain && newGrokerSubdomain != "" && newGrokerSubdomain != atomicState.grokerSubdomain) {
|
|
||||||
atomicState.grokerSubdomain = "$newGrokerSubdomain"
|
|
||||||
atomicState.isBucketCreated = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newAccessKey && newAccessKey != atomicState.accessKey) {
|
|
||||||
atomicState.accessKey = "$newAccessKey"
|
|
||||||
atomicState.isBucketCreated = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def installed() {
|
def installed() {
|
||||||
atomicState.version = "1.0.18"
|
atomicState.version = "1.1.0"
|
||||||
|
|
||||||
|
atomicState.isBucketCreated = false
|
||||||
|
atomicState.grokerSubdomain = "groker"
|
||||||
|
|
||||||
subscribeToEvents()
|
subscribeToEvents()
|
||||||
|
|
||||||
atomicState.isBucketCreated = false
|
atomicState.isBucketCreated = false
|
||||||
atomicState.grokerSubdomain = "groker"
|
atomicState.grokerSubdomain = "groker"
|
||||||
atomicState.eventBuffer = []
|
|
||||||
|
|
||||||
runEvery15Minutes(flushBuffer)
|
|
||||||
|
|
||||||
log.debug "installed (version $atomicState.version)"
|
log.debug "installed (version $atomicState.version)"
|
||||||
}
|
}
|
||||||
|
|
||||||
def updated() {
|
def updated() {
|
||||||
atomicState.version = "1.0.18"
|
atomicState.version = "1.1.0"
|
||||||
unsubscribe()
|
unsubscribe()
|
||||||
|
|
||||||
if (atomicState.bucketKey != null && atomicState.accessKey != null) {
|
if (atomicState.bucketKey != null && atomicState.accessKey != null) {
|
||||||
atomicState.isBucketCreated = false
|
atomicState.isBucketCreated = false
|
||||||
}
|
}
|
||||||
if (atomicState.eventBuffer == null) {
|
|
||||||
atomicState.eventBuffer = []
|
|
||||||
}
|
|
||||||
if (atomicState.grokerSubdomain == null || atomicState.grokerSubdomain == "") {
|
if (atomicState.grokerSubdomain == null || atomicState.grokerSubdomain == "") {
|
||||||
atomicState.grokerSubdomain = "groker"
|
atomicState.grokerSubdomain = "groker"
|
||||||
}
|
}
|
||||||
@@ -327,37 +325,17 @@ def genericHandler(evt) {
|
|||||||
eventHandler(key, value)
|
eventHandler(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a handler function for flushing the event buffer
|
|
||||||
// after a specified amount of time to reduce the load on ST servers
|
|
||||||
def flushBuffer() {
|
|
||||||
def eventBuffer = atomicState.eventBuffer
|
|
||||||
log.trace "About to flush the buffer on schedule"
|
|
||||||
if (eventBuffer != null && eventBuffer.size() > 0) {
|
|
||||||
atomicState.eventBuffer = []
|
|
||||||
tryShipEvents(eventBuffer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def eventHandler(name, value) {
|
def eventHandler(name, value) {
|
||||||
def epoch = now() / 1000
|
def epoch = now() / 1000
|
||||||
def eventBuffer = atomicState.eventBuffer ?: []
|
|
||||||
eventBuffer << [key: "$name", value: "$value", epoch: "$epoch"]
|
|
||||||
|
|
||||||
if (eventBuffer.size() >= 10) {
|
def event = new JsonSlurper().parseText("{\"key\": \"$name\", \"value\": \"$value\", \"epoch\": \"$epoch\"}")
|
||||||
// Clear eventBuffer right away since we've already pulled it off of atomicState to reduce the risk of missing
|
|
||||||
// events. This assumes the grokerSubdomain, accessKey, and bucketKey are set correctly to avoid the eventBuffer
|
tryShipEvents(event)
|
||||||
// from growing unbounded.
|
|
||||||
atomicState.eventBuffer = []
|
log.debug "Shipped Event: " + event
|
||||||
tryShipEvents(eventBuffer)
|
|
||||||
} else {
|
|
||||||
// Make sure we persist the updated eventBuffer with the new event added back to atomicState
|
|
||||||
atomicState.eventBuffer = eventBuffer
|
|
||||||
}
|
|
||||||
log.debug "Event added to buffer: " + eventBuffer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// a helper function for shipping the atomicState.eventBuffer to Initial State
|
def tryShipEvents(event) {
|
||||||
def tryShipEvents(eventBuffer) {
|
|
||||||
|
|
||||||
def grokerSubdomain = atomicState.grokerSubdomain
|
def grokerSubdomain = atomicState.grokerSubdomain
|
||||||
// can't ship events if there is no grokerSubdomain
|
// can't ship events if there is no grokerSubdomain
|
||||||
@@ -380,7 +358,7 @@ def tryShipEvents(eventBuffer) {
|
|||||||
"X-IS-AccessKey": "${accessKey}",
|
"X-IS-AccessKey": "${accessKey}",
|
||||||
"Accept-Version": "0.0.2"
|
"Accept-Version": "0.0.2"
|
||||||
],
|
],
|
||||||
body: eventBuffer
|
body: event
|
||||||
]
|
]
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user