Merge pull request #992 from SmartThingsCommunity/staging

Rolling up staging to prod
This commit is contained in:
Vinay Rao
2016-06-14 13:11:06 -07:00
committed by GitHub
5 changed files with 83 additions and 82 deletions

View File

@@ -403,39 +403,21 @@ def refresh() {
if (device.getDataValue("manufacturer") == "SmartThings") { if (device.getDataValue("manufacturer") == "SmartThings") {
log.debug "Refreshing Values for manufacturer: SmartThings " log.debug "Refreshing Values for manufacturer: SmartThings "
refreshCmds = refreshCmds + [ /* These values of Motion Threshold Multiplier(0x01) and Motion Threshold (0x0276)
/* These values of Motion Threshold Multiplier(01) and Motion Threshold (7602) seem to be giving pretty accurate results for the XYZ co-ordinates for this manufacturer.
seem to be giving pretty accurate results for the XYZ co-ordinates for this manufacturer. Separating these out in a separate if-else because I do not want to touch Centralite part
Separating these out in a separate if-else because I do not want to touch Centralite part as of now.
as of now. */
*/ refreshCmds += zigbee.writeAttribute(0xFC02, 0x0000, 0x20, 0x01, [mfgCode: manufacturerCode])
refreshCmds += zigbee.writeAttribute(0xFC02, 0x0002, 0x21, 0x0276, [mfgCode: manufacturerCode])
"zcl mfg-code ${manufacturerCode}", "delay 200",
"zcl global write 0xFC02 0 0x20 {01}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 400",
"zcl mfg-code ${manufacturerCode}", "delay 200",
"zcl global write 0xFC02 2 0x21 {7602}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 400",
]
} else { } else {
refreshCmds = refreshCmds + [ refreshCmds += zigbee.writeAttribute(0xFC02, 0x0000, 0x20, 0x02, [mfgCode: manufacturerCode])
/* sensitivity - default value (8) */
"zcl mfg-code ${manufacturerCode}", "delay 200",
"zcl global write 0xFC02 0 0x20 {02}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 400",
]
} }
//Common refresh commands //Common refresh commands
refreshCmds = refreshCmds + [ refreshCmds += zigbee.readAttribute(0x0402, 0x0000) +
"st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200", zigbee.readAttribute(0x0001, 0x0020) +
"st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 200", zigbee.readAttribute(0xFC02, 0x0010, [mfgCode: manufacturerCode])
"zcl mfg-code ${manufacturerCode}", "delay 200",
"zcl global read 0xFC02 0x0010",
"send 0x${device.deviceNetworkId} 1 1","delay 400"
]
return refreshCmds + enrollResponse() return refreshCmds + enrollResponse()
} }
@@ -443,38 +425,15 @@ def refresh() {
def configure() { def configure() {
sendEvent(name: "checkInterval", value: 7200, displayed: false) sendEvent(name: "checkInterval", value: 7200, displayed: false)
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "Configuring Reporting" log.debug "Configuring Reporting"
def configCmds = [ def configCmds = enrollResponse() +
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200", zigbee.batteryConfig() +
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500", zigbee.temperatureConfig() +
zigbee.configureReporting(0xFC02, 0x0010, 0x18, 10, 3600, 0x01, [mfgCode: manufacturerCode]) +
"zdo bind 0x${device.deviceNetworkId} ${endpointId} 1 1 {${device.zigbeeId}} {}", "delay 200", zigbee.configureReporting(0xFC02, 0x0012, 0x29, 1, 3600, 0x0001, [mfgCode: manufacturerCode]) +
"zcl global send-me-a-report 1 0x20 0x20 30 21600 {01}", "delay 200", //checkin time 6 hrs zigbee.configureReporting(0xFC02, 0x0013, 0x29, 1, 3600, 0x0001, [mfgCode: manufacturerCode]) +
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500", zigbee.configureReporting(0xFC02, 0x0014, 0x29, 1, 3600, 0x0001, [mfgCode: manufacturerCode])
"zdo bind 0x${device.deviceNetworkId} ${endpointId} 1 0x402 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 0x402 0 0x29 30 3600 {6400}", "delay 200",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
"zdo bind 0x${device.deviceNetworkId} ${endpointId} 1 0xFC02 {${device.zigbeeId}} {}", "delay 200",
"zcl mfg-code ${manufacturerCode}", "delay 200",
"zcl global send-me-a-report 0xFC02 0x0010 0x18 10 3600 {01}", "delay 200",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
"zcl mfg-code ${manufacturerCode}", "delay 200",
"zcl global send-me-a-report 0xFC02 0x0012 0x29 1 3600 {0100}", "delay 200",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
"zcl mfg-code ${manufacturerCode}", "delay 200",
"zcl global send-me-a-report 0xFC02 0x0013 0x29 1 3600 {0100}", "delay 200",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
"zcl mfg-code ${manufacturerCode}", "delay 200",
"zcl global send-me-a-report 0xFC02 0x0014 0x29 1 3600 {0100}", "delay 200",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500"
]
return configCmds + refresh() return configCmds + refresh()
} }

View File

@@ -29,6 +29,7 @@ metadata {
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,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 fingerprint deviceId: "0x0701", inClusters: "0x5E,0x72,0x5A,0x80,0x73,0x86,0x84,0x85,0x59,0x71,0x70,0x7A,0x98" // Vision door/window
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x98,0x86,0x72,0x5A,0x85,0x59,0x73,0x80,0x71,0x31,0x70,0x84,0x7A" // Vision Motion
} }
// simulator metadata // simulator metadata
@@ -263,5 +264,9 @@ def retypeBasedOnMSR() {
log.debug "Changing device type to Door / Window Sensor Plus (SG)" log.debug "Changing device type to Door / Window Sensor Plus (SG)"
setDeviceType("Door / Window Sensor Plus (SG)") setDeviceType("Door / Window Sensor Plus (SG)")
break break
case "0109-2002-0205": // Vision Motion
log.debug "Changing device type to Vision Motion Sensor Plus (SG)"
setDeviceType("Vision Motion Sensor Plus (SG)")
break
} }
} }

