mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-19 05:10:51 +00:00
Compare commits
1 Commits
PROD_2016.
...
MSA-1518-2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e061a25228 |
@@ -127,10 +127,9 @@ def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv5.SensorMultilevelR
|
|||||||
def map = [ displayed: true ]
|
def map = [ displayed: true ]
|
||||||
switch (cmd.sensorType) {
|
switch (cmd.sensorType) {
|
||||||
case 1:
|
case 1:
|
||||||
def cmdScale = cmd.scale == 1 ? "F" : "C"
|
map.name = "temperature"
|
||||||
map.name = "temperature"
|
map.unit = cmd.scale == 1 ? "F" : "C"
|
||||||
map.unit = getTemperatureScale()
|
map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, map.unit, cmd.precision)
|
||||||
map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision)
|
|
||||||
break
|
break
|
||||||
case 3:
|
case 3:
|
||||||
map.name = "illuminance"
|
map.name = "illuminance"
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ def ping() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def refresh() {
|
def refresh() {
|
||||||
zigbee.onOffRefresh() + zigbee.levelRefresh()
|
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.onOffConfig() + zigbee.levelConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
def healthPoll() {
|
def healthPoll() {
|
||||||
@@ -105,7 +105,9 @@ def healthPoll() {
|
|||||||
def configure() {
|
def configure() {
|
||||||
unschedule()
|
unschedule()
|
||||||
runEvery5Minutes("healthPoll")
|
runEvery5Minutes("healthPoll")
|
||||||
|
log.debug "Configuring Reporting and Bindings."
|
||||||
// Device-Watch allows 2 check-in misses from device
|
// Device-Watch allows 2 check-in misses from device
|
||||||
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||||
zigbee.onOffRefresh() + zigbee.levelRefresh()
|
// minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
|
||||||
|
zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -189,4 +189,4 @@ private calcDigestAuth(String method, String uri) {
|
|||||||
def response = hashMD5("${HA1}::::auth:${HA2}")
|
def response = hashMD5("${HA1}::::auth:${HA2}")
|
||||||
|
|
||||||
'Digest username="'+ getUsername() + '", realm="", nonce="", uri="'+ uri +'", qop=auth, nc=, cnonce="", response="' + response + '", opaque=""'
|
'Digest username="'+ getUsername() + '", realm="", nonce="", uri="'+ uri +'", qop=auth, nc=, cnonce="", response="' + response + '", opaque=""'
|
||||||
}
|
}
|
||||||
@@ -104,21 +104,8 @@ def parse(String description) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
def cluster = zigbee.parse(description)
|
log.warn "DID NOT PARSE MESSAGE for description : $description"
|
||||||
|
log.debug zigbee.parseDescriptionAsMap(description)
|
||||||
if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07){
|
|
||||||
if (cluster.data[0] == 0x00) {
|
|
||||||
log.debug "ON/OFF REPORTING CONFIG RESPONSE: " + cluster
|
|
||||||
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log.warn "DID NOT PARSE MESSAGE for description : $description"
|
|
||||||
log.debug "${cluster}"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,10 +128,8 @@ def refresh() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def configure() {
|
def configure() {
|
||||||
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
|
// Device-Watch allows 2 check-in misses from device
|
||||||
// enrolls with default periodic reporting until newer 5 min interval is confirmed
|
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||||
sendEvent(name: "checkInterval", value: 3 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
|
||||||
|
|
||||||
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
|
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
|
||||||
zigbee.onOffConfig(0, 300) + powerConfig() + refresh()
|
zigbee.onOffConfig(0, 300) + powerConfig() + refresh()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,28 +118,14 @@ private Map parseCatchAllMessage(String description) {
|
|||||||
if (shouldProcessMessage(cluster)) {
|
if (shouldProcessMessage(cluster)) {
|
||||||
switch(cluster.clusterId) {
|
switch(cluster.clusterId) {
|
||||||
case 0x0001:
|
case 0x0001:
|
||||||
// 0x07 - configure reporting
|
resultMap = getBatteryResult(cluster.data.last())
|
||||||
if (cluster.command != 0x07) {
|
|
||||||
resultMap = getBatteryResult(cluster.data.last())
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
|
|
||||||
case 0x0402:
|
case 0x0402:
|
||||||
if (cluster.command == 0x07) {
|
// temp is last 2 data values. reverse to swap endian
|
||||||
if (cluster.data[0] == 0x00){
|
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
|
||||||
log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster
|
def value = getTemperature(temp)
|
||||||
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
resultMap = getTemperatureResult(value)
|
||||||
}
|
|
||||||
else {
|
|
||||||
log.warn "TEMP REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// temp is last 2 data values. reverse to swap endian
|
|
||||||
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
|
|
||||||
def value = getTemperature(temp)
|
|
||||||
resultMap = getTemperatureResult(value)
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,8 +135,10 @@ private Map parseCatchAllMessage(String description) {
|
|||||||
|
|
||||||
private boolean shouldProcessMessage(cluster) {
|
private boolean shouldProcessMessage(cluster) {
|
||||||
// 0x0B is default response indicating message got through
|
// 0x0B is default response indicating message got through
|
||||||
|
// 0x07 is bind message
|
||||||
boolean ignoredMessage = cluster.profileId != 0x0104 ||
|
boolean ignoredMessage = cluster.profileId != 0x0104 ||
|
||||||
cluster.command == 0x0B ||
|
cluster.command == 0x0B ||
|
||||||
|
cluster.command == 0x07 ||
|
||||||
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
|
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
|
||||||
return !ignoredMessage
|
return !ignoredMessage
|
||||||
}
|
}
|
||||||
@@ -304,9 +292,8 @@ def refresh() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def configure() {
|
def configure() {
|
||||||
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
|
// Device-Watch allows 2 check-in misses from device
|
||||||
// enrolls with default periodic reporting until newer 5 min interval is confirmed
|
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||||
sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
|
||||||
|
|
||||||
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
|
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
|
||||||
log.debug "Configuring Reporting, IAS CIE, and Bindings."
|
log.debug "Configuring Reporting, IAS CIE, and Bindings."
|
||||||
|
|||||||
@@ -122,37 +122,19 @@ private Map parseCatchAllMessage(String description) {
|
|||||||
if (shouldProcessMessage(cluster)) {
|
if (shouldProcessMessage(cluster)) {
|
||||||
switch(cluster.clusterId) {
|
switch(cluster.clusterId) {
|
||||||
case 0x0001:
|
case 0x0001:
|
||||||
// 0x07 - configure reporting
|
resultMap = getBatteryResult(cluster.data.last())
|
||||||
if (cluster.command != 0x07) {
|
|
||||||
resultMap = getBatteryResult(cluster.data.last())
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
|
|
||||||
case 0x0402:
|
case 0x0402:
|
||||||
if (cluster.command == 0x07) {
|
// temp is last 2 data values. reverse to swap endian
|
||||||
if (cluster.data[0] == 0x00) {
|
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
|
||||||
log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster
|
def value = getTemperature(temp)
|
||||||
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
resultMap = getTemperatureResult(value)
|
||||||
}
|
|
||||||
else {
|
|
||||||
log.warn "TEMP REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// temp is last 2 data values. reverse to swap endian
|
|
||||||
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
|
|
||||||
def value = getTemperature(temp)
|
|
||||||
resultMap = getTemperatureResult(value)
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
|
|
||||||
case 0x0406:
|
case 0x0406:
|
||||||
// 0x07 - configure reporting
|
log.debug 'motion'
|
||||||
if (cluster.command != 0x07) {
|
resultMap.name = 'motion'
|
||||||
log.debug 'motion'
|
|
||||||
resultMap.name = 'motion'
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -162,8 +144,10 @@ private Map parseCatchAllMessage(String description) {
|
|||||||
|
|
||||||
private boolean shouldProcessMessage(cluster) {
|
private boolean shouldProcessMessage(cluster) {
|
||||||
// 0x0B is default response indicating message got through
|
// 0x0B is default response indicating message got through
|
||||||
|
// 0x07 is bind message
|
||||||
boolean ignoredMessage = cluster.profileId != 0x0104 ||
|
boolean ignoredMessage = cluster.profileId != 0x0104 ||
|
||||||
cluster.command == 0x0B ||
|
cluster.command == 0x0B ||
|
||||||
|
cluster.command == 0x07 ||
|
||||||
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
|
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
|
||||||
return !ignoredMessage
|
return !ignoredMessage
|
||||||
}
|
}
|
||||||
@@ -319,9 +303,8 @@ def refresh() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def configure() {
|
def configure() {
|
||||||
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
|
// Device-Watch allows 2 check-in misses from device
|
||||||
// enrolls with default periodic reporting until newer 5 min interval is confirmed
|
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||||
sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
|
||||||
|
|
||||||
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
|
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
|
||||||
log.debug "Configuring Reporting, IAS CIE, and Bindings."
|
log.debug "Configuring Reporting, IAS CIE, and Bindings."
|
||||||
|
|||||||
@@ -147,33 +147,20 @@ private Map parseCatchAllMessage(String description) {
|
|||||||
if (shouldProcessMessage(cluster)) {
|
if (shouldProcessMessage(cluster)) {
|
||||||
switch(cluster.clusterId) {
|
switch(cluster.clusterId) {
|
||||||
case 0x0001:
|
case 0x0001:
|
||||||
// 0x07 - configure reporting
|
resultMap = getBatteryResult(cluster.data.last())
|
||||||
if (cluster.command != 0x07) {
|
|
||||||
resultMap = getBatteryResult(cluster.data.last())
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
|
|
||||||
case 0xFC02:
|
case 0xFC02:
|
||||||
log.debug 'ACCELERATION'
|
log.debug 'ACCELERATION'
|
||||||
break
|
break
|
||||||
|
|
||||||
case 0x0402:
|
case 0x0402:
|
||||||
if (cluster.command == 0x07) {
|
log.debug 'TEMP'
|
||||||
if(cluster.data[0] == 0x00) {
|
// temp is last 2 data values. reverse to swap endian
|
||||||
log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster
|
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
|
||||||
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
def value = getTemperature(temp)
|
||||||
}
|
resultMap = getTemperatureResult(value)
|
||||||
else {
|
break
|
||||||
log.warn "TEMP REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// temp is last 2 data values. reverse to swap endian
|
|
||||||
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
|
|
||||||
def value = getTemperature(temp)
|
|
||||||
resultMap = getTemperatureResult(value)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,8 +169,10 @@ private Map parseCatchAllMessage(String description) {
|
|||||||
|
|
||||||
private boolean shouldProcessMessage(cluster) {
|
private boolean shouldProcessMessage(cluster) {
|
||||||
// 0x0B is default response indicating message got through
|
// 0x0B is default response indicating message got through
|
||||||
|
// 0x07 is bind message
|
||||||
boolean ignoredMessage = cluster.profileId != 0x0104 ||
|
boolean ignoredMessage = cluster.profileId != 0x0104 ||
|
||||||
cluster.command == 0x0B ||
|
cluster.command == 0x0B ||
|
||||||
|
cluster.command == 0x07 ||
|
||||||
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
|
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
|
||||||
return !ignoredMessage
|
return !ignoredMessage
|
||||||
}
|
}
|
||||||
@@ -412,9 +401,8 @@ def refresh() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def configure() {
|
def configure() {
|
||||||
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
|
// Device-Watch allows 2 check-in misses from device
|
||||||
// enrolls with default periodic reporting until newer 5 min interval is confirmed
|
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||||
sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
|
||||||
|
|
||||||
log.debug "Configuring Reporting"
|
log.debug "Configuring Reporting"
|
||||||
|
|
||||||
|
|||||||
@@ -109,28 +109,15 @@ private Map parseCatchAllMessage(String description) {
|
|||||||
if (shouldProcessMessage(cluster)) {
|
if (shouldProcessMessage(cluster)) {
|
||||||
switch(cluster.clusterId) {
|
switch(cluster.clusterId) {
|
||||||
case 0x0001:
|
case 0x0001:
|
||||||
// 0x07 - configure reporting
|
resultMap = getBatteryResult(cluster.data.last())
|
||||||
if (cluster.command != 0x07) {
|
|
||||||
resultMap = getBatteryResult(cluster.data.last())
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
|
|
||||||
case 0x0402:
|
case 0x0402:
|
||||||
if (cluster.command == 0x07){
|
log.debug 'TEMP'
|
||||||
if (cluster.data[0] == 0x00) {
|
// temp is last 2 data values. reverse to swap endian
|
||||||
log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster
|
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
|
||||||
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
def value = getTemperature(temp)
|
||||||
}
|
resultMap = getTemperatureResult(value)
|
||||||
else {
|
|
||||||
log.warn "TEMP REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// temp is last 2 data values. reverse to swap endian
|
|
||||||
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
|
|
||||||
def value = getTemperature(temp)
|
|
||||||
resultMap = getTemperatureResult(value)
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,8 +127,10 @@ private Map parseCatchAllMessage(String description) {
|
|||||||
|
|
||||||
private boolean shouldProcessMessage(cluster) {
|
private boolean shouldProcessMessage(cluster) {
|
||||||
// 0x0B is default response indicating message got through
|
// 0x0B is default response indicating message got through
|
||||||
|
// 0x07 is bind message
|
||||||
boolean ignoredMessage = cluster.profileId != 0x0104 ||
|
boolean ignoredMessage = cluster.profileId != 0x0104 ||
|
||||||
cluster.command == 0x0B ||
|
cluster.command == 0x0B ||
|
||||||
|
cluster.command == 0x07 ||
|
||||||
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
|
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
|
||||||
return !ignoredMessage
|
return !ignoredMessage
|
||||||
}
|
}
|
||||||
@@ -266,9 +255,8 @@ def refresh() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def configure() {
|
def configure() {
|
||||||
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
|
// Device-Watch allows 2 check-in misses from device
|
||||||
// enrolls with default periodic reporting until newer 5 min interval is confirmed
|
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||||
sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
|
||||||
|
|
||||||
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
|
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
|
||||||
log.debug "Configuring Reporting, IAS CIE, and Bindings."
|
log.debug "Configuring Reporting, IAS CIE, and Bindings."
|
||||||
|
|||||||
@@ -93,37 +93,20 @@ private Map parseCatchAllMessage(String description) {
|
|||||||
if (shouldProcessMessage(cluster)) {
|
if (shouldProcessMessage(cluster)) {
|
||||||
switch(cluster.clusterId) {
|
switch(cluster.clusterId) {
|
||||||
case 0x0001:
|
case 0x0001:
|
||||||
// 0x07 - configure reporting
|
resultMap = getBatteryResult(cluster.data.last())
|
||||||
if (cluster.command != 0x07) {
|
|
||||||
resultMap = getBatteryResult(cluster.data.last())
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
|
|
||||||
case 0x0402:
|
case 0x0402:
|
||||||
if (cluster.command == 0x07) {
|
// temp is last 2 data values. reverse to swap endian
|
||||||
if (cluster.data[0] == 0x00){
|
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
|
||||||
log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster
|
def value = getTemperature(temp)
|
||||||
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
resultMap = getTemperatureResult(value)
|
||||||
}
|
break
|
||||||
else {
|
|
||||||
log.warn "TEMP REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// temp is last 2 data values. reverse to swap endian
|
|
||||||
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
|
|
||||||
def value = getTemperature(temp)
|
|
||||||
resultMap = getTemperatureResult(value)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
|
|
||||||
case 0xFC45:
|
case 0xFC45:
|
||||||
// 0x07 - configure reporting
|
String pctStr = cluster.data[-1, -2].collect { Integer.toHexString(it) }.join('')
|
||||||
if (cluster.command != 0x07) {
|
String display = Math.round(Integer.valueOf(pctStr, 16) / 100)
|
||||||
String pctStr = cluster.data[-1, -2].collect { Integer.toHexString(it) }.join('')
|
resultMap = getHumidityResult(display)
|
||||||
String display = Math.round(Integer.valueOf(pctStr, 16) / 100)
|
|
||||||
resultMap = getHumidityResult(display)
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,8 +116,10 @@ private Map parseCatchAllMessage(String description) {
|
|||||||
|
|
||||||
private boolean shouldProcessMessage(cluster) {
|
private boolean shouldProcessMessage(cluster) {
|
||||||
// 0x0B is default response indicating message got through
|
// 0x0B is default response indicating message got through
|
||||||
|
// 0x07 is bind message
|
||||||
boolean ignoredMessage = cluster.profileId != 0x0104 ||
|
boolean ignoredMessage = cluster.profileId != 0x0104 ||
|
||||||
cluster.command == 0x0B ||
|
cluster.command == 0x0B ||
|
||||||
|
cluster.command == 0x07 ||
|
||||||
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
|
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
|
||||||
return !ignoredMessage
|
return !ignoredMessage
|
||||||
}
|
}
|
||||||
@@ -279,9 +264,8 @@ def refresh()
|
|||||||
}
|
}
|
||||||
|
|
||||||
def configure() {
|
def configure() {
|
||||||
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
|
// Device-Watch allows 2 check-in misses from device
|
||||||
// enrolls with default periodic reporting until newer 5 min interval is confirmed
|
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||||
sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
|
||||||
|
|
||||||
log.debug "Configuring Reporting and Bindings."
|
log.debug "Configuring Reporting and Bindings."
|
||||||
def humidityConfigCmds = [
|
def humidityConfigCmds = [
|
||||||
|
|||||||
@@ -60,21 +60,8 @@ def parse(String description) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
def cluster = zigbee.parse(description)
|
log.warn "DID NOT PARSE MESSAGE for description : $description"
|
||||||
|
log.debug zigbee.parseDescriptionAsMap(description)
|
||||||
if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07) {
|
|
||||||
if (cluster.data[0] == 0x00) {
|
|
||||||
log.debug "ON/OFF REPORTING CONFIG RESPONSE: " + cluster
|
|
||||||
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log.warn "DID NOT PARSE MESSAGE for description : $description"
|
|
||||||
log.debug "${cluster}"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,15 +84,13 @@ def ping() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def refresh() {
|
def refresh() {
|
||||||
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.onOffConfig(0, 300) + zigbee.levelConfig()
|
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.onOffConfig() + zigbee.levelConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
def configure() {
|
def configure() {
|
||||||
log.debug "Configuring Reporting and Bindings."
|
log.debug "Configuring Reporting and Bindings."
|
||||||
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
|
// Device-Watch allows 2 check-in misses from device
|
||||||
// enrolls with default periodic reporting until newer 5 min interval is confirmed
|
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||||
sendEvent(name: "checkInterval", value: 3 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
|
||||||
|
|
||||||
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
|
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
|
||||||
zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh()
|
zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ def parse(String description) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
def zigbeeMap = zigbee.parseDescriptionAsMap(description)
|
def zigbeeMap = zigbee.parseDescriptionAsMap(description)
|
||||||
def cluster = zigbee.parse(description)
|
log.trace "zigbeeMap : $zigbeeMap"
|
||||||
|
|
||||||
if (zigbeeMap?.clusterInt == COLOR_CONTROL_CLUSTER) {
|
if (zigbeeMap?.clusterInt == COLOR_CONTROL_CLUSTER) {
|
||||||
if(zigbeeMap.attrInt == ATTRIBUTE_HUE){ //Hue Attribute
|
if(zigbeeMap.attrInt == ATTRIBUTE_HUE){ //Hue Attribute
|
||||||
@@ -107,18 +107,8 @@ def parse(String description) {
|
|||||||
sendEvent(name: "saturation", value: saturationValue, descriptionText: "Color has changed", displayed: false)
|
sendEvent(name: "saturation", value: saturationValue, descriptionText: "Color has changed", displayed: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07) {
|
|
||||||
if (cluster.data[0] == 0x00){
|
|
||||||
log.debug "ON/OFF REPORTING CONFIG RESPONSE: " + cluster
|
|
||||||
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
log.info "DID NOT PARSE MESSAGE for description : $description"
|
log.info "DID NOT PARSE MESSAGE for description : $description"
|
||||||
log.debug zigbeeMap
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,15 +128,13 @@ def ping() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def refresh() {
|
def refresh() {
|
||||||
zigbee.onOffRefresh() + zigbee.readAttribute(0x0008, 0x00) + zigbee.readAttribute(0x0300, 0x00) + zigbee.readAttribute(0x0300, ATTRIBUTE_COLOR_TEMPERATURE) + zigbee.readAttribute(0x0300, ATTRIBUTE_HUE) + zigbee.readAttribute(0x0300, ATTRIBUTE_SATURATION) + zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01)
|
zigbee.onOffRefresh() + zigbee.readAttribute(0x0008, 0x00) + zigbee.readAttribute(0x0300, 0x00) + zigbee.readAttribute(0x0300, ATTRIBUTE_COLOR_TEMPERATURE) + zigbee.readAttribute(0x0300, ATTRIBUTE_HUE) + zigbee.readAttribute(0x0300, ATTRIBUTE_SATURATION) + zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01)
|
||||||
}
|
}
|
||||||
|
|
||||||
def configure() {
|
def configure() {
|
||||||
log.debug "Configuring Reporting and Bindings."
|
log.debug "Configuring Reporting and Bindings."
|
||||||
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
|
// Device-Watch allows 2 check-in misses from device
|
||||||
// enrolls with default periodic reporting until newer 5 min interval is confirmed
|
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||||
sendEvent(name: "checkInterval", value: 3 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
|
||||||
|
|
||||||
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
|
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
|
||||||
zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01) + zigbee.readAttribute(0x0006, 0x00) + zigbee.readAttribute(0x0008, 0x00) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, 0x00) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_COLOR_TEMPERATURE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION)
|
zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01) + zigbee.readAttribute(0x0006, 0x00) + zigbee.readAttribute(0x0008, 0x00) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, 0x00) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_COLOR_TEMPERATURE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION)
|
||||||
}
|
}
|
||||||
@@ -189,5 +177,5 @@ def setHue(value) {
|
|||||||
|
|
||||||
def setSaturation(value) {
|
def setSaturation(value) {
|
||||||
def scaledSatValue = zigbee.convertToHexString(Math.round(value * 0xfe / 100.0), 2)
|
def scaledSatValue = zigbee.convertToHexString(Math.round(value * 0xfe / 100.0), 2)
|
||||||
zigbee.command(COLOR_CONTROL_CLUSTER, SATURATION_COMMAND, scaledSatValue, "0500") + "delay 1000" + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION)
|
zigbee.command(COLOR_CONTROL_CLUSTER, SATURATION_COMMAND, scaledSatValue, "0500") //payload-> sat value, transition time
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,21 +83,8 @@ def parse(String description) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
def cluster = zigbee.parse(description)
|
log.warn "DID NOT PARSE MESSAGE for description : $description"
|
||||||
|
log.debug zigbee.parseDescriptionAsMap(description)
|
||||||
if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07) {
|
|
||||||
if (cluster.data[0] == 0x00) {
|
|
||||||
log.debug "ON/OFF REPORTING CONFIG RESPONSE: " + cluster
|
|
||||||
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log.warn "DID NOT PARSE MESSAGE for description : $description"
|
|
||||||
log.debug "${cluster}"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,15 +108,13 @@ def ping() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def refresh() {
|
def refresh() {
|
||||||
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh() + zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.colorTemperatureConfig()
|
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh() + zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.colorTemperatureConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
def configure() {
|
def configure() {
|
||||||
log.debug "Configuring Reporting and Bindings."
|
log.debug "Configuring Reporting and Bindings."
|
||||||
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
|
// Device-Watch allows 2 check-in misses from device
|
||||||
// enrolls with default periodic reporting until newer 5 min interval is confirmed
|
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||||
sendEvent(name: "checkInterval", value: 3 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
|
||||||
|
|
||||||
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
|
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
|
||||||
zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh()
|
zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,10 +37,7 @@ preferences {
|
|||||||
|
|
||||||
def mainPage() {
|
def mainPage() {
|
||||||
def bridges = bridgesDiscovered()
|
def bridges = bridgesDiscovered()
|
||||||
|
if (state.username && bridges) {
|
||||||
if (state.refreshUsernameNeeded) {
|
|
||||||
return bridgeLinking()
|
|
||||||
} else if (state.username && bridges) {
|
|
||||||
return bulbDiscovery()
|
return bulbDiscovery()
|
||||||
} else {
|
} else {
|
||||||
return bridgeDiscovery()
|
return bridgeDiscovery()
|
||||||
@@ -105,22 +102,13 @@ def bridgeLinking() {
|
|||||||
|
|
||||||
def nextPage = ""
|
def nextPage = ""
|
||||||
def title = "Linking with your Hue"
|
def title = "Linking with your Hue"
|
||||||
def paragraphText
|
def paragraphText
|
||||||
if (selectedHue) {
|
if (selectedHue) {
|
||||||
if (state.refreshUsernameNeeded) {
|
|
||||||
paragraphText = "The current Hue username is invalid.\n\nPlease press the button on your Hue Bridge to re-link. "
|
|
||||||
} else {
|
|
||||||
paragraphText = "Press the button on your Hue Bridge to setup a link. "
|
paragraphText = "Press the button on your Hue Bridge to setup a link. "
|
||||||
}
|
} 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."
|
}
|
||||||
}
|
|
||||||
if (state.username) { //if discovery worked
|
if (state.username) { //if discovery worked
|
||||||
if (state.refreshUsernameNeeded) {
|
|
||||||
state.refreshUsernameNeeded = false
|
|
||||||
// Issue one poll with new username to cancel local polling with old username
|
|
||||||
poll()
|
|
||||||
}
|
|
||||||
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'!"
|
||||||
@@ -927,15 +915,8 @@ private handleCommandResponse(body) {
|
|||||||
updates[childDeviceNetworkId]."$eventType" = v
|
updates[childDeviceNetworkId]."$eventType" = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (payload?.error) {
|
} else if (payload.error) {
|
||||||
log.warn "Error returned from Hue bridge, error = ${payload?.error}"
|
log.warn "Error returned from Hue bridge error = ${body?.error}"
|
||||||
// Check for unauthorized user
|
|
||||||
if (payload?.error?.type?.value == 1) {
|
|
||||||
log.error "Hue username is not valid"
|
|
||||||
state.refreshUsernameNeeded = true
|
|
||||||
state.username = null
|
|
||||||
}
|
|
||||||
return []
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1213,7 +1194,7 @@ private poll() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private isOnline(id) {
|
private isOnline(id) {
|
||||||
return (state.bulbs[id]?.online != null && state.bulbs[id]?.online) || state.bulbs[id]?.online == null
|
return (state.bulbs[id].online != null && state.bulbs[id].online) || state.bulbs[id].online == null
|
||||||
}
|
}
|
||||||
|
|
||||||
private put(path, body) {
|
private put(path, body) {
|
||||||
@@ -1280,7 +1261,7 @@ def convertBulbListToMap() {
|
|||||||
try {
|
try {
|
||||||
if (state.bulbs instanceof java.util.List) {
|
if (state.bulbs instanceof java.util.List) {
|
||||||
def map = [:]
|
def map = [:]
|
||||||
state.bulbs?.unique {it.id}.each { bulb ->
|
state.bulbs.unique {it.id}.each { bulb ->
|
||||||
map << ["${bulb.id}":["id":bulb.id, "name":bulb.name, "type": bulb.type, "modelid": bulb.modelid, "hub":bulb.hub, "online": bulb.online]]
|
map << ["${bulb.id}":["id":bulb.id, "name":bulb.name, "type": bulb.type, "modelid": bulb.modelid, "hub":bulb.hub, "online": bulb.online]]
|
||||||
}
|
}
|
||||||
state.bulbs = map
|
state.bulbs = map
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ def authPage() {
|
|||||||
def description = null
|
def description = null
|
||||||
if (!state.HarmonyAccessToken) {
|
if (!state.HarmonyAccessToken) {
|
||||||
if (!state.accessToken) {
|
if (!state.accessToken) {
|
||||||
log.debug "Harmony - About to create access token"
|
log.debug "About to create access token"
|
||||||
createAccessToken()
|
createAccessToken()
|
||||||
}
|
}
|
||||||
description = "Click to enter Harmony Credentials"
|
description = "Click to enter Harmony Credentials"
|
||||||
@@ -141,13 +141,13 @@ def callback() {
|
|||||||
def redirectUrl = null
|
def redirectUrl = null
|
||||||
if (params.authQueryString) {
|
if (params.authQueryString) {
|
||||||
redirectUrl = URLDecoder.decode(params.authQueryString.replaceAll(".+&redirect_url=", ""))
|
redirectUrl = URLDecoder.decode(params.authQueryString.replaceAll(".+&redirect_url=", ""))
|
||||||
log.debug "Harmony - redirectUrl: ${redirectUrl}"
|
log.debug "redirectUrl: ${redirectUrl}"
|
||||||
} else {
|
} else {
|
||||||
log.warn "Harmony - No authQueryString"
|
log.warn "No authQueryString"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.HarmonyAccessToken) {
|
if (state.HarmonyAccessToken) {
|
||||||
log.debug "Harmony - Access token already exists"
|
log.debug "Access token already exists"
|
||||||
discovery()
|
discovery()
|
||||||
success()
|
success()
|
||||||
} else {
|
} else {
|
||||||
@@ -155,27 +155,27 @@ def callback() {
|
|||||||
if (code) {
|
if (code) {
|
||||||
if (code.size() > 6) {
|
if (code.size() > 6) {
|
||||||
// Harmony code
|
// Harmony code
|
||||||
log.debug "Harmony - Exchanging code for access token"
|
log.debug "Exchanging code for access token"
|
||||||
receiveToken(redirectUrl)
|
receiveToken(redirectUrl)
|
||||||
} else {
|
} else {
|
||||||
// Initiate the Harmony OAuth flow.
|
// Initiate the Harmony OAuth flow.
|
||||||
init()
|
init()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.debug "Harmony - This code should be unreachable"
|
log.debug "This code should be unreachable"
|
||||||
success()
|
success()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def init() {
|
def init() {
|
||||||
log.debug "Harmony - Requesting Code"
|
log.debug "Requesting Code"
|
||||||
def oauthParams = [client_id: "${appSettings.clientId}", scope: "remote", response_type: "code", redirect_uri: "${servercallbackUrl}" ]
|
def oauthParams = [client_id: "${appSettings.clientId}", scope: "remote", response_type: "code", redirect_uri: "${servercallbackUrl}" ]
|
||||||
redirect(location: "https://home.myharmony.com/oauth2/authorize?${toQueryString(oauthParams)}")
|
redirect(location: "https://home.myharmony.com/oauth2/authorize?${toQueryString(oauthParams)}")
|
||||||
}
|
}
|
||||||
|
|
||||||
def receiveToken(redirectUrl = null) {
|
def receiveToken(redirectUrl = null) {
|
||||||
log.debug "Harmony - receiveToken"
|
log.debug "receiveToken"
|
||||||
def oauthParams = [ client_id: "${appSettings.clientId}", client_secret: "${appSettings.clientSecret}", grant_type: "authorization_code", code: params.code ]
|
def oauthParams = [ client_id: "${appSettings.clientId}", client_secret: "${appSettings.clientSecret}", grant_type: "authorization_code", code: params.code ]
|
||||||
def params = [
|
def params = [
|
||||||
uri: "https://home.myharmony.com/oauth2/token?${toQueryString(oauthParams)}",
|
uri: "https://home.myharmony.com/oauth2/token?${toQueryString(oauthParams)}",
|
||||||
@@ -186,7 +186,7 @@ def receiveToken(redirectUrl = null) {
|
|||||||
}
|
}
|
||||||
} catch (java.util.concurrent.TimeoutException e) {
|
} catch (java.util.concurrent.TimeoutException e) {
|
||||||
fail(e)
|
fail(e)
|
||||||
log.warn "Harmony - Connection timed out, please try again later."
|
log.warn "Connection timed out, please try again later."
|
||||||
}
|
}
|
||||||
discovery()
|
discovery()
|
||||||
if (state.HarmonyAccessToken) {
|
if (state.HarmonyAccessToken) {
|
||||||
@@ -310,7 +310,7 @@ def buildRedirectUrl(page) {
|
|||||||
|
|
||||||
def installed() {
|
def installed() {
|
||||||
if (!state.accessToken) {
|
if (!state.accessToken) {
|
||||||
log.debug "Harmony - About to create access token"
|
log.debug "About to create access token"
|
||||||
createAccessToken()
|
createAccessToken()
|
||||||
} else {
|
} else {
|
||||||
initialize()
|
initialize()
|
||||||
@@ -319,7 +319,7 @@ def installed() {
|
|||||||
|
|
||||||
def updated() {
|
def updated() {
|
||||||
if (!state.accessToken) {
|
if (!state.accessToken) {
|
||||||
log.debug "Harmony - About to create access token"
|
log.debug "About to create access token"
|
||||||
createAccessToken()
|
createAccessToken()
|
||||||
} else {
|
} else {
|
||||||
initialize()
|
initialize()
|
||||||
@@ -330,9 +330,9 @@ def uninstalled() {
|
|||||||
if (state.HarmonyAccessToken) {
|
if (state.HarmonyAccessToken) {
|
||||||
try {
|
try {
|
||||||
state.HarmonyAccessToken = ""
|
state.HarmonyAccessToken = ""
|
||||||
log.debug "Harmony - Success disconnecting Harmony from SmartThings"
|
log.debug "Success disconnecting Harmony from SmartThings"
|
||||||
} catch (groovyx.net.http.HttpResponseException e) {
|
} catch (groovyx.net.http.HttpResponseException e) {
|
||||||
log.error "Harmony - Error disconnecting Harmony from SmartThings: ${e.statusCode}"
|
log.error "Error disconnecting Harmony from SmartThings: ${e.statusCode}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -341,8 +341,7 @@ def initialize() {
|
|||||||
state.aux = 0
|
state.aux = 0
|
||||||
if (selectedhubs || selectedactivities) {
|
if (selectedhubs || selectedactivities) {
|
||||||
addDevice()
|
addDevice()
|
||||||
runEvery5Minutes("poll")
|
runEvery5Minutes("poll")
|
||||||
getActivityList()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,7 +350,7 @@ def getHarmonydevices() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Map discoverDevices() {
|
Map discoverDevices() {
|
||||||
log.trace "Harmony - Discovering devices..."
|
log.trace "Discovering devices..."
|
||||||
discovery()
|
discovery()
|
||||||
if (getHarmonydevices() != []) {
|
if (getHarmonydevices() != []) {
|
||||||
def devices = state.Harmonydevices.hubs
|
def devices = state.Harmonydevices.hubs
|
||||||
@@ -381,52 +380,52 @@ def discovery() {
|
|||||||
try {
|
try {
|
||||||
httpGet(uri: url, headers: ["Accept": "application/json"]) {response ->
|
httpGet(uri: url, headers: ["Accept": "application/json"]) {response ->
|
||||||
if (response.status == 200) {
|
if (response.status == 200) {
|
||||||
log.debug "Harmony - valid Token"
|
log.debug "valid Token"
|
||||||
state.Harmonydevices = response.data
|
state.Harmonydevices = response.data
|
||||||
state.resethub = false
|
state.resethub = false
|
||||||
} else {
|
} else {
|
||||||
log.debug "Harmony - Error: $response.status"
|
log.debug "Error: $response.status"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (groovyx.net.http.HttpResponseException e) {
|
} catch (groovyx.net.http.HttpResponseException e) {
|
||||||
if (e.statusCode == 401) { // token is expired
|
if (e.statusCode == 401) { // token is expired
|
||||||
state.remove("HarmonyAccessToken")
|
state.remove("HarmonyAccessToken")
|
||||||
log.warn "Harmony - Harmony Access token has expired"
|
log.warn "Harmony Access token has expired"
|
||||||
}
|
}
|
||||||
} catch (java.net.SocketTimeoutException e) {
|
} catch (java.net.SocketTimeoutException e) {
|
||||||
log.warn "Harmony - Connection to the hub timed out. Please restart the hub and try again."
|
log.warn "Connection to the hub timed out. Please restart the hub and try again."
|
||||||
state.resethub = true
|
state.resethub = true
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.info "Harmony - Error: $e"
|
log.info "Logitech Harmony - Error: $e"
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
def addDevice() {
|
def addDevice() {
|
||||||
log.trace "Harmony - Adding Hubs"
|
log.trace "Adding Hubs"
|
||||||
selectedhubs.each { dni ->
|
selectedhubs.each { dni ->
|
||||||
def d = getChildDevice(dni)
|
def d = getChildDevice(dni)
|
||||||
if(!d) {
|
if(!d) {
|
||||||
def newAction = state.HarmonyHubs.find { it.key == dni }
|
def newAction = state.HarmonyHubs.find { it.key == dni }
|
||||||
d = addChildDevice("smartthings", "Logitech Harmony Hub C2C", dni, null, [label:"${newAction.value}"])
|
d = addChildDevice("smartthings", "Logitech Harmony Hub C2C", dni, null, [label:"${newAction.value}"])
|
||||||
log.trace "Harmony - Created ${d.displayName} with id $dni"
|
log.trace "created ${d.displayName} with id $dni"
|
||||||
poll()
|
poll()
|
||||||
} else {
|
} else {
|
||||||
log.trace "Harmony - Found ${d.displayName} with id $dni already exists"
|
log.trace "found ${d.displayName} with id $dni already exists"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.trace "Harmony - Adding Activities"
|
log.trace "Adding Activities"
|
||||||
selectedactivities.each { dni ->
|
selectedactivities.each { dni ->
|
||||||
def d = getChildDevice(dni)
|
def d = getChildDevice(dni)
|
||||||
if(!d) {
|
if(!d) {
|
||||||
def newAction = state.HarmonyActivities.find { it.key == dni }
|
def newAction = state.HarmonyActivities.find { it.key == dni }
|
||||||
if (newAction) {
|
if (newAction) {
|
||||||
d = addChildDevice("smartthings", "Harmony Activity", dni, null, [label:"${newAction.value} [Harmony Activity]"])
|
d = addChildDevice("smartthings", "Harmony Activity", dni, null, [label:"${newAction.value} [Harmony Activity]"])
|
||||||
log.trace "Harmony - Created ${d.displayName} with id $dni"
|
log.trace "created ${d.displayName} with id $dni"
|
||||||
poll()
|
poll()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.trace "Harmony - Found ${d.displayName} with id $dni already exists"
|
log.trace "found ${d.displayName} with id $dni already exists"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -456,17 +455,17 @@ def activity(dni,mode) {
|
|||||||
|
|
||||||
def activityResponse(response, data) {
|
def activityResponse(response, data) {
|
||||||
if (response.hasError()) {
|
if (response.hasError()) {
|
||||||
log.error "Harmony - response has error: $response.errorMessage"
|
log.error "Logitech Harmony - response has error: $response.errorMessage"
|
||||||
if (response.status == 401) { // token is expired
|
if (response.status == 401) { // token is expired
|
||||||
state.remove("HarmonyAccessToken")
|
state.remove("HarmonyAccessToken")
|
||||||
log.warn "Harmony - Access token has expired"
|
log.warn "Logitech Harmony - Access token has expired"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (response.status == 200) {
|
if (response.status == 200) {
|
||||||
log.trace "Harmony - Command sent succesfully"
|
log.trace "Command sent succesfully"
|
||||||
poll()
|
poll()
|
||||||
} else {
|
} else {
|
||||||
log.trace "Harmony - Command failed. Error: $response.status"
|
log.trace "Command failed. Error: $response.status"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -482,16 +481,16 @@ def poll() {
|
|||||||
]
|
]
|
||||||
asynchttp_v1.get('pollResponse', params)
|
asynchttp_v1.get('pollResponse', params)
|
||||||
} else {
|
} else {
|
||||||
log.warn "Harmony - Access token has expired"
|
log.warn "Logitech Harmony - Access token has expired"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def pollResponse(response, data) {
|
def pollResponse(response, data) {
|
||||||
if (response.hasError()) {
|
if (response.hasError()) {
|
||||||
log.error "Harmony - response has error: $response.errorMessage"
|
log.error "Logitech Harmony - response has error: $response.errorMessage"
|
||||||
if (response.status == 401) { // token is expired
|
if (response.status == 401) { // token is expired
|
||||||
state.remove("HarmonyAccessToken")
|
state.remove("HarmonyAccessToken")
|
||||||
log.warn "Harmony - Access token has expired"
|
log.warn "Logitech Harmony - Access token has expired"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
def ResponseValues
|
def ResponseValues
|
||||||
@@ -499,7 +498,7 @@ def pollResponse(response, data) {
|
|||||||
// json response already parsed into JSONElement object
|
// json response already parsed into JSONElement object
|
||||||
ResponseValues = response.json
|
ResponseValues = response.json
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.error "Harmony - error parsing json from response: $e"
|
log.error "Logitech Harmony - error parsing json from response: $e"
|
||||||
}
|
}
|
||||||
if (ResponseValues) {
|
if (ResponseValues) {
|
||||||
def map = [:]
|
def map = [:]
|
||||||
@@ -521,7 +520,7 @@ def pollResponse(response, data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.trace "Harmony - error response: $it.value.message"
|
log.trace "Logitech Harmony - error response: $it.value.message"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
def activities = getChildDevices()
|
def activities = getChildDevices()
|
||||||
@@ -546,43 +545,11 @@ def pollResponse(response, data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.debug "Harmony - did not get json results from response body: $response.data"
|
log.debug "Logitech Harmony - did not get json results from response body: $response.data"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def getActivityList() {
|
|
||||||
if (state.HarmonyAccessToken) {
|
|
||||||
def Params = [auth: state.HarmonyAccessToken]
|
|
||||||
def url = "https://home.myharmony.com/cloudapi/activity/all?${toQueryString(Params)}"
|
|
||||||
try {
|
|
||||||
httpGet(uri: url, headers: ["Accept": "application/json"]) {response ->
|
|
||||||
response.data.hubs.each {
|
|
||||||
def hub = getChildDevice("harmony-${it.key}")
|
|
||||||
if (hub) {
|
|
||||||
def hubname = getHubName("${it.key}")
|
|
||||||
def activities = []
|
|
||||||
def aux = it.value.response.data.activities.size()
|
|
||||||
if (aux >= 1) {
|
|
||||||
activities = it.value.response.data.activities.collect {
|
|
||||||
[id: it.key, name: it.value['name'], type: it.value['type']]
|
|
||||||
}
|
|
||||||
activities += [id: "off", name: "Activity OFF", type: "0"]
|
|
||||||
}
|
|
||||||
hub.sendEvent(name: "activities", value: new groovy.json.JsonBuilder(activities).toString(), descriptionText: "Activities are ${activities.collect { it.name }?.join(', ')}", display: false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (groovyx.net.http.HttpResponseException e) {
|
|
||||||
log.trace e
|
|
||||||
} catch (java.net.SocketTimeoutException e) {
|
|
||||||
log.trace e
|
|
||||||
} catch(Exception e) {
|
|
||||||
log.trace e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def getActivityName(activity,hubId) {
|
def getActivityName(activity,hubId) {
|
||||||
// GET ACTIVITY'S NAME
|
// GET ACTIVITY'S NAME
|
||||||
def actname = activity
|
def actname = activity
|
||||||
@@ -643,7 +610,7 @@ def sendNotification(msg) {
|
|||||||
|
|
||||||
def hookEventHandler() {
|
def hookEventHandler() {
|
||||||
// log.debug "In hookEventHandler method."
|
// log.debug "In hookEventHandler method."
|
||||||
log.debug "Harmony - request = ${request}"
|
log.debug "request = ${request}"
|
||||||
|
|
||||||
def json = request.JSON
|
def json = request.JSON
|
||||||
|
|
||||||
@@ -652,14 +619,14 @@ def hookEventHandler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def listDevices() {
|
def listDevices() {
|
||||||
log.debug "Harmony - getDevices(), params: ${params}"
|
log.debug "getDevices, params: ${params}"
|
||||||
allDevices.collect {
|
allDevices.collect {
|
||||||
deviceItem(it)
|
deviceItem(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def getDevice() {
|
def getDevice() {
|
||||||
log.debug "Harmony - getDevice(), params: ${params}"
|
log.debug "getDevice, params: ${params}"
|
||||||
def device = allDevices.find { it.id == params.id }
|
def device = allDevices.find { it.id == params.id }
|
||||||
if (!device) {
|
if (!device) {
|
||||||
render status: 404, data: '{"msg": "Device not found"}'
|
render status: 404, data: '{"msg": "Device not found"}'
|
||||||
@@ -672,7 +639,7 @@ def updateDevice() {
|
|||||||
def data = request.JSON
|
def data = request.JSON
|
||||||
def command = data.command
|
def command = data.command
|
||||||
def arguments = data.arguments
|
def arguments = data.arguments
|
||||||
log.debug "Harmony - updateDevice(), params: ${params}, request: ${data}"
|
log.debug "updateDevice, params: ${params}, request: ${data}"
|
||||||
if (!command) {
|
if (!command) {
|
||||||
render status: 400, data: '{"msg": "command is required"}'
|
render status: 400, data: '{"msg": "command is required"}'
|
||||||
} else {
|
} else {
|
||||||
@@ -740,7 +707,7 @@ def getDeviceCapabilityCommands(deviceCapabilities) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def listSubscriptions() {
|
def listSubscriptions() {
|
||||||
log.debug "Harmony - listSubscriptions()"
|
log.debug "listSubscriptions()"
|
||||||
app.subscriptions?.findAll { it.device?.device && it.device.id }?.collect {
|
app.subscriptions?.findAll { it.device?.device && it.device.id }?.collect {
|
||||||
def deviceInfo = state[it.device.id]
|
def deviceInfo = state[it.device.id]
|
||||||
def response = [
|
def response = [
|
||||||
@@ -761,17 +728,17 @@ def addSubscription() {
|
|||||||
def attribute = data.attributeName
|
def attribute = data.attributeName
|
||||||
def callbackUrl = data.callbackUrl
|
def callbackUrl = data.callbackUrl
|
||||||
|
|
||||||
log.debug "Harmony - addSubscription, params: ${params}, request: ${data}"
|
log.debug "Logitech Harmony - addSubscription, params: ${params}, request: ${data}"
|
||||||
if (!attribute) {
|
if (!attribute) {
|
||||||
render status: 400, data: '{"msg": "attributeName is required"}'
|
render status: 400, data: '{"msg": "attributeName is required"}'
|
||||||
} else {
|
} else {
|
||||||
def device = allDevices.find { it.id == data.deviceId }
|
def device = allDevices.find { it.id == data.deviceId }
|
||||||
if (device) {
|
if (device) {
|
||||||
if (!state.harmonyHubs) {
|
if (!state.harmonyHubs) {
|
||||||
log.debug "Harmony - Adding callbackUrl: $callbackUrl"
|
log.debug "Adding callbackUrl: $callbackUrl"
|
||||||
state[device.id] = [callbackUrl: callbackUrl]
|
state[device.id] = [callbackUrl: callbackUrl]
|
||||||
}
|
}
|
||||||
log.debug "Harmony - Adding subscription"
|
log.debug "Adding subscription"
|
||||||
def subscription = subscribe(device, attribute, deviceHandler)
|
def subscription = subscribe(device, attribute, deviceHandler)
|
||||||
if (!subscription || !subscription.eventSubscription) {
|
if (!subscription || !subscription.eventSubscription) {
|
||||||
subscription = app.subscriptions?.find { it.device?.device && it.device.id == data.deviceId && it.data == attribute && it.handler == 'deviceHandler' }
|
subscription = app.subscriptions?.find { it.device?.device && it.device.id == data.deviceId && it.data == attribute && it.handler == 'deviceHandler' }
|
||||||
@@ -799,7 +766,7 @@ def removeSubscription() {
|
|||||||
|
|
||||||
log.debug "removeSubscription, params: ${params}, subscription: ${subscription}, device: ${device}"
|
log.debug "removeSubscription, params: ${params}, subscription: ${subscription}, device: ${device}"
|
||||||
if (device) {
|
if (device) {
|
||||||
log.debug "Harmony - Removing subscription for device: ${device.id}"
|
log.debug "Removing subscription for device: ${device.id}"
|
||||||
state.remove(device.id)
|
state.remove(device.id)
|
||||||
unsubscribe(device)
|
unsubscribe(device)
|
||||||
}
|
}
|
||||||
@@ -823,17 +790,17 @@ def deviceHandler(evt) {
|
|||||||
def deviceInfo = state[evt.deviceId]
|
def deviceInfo = state[evt.deviceId]
|
||||||
if (state.harmonyHubs) {
|
if (state.harmonyHubs) {
|
||||||
state.harmonyHubs.each { harmonyHub ->
|
state.harmonyHubs.each { harmonyHub ->
|
||||||
log.trace "Harmony - Sending data to $harmonyHub.name"
|
log.trace "Logitech Harmony - Sending data to $harmonyHub.name"
|
||||||
sendToHarmony(evt, harmonyHub.callbackUrl)
|
sendToHarmony(evt, harmonyHub.callbackUrl)
|
||||||
}
|
}
|
||||||
} else if (deviceInfo) {
|
} else if (deviceInfo) {
|
||||||
if (deviceInfo.callbackUrl) {
|
if (deviceInfo.callbackUrl) {
|
||||||
sendToHarmony(evt, deviceInfo.callbackUrl)
|
sendToHarmony(evt, deviceInfo.callbackUrl)
|
||||||
} else {
|
} else {
|
||||||
log.warn "Harmony - No callbackUrl set for device: ${evt.deviceId}"
|
log.warn "No callbackUrl set for device: ${evt.deviceId}"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.warn "Harmony - No subscribed device found for device: ${evt.deviceId}"
|
log.warn "No subscribed device found for device: ${evt.deviceId}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -857,12 +824,12 @@ def sendToHarmony(evt, String callbackUrl) {
|
|||||||
body: [evt: [deviceId: evt.deviceId, name: evt.name, value: evt.value]]
|
body: [evt: [deviceId: evt.deviceId, name: evt.name, value: evt.value]]
|
||||||
]
|
]
|
||||||
try {
|
try {
|
||||||
log.debug "Harmony - Sending data to Harmony Cloud: $params"
|
log.debug "Sending data to Harmony Cloud: $params"
|
||||||
httpPostJson(params) { resp ->
|
httpPostJson(params) { resp ->
|
||||||
log.debug "Harmony - Cloud Response: ${resp.status}"
|
log.debug "Harmony Cloud - Response: ${resp.status}"
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.error "Harmony - Cloud Something went wrong: $e"
|
log.error "Harmony Cloud - Something went wrong: $e"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -887,10 +854,10 @@ def activityCallback() {
|
|||||||
if (data.errorCode == "200") {
|
if (data.errorCode == "200") {
|
||||||
device.setCurrentActivity(data.currentActivityId)
|
device.setCurrentActivity(data.currentActivityId)
|
||||||
} else {
|
} else {
|
||||||
log.warn "Harmony - Activity callback error: ${data}"
|
log.warn "Activity callback error: ${data}"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.warn "Harmony - Activity callback sent to non-existant dni: ${params.dni}"
|
log.warn "Activity callback sent to non-existant dni: ${params.dni}"
|
||||||
}
|
}
|
||||||
render status: 200, data: '{"msg": "Successfully received callbackUrl"}'
|
render status: 200, data: '{"msg": "Successfully received callbackUrl"}'
|
||||||
}
|
}
|
||||||
@@ -924,13 +891,13 @@ def harmony() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def deleteHarmony() {
|
def deleteHarmony() {
|
||||||
log.debug "Harmony - Trying to delete Harmony hub with mac: ${params.mac}"
|
log.debug "Trying to delete Harmony hub with mac: ${params.mac}"
|
||||||
def harmonyHub = state.harmonyHubs?.find { it.mac == params.mac }
|
def harmonyHub = state.harmonyHubs?.find { it.mac == params.mac }
|
||||||
if (harmonyHub) {
|
if (harmonyHub) {
|
||||||
log.debug "Harmony - Deleting Harmony hub with mac: ${params.mac}"
|
log.debug "Deleting Harmony hub with mac: ${params.mac}"
|
||||||
state.harmonyHubs.remove(harmonyHub)
|
state.harmonyHubs.remove(harmonyHub)
|
||||||
} else {
|
} else {
|
||||||
log.debug "Harmony - Couldn't find Harmony hub with mac: ${params.mac}"
|
log.debug "Couldn't find Harmony hub with mac: ${params.mac}"
|
||||||
}
|
}
|
||||||
render status: 204, data: "{}"
|
render status: 204, data: "{}"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user