Compare commits

..

1 Commits

Author SHA1 Message Date
Yuri
b74af1c23e MSA-1631: Hi!
We want to introduce the web service smart app for SmartThings devices integration into our voice controlled ai bulter: https://play.google.com/store/apps/details?id=ai.cubic.home 
Please, provide your review. 

Regards Cubic Team
2016-12-02 05:56:39 -08:00
12 changed files with 345 additions and 299 deletions

View File

@@ -22,10 +22,9 @@ metadata {
capability "Sensor"
capability "Health Check"
fingerprint mfr:"0063", prod:"4457", deviceJoinName: "GE In-Wall Smart Dimmer "
fingerprint mfr:"0063", prod:"4944", deviceJoinName: "GE In-Wall Smart Dimmer "
fingerprint mfr:"0063", prod:"5044", deviceJoinName: "GE Plug-In Smart Dimmer "
fingerprint mfr:"0063", prod:"4944", model:"3034", deviceJoinName: "GE In-Wall Smart Fan Control"
fingerprint mfr:"0063", prod:"4457", deviceJoinName: "Z-Wave Wall Dimmer"
fingerprint mfr:"0063", prod:"4944", deviceJoinName: "Z-Wave Wall Dimmer"
fingerprint mfr:"0063", prod:"5044", deviceJoinName: "Z-Wave Plug-In Dimmer"
}
simulator {

View File

@@ -39,7 +39,7 @@ metadata {
}
def generatePresenceEvent(boolean present) {
log.info "Life360 generatePresenceEvent($present)"
log.debug "Here in generatePresenceEvent!"
def value = formatValue(present)
def linkText = getLinkText(device)
def descriptionText = formatDescriptionText(linkText, present)

View File

@@ -128,7 +128,7 @@ private Map parseCatchAllMessage(String description) {
if (cluster.command == 0x07) {
if (cluster.data[0] == 0x00){
log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster
resultMap = [name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]]
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
else {
log.warn "TEMP REPORTING CONFIG FAILED- error code:${cluster.data[0]}"

View File

@@ -132,7 +132,7 @@ private Map parseCatchAllMessage(String description) {
if (cluster.command == 0x07) {
if (cluster.data[0] == 0x00) {
log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster
resultMap = [name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]]
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
else {
log.warn "TEMP REPORTING CONFIG FAILED- error code:${cluster.data[0]}"

View File

@@ -161,7 +161,7 @@ private Map parseCatchAllMessage(String description) {
if (cluster.command == 0x07) {
if(cluster.data[0] == 0x00) {
log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster
resultMap = [name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]]
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
else {
log.warn "TEMP REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
@@ -339,7 +339,7 @@ private Map getContactResult(value) {
log.debug "Contact: ${device.displayName} value = ${value}"
def descriptionText = value == 'open' ? '{{ device.displayName }} was opened' : '{{ device.displayName }} was closed'
sendEvent(name: 'contact', value: value, descriptionText: descriptionText, displayed: false, translatable: true)
return [name: 'status', value: value, descriptionText: descriptionText, translatable: true]
sendEvent(name: 'status', value: value, descriptionText: descriptionText, translatable: true)
}
private getAccelerationResult(numValue) {

View File

@@ -119,7 +119,7 @@ private Map parseCatchAllMessage(String description) {
if (cluster.command == 0x07){
if (cluster.data[0] == 0x00) {
log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster
resultMap = [name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]]
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
else {
log.warn "TEMP REPORTING CONFIG FAILED- error code:${cluster.data[0]}"

View File

@@ -103,7 +103,7 @@ private Map parseCatchAllMessage(String description) {
if (cluster.command == 0x07) {
if (cluster.data[0] == 0x00){
log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster
resultMap = [name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]]
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
else {
log.warn "TEMP REPORTING CONFIG FAILED- error code:${cluster.data[0]}"

View File

@@ -24,10 +24,6 @@ metadata {
fingerprint inClusters: "0x26", deviceJoinName: "Z-Wave Dimmer"
fingerprint mfr:"001D", prod:"1902", deviceJoinName: "Z-Wave Dimmer"
fingerprint mfr:"001D", prod:"1B03", model:"0334", deviceJoinName: "Leviton Universal Dimmer"
fingerprint mfr:"011A", prod:"0102", model:"0201", deviceJoinName: "Enerwave In-Wall Dimmer"
fingerprint mfr:"001D", prod:"1001", model:"0334", deviceJoinName: "Leviton 3-Speed Fan Controller"
fingerprint mfr:"001D", prod:"0602", model:"0334", deviceJoinName: "Leviton Magnetic Low Voltage Dimmer"
fingerprint mfr:"001D", prod:"0401", model:"0334", deviceJoinName: "Leviton 600W Incandescent Dimmer"
}
simulator {

View File

@@ -1,273 +0,0 @@
/**
* Copyright 2015 SmartThings
*
* 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.
*
* Z-Wave Door/Window Sensor
*
* Author: SmartThings
* Date: 2013-11-3
*/
metadata {
definition (name: "Z-Wave Door Sensor as Smoke Detector", namespace: "smartthings", author: "SmartThings") {
capability "Contact Sensor"
capability "Sensor"
capability "Battery"
capability "Configuration"
fingerprint deviceId: "0x2001", inClusters: "0x30,0x80,0x84,0x85,0x86,0x72"
fingerprint deviceId: "0x07", inClusters: "0x30"
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x98"
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x86,0x72,0x98", outClusters: "0x5A,0x82"
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x80,0x71,0x85,0x70,0x72,0x86,0x30,0x31,0x84,0x59,0x73,0x5A,0x8F,0x98,0x7A", outClusters:"0x20" // Philio multi+
}
// simulator metadata
simulator {
// status messages
status "fire": "command: 2001, payload: FF"
status "safe": "command: 2001, payload: 00"
status "wake up": "command: 8407, payload: "
}
// UI tile definitions
tiles {
standardTile("contact", "device.contact", width: 2, height: 2) {
state "fire",label: '${name}',icon: "st.alarm.smoke.smoke",backgroundColor: "#ffa81e"
state "safe",label: '${name}',icon: "st.alarm.smoke.clear",backgroundColor: "#79b821"
}
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
state "battery", label:'${currentValue}% battery', unit:""
}
main "contact"
details(["contact", "battery"])
}
}
def parse(String description) {
def result = null
if (description.startsWith("Err 106")) {
if (state.sec) {
log.debug description
} else {
result = createEvent(
descriptionText: "This sensor failed to complete the network security key exchange. If you are unable to control it via SmartThings, you must remove it from your network and add it again.",
eventType: "ALERT",
name: "secureInclusion",
value: "failed",
isStateChange: true,
)
}
} else if (description != "updated") {
def cmd = zwave.parse(description, [0x20: 1, 0x25: 1, 0x30: 1, 0x31: 5, 0x80: 1, 0x84: 1, 0x71: 3, 0x9C: 1])
if (cmd) {
result = zwaveEvent(cmd)
}
}
log.debug "parsed '$description' to $result"
return result
}
def updated() {
def cmds = []
if (!state.MSR) {
cmds = [
command(zwave.manufacturerSpecificV2.manufacturerSpecificGet()),
"delay 1200",
zwave.wakeUpV1.wakeUpNoMoreInformation().format()
]
} else if (!state.lastbat) {
cmds = []
} else {
cmds = [zwave.wakeUpV1.wakeUpNoMoreInformation().format()]
}
response(cmds)
}
def configure() {
commands([
zwave.manufacturerSpecificV2.manufacturerSpecificGet(),
zwave.batteryV1.batteryGet()
], 6000)
}
def sensorValueEvent(value) {
if (value) {
createEvent(name: "contact", value: "fire", descriptionText: "$device.displayName fire detected")
} else {
createEvent(name: "contact", value: "safe", descriptionText: "$device.displayName is safe")
}
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd)
{
sensorValueEvent(cmd.value)
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd)
{
sensorValueEvent(cmd.value)
}
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd)
{
sensorValueEvent(cmd.value)
}
def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv1.SensorBinaryReport cmd)
{
sensorValueEvent(cmd.sensorValue)
}
def zwaveEvent(physicalgraph.zwave.commands.sensoralarmv1.SensorAlarmReport cmd)
{
sensorValueEvent(cmd.sensorState)
}
def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd)
{
def result = []
if (cmd.notificationType == 0x06 && cmd.event == 0x16) {
result << sensorValueEvent(1)
} else if (cmd.notificationType == 0x06 && cmd.event == 0x17) {
result << sensorValueEvent(0)
} else if (cmd.notificationType == 0x07) {
if (cmd.v1AlarmType == 0x07) { // special case for nonstandard messages from Monoprice door/window sensors
result << sensorValueEvent(cmd.v1AlarmLevel)
} else if (cmd.event == 0x01 || cmd.event == 0x02) {
result << sensorValueEvent(1)
} else if (cmd.event == 0x03) {
result << createEvent(descriptionText: "$device.displayName covering was removed", isStateChange: true)
if(!state.MSR) result << response(command(zwave.manufacturerSpecificV2.manufacturerSpecificGet()))
} else if (cmd.event == 0x05 || cmd.event == 0x06) {
result << createEvent(descriptionText: "$device.displayName detected glass breakage", isStateChange: true)
} else if (cmd.event == 0x07) {
if(!state.MSR) result << response(command(zwave.manufacturerSpecificV2.manufacturerSpecificGet()))
result << createEvent(name: "motion", value: "active", descriptionText:"$device.displayName detected motion")
}
} else if (cmd.notificationType) {
def text = "Notification $cmd.notificationType: event ${([cmd.event] + cmd.eventParameter).join(", ")}"
result << createEvent(name: "notification$cmd.notificationType", value: "$cmd.event", descriptionText: text, displayed: false)
} else {
def value = cmd.v1AlarmLevel == 255 ? "active" : cmd.v1AlarmLevel ?: "inactive"
result << createEvent(name: "alarm $cmd.v1AlarmType", value: value, displayed: false)
}
result
}
def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
{
def event = createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)
def cmds = []
if (!state.MSR) {
cmds << command(zwave.manufacturerSpecificV2.manufacturerSpecificGet())
cmds << "delay 1200"
}
if (!state.lastbat || now() - state.lastbat > 53*60*60*1000) {
cmds << command(zwave.batteryV1.batteryGet())
} else {
cmds << zwave.wakeUpV1.wakeUpNoMoreInformation().format()
}
[event, response(cmds)]
}
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
def map = [ name: "battery", unit: "%" ]
if (cmd.batteryLevel == 0xFF) {
map.value = 1
map.descriptionText = "${device.displayName} has a low battery"
map.isStateChange = true
} else {
map.value = cmd.batteryLevel
}
state.lastbat = now()
[createEvent(map), response(zwave.wakeUpV1.wakeUpNoMoreInformation())]
}
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
def result = []
def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
log.debug "msr: $msr"
updateDataValue("MSR", msr)
retypeBasedOnMSR()
result << createEvent(descriptionText: "$device.displayName MSR: $msr", isStateChange: false)
if (msr == "011A-0601-0901") { // Enerwave motion doesn't always get the associationSet that the hub sends on join
result << response(zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId))
} else if (!device.currentState("battery")) {
if (msr == "0086-0102-0059") {
result << response(zwave.securityV1.securityMessageEncapsulation().encapsulate(zwave.batteryV1.batteryGet()).format())
} else {
result << response(command(zwave.batteryV1.batteryGet()))
}
}
result
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x20: 1, 0x25: 1, 0x30: 1, 0x31: 5, 0x80: 1, 0x84: 1, 0x71: 3, 0x9C: 1])
// log.debug "encapsulated: $encapsulatedCommand"
if (encapsulatedCommand) {
state.sec = 1
zwaveEvent(encapsulatedCommand)
}
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
createEvent(descriptionText: "$device.displayName: $cmd", displayed: false)
}
private command(physicalgraph.zwave.Command cmd) {
if (state.sec == 1) {
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
} else {
cmd.format()
}
}
private commands(commands, delay=200) {
delayBetween(commands.collect{ command(it) }, delay)
}
def retypeBasedOnMSR() {
switch (state.MSR) {
case "0086-0002-002D":
log.debug "Changing device type to Z-Wave Water Sensor"
setDeviceType("Z-Wave Water Sensor")
break
case "011F-0001-0001": // Schlage motion
case "014A-0001-0001": // Ecolink motion
case "014A-0004-0001": // Ecolink motion +
case "0060-0001-0002": // Everspring SP814
case "0060-0001-0003": // Everspring HSP02
case "011A-0601-0901": // Enerwave ZWN-BPC
log.debug "Changing device type to Z-Wave Motion Sensor"
setDeviceType("Z-Wave Motion Sensor")
break
case "013C-0002-000D": // Philio multi +
log.debug "Changing device type to 3-in-1 Multisensor Plus (SG)"
setDeviceType("3-in-1 Multisensor Plus (SG)")
break
case "0109-2001-0106": // Vision door/window
log.debug "Changing device type to Z-Wave Plus Door/Window Sensor"
setDeviceType("Z-Wave Plus Door/Window Sensor")
break
case "0109-2002-0205": // Vision Motion
log.debug "Changing device type to Z-Wave Plus Motion/Temp Sensor"
setDeviceType("Z-Wave Plus Motion/Temp Sensor")
break
}
}

View File

@@ -25,9 +25,6 @@ metadata {
fingerprint mfr:"0063", prod:"4F50", model:"3031", deviceJoinName: "GE Plug-in Outdoor Switch"
fingerprint mfr:"001D", prod:"1D04", model:"0334", deviceJoinName: "Leviton Outlet"
fingerprint mfr:"001D", prod:"1C02", model:"0334", deviceJoinName: "Leviton Switch"
fingerprint mfr:"001D", prod:"0301", model:"0334", deviceJoinName: "Leviton 15A Switch"
fingerprint mfr:"011A", prod:"0101", model:"0102", deviceJoinName: "Enerwave On/Off Switch"
fingerprint mfr:"011A", prod:"0101", model:"0603", deviceJoinName: "Enerwave Duplex Receptacle"
}
// simulator metadata

View File

@@ -0,0 +1,327 @@
/**
* Cubic Home
* sdfssdfsfsdfsdfdsf
* Copyright 2016 Nikolay Zenovkin
*
* 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.
*
*/
definition(
name: "Cubic Butler for Smart Home",
namespace: "cubicrobotics",
author: "Cubic Robotics",
description: "Hey, Im Cubic, AI butler for smart home! \n" +
"I am the one and only app you need to control an entire home. \n" +
"Right now I can help you to control your SmartThings devices via natural speech and dashboard.\n" +
"Speak naturally, dont learn robot! My A.I. is designed for a smart home control.\n" +
"- You dont have to remember exact commands and phrases.\n" +
"- I have memory, and every new request will be processed in the context of previous ones.\n" +
"- I can ask clarifying questions, if Im not sure what you mean.",
category: "Convenience",
iconUrl: "https://lh3.googleusercontent.com/GX5BRhaFq22HpAEU6tD4JXvizlxWFuB9zjyZE39-pLpZvQvvUmVpWXa0v4-oaxz4tg=w300-rw",
iconX2Url: "https://lh3.googleusercontent.com/GX5BRhaFq22HpAEU6tD4JXvizlxWFuB9zjyZE39-pLpZvQvvUmVpWXa0v4-oaxz4tg=w300-rw",
iconX3Url: "https://lh3.googleusercontent.com/GX5BRhaFq22HpAEU6tD4JXvizlxWFuB9zjyZE39-pLpZvQvvUmVpWXa0v4-oaxz4tg=w300-rw",
oauth: [displayName: "Cubic Home", displayLink: "http://cubic.ai/"])
preferences {
section("Welcome to Cubic") {
// TODO: put inputs here
}
section("Allow Cubic to control these switches") {
input "switches", "capability.switch", multiple: true, required: false
}
section("Allow Cubic to control these motion sensors") {
input "motionSensors", "capability.motionSensor", multiple: true, required: false
}
section("Allow Cubic to control these bulbs") {
input "lamps", "capability.colorControl", multiple: true, required: false
}
section("Allow Cubic to control these thermostats") {
input "thermostats", "capability.thermostat", multiple: true, required: false
}
section("Allow Cubic to control these water sensors") {
input "waterSensors", "capability.waterSensor", multiple: true, required: false
}
section("Allow Cubic to control these CO sensors") {
input "smokeSensors", "capability.carbonMonoxideDetector", multiple: true, required: false
}
section("Allow Cubic to control these door controls") {
input "doorControls", "capability.doorControl", multiple: true, required: false
}
}
mappings {
path("/devices") {
action:
[
GET: "getDevices"
]
}
path("/devices/:id") {
action:
[
PUT: "updateDevice",
GET: "getDevice"
]
}
}
def installed() {
log.debug "Installed with settings: ${settings}"
initialize()
}
def updated() {
log.debug "Updated with settings: ${settings}"
unsubscribe()
initialize()
}
def initialize() {
subscribe(motionSensors, "motion", motionHandler)
subscribe(switches, "switch", switchHandler)
subscribe(thermostats, "thermostat.temperature", thermostatHandler)
subscribe(waterSensors, "waterSensor", waterHandler)
subscribe(smokeSensors, "carbonMonoxideDetector", smokeHandler)
subscribe(doorControls, "doorControl", doorControlHandler)
}
def doorControlHandler(evt) {
if (evt.isStateChanged()) {
sendPushEvent(evt.deviceId,
"DOOR_CONTROL_SMART_THINGS",
evt.value
)
}
}
def smokeHandler(evt) {
if (evt.isStateChanged()) {
sendPushEvent(evt.deviceId,
"SMOKE_CO_SENSOR_SMART_THINGS",
evt.value
)
}
}
def thermostatHandler(evt) {
if (evt.isStateChanged()) {
sendPushEvent(evt.deviceId,
"THERMOSTAT_SMART_THINGS",
evt.value
)
}
}
def waterHandler(evt) {
if (evt.isStateChanged()) {
sendPushEvent(evt.deviceId,
"WATER_SENSOR_SMART_THINGS",
evt.value
)
}
}
def motionHandler(evt) {
if ("active" == evt.value) {
sendPushEvent(evt.deviceId,
"MOTION_SENSOR_SMART_THINGS",
evt.value)
}
}
def switchHandler(evt) {
log.debug "$evt.deviceId switch changed state to $evt.value"
}
def getDevices() {
def resp = []
switches.each {
resp << extractSwitch(it)
}
motionSensors.each {
resp << extractMotionSensor(it)
}
lamps.each {
resp << extractLamp(it)
}
thermostats.each {
resp << extractThermostat(it)
}
return resp
}
def getDevice() {
def id = params.id
log.info "Getting device by id " + id
def device = findDeviceById(id);
if (device == null) {
httpError(400, "$id is not a valid id for switch specified")
} else if (device.type == "SWITCH_SMART_THINGS") {
return extractSwitch(device.device);
} else if (device.type == "THERMOSTAT_SMART_THINGS") {
return extractThermostat(device.device);
} else if (device.type == "LAMP_SMART_THINGS") {
return extractLamp(device.device);
} else if (device.type == "MOTION_SENSOR_SMART_THINGS") {
return extractMotionSensor(device.device);
}
return nil
}
void updateDevice() {
def id = params.id
def device = findDeviceById(id)
if (device == null) {
httpError(400, "$id is not a valid switch id")
} else if (device.type == "SWITCH_SMART_THINGS") {
changeSwitchState(device, request.JSON?.powered)
} else if (device.type == "THERMOSTAT_SMART_THINGS") {
def heating_setpoint = request.JSON?.heating_setpoint
def cooling_setpoint = request.JSON?.cooling_setpoint
def thermostat_setpoint = request.JSON?.thermostat_setpoint
if (heating_setpoint != null) {
device.device.setHeatingSetpoint(heating_setpoint)
}
if (cooling_setpoint != null) {
device.device.setCoolingSetpoint(cooling_setpoint)
}
//if (thermostat_setpoint != null) {
// device.device.setThermostatSetpoint(thermostat_setpoint)
//}
} else if (device.type == "LAMP_SMART_THINGS") {
def powered = request.JSON?.powered
def color_h = request.JSON?.color_h
def color_s = request.JSON?.color_s
def color_b = request.JSON?.color_b
def color_temperature = request.JSON?.color_temperature
if (powered != null) {
changeSwitchState(device, request.JSON?.powered)
}
if (color_h != null) {
device.device.setHue(color_h)
}
if (color_b != null) {
device.device.setLevel(color_b)
}
if (color_s != null) {
device.device.setSaturation(color_s)
}
if (color_temperature != null) {
device.device.setColorTemperature(color_temperature)
}
} else if (device.type == "MOTION_SENSOR_SMART_THINGS") {
httpError(400, "Unable to control motion sensor")
}
}
def findDeviceById(id) {
def device = switches.find { it.id == id }
def type = "SWITCH_SMART_THINGS"
if (device == null) {
device = thermostats.find { it.id == id }
type = "THERMOSTAT_SMART_THINGS"
}
if (device == null) {
device = lamps.find { it.id == id }
type = "LAMP_SMART_THINGS"
}
if (device == null) {
device = motionSensors.find { it.id == id }
type = "MOTION_SENSOR_SMART_THINGS"
}
if (device == null) {
return null;
}
return [device: device, type: type];
}
def extractSwitch(it) {
return [id: it.id, type: "SWITCH_SMART_THINGS", state: [name: it.displayName, powered: it.currentValue("switch") == "on" ? true : false]]
}
def extractMotionSensor(it) {
return [id: it.id, type: "MOTION_SENSOR_SMART_THINGS", state: [name: it.displayName, state: it.currentValue("motion")]]
}
def extractLamp(it) {
return [id: it.id, type: "LAMP_SMART_THINGS", state: [name : it.displayName,
color_h : it.currentValue("hue"), color_s: it.currentValue("saturation"), color_b: it.currentValue("level"),
color_temperature: it.currentValue("colorTemperature"), powered: it.currentValue("switch") == "on" ? true : false]]
}
def extractThermostat(it) {
return [id: it.id, type: "THERMOSTAT_SMART_THINGS", state: [name : it.displayName,
temperature : it.currentValue("temperature"),
heating_setpoint : it.currentValue("heatingSetpoint"),
cooling_setpoint : it.currentValue("coolingSetpoint"),
thermostat_setpoint : it.currentValue("thermostatSetpoint"),
thermostat_mode : it.currentValue("thermostatMode"),
thermostat_fan_mode : it.currentValue("thermostatFanMode"),
thermostat_operating_state: it.currentValue("thermostatOperatingState")]]
}
def changeSwitchState(device, powered) {
log.info "Updating device " + device.device.displayName + " to state $powered"
switch (powered) {
case "true":
device.device.on()
break
case "false":
device.device.off()
break
default:
httpError(400, "$powered is not a valid power state for switch specified")
}
}
def sendPushEvent(pushEvent) {
def params = [
uri : "https://intent-processor-stage.cubic.ai/api/v1/pushEvent",
headers : [
Authorization: "Bearer -gm-IOuQR3W2Gim8Tjwsuw",
Accept : "/"
],
body : pushEvent,
requestContentType: "application/json"
]
try {
httpPost(params) { resp ->
log.debug "response data: ${resp.data}"
log.debug "response contentType: ${resp.contentType}"
}
} catch (e) {
log.debug "something went wrong: $e"
}
}
def sendPushEvent(id, type, state) {
sendPushEvent(
[device_id : id,
device_type: type,
state : state]
)
}

View File

@@ -289,12 +289,12 @@ def initializeLife360Connection() {
state.life360AccessToken = result.data.access_token
return true;
}
log.info "Life360 initializeLife360Connection, response=${result.data}"
log.debug "Response=${result.data}"
return false;
}
catch (e) {
log.error "Life360 initializeLife360Connection, error: $e"
log.debug e
return false;
}
@@ -656,7 +656,7 @@ def generateInitialEvent (member, childDevice) {
try { // we are going to just ignore any errors
log.info "Life360 generateInitialEvent($member, $childDevice)"
log.debug "Generate Initial Event for New Device for Member = ${member.id}"
def place = state.places.find{it.id==settings.place}
@@ -677,8 +677,6 @@ def generateInitialEvent (member, childDevice) {
// log.debug "Distance Away = ${distanceAway}"
boolean isPresent = (distanceAway <= placeRadius)
log.info "Life360 generateInitialEvent, member: ($memberLatitude, $memberLongitude), place: ($placeLatitude, $placeLongitude), radius: $placeRadius, dist: $distanceAway, present: $isPresent"
// log.debug "External Id=${app.id}:${member.id}"
@@ -720,7 +718,7 @@ def haversine(lat1, lon1, lat2, lon2) {
def placeEventHandler() {
log.info "Life360 placeEventHandler: params=$params, settings.place=$settings.place"
log.debug "In placeEventHandler method."
// the POST to this end-point will look like:
// POST http://test.com/webhook?circleId=XXXX&placeId=XXXX&userId=XXXX&direction=arrive
@@ -731,6 +729,8 @@ def placeEventHandler() {
def direction = params?.direction
def timestamp = params?.timestamp
log.debug "Life360 Event: Circle: ${circleId}, Place: ${placeId}, User: ${userId}, Direction: ${direction}"
if (placeId == settings.place) {
def presenceState = (direction=="in")
@@ -745,10 +745,10 @@ def placeEventHandler() {
if (deviceWrapper) {
deviceWrapper.generatePresenceEvent(presenceState)
log.debug "Life360 event raised on child device: ${externalId}"
log.debug "Event raised on child device: ${externalId}"
}
else {
log.warn "Life360 couldn't find child device associated with inbound Life360 event."
log.debug "Couldn't find child device associated with inbound Life360 event."
}
}