Compare commits

..

2 Commits

2 changed files with 148 additions and 32 deletions

View File

@@ -3,7 +3,7 @@
* *
* Author: Fidure * Author: Fidure
* Date: 2014-12-13 * Date: 2014-12-13
* Updated: 2016-1-29 * Updated: 2015-08-26
*/ */
metadata { metadata {
// Automatically generated. Make future change here. // Automatically generated. Make future change here.
@@ -207,8 +207,7 @@ 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": result += createEvent("name":"displayTemperature", "value": getDisplayTemperature(atMap.value))
getDisplayTemperature(atMap.value))
break; break;
case "0005": case "0005":
//log.debug "hex time: ${descMap.value}" //log.debug "hex time: ${descMap.value}"
@@ -228,7 +227,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"
@@ -299,7 +298,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)])
@@ -314,9 +313,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')
@@ -340,9 +339,8 @@ 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 if the type is not in the map, // return number of hex chars
// then it's likely a malformed msg and should not be parsed return map.get(t) * 2
return (map.get(t) ?: 256) * 2
} }
@@ -379,13 +377,15 @@ 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.getOffset(date.getTime()); time -= location.timeZone.getRawOffset() + location.timeZone.getDSTSavings();
def d = new Date(time); def d = new Date(time);
@@ -611,14 +611,12 @@ def checkLastTimeSync(delay)
if (!lastSync) if (!lastSync)
lastSync = "${new Date(0)}" lastSync = "${new Date(0)}"
if (!settings.sync_clock) if (settings.sync_clock ?: false && lastSync != new Date(0))
{ {
if (lastSync != new Date(0)) sendEvent("name":"lastTimeSync", "value":"${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()
@@ -651,7 +649,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]) +
@@ -733,7 +731,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()
@@ -807,31 +805,32 @@ 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 ?: "Unlocked") }?.key val = getLockMap().find { it.value == (settings.lock_level ?: "Full") }?.key
else else
val = "00" val = "00"
["st wattr 0x${device.deviceNetworkId} 1 0x204 1 0x30 {${val}}", "st rattr 0x${device.deviceNetworkId} 1 0x204 0x01"
"st rattr 0x${device.deviceNetworkId} 1 0x204 0x01", "delay 500"]
} }
def setThermostatTime() def setThermostatTime()
{ {
if (false == (settings.sync_clock ?: false)) if ((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.getOffset(date.getTime()); millis += location.timeZone.getRawOffset() + location.timeZone.getDSTSavings();
//convert to seconds //convert to seconds
millis /= 1000; millis /= 1000;

View File

@@ -0,0 +1,117 @@
definition(
name: "EyXAr Notifications",
namespace: "eyxar",
author: "EyXAr",
description: "Phone and Voice notification of your door sensor status and phone presence sensor autonitification.",
category: "SmartThings Labs",
iconUrl: "https://s3.amazonaws.com/for-st/For_ST_60px.png",
iconX2Url: "https://s3.amazonaws.com/for-st/For_ST_120px.png",
iconX3Url: "https://s3.amazonaws.com/for-st/For_ST_256px.png"
)
/* For ST will only work if EyXAr Notification is installed and set-up first. */
preferences {
section("EyXAr Auto Notifications - For Voice Notification, Install the app 'FOR ST' in Google Play")
{
input "door", "capability.contactSensor", title: "Select Door/Contact", required: false, multiple: true
}
section("Send Notifications by Text or use below option?") {
input("recipients", "contact", title: "Send notifications to"){
input "phone", "phone", title: "Phone Number (optional, text charges may apply)",
description: "Phone Number", required: false
}
}
section("If combine with 'For ST' android app, this will add features of voice notifications.") {
input "sendPush", "bool", required: false,
title: "Phone/Tablet Auto Notification (Must be set to On =>>)"
}
}
/* Presense */
section("Phone Presence Auto Notifications - For Voice notifications install 'FOR ST' in Google Play") {
input "presence", "capability.presenceSensor", title: "Select Phone/Tablet to Detect: (mandatory & rest below are optional)", required: false, multiple: true
}
def installed() {
initialize()
/* Presense */
subscribe(door, "contact.open", doorOpenHandler)
subscribe(door, "contact.closed", doorClosedHandler)
subscribe(presence, "presence", myHandler)
subscribe(presence, "presence", presenceHandler)
}
def updated() {
initialize()
}
def initialize() {
subscribe(door, "contact.open", doorOpenHandler)
subscribe(door, "contact.closed", doorClosedHandler)
subscribe(presence, "presence", myHandler)
subscribe(presence, "presence", presenceHandler)
}
def doorOpenHandler(evt) {
def message = "EyXAr Detected the ${evt.displayName} is ${evt.value}!"
if (sendPush) {
sendPush(message)
}
if (phone) {
sendSms(phone, message)
}
}
def doorClosedHandler(evt) {
def message = "EyXAr Detected the ${evt.displayName} is ${evt.value}!"
if (sendPush) {
sendPush(message)
}
if (phone) {
sendSms(phone, message)
}
}
def contactHandler(evt) {
if("open" == evt.value)
// contact was opened, turn on a light maybe?
log.debug "Contact is in ${evt.value} state"
if("closed" == evt.value)
// contact was closed, turn off the light?
log.debug "Contact is in ${evt.value} state"
}
/* Presense */
def myHandler(evt) {
if("present" == evt.value)
def message = "EyXAr Detected ${evt.displayName} is ${evt.value}!"
if (sendPush) {
sendPush(message)
}
if (phone) {
sendSms(phone, message)
}
}
def presenceHandler(evt) {
if (evt.value == "present") {
log.debug "EyXAr ${evt.displayName} has arrived at the ${location}!"
sendPush("EyXAr ${evt.displayName} has arrived at the ${location}!")
} else if (evt.value == "not present") {
log.debug "EyXAr ${evt.displayName} has left the ${location}!"
sendPush("EyXAr ${evt.displayName} has left the ${location}!")
}
}