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
2 changed files with 384 additions and 358 deletions

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

@@ -26,44 +26,23 @@ definition(
preferences {
section("Control these contact sensors...") {
input "contact", "capability.contactSensor", multiple:true, required:false
}
section("Control these switches...") {
input "switches", "capability.switch", multiple:true, required:false
}
section("Control these smoke alarms...") {
input "smoke_alarms", "capability.smokeDetector", multiple:true, required:false
}
section("Control these window shades...") {
input "shades", "capability.windowShade", multiple:true, required:false
}
section("Control these garage doors...") {
input "garage", "capability.garageDoorControl", multiple:true, required:false
}
section("Control these water sensors...") {
input "water_sensors", "capability.waterSensor", multiple:true, required:false
input "switches", "capability.switch", multiple:true
}
section("Control these motion sensors...") {
input "motions", "capability.motionSensor", multiple:true, required:false
input "motions", "capability.motionSensor", multiple:true
}
section("Control these presence sensors...") {
input "presence_sensors", "capability.presenceSensor", multiple:true, required:false
input "presence_sensors", "capability.presenceSensor", multiple:true
}
section("Control these outlets...") {
input "outlets", "capability.switch", multiple:true, required:false
}
section("Control these power meters...") {
input "meters", "capability.powerMeter", multiple:true, required:false
input "outlets", "capability.switch", multiple:true
}
section("Control these locks...") {
input "locks", "capability.lock", multiple:true, required:false
input "locks", "capability.lock", multiple:true
}
section("Control these temperature sensors...") {
input "temperature_sensors", "capability.temperatureMeasurement", multiple:true, required:false
}
section("Control these batteries...") {
input "batteries", "capability.battery", multiple:true, required:false
section("Control these locks...") {
input "temperature_sensors", "capability.temperatureMeasurement"
}
}
@@ -82,13 +61,13 @@ def updated() {
def initialize() {
// TODO: subscribe to attributes, devices, locations, etc.
//subscribe(outlet, "energy", outletHandler)
//subscribe(outlet, "switch", outletHandler)
subscribe(outlet, "energy", outletHandler)
subscribe(outlet, "switch", outletHandler)
}
// TODO: implement event handlers
def outletHandler(evt) {
//log.debug "$outlet.currentEnergy"
log.debug "$outlet.currentEnergy"
//TODO call G API
}
@@ -104,14 +83,9 @@ mappings {
GET: "getAllDevices"
]
}
path("/doorlocks/lock/:id") {
path("/doorlocks/:id/:command") {
action: [
GET: "lockDoorLock"
]
}
path("/doorlocks/unlock/:id") {
action: [
GET: "unlockDoorLock"
GET: "updateDoorLock"
]
}
path("/doorlocks/:id") {
@@ -119,70 +93,10 @@ mappings {
GET: "getDoorLockStatus"
]
}
path("/contacts/:id") {
action: [
GET: "getContactStatus"
]
}
path("/smoke/:id") {
action: [
GET: "getSmokeStatus"
]
}
path("/shades/open/:id") {
action: [
GET: "openShade"
]
}
path("/shades/preset/:id") {
action: [
GET: "presetShade"
]
}
path("/shades/close/:id") {
action: [
GET: "closeShade"
]
}
path("/shades/:id") {
action: [
GET: "getShadeStatus"
]
}
path("/garage/open/:id") {
action: [
GET: "openGarage"
]
}
path("/garage/close/:id") {
action: [
GET: "closeGarage"
]
}
path("/garage/:id") {
action: [
GET: "getGarageStatus"
]
}
path("/watersensors/:id") {
action: [
GET: "getWaterSensorStatus"
]
}
path("/tempsensors/:id") {
action: [
GET: "getTempSensorsStatus"
]
}
path("/meters/:id") {
action: [
GET: "getMeterStatus"
]
}
path("/batteries/:id") {
action: [
GET: "getBatteryStatus"
]
}
path("/presences/:id") {
action: [
@@ -199,29 +113,14 @@ mappings {
GET: "getOutletStatus"
]
}
path("/outlets/turnon/:id") {
path("/outlets/:id/:command") {
action: [
GET: "turnOnOutlet"
GET: "updateOutlet"
]
}
path("/outlets/turnoff/:id") {
path("/switches/:command") {
action: [
GET: "turnOffOutlet"
]
}
path("/switches/turnon/:id") {
action: [
GET: "turnOnSwitch"
]
}
path("/switches/turnoff/:id") {
action: [
GET: "turnOffSwitch"
]
}
path("/switches/:id") {
action: [
GET: "getSwitchStatus"
PUT: "updateSwitch"
]
}
}
@@ -229,149 +128,12 @@ mappings {
//API Methods
def getAllDevices() {
def locks_list = locks.collect{device(it,"Lock")}
def contact_list = contact.collect{device(it,"Contact Sensor")}
def smokes_list = smoke_alarms.collect{device(it,"Smoke Alarm")}
def shades_list = shades.collect{device(it,"Window Shade")}
def garage_list = garage.collect{device(it,"Garage Door")}
def water_sensors_list = water_sensors.collect{device(it,"Water Sensor")}
def presences_list = presence_sensors.collect{device(it,"Presence")}
def motions_list = motions.collect{device(it,"Motion")}
def outlets_list = outlets.collect{device(it,"Outlet")}
def switches_list = switches.collect{device(it,"Switch")}
def temp_list = temperature_sensors.collect{device(it,"Temperature")}
def meters_list = meters.collect{device(it,"Power Meters")}
def battery_list = batteries.collect{device(it,"Batteries")}
return smokes_list + contact_list + water_sensors_list + shades_list + garage_list + locks_list + presences_list + motions_list + outlets_list + switches_list + temp_list + meters_list + battery_list
}
//contact sensors
def getContactStatus() {
def device = contact.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
def args = getTempSensorsStatus(device.id)
return [Device_state: device.currentValue('contact')] + args
}
}
//smoke detectors
def getSmokeStatus() {
def device = smoke_alarms.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
def bat = getBatteryStatus(device.id)
return [Device_state: device.currentValue('smoke')] + bat
}
}
//garage
def getGarageStatus() {
def device = garage.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
return [Device_state: device.currentValue('door')]
}
}
def openGarage() {
def device = garage.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.open();
return [Device_id: params.id, result_action: "200"]
}
}
def closeGarage() {
def device = garage.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.close();
return [Device_id: params.id, result_action: "200"]
}
}
//shades
def getShadeStatus() {
def device = shades.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
return [Device_state: device.currentValue('windowShade')]
}
}
def openShade() {
def device = shades.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.open();
return [Device_id: params.id, result_action: "200"]
}
}
def presetShade() {
def device = shades.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.presetPosition();
return [Device_id: params.id, result_action: "200"]
}
}
def closeShade() {
def device = shades.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.close();
return [Device_id: params.id, result_action: "200"]
}
}
//water sensor
def getWaterSensorStatus() {
def device = water_sensors.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
def bat = getBatteryStatus(device.id)
return [Device_state: device.currentValue('water')] + bat
}
}
//batteries
def getBatteryStatus() {
def device = batteries.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
return [Device_state: device.latestValue("battery")]
}
}
def getBatteryStatus(id) {
def device = batteries.find { it.id == id }
if (!device) {
return []
} else {
return [battery_state: device.latestValue("battery")]
}
return [Locks: locks_list, Presences: presences_list, Motions: motions_list, Outlets: outlets_list, Switches: switches_list, Temperatures: temp_list]
}
//LOCKS
@@ -380,34 +142,30 @@ def getDoorLockStatus() {
if (!device) {
httpError(404, "Device not found")
} else {
def bat = getBatteryStatus(device.id)
return [Device_state: device.currentValue('lock')] + bat
return [Device_state: device.currentValue('lock')]
}
}
def lockDoorLock() {
def updateDoorLock() {
def command = params.command
def device = locks.find { it.id == params.id }
if (!device) {
if (command){
if (!device) {
httpError(404, "Device not found")
} else {
device.lock();
if(command == "toggle")
{
if(device.currentValue('lock') == "locked")
device.unlock();
else
device.lock();
return [Device_id: params.id, result_action: "200"]
return [Device_id: params.id, result_action: "200"]
}
}
}
}
def unlockDoorLock() {
def device = locks.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.unlock();
return [Device_id: params.id, result_action: "200"]
}
}
//PRESENCE
def getPresenceStatus() {
@@ -415,8 +173,7 @@ def getPresenceStatus() {
if (!device) {
httpError(404, "Device not found")
} else {
def bat = getBatteryStatus(device.id)
return [Device_state: device.currentValue('presence')] + bat
return [Device_state: device.currentValue('presence')]
}
}
@@ -427,8 +184,7 @@ def getMotionStatus() {
if (!device) {
httpError(404, "Device not found")
} else {
def args = getTempSensorsStatus(device.id)
return [Device_state: device.currentValue('motion')] + args
return [Device_state: device.currentValue('motion')]
}
}
@@ -439,98 +195,52 @@ def getOutletStatus() {
if (!device) {
httpError(404, "Device not found")
} else {
def watt = getMeterStatus(device.id)
return [Device_state: device.currentSwitch] + watt
return [Device_state: device.currentSwitch, Current_watt: device.currentValue("energy")]
}
}
def getMeterStatus() {
def updateOutlet() {
def device = meters.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
return [Device_id: device.id, Device_type: device.type, Current_watt: device.currentValue("power")]
}
}
def getMeterStatus(id) {
def device = meters.find { it.id == id }
if (!device) {
return []
} else {
return [Current_watt: device.currentValue("power")]
}
}
def turnOnOutlet() {
def command = params.command
def device = outlets.find { it.id == params.id }
if (command){
if (!device) {
httpError(404, "Device not found")
} else {
device.on();
if(command == "toggle")
{
if(device.currentSwitch == "on")
device.off();
else
device.on();
return [Device_id: params.id, result_action: "200"]
return [Device_id: params.id, result_action: "200"]
}
}
}
}
def turnOffOutlet() {
def device = outlets.find { it.id == params.id }
if (command){
if (!device) {
httpError(404, "Device not found")
} else {
device.off();
return [Device_id: params.id, result_action: "200"]
}
}
}
}
//SWITCH
def getSwitchStatus() {
def device = switches.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
return [Device_state: device.currentValue('switch')]
}
}
def turnOnSwitch() {
def updateSwitch() {
def command = params.command
def device = switches.find { it.id == params.id }
if (command){
if (!device) {
httpError(404, "Device not found")
} else {
device.on();
if(command == "toggle")
{
if(device.currentSwitch == "on")
device.off();
else
device.on();
return [Device_id: params.id, result_action: "200"]
return [Device_id: params.id, result_action: "200"]
}
}
}
}
def turnOffSwitch() {
def device = switches.find { it.id == params.id }
if (command){
if (!device) {
httpError(404, "Device not found")
} else {
device.on();
return [Device_id: params.id, result_action: "200"]
}
}
}
//TEMPERATURE
def getTempSensorsStatus() {
@@ -538,17 +248,6 @@ def getTempSensorsStatus() {
if (!device) {
httpError(404, "Device not found")
} else {
def bat = getBatteryStatus(device.id)
return [Device_state: device.currentValue('temperature')] + bat
}
}
def getTempSensorsStatus(id) {
def device = temperature_sensors.find { it.id == id }
if (!device) {
return []
} else {
def bat = getBatteryStatus(device.id)
return [temperature: device.currentValue('temperature')] + bat
}
return [Device_state: device.currentValue('temperature')]
}
}