Compare commits

...

12 Commits

Author SHA1 Message Date
Vinay Rao
b05d956d95 Merge pull request #830 from SmartThingsCommunity/staging
Rolling up changes to production from staging 2016-04-26 Release
2016-04-26 10:59:05 -07:00
Donald C. Kirker
6cdb80db1f Merge pull request #836 from mckeed/staging
Add auto-retyping for Astralink sensors SING-44
2016-04-25 17:41:32 -07:00
Duncan McKee
4db99824af Add Astralink sensors to zw door/window retypeBasedOnMSR 2016-04-25 16:40:47 -04:00
Vinay Rao
b2e245bd85 Merge pull request #833 from SmartThingsCommunity/production
Rolling down hotfix for deploy tool to staging
2016-04-25 12:28:55 -07:00
Vinay Rao
9a9854cf92 Merge pull request #831 from jord98716/DEVTOOLS-636-a
DEVTOOLS-636: Increment version of executable-deployment-scripts
2016-04-25 12:27:42 -07:00
Jordan Howe
37f1726ee6 DEVTOOLS-636: Increment version of executable-deployment-scripts 2016-04-25 09:57:53 -05:00
Vinay Rao
d5ea735df7 Merge pull request #810 from SmartThingsCommunity/master
Rolling up master to staging
2016-04-19 15:50:22 -07:00
Vinay Rao
6428719c79 Merge pull request #809 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-04-19 15:41:56 -07:00
Yaima
33ef75091b Merge pull request #783 from Yaima/master
Fixes broken htmlTile
2016-04-14 16:05:55 -07:00
Yaima Valdivia
1bcad614ec Fixes broken htmlTile 2016-04-14 16:03:58 -07:00
Luke Bredeson
3ab83350f3 Merge pull request #761 from lbredeso/hue-event-subscription-improvements
EX-3: Improve Hue (Connect) event subscriptions
2016-04-14 16:58:01 -05:00
Luke Bredeson
237d6a79e9 EX-3: Improve Hue (Connect) event subscriptions 2016-04-05 13:28:45 -05:00
4 changed files with 147 additions and 31 deletions

View File

