Compare commits

..

1 Commits

Author SHA1 Message Date
ronald Jack
30eafb604d MSA-2033: tcp 2017-06-12 13:27:25 -07:00
2 changed files with 412 additions and 317 deletions

View File

@@ -1,317 +0,0 @@
/**
* RealApplication_CA
*
* Copyright 2017 Venkata Kishore Chilakala
*
* 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: "RealApplication_CA",
namespace: "CA",
author: "Venkata Kishore Chilakala",
description: "myApp",
category: "SmartThings Labs",
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("Allow External Service to Control These Things...")
{
input "motions", "capability.motionSensor", title: "Which Motion Sensors?", multiple: true, required: false
input "contacts", "capability.contactSensor",title: "Which Contact Sensor?", multiple: true, required: false
input "presences", "capability.presenceSensor",title: "Which Presence Sensor?", multiple: true, required: false
input "switches", "capability.switchLevel", title: "Which Switches?", multiple: true, required: false
input "levelSwitches","capability.switchLevel",title: "Which Level Switch?",multiple: true, required:false
input "relativeHumidity","capability.relativeHumidityMeasurement",title: "Humidity",multiple:true,required:false
input "temperature","capability.temperatureMeasurement",title: "Temperature Measurement",multiple:true,required:false
input "lock","capability.lock",title: "Door Lock", multiple:true,required:false
input "hubs",title: "Hubs",multiple:false,required:false
}
}
def installed() {
initialize()
}
def updated() {
initialize()
}
mappings {
path("/devices")
{
action:[
GET:"listDevices"
]
}
path("/hubs") {
log.debug "list action"
action: [
GET: "listAll"
]
}
path("/switches") {
action: [
GET:"listSwitches",
PUT:"updateSwitches"
]
}
path("/switches/:id") {
action: [
GET:"showSwitch",
PUT:"updateSwitch"
]
}
path("/levelSwitches") {
action: [
GET:"listLevelSwitches",
PUT:"updateLevelSwitches"
]
}
path("/levelSwitches/:id") {
action: [
GET:"showLevelSwitch",
PUT:"updateLevelSwitch"
]
}
path("/motions") {
action: [
GET:"listMotions",
PUT:"updateMotions"
]
}
path("/motions/:id"){
action:[
GET:"showMotion",
PUT:"updateMotion"
]
}
path("/presences")
{
action:[
GET:"listPresenceSensor",
PUT:"updatePresenceSensor"
]
}
path("/presences/:id")
{
action:[
GET:"showPresence",
PUT:"updatePresence"
]
}
path("/locks") {
action: [
GET:"listLocks",
PUT:"updateLocks"
]
}
path("/locks/:id") {
action: [
GET:"showLock",
PUT:"updateLock"
]
}
path("/contacts")
{
action: [
GET: "listContacts",
PUP: "updateContacts"
]
}
path ("/contacts/:id")
{
action:[
GET:"showContact",
PUT:"updateContact"
]
}
}
def listAll()
{
[location_id :location.id,hub_id:location.hubs*.id,hub_type:location.hubs*.type,hub_name:location.hubs*.name,hub_firm_ver:location.hubs*.firmwareVersionString,hub_ip:location.hubs*.localIP,hub_port:location.hubs*.localSrvPortTCP]
}
def listSwitches() {
switches.collect { device(it,"switch") }
}
void updateSwitches() {
updateAll(switches)
}
def showSwitch() {
show(switches, "switch")
}
void updateSwitch() {
update(switches)
}
def listLevelSwitches() {
levelSwitches.collect { device(it,"level") }
// motions.collect { device(it,"motion") }
}
void updateLevelSwitches() {
updateAll(levelSwitches)
}
def showLevelSwitch() {
show(levelSwitches, "level")
}
void updateLevelSwitch() {
update(levelSwitches)
}
def listLocks() {
lock.collect { device(it,"lock") }
}
void updateLocks() {
updateAll(lock)
}
def showLock() {
show(lock, "lock")
}
void updateLock() {
update(lock)
}
def listMotions() {
motions.collect { device(it,"motion") }
}
void updateMotions()
{
updateAll(motions)
}
def showMotion()
{
show(motions, "motion")
}
void updateMotion()
{
update(motions)
}
def listPresenceSensor()
{
presences.collect{device(it,"presence")}
}
void updatePresenceSensor()
{
updateAll(presences)
}
def showPresence()
{
show(presences,"presence")
}
void updatePresence()
{
update(presences)
}
def listContacts(){
contacts.collect{device(it,"contact")}
}
void updateContacts()
{
updateAll(contacts)
}
def showContact()
{
show(contacts,"contact")
}
void updateContact()
{
update(contacts)
}
private device(it, name) {
if (it) {
def s = it.currentState(name)
[
id: it.id,
name: it.displayName,
label: it.displayName,
hub_name: it.hub.name,
hub_id: it.hub.id,
hub_ip: it.hub.localIP,
hub_port: it.hub.localSrvPortTCP,
state: s
]
}
}
private void updateAll(devices) {
def command = request.JSON?.command
if (command) {
devices."$command"()
}
}
private show(devices, name) {
def device = devices.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
}
else {
log.debug " state s :: ${s}"
log.debug "devices :: ${devices}"
log.debug "name :: ${name}"
def s = device.currentState(name)
[id: device.id, label: device.displayName, name: device.displayName,state:s]
}
}
private void update(devices) {
log.debug "update, request: ${request.JSON}, params: ${params}, devices: $devices.id"
def command = request.JSON?.command
def value = request.JSON?.value
log.debug "$value"
log.debug "$command"
if (command) {
def device = devices.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
if("$command"=="on")
{
device."$command"()
}else if("$command"=="off")
{
device."$command"()
}else if("$command"=="lock")
{
device."$command"()
}else if("$command"=="unlock")
{
device."$command"()
}else
{
device.setLevel("$command")
}
}
}
}
def initialize() {
}

View File

@@ -0,0 +1,412 @@
/**
* 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.
*
*/
definition(
name: "Tcp Bulbs (Connect)",
namespace: "mujica",
author: "SmartThings-Ule",
description: "Connect your TCP bulbs to SmartThings using local integration. You must have a geteway with firmware ver 2",
category: "SmartThings Labs",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/tcp.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/tcp@2x.png",
singleInstance: true
)
preferences {
page(name: "iniSettings", title: "Connect Your TCP Lights to SmartThings", content: "iniSettings")
page(name: "chooseBulbs", title: "Choose Bulbs to Control With SmartThings", content: "bulbDiscovery")
}
def iniSettings(){
state.loadStatus = "Inactive"
log.trace "state.loadStatus ${state.loadStatus}"
return dynamicPage(name:"iniSettings", title:"Connect Your TCP Lights to SmartThings", nextPage:"chooseBulbs", install:false, uninstall: true) {
section("TCP Connected Remote Credentials") {
input "ipGateway", "text", title: "Enter TCP Gateway IP", required: true
paragraph "Tap 'Next' after you have entered the ip of your TCP Connected Gateway.\r\n\r\nOnce your ip are accepted, SmartThings will scan your TCP installation for Bulbs."
}
}
}
def bulbDiscovery() {
debugOut "bulbDiscovery()"
//getToken()
state.token = "1234567890"
if (state.loadStatus == "Inactive"){
state.count = 0
state.loadStatus = "Loading"
log.trace "state.loadStatus ${state.loadStatus}"
deviceDiscovery()
}
log.trace "state.count ${state.count}"
state.count = state.count + 1
log.trace "state.count ${state.count}"
if(state.loadStatus == "Loaded" ){
def options = devicesDiscovered() ?: []
log.trace "state.loadStatus ${state.loadStatus}"
return dynamicPage(name:"chooseBulbs", title:"", nextPage:"", install:true, uninstall: true) {
section("Tap Below to View Device List") {
input "selectedBulbs", "enum", required:false, title:"Select Bulb", multiple:true, options:options
paragraph """Tap 'Done' after you have selected the desired devices."""
}
}
}else{
if (state.count)
log.trace "state.loadStatus ${state.loadStatus}"
def msg = state.count >= 3 ? "The TCP Gateway is not responding, please verify the ip address" : "Please wait while we discover your devices. Discovery can take some minutes or more, so sit back and relax! Select your device below once discovered."
return dynamicPage(name:"chooseBulbs", title:"", nextPage:"", refreshInterval:5) {
section(msg) {}
}
}
}
def installed() {
debugOut "Installed with settings: ${settings}"
unschedule()
unsubscribe()
setupBulbs()
def cron = "0 0/1 * * * ?"
log.debug "schedule('$cron', syncronizeDevices)"
schedule(cron, syncronizeDevices)
}
def updated() {
debugOut "Updated with settings: ${settings}"
unschedule()
setupBulbs()
def cron = "0 0/1 * * * ?"
log.debug "schedule('$cron', syncronizeDevices)"
schedule(cron, syncronizeDevices)
}
def uninstalled()
{
unschedule() //in case we have hanging runIn()'s
}
private removeChildDevices(delete)
{
debugOut "deleting ${delete.size()} bulbs"
debugOut "deleting ${delete}"
delete.each {
deleteChildDevice(it.device.deviceNetworkId)
}
}
def uninstallFromChildDevice(childDevice)
{
def errorMsg = "uninstallFromChildDevice was called and "
if (!settings.selectedBulbs) {
debugOut errorMsg += "had empty list passed in"
return
}
def dni = childDevice.device.deviceNetworkId
if ( !dni ) {
debugOut errorMsg += "could not find dni of device"
return
}
def newDeviceList = settings.selectedBulbs - dni
app.updateSetting("selectedBulbs", newDeviceList)
debugOut errorMsg += "completed succesfully"
}
def setupBulbs() {
debugOut "setupBulbs()"
def bulbs = state.devices
def deviceFile = "TCP Bulb"
selectedBulbs.each { did ->
//see if this is a selected bulb and install it if not already
def d = getChildDevice(did)
if(!d) {
def newBulb = bulbs.find { (it.did) == did }
d = addChildDevice("mujica", deviceFile, did, null, [name: "${newBulb?.name}", label: "${newBulb?.name}", completedSetup: true,"data":["model":newBulb?.model,"nodetype":newBulb?.nodetype,"node":newBulb?.node,"dni":did]])
} else {
infoOut "Avoid add existent device ${did}"
}
}
def delete = getChildDevices().findAll { !selectedBulbs?.contains(it.deviceNetworkId) }
removeChildDevices(delete)
}
def deviceDiscovery() {
log.trace "deviceDiscovery()"
def data = "<gip><version>1</version><token>${state.token}</token></gip>"
def Params = [
cmd: "RoomGetCarousel",
data: "${data}",
fmt: "json"
]
def cmd = toQueryString(Params)
debugOut "deviceDiscovery()"
apiGet(cmd,"RoomGetCarouselHandler")
}
def apiGet(String data, String calledBackHandler) {
debugOut "apiGet($data, $calledBackHandler) $ipGateway"
sendHubCommand(new physicalgraph.device.HubAction([
method: "GET",
path: "/gwr/gop.php?$data",
headers: [
HOST: "$ipGateway:80"
]], getNetworkId("$ipGateway","80"), [callback: calledBackHandler]))
}
void SendCommandHandler(physicalgraph.device.HubResponse hubResponse){
debugOut "SendCommandHandler($hubResponse)"
debugOut "hubResponse.body ${hubResponse.body}"
}
void RoomGetCarouselHandler(physicalgraph.device.HubResponse hubResponse){
debugOut "RoomGetCarouselHandler($hubResponse)"
def bodyXml
if (hubResponse?.body?.contains("<gip>"))
{ // description.xml response (application/xml)
debugOut "body contains xml"
bodyXml = new XmlSlurper().parseText(hubResponse.body)
debugOut "bodyXml $bodyXml"
}
def rooms = ""
def devices = []
def deviceList = []
rooms = bodyXml.room
debugOut "rooms ${rooms[1]}"
rooms.each({
devices = it.device
debugOut "it.device ${it.device}"
def roomName = it.name
debugOut "roomName = ${it.name}"
debugOut "devices[1] ${devices[1]}"
debugOut "devices[1] != null"
def roomId = it?.rid
debugOut "Room Device Data: did:${roomId} roomName:${roomName}"
devices.each({
debugOut "Bulb Device Data: did:${it?.did} room:${roomName} BulbName:${it?.name}"
deviceList += ["name" : "${roomName} ${it?.name}", "did" : "${it?.did}", "type" : "${devices?.type}", "node" : "${devices?.node}", "nodetype" : "${devices?.nodetype}", "model" : "${devices?.prodmodel}"]
})
})
devices = ["devices" : deviceList]
debugOut "devices $devices"
state.devices = devices.devices
state.loadStatus = "Loaded"
}
def getDevices()
{
state.devices = state.devices ?: [:]
}
void RoomGetCarouselUpdateHandler(physicalgraph.device.HubResponse hubResponse){
debugOut "RoomGetCarouselUpdateHandler($hubResponse)"
debugOut "msg ${parseLanMessage(hubResponse.body)}"
def bodyXml
if (hubResponse?.body?.contains("<gip>"))
{
debugOut "body contains xml"
bodyXml = new XmlSlurper().parseText(hubResponse.body)
}
def rooms = ""
def devices = []
def deviceList = []
rooms = bodyXml.room
rooms.each({
devices = it.device
devices.each({
def dni = it.did.text()
def bulb = getChildDevice(dni)
if ( bulb ){
def power = it.power ? it.power.text() as float :0
sendEvent( dni, [name: "power", value: power*1000] )
if (( it.state.text() == "1" ) && ( bulb?.currentValue("switch") != "on" ))
sendEvent( dni, [name: "switch",value:"on"] )
if (( it.state.text() == "0" ) && ( bulb?.currentValue("switch") != "off" ))
sendEvent( dni, [name: "switch",value:"off"] )
if ( it.level.text() != bulb?.currentValue("level")) {
sendEvent( dni, [name: "level",value: "${it.level.text()}"] )
sendEvent( dni, [name: "setLevel",value: "${it.level.text()}"] )
}
}
})
})
}
Map devicesDiscovered() {
def devices = state.devices
def map = [:]
if (devices instanceof java.util.Map) {
devices.each {
def value = "${it?.name}"
def key = it?.did
map["${key}"] = value
}
} else { //backwards compatable
devices.each {
def value = "${it?.name}"
def key = it?.did
map["${key}"] = value
}
}
map
}
def getToken() {
state.token = "1234567890"
}
String toQueryString(Map m) {
return m.collect { k, v -> "${k}=${URLEncoder.encode(v.toString())}" }.sort().join("&")
}
def syncronizeDevices() {
poll(null)
}
def getNetworkId(ipaddr, port) {
"${ipaddr.tokenize('.').collect {String.format('%02X', it.toInteger())}.join()}:${String.format('%04X', port.toInteger())}"
}
/**************************************************************************
Child Device Call In Methods
**************************************************************************/
def on(childDevice) {
def dni = childDevice.device.deviceNetworkId
def data = ""
def cmd = ""
data = "<gip><version>1</version><token>$state.token</token><did>${dni}</did><type>power</type><value>1</value></gip>"
cmd = "DeviceSendCommand"
def qParams = [
cmd: cmd,
data: "${data}",
fmt: "json"
]
cmd = toQueryString(qParams)
apiGet(cmd,"SendCommandHandler" )
}
def off(childDevice) {
def dni = childDevice.device.deviceNetworkId
def data = ""
def cmd = ""
data = "<gip><version>1</version><token>$state.token</token><did>${dni}</did><type>power</type><value>0</value></gip>"
cmd = "DeviceSendCommand"
def qParams = [
cmd: cmd,
data: "${data}",
fmt: "json"
]
cmd = toQueryString(qParams)
apiGet(cmd,"SendCommandHandler")
}
def setLevel(childDevice, value) {
debugOut "setLevel request from child device"
def dni = childDevice.device.deviceNetworkId
def data = ""
def cmd = ""
data = "<gip><version>1</version><token>${state.token}</token><did>${dni}</did><type>level</type><value>${value}</value></gip>"
cmd = "DeviceSendCommand"
def qParams = [
cmd: cmd,
data: "${data}",
fmt: "json"
]
cmd = toQueryString(qParams)
apiGet(cmd,"SendCommandHandler")
}
def poll(childDevice) {
infoOut "poll()"
def eventTime = new Date().time
if ((state.lastPollTime ?:0) + 10000 <= eventTime ){
state.lastPollTime = new Date().time
def Params = [
cmd: "RoomGetCarousel",
data: "<gip><version>1</version><token>${state.token}</token></gip>",
fmt: "json"
]
def cmd = toQueryString(Params)
apiGet(cmd,"RoomGetCarouselUpdateHandler")
}else{
infoOut "Multiple poll requests avoided"
}
}
/**************************************************************************
Msg Methods
**************************************************************************/
def debugOut(msg) {
//log.debug msg
}
def traceOut(msg) {
log.trace msg
}
def infoOut(msg) {
log.info msg
}