View File

@@ -21,6 +21,13 @@ metadata {
capability "Motion Sensor" capability "Motion Sensor"
capability "Sensor" capability "Sensor"
capability "Battery" capability "Battery"
fingerprint mfr: "011F", prod: "0001", model: "0001", deviceJoinName: "Schlage Motion Sensor" // Schlage motion
fingerprint mfr: "014A", prod: "0001", model: "0001", deviceJoinName: "Ecolink Motion Sensor" // Ecolink motion
fingerprint mfr: "014A", prod: "0004", model: "0001", deviceJoinName: "Ecolink Motion Sensor" // Ecolink motion +
fingerprint mfr: "0060", prod: "0001", model: "0002", deviceJoinName: "Everspring Motion Sensor" // Everspring SP814
fingerprint mfr: "0060", prod: "0001", model: "0003", deviceJoinName: "Everspring Motion Sensor" // Everspring HSP02
fingerprint mfr: "011A", prod: "0601", model: "0901", deviceJoinName: "Enerwave Motion Sensor" // Enerwave ZWN-BPC
} }
simulator { simulator {
@@ -125,9 +132,9 @@ def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
} }
if (!state.lastbat || (new Date().time) - state.lastbat > 53*60*60*1000) { if (!state.lastbat || (new Date().time) - state.lastbat > 53*60*60*1000) {
result << response(zwave.batteryV1.batteryGet()) result << response(zwave.batteryV1.batteryGet())
result << response("delay 1200") } else {
result << response(zwave.wakeUpV1.wakeUpNoMoreInformation())
} }
result << response(zwave.wakeUpV1.wakeUpNoMoreInformation())
result result
} }

View File

