Compare commits

...

31 Commits

Author SHA1 Message Date
Vinay Rao
566425c531 Merge pull request #869 from SmartThingsCommunity/staging
Rolling up staging to production 05-10
2016-05-10 13:40:49 -07:00
Vinay Rao
e7448e7908 Merge pull request #848 from SmartThingsCommunity/master
Rolling up master to staging
2016-05-03 10:59:58 -07:00
Vinay Rao
973c16f088 Merge pull request #842 from SmartThingsCommunity/staging
Rolling up changes to production from staging 2016-05-03 Release
2016-05-03 10:20:53 -07:00
Luke Bredeson
77f880af6e Merge pull request #841 from lbredeso/hue-connect-updated-failure
SHARD-174: Hue (Connect) updated() calls can fail in certain situations
2016-04-28 13:28:07 -05:00
Luke Bredeson
1c4386a67b SHARD-174: Hue (Connect) updated() calls can fail in certain situations 2016-04-28 11:09:52 -05:00
Matt Pennig
88dd510e72 Merge pull request #832 from SmartThingsCommunity/two-line-multiattribute-controls
Adding test cases for multi-line controls in multiattribute tiles
2016-04-26 13:49:57 -05:00
Vinay Rao
e278a3b57d Merge pull request #838 from SmartThingsCommunity/master
Rolling up master to staging
2016-04-26 11:34:03 -07:00
Vinay Rao
7786df3262 Merge pull request #837 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-04-26 11:25:59 -07:00
Matt Pennig
5ac08e5a92 adding multi-line text for standard and value tiles 2016-04-26 13:13:20 -05:00
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
72b51d50bc Merge pull request #834 from SmartThingsCommunity/staging
Rolling down hotfix for deploy tool to master
2016-04-25 12:33:13 -07: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
Matt Pennig
1e27ff5d4a Adding test cases for multi-line controls in multiattribute tiles 2016-04-25 11:58:18 -05:00
Jordan Howe
37f1726ee6 DEVTOOLS-636: Increment version of executable-deployment-scripts 2016-04-25 09:57:53 -05:00
Jack Chi
c7e8079ff1 Merge pull request #757 from jackchi/add-healthcheck-smartsense
[CHF-112] Add Health Check capability to SmartThings SmartSense products
2016-04-22 11:11:59 -07:00
jackchi
481d13a571 [CHF-112] Add Health Check capability to SmartThings SmartSense products 2016-04-22 11:10:48 -07:00
Luke Bredeson
9d83b850ca Merge pull request #813 from lbredeso/updated-settings-state-fix
SHARD-159: Wemo (Connect) updated() fails in certain IP change scenarios
2016-04-20 16:31:36 -05:00
Luke Bredeson
84de336a1a SHARD-159: Wemo (Connect) updated() fails in certain IP change scenarios 2016-04-20 16:07:11 -05:00
Lars Finander
8b465b03b4 Merge pull request #808 from larsfinander/DVCSMP-1716_Philips_Hue_Invalid_parameter
DVCSMP-1716 Philips Hue: Invalid hue parameter used in setColor
2016-04-20 11:11:39 -07:00
Vinay Rao
2f81964479 Merge pull request #775 from motley74/nyce_hinge
Added fingerprint for NYCE door hinge sensor
2016-04-20 10:29:06 -07: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
Lars Finander
327f8dfb00 DVCSMP-1716 Philips Hue: Invalid hue parameter used in setColor
-Replaced transition with transitiontime according to Hue API
2016-04-19 15:05:21 -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
Michael Hudson
235e3f5507 Added fingerprint for NYCE door hinge sensor 2016-04-12 18:23:28 -06:00
Luke Bredeson
237d6a79e9 EX-3: Improve Hue (Connect) event subscriptions 2016-04-05 13:28:45 -05:00
15 changed files with 270 additions and 94 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