@@ -9,7 +9,7 @@ apply plugin: 'smartthings-slack'
buildscript { buildscript {
dependencies { dependencies {
classpath "com.smartthings.deployment:executable-deployment-scripts:1.0.7" classpath "com.smartthings.deployment:executable-deployment-scripts:1.0.8"
} }
repositories { repositories {
mavenLocal() mavenLocal()

View File

@@ -33,7 +33,7 @@ metadata {
state "power", label: '${currentValue} W' state "power", label: '${currentValue} W'
} }
htmlTile(name: "powerContent", attribute: "powerContent", type: "HTML", whitelist: "www.wattvision.com" , url: '${currentValue}', width: 3, height: 2) htmlTile(name: "powerContent", attribute: "powerContent", type: "HTML", whitelist: ["www.wattvision.com"] , url: '${currentValue}', width: 3, height: 2)
standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat") { standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat") {
state "default", label: '', action: "refresh.refresh", icon: "st.secondary.refresh" state "default", label: '', action: "refresh.refresh", icon: "st.secondary.refresh"

View File

@@ -25,7 +25,10 @@ metadata {
fingerprint deviceId: "0x2001", inClusters: "0x30,0x80,0x84,0x85,0x86,0x72" fingerprint deviceId: "0x2001", inClusters: "0x30,0x80,0x84,0x85,0x86,0x72"
fingerprint deviceId: "0x07", inClusters: "0x30" 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,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+
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x72,0x5A,0x80,0x73,0x86,0x84,0x85,0x59,0x71,0x70,0x7A,0x98" // Vision door/window
} }
// simulator metadata // simulator metadata
@@ -240,7 +243,7 @@ def batteryGetCommand() {
def retypeBasedOnMSR() { def retypeBasedOnMSR() {
switch (state.MSR) { switch (state.MSR) {
case "0086-0002-002D": case "0086-0002-002D":
log.debug("Changing device type to Z-Wave Water Sensor") log.debug "Changing device type to Z-Wave Water Sensor"
setDeviceType("Z-Wave Water Sensor") setDeviceType("Z-Wave Water Sensor")
break break
case "011F-0001-0001": // Schlage motion case "011F-0001-0001": // Schlage motion
@@ -249,9 +252,16 @@ def retypeBasedOnMSR() {
case "0060-0001-0002": // Everspring SP814 case "0060-0001-0002": // Everspring SP814
case "0060-0001-0003": // Everspring HSP02 case "0060-0001-0003": // Everspring HSP02
case "011A-0601-0901": // Enerwave ZWN-BPC case "011A-0601-0901": // Enerwave ZWN-BPC
log.debug("Changing device type to Z-Wave Motion Sensor") log.debug "Changing device type to Z-Wave Motion Sensor"
setDeviceType("Z-Wave Motion Sensor") setDeviceType("Z-Wave Motion Sensor")
break 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 Door / Window Sensor Plus (SG)"
setDeviceType("Door / Window Sensor Plus (SG)")
break
} }
} }

View File

@@ -60,7 +60,7 @@ def bridgeDiscovery(params=[:])
app.updateSetting("selectedHue", "") app.updateSetting("selectedHue", "")
} }
subscribe(location, null, locationHandler, [filterEvents:false]) ssdpSubscribe()
//bridge discovery request every 15 //25 seconds //bridge discovery request every 15 //25 seconds
if((bridgeRefreshCount % 5) == 0) { if((bridgeRefreshCount % 5) == 0) {
@@ -152,6 +152,10 @@ private discoverBridges() {
sendHubCommand(new physicalgraph.device.HubAction("lan discovery urn:schemas-upnp-org:device:basic:1", physicalgraph.device.Protocol.LAN)) sendHubCommand(new physicalgraph.device.HubAction("lan discovery urn:schemas-upnp-org:device:basic:1", physicalgraph.device.Protocol.LAN))
} }
void ssdpSubscribe() {
subscribe(location, "ssdpTerm.urn:schemas-upnp-org:device:basic:1", ssdpBridgeHandler)
}
private sendDeveloperReq() { private sendDeveloperReq() {
def token = app.id def token = app.id
def host = getBridgeIP() def host = getBridgeIP()
@@ -161,7 +165,7 @@ private sendDeveloperReq() {
headers: [ headers: [
HOST: host HOST: host
], ],
body: [devicetype: "$token-0"]], "${selectedHue}")) body: [devicetype: "$token-0"]], "${selectedHue}", [callback: "usernameHandler"]))
} }
private discoverHueBulbs() { private discoverHueBulbs() {
@@ -171,7 +175,7 @@ private discoverHueBulbs() {
path: "/api/${state.username}/lights", path: "/api/${state.username}/lights",
headers: [ headers: [
HOST: host HOST: host
]], "${selectedHue}")) ]], "${selectedHue}", [callback: "lightsHandler"]))
} }
private verifyHueBridge(String deviceNetworkId, String host) { private verifyHueBridge(String deviceNetworkId, String host) {
@@ -181,7 +185,7 @@ private verifyHueBridge(String deviceNetworkId, String host) {
path: "/description.xml", path: "/description.xml",
headers: [ headers: [
HOST: host HOST: host
]], deviceNetworkId)) ]], deviceNetworkId, [callback: "bridgeDescriptionHandler"]))
} }
private verifyHueBridges() { private verifyHueBridges() {
@@ -293,8 +297,9 @@ def bulbListHandler(hub, data = "") {
} }
} }
def bridge = null def bridge = null
if (selectedHue) if (selectedHue) {
bridge = getChildDevice(selectedHue) bridge = getChildDevice(selectedHue)
}
bridge.sendEvent(name: "bulbList", value: hub, data: bulbs, isStateChange: true, displayed: false) bridge.sendEvent(name: "bulbList", value: hub, data: bulbs, isStateChange: true, displayed: false)
msg = "${bulbs.size()} bulbs found. ${bulbs}" msg = "${bulbs.size()} bulbs found. ${bulbs}"
return msg return msg
@@ -382,8 +387,9 @@ def addBridge() {
def oldDNI = it.deviceNetworkId def oldDNI = it.deviceNetworkId
log.debug "updating dni for device ${it} with $newDNI - previous DNI = ${it.deviceNetworkId}" log.debug "updating dni for device ${it} with $newDNI - previous DNI = ${it.deviceNetworkId}"
it.setDeviceNetworkId("${newDNI}") it.setDeviceNetworkId("${newDNI}")
if (oldDNI == selectedHue) if (oldDNI == selectedHue) {
app.updateSetting("selectedHue", newDNI) app.updateSetting("selectedHue", newDNI)
}
newbridge = false newbridge = false
} }
} }
@@ -412,6 +418,111 @@ def addBridge() {
} }
} }
def ssdpBridgeHandler(evt) {
def description = evt.description
log.trace "Location: $description"
def hub = evt?.hubId
def parsedEvent = parseLanMessage(description)
parsedEvent << ["hub":hub]
def bridges = getHueBridges()
log.trace bridges.toString()
if (!(bridges."${parsedEvent.ssdpUSN.toString()}")) {
//bridge does not exist
log.trace "Adding bridge ${parsedEvent.ssdpUSN}"
bridges << ["${parsedEvent.ssdpUSN.toString()}":parsedEvent]
} else {
// update the values
def ip = convertHexToIP(parsedEvent.networkAddress)
def port = convertHexToInt(parsedEvent.deviceAddress)
def host = ip + ":" + port
log.debug "Device ($parsedEvent.mac) was already found in state with ip = $host."
def dstate = bridges."${parsedEvent.ssdpUSN.toString()}"
def dni = "${parsedEvent.mac}"
def d = getChildDevice(dni)
def networkAddress = null
if (!d) {
childDevices.each {
if (it.getDeviceDataByName("mac")) {
def newDNI = "${it.getDeviceDataByName("mac")}"
if (newDNI != it.deviceNetworkId) {
def oldDNI = it.deviceNetworkId
log.debug "updating dni for device ${it} with $newDNI - previous DNI = ${it.deviceNetworkId}"
it.setDeviceNetworkId("${newDNI}")
if (oldDNI == selectedHue) {
app.updateSetting("selectedHue", newDNI)
}
doDeviceSync()
}
}
}
} else {
if (d.getDeviceDataByName("networkAddress")) {
networkAddress = d.getDeviceDataByName("networkAddress")
} else {
networkAddress = d.latestState('networkAddress').stringValue
}
log.trace "Host: $host - $networkAddress"
if (host != networkAddress) {
log.debug "Device's port or ip changed for device $d..."
dstate.ip = ip
dstate.port = port
dstate.name = "Philips hue ($ip)"
d.sendEvent(name:"networkAddress", value: host)
d.updateDataValue("networkAddress", host)
}
}
}
}
void bridgeDescriptionHandler(physicalgraph.device.HubResponse hubResponse) {
log.trace "description.xml response (application/xml)"
def body = hubResponse.xml
if (body?.device?.modelName?.text().startsWith("Philips hue bridge")) {
def bridges = getHueBridges()
def bridge = bridges.find {it?.key?.contains(body?.device?.UDN?.text())}
if (bridge) {
bridge.value << [name:body?.device?.friendlyName?.text(), serialNumber:body?.device?.serialNumber?.text(), verified: true]
} else {
log.error "/description.xml returned a bridge that didn't exist"
}
}
}
void lightsHandler(physicalgraph.device.HubResponse hubResponse) {
if (isValidSource(hubResponse.mac)) {
def body = hubResponse.json
if (!body?.state?.on) { //check if first time poll made it here by mistake
def bulbs = getHueBulbs()
log.debug "Adding bulbs to state!"
body.each { k, v ->
bulbs[k] = [id: k, name: v.name, type: v.type, modelid: v.modelid, hub: hubResponse.hubId]
}
}
}
}
void usernameHandler(physicalgraph.device.HubResponse hubResponse) {
if (isValidSource(hubResponse.mac)) {
def body = hubResponse.json
if (body.success != null) {
if (body.success[0] != null) {
if (body.success[0].username)
state.username = body.success[0].username
}
} else if (body.error != null) {
//TODO: handle retries...
log.error "ERROR: application/json ${body.error}"
}
}
}
/**
* @deprecated This has been replaced by the combination of {@link #ssdpBridgeHandler()}, {@link #bridgeDescriptionHandler()},
* {@link #lightsHandler()}, and {@link #usernameHandler()}. After a pending event subscription migration, it can be removed.
*/
@Deprecated
def locationHandler(evt) { def locationHandler(evt) {
def description = evt.description def description = evt.description
log.trace "Location: $description" log.trace "Location: $description"
@@ -447,17 +558,19 @@ def locationHandler(evt) {
def oldDNI = it.deviceNetworkId def oldDNI = it.deviceNetworkId
log.debug "updating dni for device ${it} with $newDNI - previous DNI = ${it.deviceNetworkId}" log.debug "updating dni for device ${it} with $newDNI - previous DNI = ${it.deviceNetworkId}"
it.setDeviceNetworkId("${newDNI}") it.setDeviceNetworkId("${newDNI}")
if (oldDNI == selectedHue) if (oldDNI == selectedHue) {
app.updateSetting("selectedHue", newDNI) app.updateSetting("selectedHue", newDNI)
}
doDeviceSync() doDeviceSync()
} }
} }
} }
} else { } else {
if (d.getDeviceDataByName("networkAddress")) if (d.getDeviceDataByName("networkAddress")) {
networkAddress = d.getDeviceDataByName("networkAddress") networkAddress = d.getDeviceDataByName("networkAddress")
else } else {
networkAddress = d.latestState('networkAddress').stringValue networkAddress = d.latestState('networkAddress').stringValue
}
log.trace "Host: $host - $networkAddress" log.trace "Host: $host - $networkAddress"
if(host != networkAddress) { if(host != networkAddress) {
log.debug "Device's port or ip changed for device $d..." log.debug "Device's port or ip changed for device $d..."
@@ -490,8 +603,9 @@ def locationHandler(evt) {
def body = new groovy.json.JsonSlurper().parseText(parsedEvent.body) def body = new groovy.json.JsonSlurper().parseText(parsedEvent.body)
if (body.success != null) { if (body.success != null) {
if (body.success[0] != null) { if (body.success[0] != null) {
if (body.success[0].username) if (body.success[0].username) {
state.username = body.success[0].username state.username = body.success[0].username
}
} }
} else if (body.error != null) { } else if (body.error != null) {
//TODO: handle retries... //TODO: handle retries...
@@ -516,11 +630,7 @@ def doDeviceSync(){
log.trace "Doing Hue Device Sync!" log.trace "Doing Hue Device Sync!"
convertBulbListToMap() convertBulbListToMap()
poll() poll()
try { ssdpSubscribe()
subscribe(location, null, locationHandler, [filterEvents:false])
} catch (all) {
log.trace "Subscription already exist"
}
discoverBridges() discoverBridges()
} }
@@ -747,15 +857,11 @@ private getId(childDevice) {
private poll() { private poll() {
def host = getBridgeIP() def host = getBridgeIP()
def uri = "/api/${state.username}/lights/" def uri = "/api/${state.username}/lights/"
try { log.debug "GET: $host$uri"
sendHubCommand(new physicalgraph.device.HubAction("""GET ${uri} HTTP/1.1 sendHubCommand(new physicalgraph.device.HubAction("""GET ${uri} HTTP/1.1
HOST: ${host} HOST: ${host}
""", physicalgraph.device.Protocol.LAN, selectedHue)) """, physicalgraph.device.Protocol.LAN, selectedHue))
} catch (all) {
log.warn "Parsing Body failed - trying again..."
doDeviceSync()
}
} }
private put(path, body) { private put(path, body) {