mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-08 05:31:56 +00:00
INSIDE-787: Improve Wemo (Connect) event subscriptions
This commit is contained in:
@@ -16,14 +16,14 @@
|
|||||||
* Date: 2013-09-06
|
* Date: 2013-09-06
|
||||||
*/
|
*/
|
||||||
definition(
|
definition(
|
||||||
name: "Wemo (Connect)",
|
name: "Wemo (Connect)",
|
||||||
namespace: "smartthings",
|
namespace: "smartthings",
|
||||||
author: "SmartThings",
|
author: "SmartThings",
|
||||||
description: "Allows you to integrate your WeMo Switch and Wemo Motion sensor with SmartThings.",
|
description: "Allows you to integrate your WeMo Switch and Wemo Motion sensor with SmartThings.",
|
||||||
category: "SmartThings Labs",
|
category: "SmartThings Labs",
|
||||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/wemo.png",
|
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/wemo.png",
|
||||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/wemo@2x.png",
|
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/wemo@2x.png",
|
||||||
singleInstance: true
|
singleInstance: true
|
||||||
)
|
)
|
||||||
|
|
||||||
preferences {
|
preferences {
|
||||||
@@ -39,7 +39,7 @@ private getFriendlyName(String deviceNetworkId) {
|
|||||||
sendHubCommand(new physicalgraph.device.HubAction("""GET /setup.xml HTTP/1.1
|
sendHubCommand(new physicalgraph.device.HubAction("""GET /setup.xml HTTP/1.1
|
||||||
HOST: ${deviceNetworkId}
|
HOST: ${deviceNetworkId}
|
||||||
|
|
||||||
""", physicalgraph.device.Protocol.LAN, "${deviceNetworkId}"))
|
""", physicalgraph.device.Protocol.LAN, "${deviceNetworkId}", [callback: "setupHandler"]))
|
||||||
}
|
}
|
||||||
|
|
||||||
private verifyDevices() {
|
private verifyDevices() {
|
||||||
@@ -52,6 +52,13 @@ private verifyDevices() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ssdpSubscribe() {
|
||||||
|
subscribe(location, "ssdpTerm.urn:Belkin:device:insight:1", ssdpSwitchHandler)
|
||||||
|
subscribe(location, "ssdpTerm.urn:Belkin:device:controllee:1", ssdpSwitchHandler)
|
||||||
|
subscribe(location, "ssdpTerm.urn:Belkin:device:sensor:1", ssdpMotionHandler)
|
||||||
|
subscribe(location, "ssdpTerm.urn:Belkin:device:lightswitch:1", ssdpLightSwitchHandler)
|
||||||
|
}
|
||||||
|
|
||||||
def firstPage()
|
def firstPage()
|
||||||
{
|
{
|
||||||
if(canInstallLabs())
|
if(canInstallLabs())
|
||||||
@@ -62,7 +69,7 @@ def firstPage()
|
|||||||
|
|
||||||
log.debug "REFRESH COUNT :: ${refreshCount}"
|
log.debug "REFRESH COUNT :: ${refreshCount}"
|
||||||
|
|
||||||
subscribe(location, null, locationHandler, [filterEvents:false])
|
ssdpSubscribe()
|
||||||
|
|
||||||
//ssdp request every 25 seconds
|
//ssdp request every 25 seconds
|
||||||
if((refreshCount % 5) == 0) {
|
if((refreshCount % 5) == 0) {
|
||||||
@@ -105,9 +112,7 @@ def devicesDiscovered() {
|
|||||||
def motions = getWemoMotions()
|
def motions = getWemoMotions()
|
||||||
def lightSwitches = getWemoLightSwitches()
|
def lightSwitches = getWemoLightSwitches()
|
||||||
def devices = switches + motions + lightSwitches
|
def devices = switches + motions + lightSwitches
|
||||||
def list = []
|
devices?.collect{ [app.id, it.ssdpUSN].join('.') }
|
||||||
|
|
||||||
list = devices?.collect{ [app.id, it.ssdpUSN].join('.') }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def switchesDiscovered() {
|
def switchesDiscovered() {
|
||||||
@@ -175,8 +180,9 @@ def updated() {
|
|||||||
|
|
||||||
def initialize() {
|
def initialize() {
|
||||||
unsubscribe()
|
unsubscribe()
|
||||||
unschedule()
|
unschedule()
|
||||||
subscribe(location, null, locationHandler, [filterEvents:false])
|
|
||||||
|
ssdpSubscribe()
|
||||||
|
|
||||||
if (selectedSwitches)
|
if (selectedSwitches)
|
||||||
addSwitches()
|
addSwitches()
|
||||||
@@ -189,7 +195,7 @@ def initialize() {
|
|||||||
|
|
||||||
runIn(5, "subscribeToDevices") //initial subscriptions delayed by 5 seconds
|
runIn(5, "subscribeToDevices") //initial subscriptions delayed by 5 seconds
|
||||||
runIn(10, "refreshDevices") //refresh devices, delayed by 10 seconds
|
runIn(10, "refreshDevices") //refresh devices, delayed by 10 seconds
|
||||||
runEvery5Minutes("refresh")
|
runEvery5Minutes("refresh")
|
||||||
}
|
}
|
||||||
|
|
||||||
def resubscribe() {
|
def resubscribe() {
|
||||||
@@ -199,7 +205,7 @@ def resubscribe() {
|
|||||||
|
|
||||||
def refresh() {
|
def refresh() {
|
||||||
log.debug "refresh() called"
|
log.debug "refresh() called"
|
||||||
doDeviceSync()
|
doDeviceSync()
|
||||||
refreshDevices()
|
refreshDevices()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,14 +241,14 @@ def addSwitches() {
|
|||||||
if (!d) {
|
if (!d) {
|
||||||
log.debug "Creating WeMo Switch with dni: ${selectedSwitch.value.mac}"
|
log.debug "Creating WeMo Switch with dni: ${selectedSwitch.value.mac}"
|
||||||
d = addChildDevice("smartthings", "Wemo Switch", selectedSwitch.value.mac, selectedSwitch?.value.hub, [
|
d = addChildDevice("smartthings", "Wemo Switch", selectedSwitch.value.mac, selectedSwitch?.value.hub, [
|
||||||
"label": selectedSwitch?.value?.name ?: "Wemo Switch",
|
"label": selectedSwitch?.value?.name ?: "Wemo Switch",
|
||||||
"data": [
|
"data": [
|
||||||
"mac": selectedSwitch.value.mac,
|
"mac": selectedSwitch.value.mac,
|
||||||
"ip": selectedSwitch.value.ip,
|
"ip": selectedSwitch.value.ip,
|
||||||
"port": selectedSwitch.value.port
|
"port": selectedSwitch.value.port
|
||||||
]
|
]
|
||||||
])
|
])
|
||||||
def ipvalue = convertHexToIP(selectedSwitch.value.ip)
|
def ipvalue = convertHexToIP(selectedSwitch.value.ip)
|
||||||
d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}")
|
d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}")
|
||||||
log.debug "Created ${d.displayName} with id: ${d.id}, dni: ${d.deviceNetworkId}"
|
log.debug "Created ${d.displayName} with id: ${d.id}, dni: ${d.deviceNetworkId}"
|
||||||
} else {
|
} else {
|
||||||
@@ -273,9 +279,9 @@ def addMotions() {
|
|||||||
"port": selectedMotion.value.port
|
"port": selectedMotion.value.port
|
||||||
]
|
]
|
||||||
])
|
])
|
||||||
def ipvalue = convertHexToIP(selectedMotion.value.ip)
|
def ipvalue = convertHexToIP(selectedMotion.value.ip)
|
||||||
d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}")
|
d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}")
|
||||||
log.debug "Created ${d.displayName} with id: ${d.id}, dni: ${d.deviceNetworkId}"
|
log.debug "Created ${d.displayName} with id: ${d.id}, dni: ${d.deviceNetworkId}"
|
||||||
} else {
|
} else {
|
||||||
log.debug "found ${d.displayName} with id $dni already exists"
|
log.debug "found ${d.displayName} with id $dni already exists"
|
||||||
}
|
}
|
||||||
@@ -304,26 +310,147 @@ def addLightSwitches() {
|
|||||||
"port": selectedLightSwitch.value.port
|
"port": selectedLightSwitch.value.port
|
||||||
]
|
]
|
||||||
])
|
])
|
||||||
def ipvalue = convertHexToIP(selectedLightSwitch.value.ip)
|
def ipvalue = convertHexToIP(selectedLightSwitch.value.ip)
|
||||||
d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}")
|
d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}")
|
||||||
log.debug "created ${d.displayName} with id $dni"
|
log.debug "created ${d.displayName} with id $dni"
|
||||||
} else {
|
} else {
|
||||||
log.debug "found ${d.displayName} with id $dni already exists"
|
log.debug "found ${d.displayName} with id $dni already exists"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def ssdpSwitchHandler(evt) {
|
||||||
|
def description = evt.description
|
||||||
|
def hub = evt?.hubId
|
||||||
|
def parsedEvent = parseDiscoveryMessage(description)
|
||||||
|
parsedEvent << ["hub":hub]
|
||||||
|
log.debug parsedEvent
|
||||||
|
|
||||||
|
def switches = getWemoSwitches()
|
||||||
|
if (!(switches."${parsedEvent.ssdpUSN.toString()}")) {
|
||||||
|
//if it doesn't already exist
|
||||||
|
switches << ["${parsedEvent.ssdpUSN.toString()}":parsedEvent]
|
||||||
|
} else {
|
||||||
|
log.debug "Device was already found in state..."
|
||||||
|
def d = switches."${parsedEvent.ssdpUSN.toString()}"
|
||||||
|
boolean deviceChangedValues = false
|
||||||
|
log.debug "$d.ip <==> $parsedEvent.ip"
|
||||||
|
if(d.ip != parsedEvent.ip || d.port != parsedEvent.port) {
|
||||||
|
d.ip = parsedEvent.ip
|
||||||
|
d.port = parsedEvent.port
|
||||||
|
deviceChangedValues = true
|
||||||
|
log.debug "Device's port or ip changed..."
|
||||||
|
def child = getChildDevice(parsedEvent.mac)
|
||||||
|
child.subscribe(parsedEvent.ip, parsedEvent.port)
|
||||||
|
child.poll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def ssdpMotionHandler(evt) {
|
||||||
|
log.info("ssdpMotionHandler")
|
||||||
|
def description = evt.description
|
||||||
|
def hub = evt?.hubId
|
||||||
|
def parsedEvent = parseDiscoveryMessage(description)
|
||||||
|
parsedEvent << ["hub":hub]
|
||||||
|
log.debug parsedEvent
|
||||||
|
|
||||||
|
def motions = getWemoMotions()
|
||||||
|
if (!(motions."${parsedEvent.ssdpUSN.toString()}")) {
|
||||||
|
//if it doesn't already exist
|
||||||
|
motions << ["${parsedEvent.ssdpUSN.toString()}":parsedEvent]
|
||||||
|
} else { // just update the values
|
||||||
|
log.debug "Device was already found in state..."
|
||||||
|
|
||||||
|
def d = motions."${parsedEvent.ssdpUSN.toString()}"
|
||||||
|
boolean deviceChangedValues = false
|
||||||
|
|
||||||
|
if(d.ip != parsedEvent.ip || d.port != parsedEvent.port) {
|
||||||
|
d.ip = parsedEvent.ip
|
||||||
|
d.port = parsedEvent.port
|
||||||
|
deviceChangedValues = true
|
||||||
|
log.debug "Device's port or ip changed..."
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deviceChangedValues) {
|
||||||
|
def children = getChildDevices()
|
||||||
|
log.debug "Found children ${children}"
|
||||||
|
children.each {
|
||||||
|
if (it.getDeviceDataByName("mac") == parsedEvent.mac) {
|
||||||
|
log.debug "updating ip and port, and resubscribing, for device ${it} with mac ${parsedEvent.mac}"
|
||||||
|
it.subscribe(parsedEvent.ip, parsedEvent.port)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def ssdpLightSwitchHandler(evt) {
|
||||||
|
log.info("ssdpLightSwitchHandler")
|
||||||
|
def description = evt.description
|
||||||
|
def hub = evt?.hubId
|
||||||
|
def parsedEvent = parseDiscoveryMessage(description)
|
||||||
|
parsedEvent << ["hub":hub]
|
||||||
|
log.debug parsedEvent
|
||||||
|
|
||||||
|
def lightSwitches = getWemoLightSwitches()
|
||||||
|
|
||||||
|
if (!(lightSwitches."${parsedEvent.ssdpUSN.toString()}")) {
|
||||||
|
//if it doesn't already exist
|
||||||
|
lightSwitches << ["${parsedEvent.ssdpUSN.toString()}":parsedEvent]
|
||||||
|
} else {
|
||||||
|
log.debug "Device was already found in state..."
|
||||||
|
|
||||||
|
def d = lightSwitches."${parsedEvent.ssdpUSN.toString()}"
|
||||||
|
boolean deviceChangedValues = false
|
||||||
|
|
||||||
|
if(d.ip != parsedEvent.ip || d.port != parsedEvent.port) {
|
||||||
|
d.ip = parsedEvent.ip
|
||||||
|
d.port = parsedEvent.port
|
||||||
|
deviceChangedValues = true
|
||||||
|
log.debug "Device's port or ip changed..."
|
||||||
|
def child = getChildDevice(parsedEvent.mac)
|
||||||
|
log.debug "updating ip and port, and resubscribing, for device with mac ${parsedEvent.mac}"
|
||||||
|
child.subscribe(parsedEvent.ip, parsedEvent.port)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupHandler(hubResponse) {
|
||||||
|
String contentType = hubResponse?.headers['Content-Type']
|
||||||
|
if (contentType != null && contentType == 'text/xml') {
|
||||||
|
def body = hubResponse.xml
|
||||||
|
def wemoDevices = []
|
||||||
|
String deviceType = body?.device?.deviceType?.text() ?: ""
|
||||||
|
if (deviceType.startsWith("urn:Belkin:device:controllee:1") || deviceType.startsWith("urn:Belkin:device:insight:1")) {
|
||||||
|
wemoDevices = getWemoSwitches()
|
||||||
|
} else if (deviceType.startsWith("urn:Belkin:device:sensor")) {
|
||||||
|
wemoDevices = getWemoMotions()
|
||||||
|
} else if (deviceType.startsWith("urn:Belkin:device:lightswitch")) {
|
||||||
|
wemoDevices = getWemoLightSwitches()
|
||||||
|
}
|
||||||
|
|
||||||
|
def wemoDevice = wemoDevices.find {it?.key?.contains(body?.device?.UDN?.text())}
|
||||||
|
if (wemoDevice) {
|
||||||
|
wemoDevice.value << [name:body?.device?.friendlyName?.text(), verified: true]
|
||||||
|
} else {
|
||||||
|
log.error "/setup.xml returned a wemo device that didn't exist"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
def locationHandler(evt) {
|
def locationHandler(evt) {
|
||||||
def description = evt.description
|
def description = evt.description
|
||||||
def hub = evt?.hubId
|
def hub = evt?.hubId
|
||||||
def parsedEvent = parseDiscoveryMessage(description)
|
def parsedEvent = parseDiscoveryMessage(description)
|
||||||
parsedEvent << ["hub":hub]
|
parsedEvent << ["hub":hub]
|
||||||
log.debug parsedEvent
|
log.debug parsedEvent
|
||||||
|
|
||||||
if (parsedEvent?.ssdpTerm?.contains("Belkin:device:controllee") || parsedEvent?.ssdpTerm?.contains("Belkin:device:insight")) {
|
if (parsedEvent?.ssdpTerm?.contains("Belkin:device:controllee") || parsedEvent?.ssdpTerm?.contains("Belkin:device:insight")) {
|
||||||
def switches = getWemoSwitches()
|
def switches = getWemoSwitches()
|
||||||
if (!(switches."${parsedEvent.ssdpUSN.toString()}")) {
|
if (!(switches."${parsedEvent.ssdpUSN.toString()}")) {
|
||||||
//if it doesn't already exist
|
//if it doesn't already exist
|
||||||
switches << ["${parsedEvent.ssdpUSN.toString()}":parsedEvent]
|
switches << ["${parsedEvent.ssdpUSN.toString()}":parsedEvent]
|
||||||
} else {
|
} else {
|
||||||
log.debug "Device was already found in state..."
|
log.debug "Device was already found in state..."
|
||||||
@@ -335,16 +462,16 @@ def locationHandler(evt) {
|
|||||||
d.port = parsedEvent.port
|
d.port = parsedEvent.port
|
||||||
deviceChangedValues = true
|
deviceChangedValues = true
|
||||||
log.debug "Device's port or ip changed..."
|
log.debug "Device's port or ip changed..."
|
||||||
def child = getChildDevice(parsedEvent.mac)
|
def child = getChildDevice(parsedEvent.mac)
|
||||||
child.subscribe(parsedEvent.ip, parsedEvent.port)
|
child.subscribe(parsedEvent.ip, parsedEvent.port)
|
||||||
child.poll()
|
child.poll()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (parsedEvent?.ssdpTerm?.contains("Belkin:device:sensor")) {
|
else if (parsedEvent?.ssdpTerm?.contains("Belkin:device:sensor")) {
|
||||||
def motions = getWemoMotions()
|
def motions = getWemoMotions()
|
||||||
if (!(motions."${parsedEvent.ssdpUSN.toString()}")) {
|
if (!(motions."${parsedEvent.ssdpUSN.toString()}")) {
|
||||||
//if it doesn't already exist
|
//if it doesn't already exist
|
||||||
motions << ["${parsedEvent.ssdpUSN.toString()}":parsedEvent]
|
motions << ["${parsedEvent.ssdpUSN.toString()}":parsedEvent]
|
||||||
} else { // just update the values
|
} else { // just update the values
|
||||||
log.debug "Device was already found in state..."
|
log.debug "Device was already found in state..."
|
||||||
@@ -459,6 +586,7 @@ def locationHandler(evt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
private def parseXmlBody(def body) {
|
private def parseXmlBody(def body) {
|
||||||
def decodedBytes = body.decodeBase64()
|
def decodedBytes = body.decodeBase64()
|
||||||
def bodyString
|
def bodyString
|
||||||
@@ -540,4 +668,4 @@ private Boolean hasAllHubsOver(String desiredFirmware) {
|
|||||||
|
|
||||||
private List getRealHubFirmwareVersions() {
|
private List getRealHubFirmwareVersions() {
|
||||||
return location.hubs*.firmwareVersionString.findAll { it }
|
return location.hubs*.firmwareVersionString.findAll { it }
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user