@@ -30,6 +30,7 @@ definition(
preferences { preferences {
page(name:"mainPage", title:"Hue Device Setup", content:"mainPage", refreshTimeout:5) page(name:"mainPage", title:"Hue Device Setup", content:"mainPage", refreshTimeout:5)
page(name:"bridgeDiscovery", title:"Hue Bridge Discovery", content:"bridgeDiscovery", refreshTimeout:5) page(name:"bridgeDiscovery", title:"Hue Bridge Discovery", content:"bridgeDiscovery", refreshTimeout:5)
page(name:"bridgeDiscoveryFailed", title:"Bridge Discovery Failed", content:"bridgeDiscoveryFailed", refreshTimeout:0)
page(name:"bridgeBtnPush", title:"Linking with your Hue", content:"bridgeLinking", refreshTimeout:5) page(name:"bridgeBtnPush", title:"Linking with your Hue", content:"bridgeLinking", refreshTimeout:5)
page(name:"bulbDiscovery", title:"Hue Device Setup", content:"bulbDiscovery", refreshTimeout:5) page(name:"bulbDiscovery", title:"Hue Device Setup", content:"bulbDiscovery", refreshTimeout:5)
} }
@@ -53,12 +54,21 @@ def bridgeDiscovery(params=[:])
def options = bridges ?: [] def options = bridges ?: []
def numFound = options.size() ?: 0 def numFound = options.size() ?: 0
if (numFound == 0 && state.bridgeRefreshCount > 25) { if (numFound == 0) {
log.trace "Cleaning old bridges memory" if (state.bridgeRefreshCount == 25) {
state.bridges = [:] log.trace "Cleaning old bridges memory"
state.bridgeRefreshCount = 0 state.bridges = [:]
app.updateSetting("selectedHue", "") app.updateSetting("selectedHue", "")
} } else if (state.bridgeRefreshCount > 100) {
// five minutes have passed, give up
// there seems to be a problem going back from discovey failed page in some instances (compared to pressing next)
// however it is probably a SmartThings settings issue
state.bridges = [:]
app.updateSetting("selectedHue", "")
state.bridgeRefreshCount = 0
return bridgeDiscoveryFailed()
}
}
ssdpSubscribe() ssdpSubscribe()
@@ -79,6 +89,13 @@ def bridgeDiscovery(params=[:])
} }
} }
def bridgeDiscoveryFailed() {
return dynamicPage(name:"bridgeDiscoveryFailed", title: "Bridge Discovery Failed", nextPage: "bridgeDiscovery") {
section("Failed to discover any Hue Bridges. Please confirm that the Hue Bridge is connected to the same network as your SmartThings Hub, and that it has power.") {
}
}
}
def bridgeLinking() def bridgeLinking()
{ {
int linkRefreshcount = !state.linkRefreshcount ? 0 : state.linkRefreshcount as int int linkRefreshcount = !state.linkRefreshcount ? 0 : state.linkRefreshcount as int
@@ -88,19 +105,15 @@ def bridgeLinking()
def nextPage = "" def nextPage = ""
def title = "Linking with your Hue" def title = "Linking with your Hue"
def paragraphText def paragraphText
def hueimage = null
if (selectedHue) { if (selectedHue) {
paragraphText = "Press the button on your Hue Bridge to setup a link. " paragraphText = "Press the button on your Hue Bridge to setup a link. "
hueimage = "http://huedisco.mediavibe.nl/wp-content/uploads/2013/09/pair-bridge.png"
} else { } else {
paragraphText = "You haven't selected a Hue Bridge, please Press \"Done\" and select one before clicking next." paragraphText = "You haven't selected a Hue Bridge, please Press \"Done\" and select one before clicking next."
hueimage = null
} }
if (state.username) { //if discovery worked if (state.username) { //if discovery worked
nextPage = "bulbDiscovery" nextPage = "bulbDiscovery"
title = "Success!" title = "Success!"
paragraphText = "Linking to your hub was a success! Please click 'Next'!" paragraphText = "Linking to your hub was a success! Please click 'Next'!"
hueimage = null
} }
if((linkRefreshcount % 2) == 0 && !state.username) { if((linkRefreshcount % 2) == 0 && !state.username) {
@@ -110,8 +123,6 @@ def bridgeLinking()
return dynamicPage(name:"bridgeBtnPush", title:title, nextPage:nextPage, refreshInterval:refreshInterval) { return dynamicPage(name:"bridgeBtnPush", title:title, nextPage:nextPage, refreshInterval:refreshInterval) {
section("") { section("") {
paragraph """${paragraphText}""" paragraph """${paragraphText}"""
if (hueimage != null)
image "${hueimage}"
} }
} }
} }
@@ -135,13 +146,14 @@ def bulbDiscovery() {
if((bulbRefreshCount % 5) == 0) { if((bulbRefreshCount % 5) == 0) {
discoverHueBulbs() discoverHueBulbs()
} }
def selectedBridge = state.bridges.find { key, value -> value?.serialNumber?.equalsIgnoreCase(selectedHue) }
def title = selectedBridge?.value?.name ?: "Find bridges"
return dynamicPage(name:"bulbDiscovery", title:"Bulb Discovery Started!", nextPage:"", refreshInterval:refreshInterval, install:true, uninstall: true) { return dynamicPage(name:"bulbDiscovery", title:"Bulb Discovery Started!", nextPage:"", refreshInterval:refreshInterval, install:true, uninstall: true) {
section("Please wait while we discover your Hue Bulbs. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.") { section("Please wait while we discover your Hue Bulbs. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.") {
input "selectedBulbs", "enum", required:false, title:"Select Hue Bulbs (${numFound} found)", multiple:true, options:bulboptions input "selectedBulbs", "enum", required:false, title:"Select Hue Bulbs (${numFound} found)", multiple:true, options:bulboptions
} }
section { section {
def title = getBridgeIP() ? "Hue bridge (${getBridgeIP()})" : "Find bridges"
href "bridgeDiscovery", title: title, description: "", state: selectedHue ? "complete" : "incomplete", params: [override: true] href "bridgeDiscovery", title: title, description: "", state: selectedHue ? "complete" : "incomplete", params: [override: true]
} }
@@ -348,26 +360,29 @@ def addBulbs() {
def newHueBulb def newHueBulb
if (bulbs instanceof java.util.Map) { if (bulbs instanceof java.util.Map) {
newHueBulb = bulbs.find { (app.id + "/" + it.value.id) == dni } newHueBulb = bulbs.find { (app.id + "/" + it.value.id) == dni }
if (newHueBulb != null) {
d = addChildBulb(dni, newHueBulb?.value?.type, newHueBulb?.value?.name, newHueBulb?.value?.hub) if (newHueBulb != null) {
d = addChildBulb(dni, newHueBulb?.value?.type, newHueBulb?.value?.name, newHueBulb?.value?.hub)
if (d) { if (d) {
log.debug "created ${d.displayName} with id $dni" log.debug "created ${d.displayName} with id $dni"
d.completedSetup = true
d.refresh() 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"
} }
} else { } else {
//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?.completedSetup = true
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'"
if (bulbs instanceof java.util.Map) { if (bulbs instanceof java.util.Map) {
// Update device type if incorrect // Update device type if incorrect
def newHueBulb = bulbs.find { (app.id + "/" + it.value.id) == dni } def newHueBulb = bulbs.find { (app.id + "/" + it.value.id) == dni }
upgradeDeviceType(d, newHueBulb?.value?.type) upgradeDeviceType(d, newHueBulb?.value?.type)
} }
} }
@@ -399,6 +414,7 @@ def addBridge() {
} }
if (newbridge) { if (newbridge) {
d = addChildDevice("smartthings", "Hue Bridge", selectedHue, vbridge.value.hub) d = addChildDevice("smartthings", "Hue Bridge", selectedHue, vbridge.value.hub)
d?.completedSetup = true
log.debug "created ${d.displayName} with id ${d.deviceNetworkId}" log.debug "created ${d.displayName} with id ${d.deviceNetworkId}"
def childDevice = getChildDevice(d.deviceNetworkId) def childDevice = getChildDevice(d.deviceNetworkId)
childDevice.sendEvent(name: "serialNumber", value: vbridge.value.serialNumber) childDevice.sendEvent(name: "serialNumber", value: vbridge.value.serialNumber)
@@ -486,7 +502,21 @@ void bridgeDescriptionHandler(physicalgraph.device.HubResponse hubResponse) {
def bridges = getHueBridges() def bridges = getHueBridges()
def bridge = bridges.find {it?.key?.contains(body?.device?.UDN?.text())} def bridge = bridges.find {it?.key?.contains(body?.device?.UDN?.text())}
if (bridge) { if (bridge) {
bridge.value << [name:body?.device?.friendlyName?.text(), serialNumber:body?.device?.serialNumber?.text(), verified: true] // serialNumber from API is in format of 0017882413ad (mac address), however on the actual bridge only last six
// characters are printed on the back so using that to identify bridge
def idNumber = body?.device?.serialNumber?.text()
if (idNumber?.size() >= 6)
idNumber = idNumber[-6..-1].toUpperCase()
// usually in form of bridge name followed by (ip), i.e. defaults to Philips Hue (192.168.1.2)
// replace IP with serial number to make it easier for user to identify
def name = body?.device?.friendlyName?.text()
def index = name?.indexOf('(')
if (index != -1) {
name = name.substring(0,index)
name += " ($idNumber)"
}
bridge.value << [name:name, serialNumber:body?.device?.serialNumber?.text(), verified: true]
} else { } else {
log.error "/description.xml returned a bridge that didn't exist" log.error "/description.xml returned a bridge that didn't exist"
} }