Compare commits

...

9 Commits

Author SHA1 Message Date
Derek Twaddle
387e59a9bb MSA-1748: Integrates Xandem Home to SmartThings. Coded out of personal need as there are currently no Xandem SmartApps available. App detects motion, if motion detected vat or above user defined threshold, turn on light. 2017-01-28 09:55:03 -08:00
Vinay Rao
54da556c17 Merge pull request #1620 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2017-01-25 15:48:58 -08:00
Vinay Rao
8611d2e2d2 Merge pull request #1618 from workingmonk/feature/light_capability
ICP-203 Adding Light Capability to hue lights
2017-01-25 04:13:47 -08:00
Vinay Rao
c650047f31 ICP-203 Adding Light Capability to hue lights 2017-01-25 04:12:42 -08:00
Vinay Rao
ded7501b84 Merge pull request #1614 from SmartThingsCommunity/master
Rolling up master to staging
2017-01-24 13:21:44 -08:00
Vinay Rao
eb4d5dcfb8 Merge pull request #1613 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2017-01-24 13:19:33 -08:00
Vinay Rao
6385443f20 Merge pull request #1612 from SmartThingsCommunity/production
Rolling down production hotfix to staging
2017-01-24 12:48:34 -08:00
Juan Pablo Risso
445c115c14 DVCSMP-2324 - Centralite Thermostat handle multiple attributes (#1606)
- Curly braces
- remove parseDescriptionAsMap
- descMap to it
- Appended to the result list
- Convert to list and appended
2017-01-20 17:49:15 -05:00
Vinay Rao
bd3367fe0e Merge pull request #1598 from SmartThingsCommunity/staging
Rolling down staging to master
2017-01-18 15:18:08 -08:00
6 changed files with 129 additions and 28 deletions

View File

@@ -81,51 +81,47 @@ metadata {
// parse events into attributes
def parse(String description) {
log.debug "Parse description $description"
def map = [:]
if (description?.startsWith("read attr -")) {
def descMap = parseDescriptionAsMap(description)
log.debug "Desc Map: $descMap"
if (descMap.cluster == "0201" && descMap.attrId == "0000") {
List result = []
def descMap = zigbee.parseDescriptionAsMap(description)
log.debug "Desc Map: $descMap"
List attrData = [[cluster: descMap.cluster ,attrId: descMap.attrId, value: descMap.value]]
descMap.additionalAttrs.each {
attrData << [cluster: descMap.cluster, attrId: it.attrId, value: it.value]
}
attrData.each {
def map = [:]
if (it.cluster == "0201" && it.attrId == "0000") {
log.debug "TEMP"
map.name = "temperature"
map.value = getTemperature(descMap.value)
map.value = getTemperature(it.value)
map.unit = temperatureScale
} else if (descMap.cluster == "0201" && descMap.attrId == "0011") {
} else if (it.cluster == "0201" && it.attrId == "0011") {
log.debug "COOLING SETPOINT"
map.name = "coolingSetpoint"
map.value = getTemperature(descMap.value)
map.value = getTemperature(it.value)
map.unit = temperatureScale
} else if (descMap.cluster == "0201" && descMap.attrId == "0012") {
} else if (it.cluster == "0201" && it.attrId == "0012") {
log.debug "HEATING SETPOINT"
map.name = "heatingSetpoint"
map.value = getTemperature(descMap.value)
map.value = getTemperature(it.value)
map.unit = temperatureScale
} else if (descMap.cluster == "0201" && descMap.attrId == "001c") {
} else if (it.cluster == "0201" && it.attrId == "001c") {
log.debug "MODE"
map.name = "thermostatMode"
map.value = getModeMap()[descMap.value]
} else if (descMap.cluster == "0202" && descMap.attrId == "0000") {
map.value = getModeMap()[it.value]
} else if (it.cluster == "0202" && it.attrId == "0000") {
log.debug "FAN MODE"
map.name = "thermostatFanMode"
map.value = getFanModeMap()[descMap.value]
map.value = getFanModeMap()[it.value]
}
if (map) {
result << createEvent(map)
}
log.debug "Parse returned $map"
}
def result = null
if (map) {
result = createEvent(map)
}
log.debug "Parse returned $map"
return result
}
def parseDescriptionAsMap(description) {
(description - "read attr - ").split(",").inject([:]) { map, param ->
def nameAndValue = param.split(":")
map += [(nameAndValue[0].trim()):nameAndValue[1].trim()]
}
}
def getModeMap() { [
"00":"off",
"03":"cool",

View File

@@ -17,6 +17,7 @@ metadata {
capability "Refresh"
capability "Sensor"
capability "Health Check"
capability "Light"
command "setAdjustedColor"
command "reset"

View File

@@ -18,6 +18,7 @@ metadata {
capability "Refresh"
capability "Sensor"
capability "Health Check"
capability "Light"
command "setAdjustedColor"
command "reset"

View File

@@ -14,7 +14,8 @@ metadata {
capability "Switch"
capability "Refresh"
capability "Sensor"
capability "Health Check"
capability "Health Check"
capability "Light"
command "refresh"
}

View File

@@ -16,6 +16,7 @@ metadata {
capability "Switch"
capability "Refresh"
capability "Health Check"
capability "Light"
command "refresh"
}

View File

@@ -0,0 +1,101 @@
/**
* Xandem Home Integration
*
* Copyright 2017 Derek Twaddle
*
* 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.
*
* README
*
* Hello, after purchsing Xandem Home for a rental property I noticed there were no SmartApps yet developed. This is my
* first attempt at integrating Xandem with SmartThings out of personal need and decided to share with the community.
*
* Depending on your ISP and setup, there are some preliminary steps that need to be performed before installing this app. Xandem is initially
* accessible only via local network so you will need to make some minor rule changes to your firewall / router.
*
* If you have a static IP assignment from your ISP, you may forgo the following step. If your ISP assigns an IP Address to you Dynamically
* which is what most do at Resedential installations, you will need a Dynamic DNS service. Dynamic DNS will map your randomly assigned IP
* address to a static name like (Ex: myhome.dyndns.com). No matter what your IP changes to, it will always be resolved using the same name you chose.
*
* Once the above is completed, you will need to configure your router to pass or port forward to your internal Xandem Hub. You will
* want to statically assign a local IP to the mac address of the Xandem Hub. This way you will always assign the same local IP to the Xandem Hub which can be mapped
* and used in port forwarding rules. After the IP has been assigned (Ex: 192.168.1.25) add a rule on your rounter to pass incoming Port 80 request
* to your Xandem Hub IP address on the same port. This effectively lets your router listen for and pass data from SmarthThings to your Xandem Hub.
*
* Once the above networking steps are completed, create a Xandem API key on your local Xandem Hub. Instructions can
* found here: http://documentation.xandem.com/api/#api-keys-and-authorization-header
*
* This SmartApp is a personal project you are free to use.
*/
definition(
name: "Xandem Home Integration",
namespace: "Xandem",
author: "Derek Twaddle",
description: "Integrates Xandem Home to SmartThings. Detects motion, if above a user set threshold, turn on light.",
category: "Safety & Security",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png"
)
preferences {
section("Network Configuration") {
input "ddns", "text", title: " External Hostname or Static IP", required: true
paragraph "Example: mynetwork.dyndns.org or 64.102.0.1"
input "apikey", "text", title: "API Key", required: true
paragraph "Enter the Xandem API Key generated on your local Hub"
}
section("Turn on when motion detected and at or above level:") {
input "thelevel", "text", title: "1 - 10", required: true
paragraph "Motion Level: 1 Minimal Motion - 10 High Motion"
}
section("Turn on this light") {
input "theswitch", "capability.switch", required: true
}
}
def installed() {
log.debug "Installed with settings: ${settings}"
initialize()
}
def updated() {
log.debug "Updated with settings: ${settings}"
unsubscribe()
initialize()
}
def initialize() {
runEvery5Minutes(updateStatus)
}
def updateStatus() {
def params = [
uri: "http://${ddns}/v1/data",
headers: [Authorization: "${apikey}"],
body: [data_fields: ["motion_score", "is_motion"]]
]
try {
httpPostJson(params) { resp ->
resp.headers.each {
}
// If motion detected and motion level is at or above chosen level, Light On
if (resp.data.is_motion != 0 && resp.data.motion_score >= thelevel){
theswitch.on()
log.debug "Motion detected, light on"
}
}
} catch (e) {
log.debug "something went wrong: $e"
}
}