@@ -24,6 +24,7 @@ metadata {
command "enrollResponse" command "enrollResponse"
fingerprint inClusters: "0000,0001,0003,0500,0020", manufacturer: "NYCE", model: "3010", deviceJoinName: "NYCE Door Hinge Sensor"
fingerprint inClusters: "0000,0001,0003,0406,0500,0020", manufacturer: "NYCE", model: "3011", deviceJoinName: "NYCE Door/Window Sensor" fingerprint inClusters: "0000,0001,0003,0406,0500,0020", manufacturer: "NYCE", model: "3011", deviceJoinName: "NYCE Door/Window Sensor"
fingerprint inClusters: "0000,0001,0003,0500,0020", manufacturer: "NYCE", model: "3011", deviceJoinName: "NYCE Door/Window Sensor" fingerprint inClusters: "0000,0001,0003,0500,0020", manufacturer: "NYCE", model: "3011", deviceJoinName: "NYCE Door/Window Sensor"
fingerprint inClusters: "0000,0001,0003,0406,0500,0020", manufacturer: "NYCE", model: "3014", deviceJoinName: "NYCE Tilt Sensor" fingerprint inClusters: "0000,0001,0003,0406,0500,0020", manufacturer: "NYCE", model: "3014", deviceJoinName: "NYCE Tilt Sensor"

View File

@@ -31,6 +31,7 @@ metadata {
capability "Configuration" capability "Configuration"
capability "Refresh" capability "Refresh"
capability "Sensor" capability "Sensor"
capability "Health Check"
// indicates that device keeps track of heartbeat (in state.heartbeat) // indicates that device keeps track of heartbeat (in state.heartbeat)
attribute "heartbeat", "string" attribute "heartbeat", "string"

View File

@@ -31,6 +31,7 @@ metadata {
capability "Refresh" capability "Refresh"
capability "Temperature Measurement" capability "Temperature Measurement"
capability "Water Sensor" capability "Water Sensor"
capability "Health Check"
command "enrollResponse" command "enrollResponse"

View File

@@ -31,6 +31,7 @@ metadata {
capability "Battery" capability "Battery"
capability "Temperature Measurement" capability "Temperature Measurement"
capability "Refresh" capability "Refresh"
capability "Health Check"
command "enrollResponse" command "enrollResponse"

View File

@@ -35,6 +35,7 @@ metadata {
capability "Acceleration Sensor" capability "Acceleration Sensor"
capability "Refresh" capability "Refresh"
capability "Temperature Measurement" capability "Temperature Measurement"
capability "Health Check"
command "enrollResponse" command "enrollResponse"
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05,FC02", outClusters: "0019", manufacturer: "CentraLite", model: "3320" fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05,FC02", outClusters: "0019", manufacturer: "CentraLite", model: "3320"

View File

@@ -23,8 +23,9 @@
capability "Acceleration Sensor" capability "Acceleration Sensor"
capability "Refresh" capability "Refresh"
capability "Temperature Measurement" capability "Temperature Measurement"
command "enrollResponse" capability "Health Check"
command "enrollResponse"
} }
simulator { simulator {

View File

@@ -20,6 +20,7 @@ metadata {
capability "Refresh" capability "Refresh"
capability "Temperature Measurement" capability "Temperature Measurement"
capability "Relative Humidity Measurement" capability "Relative Humidity Measurement"
capability "Health Check"
fingerprint endpointId: "01", inClusters: "0001,0003,0020,0402,0B05,FC45", outClusters: "0019,0003" fingerprint endpointId: "01", inClusters: "0001,0003,0020,0402,0B05,FC45", outClusters: "0019,0003"
} }

View File

@@ -80,19 +80,31 @@ metadata {
state "default", label:'' state "default", label:''
} }
main("standard1") // multi-line text (explicit newlines)
standardTile("multiLine", "device.multiLine", width: 2, height: 2) {
state "default", label: '${currentValue}'
}
standardTile("multiLineWithIcon", "device.multiLine", width: 2, height: 2) {
state "default", label: '${currentValue}', icon: "st.switches.switch.off"
}
main("actionRings")
details([ details([
"actionRings", "actionFlat", "noActionFlat", "actionRings", "actionFlat", "noActionFlat",
"flatLabel", "flatIconLabel", "flatIcon", "flatLabel", "flatIconLabel", "flatIcon",
"flatDefaultState", "flatImplicitDefaultState1", "flatImplicitDefaultState2", "flatDefaultState", "flatImplicitDefaultState1", "flatImplicitDefaultState2",
"multiLine", "multiLineWithIcon"
]) ])
} }
} }
def installed() { def installed() {
sendEvent(name: "switch", value: "off") sendEvent(name: "switch", value: "off")
sendEvent(name: "multiLine", value: "Line 1\nLine 2\nLine 3")
} }
def parse(String description) { def parse(String description) {

View File

@@ -69,16 +69,25 @@ metadata {
] ]
} }
valueTile("noValue", "device.nada", width: 2, height: 2) { valueTile("noValue", "device.nada", width: 4, height: 2) {
state "default", label:'${currentValue}' state "default", label:'${currentValue}'
} }
valueTile("multiLine", "device.multiLine", width: 3, height: 2) {
state "default", label: '${currentValue}'
}
valueTile("multiLineWithIcon", "device.multiLine", width: 3, height: 2) {
state "default", label: '${currentValue}', icon: "st.switches.switch.off"
}
main("text") main("text")
details([ details([
"text", "longText", "integer", "text", "longText", "integer",
"integerFloat", "pi", "floatAsText", "integerFloat", "pi", "floatAsText",
"bgColor", "bgColorRange", "bgColorRangeSingleItem", "bgColor", "bgColorRange", "bgColorRangeSingleItem",
"bgColorRangeConflict", "noValue" "bgColorRangeConflict", "noValue",
"multiLine", "multiLineWithIcon"
]) ])
} }
} }
@@ -90,6 +99,7 @@ def installed() {
sendEvent(name: "integerFloat", value: 47.0) sendEvent(name: "integerFloat", value: 47.0)
sendEvent(name: "pi", value: 3.14159) sendEvent(name: "pi", value: 3.14159)
sendEvent(name: "floatAsText", value: "3.14159") sendEvent(name: "floatAsText", value: "3.14159")
sendEvent(name: "multiLine", value: "Line 1\nLine 2\nLine 3")
} }
def parse(String description) { def parse(String description) {

View File

@@ -67,14 +67,47 @@ metadata {
attributeState "VALUE_DOWN", action: "levelDown" attributeState "VALUE_DOWN", action: "levelDown"
} }
} }
multiAttributeTile(name:"lengthyTile", type:"generic", width:6, height:4) {
tileAttribute("device.lengthyText", key: "PRIMARY_CONTROL") {
attributeState "default", label:'The value of this tile is long and should wrap to two lines', backgroundColor:"#79b821"
}
tileAttribute("device.lengthyText", key: "SECONDARY_CONTROL") {
attributeState "default", label:'The value of this tile is long and should wrap to two lines', backgroundColor:"#79b821"
}
}
multiAttributeTile(name:"multilineTile", type:"generic", width:6, height:4) {
tileAttribute("device.multilineText", key: "PRIMARY_CONTROL") {
attributeState "default", label:'Line 1 YES\nLine 2 YES\nLine 3 NO', backgroundColor:"#79b821"
}
tileAttribute("device.multilineText", key: "SECONDARY_CONTROL") {
attributeState "default", label:'Line 1 YES\nLine 2 YES\nLine 3 NO', backgroundColor:"#79b821"
}
}
multiAttributeTile(name:"lengthyTileWithIcon", type:"generic", width:6, height:4) {
tileAttribute("device.lengthyText", key: "PRIMARY_CONTROL") {
attributeState "default", label:'The value of this tile is long and should wrap to two lines', backgroundColor:"#79b821", icon: "st.switches.switch.on"
}
tileAttribute("device.lengthyText", key: "SECONDARY_CONTROL") {
attributeState "default", label:'The value of this tile is long and should wrap to two lines', backgroundColor:"#79b821", icon: "st.switches.switch.on"
}
}
multiAttributeTile(name:"multilineTileWithIcon", type:"generic", width:6, height:4) {
tileAttribute("device.multilineText", key: "PRIMARY_CONTROL") {
attributeState "default", label:'Line 1 YES\nLine 2 YES\nLine 3 NO', backgroundColor:"#79b821", icon: "st.switches.switch.on"
}
tileAttribute("device.multilineText", key: "SECONDARY_CONTROL") {
attributeState "default", label:'Line 1 YES\nLine 2 YES\nLine 3 NO', backgroundColor:"#79b821", icon: "st.switches.switch.on"
}
}
main(["basicTile"]) main(["basicTile"])
details(["basicTile", "sliderTile", "valueTile"]) details(["basicTile", "sliderTile", "valueTile", "lengthyTile", "multilineTile", "lengthyTileWithIcon", "multilineTileWithIcon"])
} }
} }
def installed() { def installed() {
sendEvent(name: "lengthyText", value: "The value of this tile is long and should wrap to two lines")
sendEvent(name: "multilineText", value: "Line 1 YES\nLine 2 YES\nLine 3 NO")
} }
def parse() { def parse() {

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
@@ -327,8 +332,7 @@ private addChildBulb(dni, hueType, name, hub, update=false, device = null) {
if (deviceType) { if (deviceType) {
return addChildDevice("smartthings", deviceType, dni, hub, ["label": name]) return addChildDevice("smartthings", deviceType, dni, hub, ["label": name])
} } else {
else {
log.warn "Device type $hueType not supported" log.warn "Device type $hueType not supported"
return null return null
} }
@@ -344,8 +348,10 @@ def addBulbs() {
newHueBulb = bulbs.find { (app.id + "/" + it.value.id) == dni } newHueBulb = bulbs.find { (app.id + "/" + it.value.id) == dni }
if (newHueBulb != null) { if (newHueBulb != null) {
d = addChildBulb(dni, newHueBulb?.value?.type, newHueBulb?.value?.name, newHueBulb?.value?.hub) d = addChildBulb(dni, newHueBulb?.value?.type, newHueBulb?.value?.name, newHueBulb?.value?.hub)
log.debug "created ${d.displayName} with id $dni" if (d) {
d.refresh() log.debug "created ${d.displayName} with id $dni"
d.refresh()
}
} else { } else {
log.debug "$dni in not longer paired to the Hue Bridge or ID changed" log.debug "$dni in not longer paired to the Hue Bridge or ID changed"
} }
@@ -353,7 +359,7 @@ def addBulbs() {
//backwards compatable //backwards compatable
newHueBulb = bulbs.find { (app.id + "/" + it.id) == dni } newHueBulb = bulbs.find { (app.id + "/" + it.id) == dni }
d = addChildBulb(dni, "Extended Color Light", newHueBulb?.value?.name, newHueBulb?.value?.hub) d = addChildBulb(dni, "Extended Color Light", newHueBulb?.value?.name, newHueBulb?.value?.hub)
d.refresh() d?.refresh()
} }
} else { } else {
log.debug "found ${d.displayName} with id $dni already exists, type: '$d.typeName'" log.debug "found ${d.displayName} with id $dni already exists, type: '$d.typeName'"
@@ -382,8 +388,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 +419,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 +559,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 +604,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 +631,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()
} }
@@ -714,7 +825,7 @@ def setColor(childDevice, huesettings) {
value.bri = Math.min(Math.round(huesettings.level * 255 / 100), 255) value.bri = Math.min(Math.round(huesettings.level * 255 / 100), 255)
} }
value.alert = huesettings.alert ? huesettings.alert : "none" value.alert = huesettings.alert ? huesettings.alert : "none"
value.transition = huesettings.transition ? huesettings.transition : 4 value.transitiontime = huesettings.transitiontime ? huesettings.transitiontime : 4
// Make sure to turn off light if requested // Make sure to turn off light if requested
if (huesettings.switch == "off") if (huesettings.switch == "off")
@@ -747,15 +858,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) {

View File

@@ -236,23 +236,22 @@ def addSwitches() {
d = getChildDevices()?.find { d = getChildDevices()?.find {
it.deviceNetworkId == selectedSwitch.value.mac || it.device.getDataValue("mac") == selectedSwitch.value.mac it.deviceNetworkId == selectedSwitch.value.mac || it.device.getDataValue("mac") == selectedSwitch.value.mac
} }
} if (!d) {
log.debug "Creating WeMo Switch with dni: ${selectedSwitch.value.mac}"
if (!d) { d = addChildDevice("smartthings", "Wemo Switch", selectedSwitch.value.mac, selectedSwitch?.value.hub, [
log.debug "Creating WeMo Switch with dni: ${selectedSwitch.value.mac}" "label": selectedSwitch?.value?.name ?: "Wemo Switch",
d = addChildDevice("smartthings", "Wemo Switch", selectedSwitch.value.mac, selectedSwitch?.value.hub, [ "data": [
"label": selectedSwitch?.value?.name ?: "Wemo Switch", "mac": selectedSwitch.value.mac,
"data": [ "ip": selectedSwitch.value.ip,
"mac": selectedSwitch.value.mac, "port": selectedSwitch.value.port
"ip": selectedSwitch.value.ip, ]
"port": selectedSwitch.value.port ])
] def ipvalue = convertHexToIP(selectedSwitch.value.ip)
]) d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}")
def ipvalue = convertHexToIP(selectedSwitch.value.ip) log.debug "Created ${d.displayName} with id: ${d.id}, dni: ${d.deviceNetworkId}"
d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}") } else {
log.debug "Created ${d.displayName} with id: ${d.id}, dni: ${d.deviceNetworkId}" log.debug "found ${d.displayName} with id $dni already exists"
} else { }
log.debug "found ${d.displayName} with id $dni already exists"
} }
} }
} }
@@ -267,23 +266,22 @@ def addMotions() {
d = getChildDevices()?.find { d = getChildDevices()?.find {
it.deviceNetworkId == selectedMotion.value.mac || it.device.getDataValue("mac") == selectedMotion.value.mac it.deviceNetworkId == selectedMotion.value.mac || it.device.getDataValue("mac") == selectedMotion.value.mac
} }
} if (!d) {
log.debug "Creating WeMo Motion with dni: ${selectedMotion.value.mac}"
if (!d) { d = addChildDevice("smartthings", "Wemo Motion", selectedMotion.value.mac, selectedMotion?.value.hub, [
log.debug "Creating WeMo Motion with dni: ${selectedMotion.value.mac}" "label": selectedMotion?.value?.name ?: "Wemo Motion",
d = addChildDevice("smartthings", "Wemo Motion", selectedMotion.value.mac, selectedMotion?.value.hub, [ "data": [
"label": selectedMotion?.value?.name ?: "Wemo Motion", "mac": selectedMotion.value.mac,
"data": [ "ip": selectedMotion.value.ip,
"mac": selectedMotion.value.mac, "port": selectedMotion.value.port
"ip": selectedMotion.value.ip, ]
"port": selectedMotion.value.port ])
] def ipvalue = convertHexToIP(selectedMotion.value.ip)
]) d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}")
def ipvalue = convertHexToIP(selectedMotion.value.ip) log.debug "Created ${d.displayName} with id: ${d.id}, dni: ${d.deviceNetworkId}"
d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}") } else {
log.debug "Created ${d.displayName} with id: ${d.id}, dni: ${d.deviceNetworkId}" log.debug "found ${d.displayName} with id $dni already exists"
} else { }
log.debug "found ${d.displayName} with id $dni already exists"
} }
} }
} }
@@ -298,23 +296,22 @@ def addLightSwitches() {
d = getChildDevices()?.find { d = getChildDevices()?.find {
it.deviceNetworkId == selectedLightSwitch.value.mac || it.device.getDataValue("mac") == selectedLightSwitch.value.mac it.deviceNetworkId == selectedLightSwitch.value.mac || it.device.getDataValue("mac") == selectedLightSwitch.value.mac
} }
} if (!d) {
log.debug "Creating WeMo Light Switch with dni: ${selectedLightSwitch.value.mac}"
if (!d) { d = addChildDevice("smartthings", "Wemo Light Switch", selectedLightSwitch.value.mac, selectedLightSwitch?.value.hub, [
log.debug "Creating WeMo Light Switch with dni: ${selectedLightSwitch.value.mac}" "label": selectedLightSwitch?.value?.name ?: "Wemo Light Switch",
d = addChildDevice("smartthings", "Wemo Light Switch", selectedLightSwitch.value.mac, selectedLightSwitch?.value.hub, [ "data": [
"label": selectedLightSwitch?.value?.name ?: "Wemo Light Switch", "mac": selectedLightSwitch.value.mac,
"data": [ "ip": selectedLightSwitch.value.ip,
"mac": selectedLightSwitch.value.mac, "port": selectedLightSwitch.value.port
"ip": selectedLightSwitch.value.ip, ]
"port": selectedLightSwitch.value.port ])
] def ipvalue = convertHexToIP(selectedLightSwitch.value.ip)
]) d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}")
def ipvalue = convertHexToIP(selectedLightSwitch.value.ip) log.debug "created ${d.displayName} with id $dni"
d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}") } else {
log.debug "created ${d.displayName} with id $dni" log.debug "found ${d.displayName} with id $dni already exists"
} else { }
log.debug "found ${d.displayName} with id $dni already exists"
} }
} }
} }