Compare commits

...

59 Commits

Author SHA1 Message Date
Vinay Rao
a06dba0b90 Merge pull request #1807 from SmartThingsCommunity/staging
Rolling up staging to production for release
2017-03-21 11:37:47 -07:00
Vinay Rao
0ec8cba885 Merge pull request #1806 from SmartThingsCommunity/production
Rolling down production hotfix to staging
2017-03-21 11:37:04 -07:00
Vinay Rao
eca8fda0f2 Merge pull request #1805 from larsfinander/revert_hue_i18_changes_staging
Hue: Revert i18 changes
2017-03-20 16:35:29 -07:00
Lars Finander
ce07c065c8 Hue: Revert i18 changes 2017-03-20 17:31:05 -06:00
Vinay Rao
17ec6270d6 Merge pull request #1803 from larsfinander/hue_translations_updated_staging
Hue: Updated errors in text not matching i18 files
2017-03-20 15:46:15 -07:00
Lars Finander
d233a65ef5 Hue: Updated errors in text not matching i18 files 2017-03-20 16:44:10 -06:00
Vinay Rao
a560c5b040 Merge pull request #1795 from larsfinander/hue_connect_translations_staging
DVCSMP-2453 HUE: add code to enable localization for Service Manage
2017-03-20 11:42:26 -07:00
Vinay Rao
3ee374028f Merge pull request #1801 from dkirker/DVCSMP-2504
DVCSMP-2504: Add fingerprints for Centrailte generic multi, motion, water leak
2017-03-20 09:45:18 -07:00
Donald Kirker
7ac7bd3034 DVCSMP-2504: Add fingerprints for Centrailte generic multi, motion, water leak 2017-03-20 07:39:37 -07:00
Lars Finander
b93a05d450 DVCSMP-2453 HUE: add code to enable localization for Service Manage
-Updated strings in app
-Added i18 files
2017-03-16 19:09:23 -06:00
Vinay Rao
f5186a41c7 Merge pull request #1787 from jackchi/dth_ux_page17
[DVCSMP-2512] Standardize Page 17 of DTH UX Improvements
2017-03-16 11:20:15 -07:00
Vinay Rao
c505f95e7a Merge pull request #1788 from ShunmugaSundar/Page_18
[DVCSMP-2513] Standardize Page 18 of DTH UX Improvements
2017-03-16 11:20:07 -07:00
Vinay Rao
173c34150a Merge pull request #1779 from jackchi/dth_ux_page16
[DVCSMP-2511] Standardize Page 16 of DTH UX Improvements
2017-03-16 11:19:59 -07:00
Vinay Rao
f6b850500e Merge pull request #1780 from ShunmugaSundar/Page_14_Changes
[DVCSMP-2509] Standardize Page 14 of DTH UX Improvements
2017-03-16 11:19:52 -07:00
Vinay Rao
e2d8af48a8 Merge pull request #1792 from SmartThingsCommunity/revert-1784-revert-1783-hue_add_bridge_if_missing_production
Revert "Revert "Hue: Re-add Hue bridge if deleted""
2017-03-16 04:37:53 -07:00
Vinay Rao
0f00c3c7c0 Revert "Revert "Hue: Re-add Hue bridge if deleted"" 2017-03-16 04:37:35 -07:00
ShunmugaSundar
2678480244 [DVCSMP-2513] Standardize Page 18 of DTH UX Improvements 2017-03-15 23:58:43 +05:30
jackchi
b5e8a46143 [DVCSMP-2512] Standardize Page 17 of DTH UX Improvements 2017-03-15 09:57:37 -07:00
Vinay Rao
6237dbd179 Merge pull request #1784 from SmartThingsCommunity/revert-1783-hue_add_bridge_if_missing_production
Revert "Hue: Re-add Hue bridge if deleted"
2017-03-14 21:18:43 -07:00
Vinay Rao
65f5597ccc Revert "Hue: Re-add Hue bridge if deleted" 2017-03-14 21:00:22 -07:00
Vinay Rao
fced2d7c61 Merge pull request #1783 from larsfinander/hue_add_bridge_if_missing_production
Hue: Re-add Hue bridge if deleted
2017-03-14 18:42:40 -07:00
Lars Finander
74552420ba Hue: Re-add Hue bridge if deleted
-Add Hue Bridge if missing during deviceSync
2017-03-14 19:28:15 -06:00
Vinay Rao
89f1302c99 Merge pull request #1777 from jackchi/dth_ux_page15
Standardize Page 15 of DTH UX Improvements
2017-03-14 17:36:30 -07:00
Vinay Rao
30d8e6d835 Merge branch 'master' into staging 2017-03-14 17:32:55 -07:00
ShunmugaSundar
6d0f9d101d [DVCSMP-2509] Standardize Page 14 of DTH UX Improvements
[DVCSMP-2509] Standardize Page 14 of DTH UX Improvements
2017-03-15 05:26:41 +05:30
jackchi
4ba55e7f0a [DVCSMP-2511] Standardize Page 16 of DTH UX Improvements 2017-03-14 15:29:37 -07:00
jackchi
8a41fb6090 [DVCSMP-2510] Standardize Page 15 of DTH UX Improvements 2017-03-14 14:47:56 -07:00
Vinay Rao
79c254cfac Merge pull request #1774 from SmartThingsCommunity/staging
Rolling up staging to production
2017-03-14 11:40:39 -07:00
Vinay Rao
72248b0004 Merge pull request #1773 from SmartThingsCommunity/production
Rolling down production to staging
2017-03-14 11:38:11 -07:00
Vinay Rao
d8b35b23ea Merge pull request #1770 from dkirker/DVCSMP-2472
DVCSMP-2472: Add Eaton Halo downlight
2017-03-14 02:28:47 -07:00
Donald Kirker
9a53e12427 DVCSMP-2472: Add Eaton Halo downlight 2017-03-14 02:20:58 -07:00
Tyler Lange
2ae163b10b Merge pull request #1764 from CosmicPuppy/ActionTiles-Fibaro-CapabilitySensorPatch
To Fibaro Flood Sensor DTHs, added Capability "Sensor" per http://doc…
2017-03-13 10:27:41 -07:00
CosmicPuppy
e3168793bd To Fibaro Flood Sensor DTHs, added Capability "Sensor" per http://docs.smartthings.com/en/latest/device-type-developers-guide/overview.html?highlight=sensor%20actuator#actuator-and-sensor.
There are some SmartApps out there using the "Actuator" and "Sensor" Capabilities and this Device doesn't show up for them (e.g., ActionTiles).
2017-03-11 00:47:36 -08:00
Tyler Lange
0baa986c61 Merge pull request #1762 from CosmicPuppy/ActionTiles-Nyce-CapabilitySensorPatch
To Nyce sensor DTHs, added Capability "Sensor" per http://docs.smartt…
2017-03-09 12:53:49 -08:00
CosmicPuppy
8484f18a0e To Nyce sensor DTHs, added Capability "Sensor" per http://docs.smartthings.com/en/latest/device-type-developers-guide/overview.html?highlight=sensor%20actuator#actuator-and-sensor.
There are some SmartApps out there using the "Actuator" and "Sensor" Capabilities and this Device doesn't show up for them (e.g., ActionTiles).
2017-03-09 00:05:14 -08:00
Vinay Rao
3c4d86bb31 Merge pull request #1761 from mckeed/ICP-399-prod
Update Fibaro Flood Sensor configuration ICP-399 ICP-398
2017-03-08 16:43:23 -08:00
Duncan McKee
1f69ab6634 Update Fibaro Flood Sensor configuration
ICP-399 ICP-398
2017-03-08 19:17:46 -05:00
Vinay Rao
b0ac006781 Merge pull request #1758 from mckeed/ICP-399-staging
Update Fibaro Flood Sensor configuration ICP-399 ICP-398
2017-03-07 17:53:27 -08:00
Duncan McKee
ef1ebc8347 Update Fibaro Flood Sensor configuration
ICP-399 ICP-398
2017-03-07 20:45:49 -05:00
Vinay Rao
aa1f2f21e8 Merge pull request #1756 from SmartThingsCommunity/master
Rolling up master to staging
2017-03-07 13:55:39 -08:00
Vinay Rao
cb6377886d Merge pull request #1755 from SmartThingsCommunity/staging
Rolling down staging to master
2017-03-07 13:54:54 -08:00
Vinay Rao
7a605373d6 Merge pull request #1754 from SmartThingsCommunity/staging
Rolling up staging to production
2017-03-07 13:27:33 -08:00
Vinay Rao
90fb9251a6 Merge pull request #1753 from SmartThingsCommunity/production
Rolling down production to staging
2017-03-07 13:27:02 -08:00
Vinay Rao
195e0babb2 Merge pull request #1752 from larsfinander/DVCSMP-2497_OpenT2T_Update_3_5_submission_staging
DVCSMP-2497 OpenT2T: Update to 3/5 submission
2017-03-06 20:52:51 -08:00
Lars Finander
065715f296 DVCSMP-2497 OpenT2T: Update to 3/5 submission 2017-03-06 21:43:42 -07:00
tslagle13
a544e2f019 Merge pull request #1712 from SmartThingsCommunity/MSA-1803-1
MSA-1803: Gideon Smart home smartapp
2017-03-06 12:07:11 -08:00
Vinay Rao
10acb76b34 Merge pull request #1747 from workingmonk/feature/zwave_chf_prod
[CHF-532] [CHF-533] Health Check Z-Wave Sleepy Fibaro Sensors
2017-03-05 13:29:49 -08:00
Jack Chi
4fc046f57f [CHF-532] [CHF-533] Health Check Z-Wave Sleepy Fibaro Sensors (#1741) 2017-03-05 13:26:30 -08:00
Vinay Rao
ff2e70b011 Merge pull request #1744 from workingmonk/feature/na04_deploy_tag
TECHOPS-1788 update deploy script
2017-03-03 16:37:42 -08:00
Vinay Rao
79e2789f68 TECHOPS-1788 update deploy script 2017-03-03 16:32:32 -08:00
Jack Chi
94a87e5c7f [CHF-532] [CHF-533] Health Check Z-Wave Sleepy Fibaro Sensors (#1741) 2017-03-02 17:53:17 -08:00
Vinay Rao
22be8ef2e8 Merge pull request #1739 from larsfinander/DVCSMP-2487_OpenT2T_Update_to_3_2_submission_staging
DVCSMP-2487 OpenT2T: Update to 3/2 submission
2017-03-02 11:26:42 -08:00
Lars Finander
2f20a339c3 DVCSMP-2487 OpenT2T: Update to 3/2 submission 2017-03-02 12:16:03 -07:00
Vinay Rao
ab79ceb857 Merge pull request #1728 from SmartThingsCommunity/staging
Rolling up staging to production
2017-02-28 14:01:19 -08:00
Nicola Russo
a583a25ef3 MSA-1803: A simple web service smartapp that allows the users to control their devices through Gideon Smart home app. 2017-02-23 15:31:44 -08:00
Vinay Rao
2151e2dd3e Merge pull request #1706 from SmartThingsCommunity/staging
Rolling up staging to production for deploy
2017-02-22 13:44:57 -08:00
Vinay Rao
bfd2b6c0fa Merge pull request #1674 from SmartThingsCommunity/staging
Rolling up staging to production
2017-02-14 12:09:12 -08:00
Vinay Rao
fc312286a2 Merge pull request #1653 from SmartThingsCommunity/staging
Rolling up staging to production for deploy
2017-02-07 14:21:49 -08:00
Vinay Rao
0846b6f34c Merge pull request #1629 from SmartThingsCommunity/staging
Rolling up staging to production
2017-01-31 13:25:26 -08:00
43 changed files with 1425 additions and 417 deletions

View File

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

View File

@@ -21,28 +21,30 @@ metadata {
capability "Tamper Alert"
capability "Temperature Measurement"
capability "Water Sensor"
fingerprint deviceId: "0x0701", inClusters: "0x5E, 0x22, 0x85, 0x59, 0x20, 0x80, 0x70, 0x56, 0x5A, 0x7A, 0x72, 0x8E, 0x71, 0x73, 0x98, 0x9C, 0x31, 0x86", outClusters: ""
capability "Health Check"
fingerprint deviceId: "0x0701", inClusters: "0x5E, 0x22, 0x85, 0x59, 0x20, 0x80, 0x70, 0x56, 0x5A, 0x7A, 0x72, 0x8E, 0x71, 0x73, 0x98, 0x9C, 0x31, 0x86", outClusters: ""
fingerprint mfr:"010F", prod:"0B01", model:"2002"
fingerprint mfr:"010F", prod:"0B01", model:"1002"
}
simulator {
}
tiles(scale: 2) {
multiAttributeTile(name:"FGFS", type:"lighting", width:6, height:4) {//with generic type secondary control text is not displayed in Android app
tileAttribute("device.water", key:"PRIMARY_CONTROL") {
attributeState("dry", icon:"st.alarm.water.dry", backgroundColor:"#00a0dc")
attributeState("wet", icon:"st.alarm.water.wet", backgroundColor:"#e86d13")
}
tileAttribute("device.tamper", key:"SECONDARY_CONTROL") {
tiles(scale: 2) {
multiAttributeTile(name:"FGFS", type:"lighting", width:6, height:4) {//with generic type secondary control text is not displayed in Android app
tileAttribute("device.water", key:"PRIMARY_CONTROL") {
attributeState("dry", icon:"st.alarm.water.dry", backgroundColor:"#00a0dc")
attributeState("wet", icon:"st.alarm.water.wet", backgroundColor:"#e86d13")
}
tileAttribute("device.tamper", key:"SECONDARY_CONTROL") {
attributeState("active", label:'tamper active', backgroundColor:"#00a0dc")
attributeState("inactive", label:'tamper inactive', backgroundColor:"#cccccc")
}
}
valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) {
}
}
valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) {
state "temperature", label:'${currentValue}°',
backgroundColors:[
[value: 31, color: "#153591"],
@@ -54,22 +56,22 @@ metadata {
[value: 96, color: "#bc2323"]
]
}
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "battery", label:'${currentValue}% battery', unit:""
}
main "FGFS"
details(["FGFS","battery", "temperature"])
}
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "battery", label:'${currentValue}% battery', unit:""
}
main "FGFS"
details(["FGFS","battery", "temperature"])
}
}
// parse events into attributes
def parse(String description) {
log.debug "Parsing '${description}'"
def result = []
if (description.startsWith("Err 106")) {
if (description.startsWith("Err 106")) {
if (state.sec) {
result = createEvent(descriptionText:description, displayed:false)
} else {
@@ -84,13 +86,13 @@ def parse(String description) {
} else if (description == "updated") {
return null
} else {
def cmd = zwave.parse(description, [0x31: 5, 0x56: 1, 0x71: 3, 0x72:2, 0x80: 1, 0x84: 2, 0x85: 2, 0x86: 1, 0x98: 1])
def cmd = zwave.parse(description, [0x31: 5, 0x56: 1, 0x71: 3, 0x72:2, 0x80: 1, 0x84: 2, 0x85: 2, 0x86: 1, 0x98: 1])
if (cmd) {
log.debug "Parsed '${cmd}'"
zwaveEvent(cmd)
}
}
if (cmd) {
log.debug "Parsed '${cmd}'"
zwaveEvent(cmd)
}
}
}
//security
@@ -107,7 +109,7 @@ def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulat
//crc16
def zwaveEvent(physicalgraph.zwave.commands.crc16encapv1.Crc16Encap cmd)
{
def versions = [0x31: 5, 0x72: 2, 0x80: 1]
def versions = [0x31: 5, 0x72: 2, 0x80: 1]
def version = versions[cmd.commandClass as Integer]
def ccObj = version ? zwave.commandClass(cmd.commandClass, version) : zwave.commandClass(cmd.commandClass)
def encapsulatedCommand = ccObj?.command(cmd.command)?.parse(cmd.data)
@@ -121,105 +123,124 @@ def zwaveEvent(physicalgraph.zwave.commands.crc16encapv1.Crc16Encap cmd)
def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd)
{
def event = createEvent(descriptionText: "${device.displayName} woke up", displayed: false)
def cmds = []
cmds << encap(zwave.batteryV1.batteryGet())
cmds << "delay 500"
cmds << encap(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 1, scale: 0))
cmds << "delay 1200"
cmds << encap(zwave.wakeUpV1.wakeUpNoMoreInformation())
[event, response(cmds)]
def cmds = []
// cmds << encap(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 1, scale: 0))
// cmds << "delay 500"
cmds << encap(zwave.batteryV1.batteryGet())
[event, response(cmds)]
}
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
log.debug "manufacturerId: ${cmd.manufacturerId}"
log.debug "manufacturerName: ${cmd.manufacturerName}"
log.debug "productId: ${cmd.productId}"
log.debug "productTypeId: ${cmd.productTypeId}"
log.debug "manufacturerName: ${cmd.manufacturerName}"
log.debug "productId: ${cmd.productId}"
log.debug "productTypeId: ${cmd.productTypeId}"
}
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.DeviceSpecificReport cmd) {
log.debug "deviceIdData: ${cmd.deviceIdData}"
log.debug "deviceIdDataFormat: ${cmd.deviceIdDataFormat}"
log.debug "deviceIdDataLengthIndicator: ${cmd.deviceIdDataLengthIndicator}"
log.debug "deviceIdType: ${cmd.deviceIdType}"
if (cmd.deviceIdType == 1 && cmd.deviceIdDataFormat == 1) {//serial number in binary format
log.debug "deviceIdDataFormat: ${cmd.deviceIdDataFormat}"
log.debug "deviceIdDataLengthIndicator: ${cmd.deviceIdDataLengthIndicator}"
log.debug "deviceIdType: ${cmd.deviceIdType}"
if (cmd.deviceIdType == 1 && cmd.deviceIdDataFormat == 1) { //serial number in binary format
String serialNumber = "h'"
cmd.deviceIdData.each{ data ->
serialNumber += "${String.format("%02X", data)}"
}
updateDataValue("serialNumber", serialNumber)
log.debug "${device.displayName} - serial number: ${serialNumber}"
}
cmd.deviceIdData.each{ data ->
serialNumber += "${String.format("%02X", data)}"
}
updateDataValue("serialNumber", serialNumber)
log.debug "${device.displayName} - serial number: ${serialNumber}"
}
def response_cmds = []
if (!device.currentState("temperature")) {
response_cmds << encap(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 1, scale: 0))
}
if (!getDataValue("version") && !zwaveInfo.ver) {
log.debug "Requesting Version Report"
response_cmds << "delay 500"
response_cmds << encap(zwave.versionV1.versionGet())
}
response_cmds << "delay 1000"
response_cmds << encap(zwave.wakeUpV2.wakeUpNoMoreInformation())
[[:], response(response_cmds)]
}
def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) {
updateDataValue("version", "${cmd.applicationVersion}.${cmd.applicationSubVersion}")
log.debug "applicationVersion: ${cmd.applicationVersion}"
log.debug "applicationSubVersion: ${cmd.applicationSubVersion}"
log.debug "zWaveLibraryType: ${cmd.zWaveLibraryType}"
log.debug "zWaveProtocolVersion: ${cmd.zWaveProtocolVersion}"
log.debug "zWaveProtocolSubVersion: ${cmd.zWaveProtocolSubVersion}"
def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) {
updateDataValue("version", "${cmd.applicationVersion}.${cmd.applicationSubVersion}")
log.debug "applicationVersion: ${cmd.applicationVersion}"
log.debug "applicationSubVersion: ${cmd.applicationSubVersion}"
log.debug "zWaveLibraryType: ${cmd.zWaveLibraryType}"
log.debug "zWaveProtocolVersion: ${cmd.zWaveProtocolVersion}"
log.debug "zWaveProtocolSubVersion: ${cmd.zWaveProtocolSubVersion}"
}
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
def result = []
def map = [:]
map.name = "battery"
map.value = cmd.batteryLevel == 255 ? 1 : cmd.batteryLevel.toString()
map.unit = "%"
map.displayed = true
createEvent(map)
result << createEvent(map)
if (!getDataValue("serialNumber")) {
result << response(encap(zwave.manufacturerSpecificV2.deviceSpecificGet()))
} else {
result << response(encap(zwave.wakeUpV2.wakeUpNoMoreInformation()))
}
result
}
def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) {
def map = [:]
if (cmd.notificationType == 5) {
switch (cmd.event) {
case 2:
map.name = "water"
map.value = "wet"
map.descriptionText = "${device.displayName} is ${map.value}"
break
case 0:
map.name = "water"
map.value = "dry"
map.descriptionText = "${device.displayName} is ${map.value}"
break
}
} else if (cmd.notificationType == 7) {
switch (cmd.event) {
case 0:
map.name = "tamper"
map.value = "inactive"
map.descriptionText = "${device.displayName}: tamper alarm has been deactivated"
if (cmd.notificationType == 5) {
switch (cmd.event) {
case 2:
map.name = "water"
map.value = "wet"
map.descriptionText = "${device.displayName} is ${map.value}"
break
case 3:
map.name = "tamper"
map.value = "active"
map.descriptionText = "${device.displayName}: tamper alarm activated"
break
}
}
createEvent(map)
case 0:
map.name = "water"
map.value = "dry"
map.descriptionText = "${device.displayName} is ${map.value}"
break
}
} else if (cmd.notificationType == 7) {
switch (cmd.event) {
case 0:
map.name = "tamper"
map.value = "inactive"
map.descriptionText = "${device.displayName}: tamper alarm has been deactivated"
break
case 3:
map.name = "tamper"
map.value = "active"
map.descriptionText = "${device.displayName}: tamper alarm activated"
break
}
}
createEvent(map)
}
def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv5.SensorMultilevelReport cmd) {
def map = [:]
if (cmd.sensorType == 1) {
// temperature
def cmdScale = cmd.scale == 1 ? "F" : "C"
map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision)
map.unit = getTemperatureScale()
map.name = "temperature"
map.displayed = true
// temperature
def cmdScale = cmd.scale == 1 ? "F" : "C"
map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision)
map.unit = getTemperatureScale()
map.name = "temperature"
map.displayed = true
}
createEvent(map)
createEvent(map)
}
def zwaveEvent(physicalgraph.zwave.commands.deviceresetlocallyv1.DeviceResetLocallyNotification cmd) {
@@ -228,19 +249,18 @@ def zwaveEvent(physicalgraph.zwave.commands.deviceresetlocallyv1.DeviceResetLoca
def configure() {
log.debug "Executing 'configure'"
def cmds = []
cmds += zwave.wakeUpV2.wakeUpIntervalSet(seconds:21600, nodeid: zwaveHubNodeId)//FGFS' default wake up interval
cmds += zwave.manufacturerSpecificV2.manufacturerSpecificGet()
cmds += zwave.manufacturerSpecificV2.deviceSpecificGet()
cmds += zwave.versionV1.versionGet()
cmds += zwave.batteryV1.batteryGet()
cmds += zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 1, scale: 0)
cmds += zwave.associationV2.associationSet(groupingIdentifier:1, nodeId: [zwaveHubNodeId])
cmds += zwave.wakeUpV2.wakeUpNoMoreInformation()
// Device wakes up every 4 hours, this interval of 8h 2m allows us to miss one wakeup notification before marking offline
sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
encapSequence(cmds, 500)
// default initial state
sendEvent(name: "water", value: "dry")
def cmds = []
cmds << zwave.associationV2.associationSet(groupingIdentifier:1, nodeId: [zwaveHubNodeId])
cmds << zwave.batteryV1.batteryGet() // other queries sent as response to BatteryReport
encapSequence(cmds, 200)
}
private secure(physicalgraph.zwave.Command cmd) {
@@ -249,7 +269,7 @@ private secure(physicalgraph.zwave.Command cmd) {
private crc16(physicalgraph.zwave.Command cmd) {
//zwave.crc16EncapV1.crc16Encap().encapsulate(cmd).format()
"5601${cmd.format()}0000"
"5601${cmd.format()}0000"
}
private encapSequence(commands, delay=200) {
@@ -257,13 +277,10 @@ private encapSequence(commands, delay=200) {
}
private encap(physicalgraph.zwave.Command cmd) {
def secureClasses = [0x20, 0x5A, 0x70, 0x71, 0x84, 0x85, 0x8E, 0x9C]
//todo: check if secure inclusion was successful
//if not do not send security-encapsulated command
if (secureClasses.find{ it == cmd.commandClassId }) {
secure(cmd)
} else {
crc16(cmd)
}
}
if (zwaveInfo.zw && !zwaveInfo.zw.contains("s")) {
// Secure inclusion failed
crc16(cmd)
} else {
secure(cmd)
}
}

View File

@@ -22,6 +22,7 @@ metadata {
capability "Sensor"
capability "Tamper Alert"
capability "Temperature Measurement"
capability "Health Check"
fingerprint deviceId: "0x0701", inClusters: "0x5E, 0x20, 0x86, 0x72, 0x5A, 0x59, 0x85, 0x73, 0x84, 0x80, 0x71, 0x56, 0x70, 0x31, 0x8E, 0x22, 0x30, 0x9C, 0x98, 0x7A", outClusters: ""
}
@@ -240,7 +241,9 @@ def zwaveEvent(physicalgraph.zwave.commands.deviceresetlocallyv1.DeviceResetLoca
def configure() {
log.debug "Executing 'configure'"
// Device-Watch simply pings if no device events received for 8 hrs & 2 minutes
sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
def cmds = []
cmds += zwave.wakeUpV2.wakeUpIntervalSet(seconds: 7200, nodeid: zwaveHubNodeId)//FGMS' default wake up interval

View File

@@ -40,10 +40,10 @@ metadata {
// UI tile definitions
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "on", action: "switch.off", icon: "st.vents.vent-open-text", backgroundColor: "#53a7c0"
state "on", action: "switch.off", icon: "st.vents.vent-open-text", backgroundColor: "#00a0dc"
state "off", action: "switch.on", icon: "st.vents.vent-closed", backgroundColor: "#ffffff"
state "obstructed", action: "clearObstruction", icon: "st.vents.vent-closed", backgroundColor: "#ff0000"
state "clearing", action: "", icon: "st.vents.vent-closed", backgroundColor: "#ffff33"
state "obstructed", action: "clearObstruction", icon: "st.vents.vent-closed", backgroundColor: "#e86d13"
state "clearing", action: "", icon: "st.vents.vent-closed", backgroundColor: "#ffffff"
}
controlTile("levelSliderControl", "device.level", "slider", height: 1, width: 2, inactiveLabel: false) {
state "level", action:"switch level.setLevel"

View File

@@ -22,7 +22,7 @@ metadata
{
standardTile("mainTile", "device.status", width: 1, height: 1, icon: "st.Entertainment.entertainment11")
{
state "default", label: "Simple Sync", icon: "st.Home.home2", backgroundColor: "#55A7FF"
state "default", label: "Simple Sync", icon: "st.Home.home2", backgroundColor: "#00a0dc"
}
def detailTiles = ["mainTile"]

View File

@@ -82,8 +82,8 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name:"motion", type: "generic", width: 6, height: 4){
tileAttribute ("device.motion", key: "PRIMARY_CONTROL") {
attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0"
attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff"
attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC"
attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc"
}
}
valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) {

View File

@@ -64,8 +64,8 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name:"motion", type: "generic", width: 6, height: 4){
tileAttribute ("device.motion", key: "PRIMARY_CONTROL") {
attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0"
attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff"
attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00a0dc"
attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc"
}
}
valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) {

View File

@@ -59,8 +59,8 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name:"motion", type: "generic", width: 6, height: 4){
tileAttribute ("device.motion", key: "PRIMARY_CONTROL") {
attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0"
attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff"
attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00a0dc"
attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc"
}
}
valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) {

View File

@@ -53,7 +53,7 @@ metadata {
// tile definitions
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC"
state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
}
valueTile("power", "device.power", decoration: "flat") {

View File

@@ -42,8 +42,8 @@ metadata {
tiles {
standardTile("presence", "device.presence", width: 2, height: 2, canChangeBackground: true) {
state "present", labelIcon:"st.presence.tile.present", backgroundColor:"#53a7c0"
state "not present", labelIcon:"st.presence.tile.not-present", backgroundColor:"#ebeef2"
state "present", labelIcon:"st.presence.tile.present", backgroundColor:"#00a0dc"
state "not present", labelIcon:"st.presence.tile.not-present", backgroundColor:"#ffffff"
}
standardTile("beep", "device.beep", decoration: "flat") {
state "beep", label:'', action:"tone.beep", icon:"st.secondary.beep", backgroundColor:"#ffffff"

View File

@@ -67,10 +67,10 @@ metadata {
}
standardTile("switch", "device.switch", width: 1, height: 1, canChangeIcon: true) {
state "on", label: '${name}', action: "forceOff", icon: "st.Electronics.electronics16", backgroundColor: "#79b821", nextState:"turningOff"
state "on", label: '${name}', action: "forceOff", icon: "st.Electronics.electronics16", backgroundColor: "#00a0dc", nextState:"turningOff"
state "turningOff", label:'TURNING OFF', icon:"st.Electronics.electronics16", backgroundColor:"#ffffff"
state "off", label: '${name}', action: "forceOn", icon: "st.Electronics.electronics16", backgroundColor: "#ffffff", nextState:"turningOn"
state "turningOn", label:'TURNING ON', icon:"st.Electronics.electronics16", backgroundColor:"#79b821"
state "turningOn", label:'TURNING ON', icon:"st.Electronics.electronics16", backgroundColor:"#00a0dc"
}
valueTile("1", "device.station1", decoration: "flat", canChangeIcon: false) {
state "station1", label:'${currentValue}', action:"preset1"

View File

@@ -81,13 +81,13 @@ metadata {
state "fanCirculate", label:'${name}', action:"switchFanMode"
}
controlTile("heatSliderControl", "device.heatingSetpoint", "slider", height: 1, width: 2, inactiveLabel: false) {
state "setHeatingSetpoint", action:"quickSetHeat", backgroundColor:"#d04e00"
state "setHeatingSetpoint", action:"quickSetHeat", backgroundColor:"#e86d13"
}
valueTile("heatingSetpoint", "device.heatingSetpoint", inactiveLabel: false, decoration: "flat") {
state "heat", label:'${currentValue}° heat', backgroundColor:"#ffffff"
}
controlTile("coolSliderControl", "device.coolingSetpoint", "slider", height: 1, width: 2, inactiveLabel: false) {
state "setCoolingSetpoint", action:"quickSetCool", backgroundColor: "#1e9cbb"
state "setCoolingSetpoint", action:"quickSetCool", backgroundColor: "#00a0dc"
}
valueTile("coolingSetpoint", "device.coolingSetpoint", inactiveLabel: false, decoration: "flat") {
state "cool", label:'${currentValue}° cool', backgroundColor:"#ffffff"

View File

@@ -53,7 +53,7 @@ metadata {
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "on", action:"switch.off", icon:"st.vents.vent-open-text", backgroundColor:"#53a7c0"
state "on", action:"switch.off", icon:"st.vents.vent-open-text", backgroundColor:"#00a0dc"
state "off", action:"switch.on", icon:"st.vents.vent-closed", backgroundColor:"#ffffff"
}
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {

View File

@@ -56,9 +56,9 @@ metadata {
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff"
state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00a0dc", nextState:"turningOff"
state "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
state "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff"
state "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00a0dc", nextState:"turningOff"
state "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
}
standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") {

View File

@@ -1,12 +1,12 @@
/**
* Device Type Definition File
*
* Device Type: Fibaro Flood Sensor
* File Name: fibaro-flood-sensor.groovy
* Initial Release: 2014-12-10
* @author: Todd Wackford
* Email: todd@wackford.net
* @version: 1.0
* Device Type: Fibaro Flood Sensor
* File Name: fibaro-flood-sensor.groovy
* Initial Release: 2014-12-10
* @author: Todd Wackford
* Email: todd@wackford.net
* @version: 1.0
*
* Copyright 2014 SmartThings
*
@@ -26,8 +26,8 @@
* not displayed to the user. We do this so we can receive events and display on device
* activity. If the user wants to display the tamper tile, adjust the tile display lines
* with the following:
* main(["water", "temperature", "tamper"])
* details(["water", "temperature", "battery", "tamper"])
* main(["water", "temperature", "tamper"])
* details(["water", "temperature", "battery", "tamper"])
*
* @param none
*
@@ -39,13 +39,18 @@ metadata {
capability "Temperature Measurement"
capability "Configuration"
capability "Battery"
command "resetParams2StDefaults"
command "listCurrentParams"
command "updateZwaveParam"
command "test"
capability "Health Check"
capability "Sensor"
command "resetParams2StDefaults"
command "listCurrentParams"
command "updateZwaveParam"
command "test"
fingerprint deviceId: "0xA102", inClusters: "0x30,0x9C,0x60,0x85,0x8E,0x72,0x70,0x86,0x80,0x84"
fingerprint mfr:"010F", prod:"0000", model:"2002"
fingerprint mfr:"010F", prod:"0000", model:"1002"
fingerprint mfr:"010F", prod:"0B00", model:"1001"
}
simulator {
@@ -72,7 +77,7 @@ metadata {
tiles {
standardTile("water", "device.water", width: 2, height: 2) {
state "dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff"
state "wet", icon:"st.alarm.water.wet", backgroundColor:"#53a7c0"
state "wet", icon:"st.alarm.water.wet", backgroundColor:"#00a0dc"
}
valueTile("temperature", "device.temperature", inactiveLabel: false) {
state "temperature", label:'${currentValue}°',
@@ -86,9 +91,9 @@ metadata {
[value: 96, color: "#bc2323"]
]
}
standardTile("tamper", "device.tamper") {
state("secure", label:"secure", icon:"st.locks.lock.locked", backgroundColor:"#ffffff")
state("tampered", label:"tampered", icon:"st.locks.lock.unlocked", backgroundColor:"#53a7c0")
standardTile("tamper", "device.tamper") {
state("secure", label:"secure", icon:"st.locks.lock.locked", backgroundColor:"#ffffff")
state("tampered", label:"tampered", icon:"st.locks.lock.unlocked", backgroundColor:"#00a0dc")
}
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
state "battery", label:'${currentValue}% battery', unit:""
@@ -106,26 +111,17 @@ metadata {
def parse(String description)
{
def result = []
if (description == "updated") {
if (!state.MSR) {
result << response(zwave.wakeUpV1.wakeUpIntervalSet(seconds: 60*60, nodeid:zwaveHubNodeId))
result << response(zwave.manufacturerSpecificV2.manufacturerSpecificGet())
}
} else {
def cmd = zwave.parse(description, [0x31: 2, 0x30: 1, 0x70: 2, 0x71: 1, 0x84: 1, 0x80: 1, 0x9C: 1, 0x72: 2, 0x56: 2, 0x60: 3])
if (cmd) {
result += zwaveEvent(cmd) //createEvent(zwaveEvent(cmd))
}
}
result << response(zwave.batteryV1.batteryGet().format())
if ( result[0] != null ) {
def cmd = zwave.parse(description, [0x31: 2, 0x30: 1, 0x70: 2, 0x71: 1, 0x84: 1, 0x80: 1, 0x9C: 1, 0x72: 2, 0x56: 2, 0x60: 3])
if (cmd) {
result += zwaveEvent(cmd) //createEvent(zwaveEvent(cmd))
}
if ( result[0] != null ) {
log.debug "Parse returned ${result}"
result
}
}
}
@@ -142,10 +138,9 @@ def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd) {
def result = [createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)]
if (!isConfigured()) {
// we're still in the process of configuring a newly joined device
result += lateConfigure(true)
result << lateConfigure(true)
} else {
result += response(zwave.wakeUpV1.wakeUpNoMoreInformation())
log.debug "We're done with WakeUp!"
result << response(zwave.wakeUpV1.wakeUpNoMoreInformation())
}
result
}
@@ -153,7 +148,7 @@ def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd) {
def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv2.SensorMultilevelReport cmd)
{
def map = [:]
switch (cmd.sensorType) {
case 1:
// temperature
@@ -184,7 +179,7 @@ def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv1.SensorBinaryReport cm
def map = [:]
map.value = cmd.sensorValue ? "active" : "inactive"
map.name = "acceleration"
if (map.value == "active") {
map.descriptionText = "$device.displayName detected vibration"
}
@@ -199,49 +194,49 @@ def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
log.debug "BasicSet with CMD = ${cmd}"
if (!isConfigured()) {
def result = []
def map = [:]
map.name = "water"
log.debug "BasicSet with CMD = ${cmd}"
if (!isConfigured()) {
def result = []
def map = [:]
map.name = "water"
map.value = cmd.value ? "wet" : "dry"
map.descriptionText = "${device.displayName} is ${map.value}"
// If we are getting a BasicSet, and isConfigured == false, then we are likely NOT properly configured.
result += lateConfigure(true)
result << createEvent(map)
result
}
// If we are getting a BasicSet, and isConfigured == false, then we are likely NOT properly configured.
result += lateConfigure(true)
result << createEvent(map)
result
}
}
def zwaveEvent(physicalgraph.zwave.commands.sensoralarmv1.SensorAlarmReport cmd)
{
def map = [:]
if (cmd.sensorType == 0x05) {
map.name = "water"
map.value = cmd.sensorState ? "wet" : "dry"
map.descriptionText = "${device.displayName} is ${map.value}"
log.debug "CMD = SensorAlarmReport: ${cmd}"
setConfigured()
} else if ( cmd.sensorType == 0) {
map.name = "tamper"
map.isStateChange = true
map.value = cmd.sensorState ? "tampered" : "secure"
map.descriptionText = "${device.displayName} has been tampered with"
runIn(30, "resetTamper") //device does not send alarm cancelation
} else if ( cmd.sensorType == 1) {
map.name = "tamper"
map.value = cmd.sensorState ? "tampered" : "secure"
map.descriptionText = "${device.displayName} has been tampered with"
runIn(30, "resetTamper") //device does not send alarm cancelation
log.debug "CMD = SensorAlarmReport: ${cmd}"
setConfigured()
} else if ( cmd.sensorType == 0) {
map.name = "tamper"
map.isStateChange = true
map.value = cmd.sensorState ? "tampered" : "secure"
map.descriptionText = "${device.displayName} has been tampered with"
runIn(30, "resetTamper") //device does not send alarm cancelation
} else if ( cmd.sensorType == 1) {
map.name = "tamper"
map.value = cmd.sensorState ? "tampered" : "secure"
map.descriptionText = "${device.displayName} has been tampered with"
runIn(30, "resetTamper") //device does not send alarm cancelation
} else {
map.descriptionText = "${device.displayName}: ${cmd}"
}
@@ -250,10 +245,10 @@ def zwaveEvent(physicalgraph.zwave.commands.sensoralarmv1.SensorAlarmReport cmd)
def resetTamper() {
def map = [:]
map.name = "tamper"
map.value = "secure"
map.descriptionText = "$device.displayName is secure"
sendEvent(map)
map.name = "tamper"
map.value = "secure"
map.descriptionText = "$device.displayName is secure"
sendEvent(map)
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
@@ -267,10 +262,10 @@ def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerS
def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
log.debug "msr: $msr"
device.updateDataValue(["MSR", msr])
if ( msr == "010F-0B00-2001" ) { //this is the msr and device type for the fibaro flood sensor
result += lateConfigure(true)
}
if ( msr == "010F-0B00-2001" ) { //this is the msr and device type for the fibaro flood sensor
result += lateConfigure(true)
}
result << createEvent(descriptionText: "$device.displayName MSR: $msr", isStateChange: false)
result
@@ -282,17 +277,17 @@ def setConfigured() {
def isConfigured() {
Boolean configured = device.getDataValue(["configured"]) as Boolean
return configured
return configured
}
def lateConfigure(setConf = False) {
def res = response(configure())
if (setConf)
setConfigured()
return res
if (setConf)
setConfigured()
return res
}
/**
@@ -304,26 +299,34 @@ def lateConfigure(setConf = False) {
*/
def configure() {
log.debug "Configuring Device..."
def cmds = []
// send associate to group 2 to get alarm data
cmds << zwave.associationV2.associationSet(groupingIdentifier:2, nodeId:[zwaveHubNodeId]).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [255], parameterNumber: 5, size: 1).format()
// send associate to group 3 to get sensor data reported only to hub
cmds << zwave.associationV2.associationSet(groupingIdentifier:3, nodeId:[zwaveHubNodeId]).format()
// Device wakes up every 4 hours, this interval allows us to miss one wakeup notification before marking offline
sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
// temp hysteresis set to .5 degrees celcius
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,50], parameterNumber: 12, size: 2).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 12).format()
// default initial state
sendEvent(name: "water", value: "dry")
def cmds = []
// send associate to group 2 to get alarm data
cmds << zwave.associationV2.associationSet(groupingIdentifier:2, nodeId:[zwaveHubNodeId]).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [255], parameterNumber: 5, size: 1).format()
// send associate to group 3 to get sensor data reported only to hub
cmds << zwave.associationV2.associationSet(groupingIdentifier:3, nodeId:[zwaveHubNodeId]).format()
// reporting frequency of temps and battery set to one hour
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,60*60], parameterNumber: 10, size: 2).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 10).format()
cmds << zwave.wakeUpV1.wakeUpNoMoreInformation().format()
// cmds << zwave.configurationV1.configurationGet(parameterNumber: 10).format()
// temp hysteresis set to .5 degrees celcius
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,50], parameterNumber: 12, size: 2).format()
// cmds << zwave.configurationV1.configurationGet(parameterNumber: 12).format()
cmds << zwave.batteryV1.batteryGet().format()
cmds << zwave.wakeUpV1.wakeUpNoMoreInformation().format()
delayBetween(cmds, 100)
}
@@ -349,18 +352,18 @@ def test() {
* @return none
*/
def updateZwaveParam(params) {
if ( params ) {
def pNumber = params.paramNumber
def pSize = params.size
def pValue = [params.value]
log.debug "Make sure device is awake and in recieve mode (triple-click?)"
log.debug "Updating ${device.displayName} parameter number '${pNumber}' with value '${pValue}' with size of '${pSize}'"
if ( params ) {
def pNumber = params.paramNumber
def pSize = params.size
def pValue = [params.value]
log.debug "Make sure device is awake and in recieve mode (triple-click?)"
log.debug "Updating ${device.displayName} parameter number '${pNumber}' with value '${pValue}' with size of '${pSize}'"
def cmds = []
cmds << zwave.configurationV1.configurationSet(configurationValue: pValue, parameterNumber: pNumber, size: pSize).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: pNumber).format()
delayBetween(cmds, 1000)
}
cmds << zwave.configurationV1.configurationSet(configurationValue: pValue, parameterNumber: pNumber, size: pSize).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: pNumber).format()
delayBetween(cmds, 1000)
}
}
/**
@@ -377,26 +380,26 @@ def updateZwaveParam(params) {
def resetParams2StDefaults() {
log.debug "Resetting ${device.displayName} parameters to SmartThings compatible defaults"
def cmds = []
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 1, size: 2).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [3], parameterNumber: 2, size: 1).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [255], parameterNumber: 5, size: 1).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [255], parameterNumber: 7, size: 1).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 9, size: 1).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,60*60], parameterNumber: 10, size: 2).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,50], parameterNumber: 12, size: 2).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 13, size: 1).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [5,220], parameterNumber: 50, size: 2).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [13,172], parameterNumber: 51, size: 2).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0,0,225], parameterNumber: 61, size: 4).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,255,0,0], parameterNumber: 62, size: 4).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 63, size: 1).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 73, size: 2).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 74, size: 1).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 75, size: 2).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 76, size: 2).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 77, size: 1).format()
delayBetween(cmds, 1200)
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 1, size: 2).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [3], parameterNumber: 2, size: 1).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [255], parameterNumber: 5, size: 1).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [255], parameterNumber: 7, size: 1).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 9, size: 1).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,60*60], parameterNumber: 10, size: 2).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,50], parameterNumber: 12, size: 2).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 13, size: 1).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [5,220], parameterNumber: 50, size: 2).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [13,172], parameterNumber: 51, size: 2).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0,0,225], parameterNumber: 61, size: 4).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,255,0,0], parameterNumber: 62, size: 4).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 63, size: 1).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 73, size: 2).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 74, size: 1).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 75, size: 2).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 76, size: 2).format()
cmds << zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 77, size: 1).format()
delayBetween(cmds, 1200)
}
/**
@@ -413,25 +416,25 @@ def resetParams2StDefaults() {
def listCurrentParams() {
log.debug "Listing of current parameter settings of ${device.displayName}"
def cmds = []
cmds << zwave.configurationV1.configurationGet(parameterNumber: 1).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 2).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 5).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 7).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 9).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 10).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 12).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 13).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 50).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 51).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 61).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 62).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 63).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 73).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 74).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 75).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 76).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 77).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 1).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 2).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 5).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 7).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 9).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 10).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 12).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 13).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 50).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 51).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 61).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 62).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 63).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 73).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 74).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 75).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 76).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: 77).format()
delayBetween(cmds, 1200)
}

View File

@@ -46,6 +46,7 @@
capability "Illuminance Measurement"
capability "Sensor"
capability "Battery"
capability "Health Check"
command "resetParams2StDefaults"
command "listCurrentParams"
@@ -81,8 +82,8 @@
tiles {
standardTile("motion", "device.motion", width: 2, height: 2) {
state "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0"
state "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff"
state "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00a0dc"
state "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc"
}
valueTile("temperature", "device.temperature", inactiveLabel: false) {
state "temperature", label:'${currentValue}°',
@@ -125,6 +126,9 @@
*/
def configure() {
log.debug "Configuring Device For SmartThings Use"
// Device-Watch simply pings if no device events received for 8 hrs & 2 minutes
sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
def cmds = []
// send associate to group 3 to get sensor data reported only to hub

View File

@@ -39,8 +39,8 @@ metadata {
tiles {
standardTile("motion", "device.motion", width: 2, height: 2) {
state "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0"
state "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff"
state "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC"
state "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc"
}
valueTile("temperature", "device.temperature", inactiveLabel: false) {
state "temperature", label:'${currentValue}°',

View File

@@ -21,6 +21,7 @@ metadata {
capability "Configuration"
capability "Battery"
capability "Refresh"
capability "Sensor"
command "enrollResponse"
@@ -31,8 +32,8 @@ metadata {
tiles {
standardTile("motion", "device.motion", width: 2, height: 2) {
state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0")
state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff")
state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC")
state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc")
}
valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false) {

View File

@@ -24,6 +24,7 @@ metadata {
capability "Contact Sensor"
capability "Refresh"
capability "Health Check"
capability "Sensor"
command "enrollResponse"
@@ -41,8 +42,8 @@ metadata {
tiles {
standardTile("contact", "device.contact", width: 2, height: 2) {
state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e")
state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821")
state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#e86d13")
state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00a0dc")
}
valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false) {

View File

@@ -33,6 +33,7 @@ metadata {
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315"
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-Seu", deviceJoinName: "Water Leak Sensor"
fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-L", deviceJoinName: "Iris Smart Water Sensor"
fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-G", deviceJoinName: "Centralite Water Sensor"
fingerprint inClusters: "0000,0001,0003,000F,0020,0402,0500", outClusters: "0019", manufacturer: "SmartThings", model: "moisturev4", deviceJoinName: "Water Leak Sensor"
}
@@ -58,7 +59,7 @@ metadata {
multiAttributeTile(name: "water", type: "generic", width: 6, height: 4) {
tileAttribute("device.water", key: "PRIMARY_CONTROL") {
attributeState "dry", label: "Dry", icon: "st.alarm.water.dry", backgroundColor: "#ffffff"
attributeState "wet", label: "Wet", icon: "st.alarm.water.wet", backgroundColor: "#53a7c0"
attributeState "wet", label: "Wet", icon: "st.alarm.water.wet", backgroundColor: "#00A0DC"
}
}
valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) {

View File

@@ -34,6 +34,7 @@ metadata {
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3325"
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3326"
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3326-L", deviceJoinName: "Iris Motion Sensor"
fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3328-G", deviceJoinName: "Centralite Micro Motion Sensor"
fingerprint inClusters: "0000,0001,0003,000F,0020,0402,0500", outClusters: "0019", manufacturer: "SmartThings", model: "motionv4", deviceJoinName: "Motion Sensor"
fingerprint inClusters: "0000,0001,0003,000F,0020,0402,0500", outClusters: "0019", manufacturer: "SmartThings", model: "motionv5", deviceJoinName: "Motion Sensor"
}

View File

@@ -30,8 +30,8 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name:"motion", type: "generic", width: 6, height: 4){
tileAttribute ("device.motion", key: "PRIMARY_CONTROL") {
attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0"
attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff"
attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC"
attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc"
}
}
valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {

View File

@@ -33,6 +33,7 @@ metadata {
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: "3321"
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05,FC02", outClusters: "0019", manufacturer: "CentraLite", model: "3321-S", deviceJoinName: "Multipurpose Sensor"
fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3323-G", deviceJoinName: "Centralite Micro Door Sensor"
fingerprint inClusters: "0000,0001,0003,000F,0020,0402,0500,FC02", outClusters: "0019", manufacturer: "SmartThings", model: "multiv4", deviceJoinName: "Multipurpose Sensor"
attribute "status", "string"

View File

@@ -52,14 +52,14 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4){
tileAttribute ("device.contact", key: "PRIMARY_CONTROL") {
attributeState "open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e"
attributeState "closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821"
attributeState "open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"##e86d13"
attributeState "closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00a0dc"
}
}
standardTile("acceleration", "device.acceleration", width: 2, height: 2) {
state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#53a7c0")
state("inactive", label:'${name}', icon:"st.motion.acceleration.inactive", backgroundColor:"#ffffff")
state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#00a0dc")
state("inactive", label:'${name}', icon:"st.motion.acceleration.inactive", backgroundColor:"#cccccc")
}
valueTile("temperature", "device.temperature", width: 2, height: 2) {
state("temperature", label:'${currentValue}°',

View File

@@ -45,8 +45,8 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name: "contact", type: "generic", width: 6, height: 4) {
tileAttribute("device.contact", key: "PRIMARY_CONTROL") {
attributeState "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
attributeState "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#79b821"
attributeState "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#e86d13"
attributeState "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#00A0DC"
}
}

View File

@@ -41,8 +41,8 @@ metadata {
tiles {
standardTile("contact", "device.contact", width: 2, height: 2) {
state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e")
state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821")
state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#e86d13")
state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00A0DC")
}
valueTile("temperature", "device.temperature", inactiveLabel: false) {

View File

@@ -44,7 +44,7 @@ metadata {
tiles {
standardTile("button", "device.button", width: 2, height: 2) {
state "default", label: "", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#ffffff"
state "button 1 pushed", label: "pushed #1", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#79b821"
state "button 1 pushed", label: "pushed #1", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#00A0DC"
}
valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false) {

View File

@@ -0,0 +1,169 @@
/**
* Copyright 2016 SmartThings
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
*/
import groovy.transform.Field
@Field Boolean hasConfiguredHealthCheck = false
metadata {
definition (name: "ZLL White Color Temperature Bulb 5000K", namespace: "smartthings", author: "SmartThings") {
capability "Actuator"
capability "Color Temperature"
capability "Configuration"
capability "Polling"
capability "Refresh"
capability "Switch"
capability "Switch Level"
capability "Health Check"
attribute "colorName", "string"
command "setGenericName"
fingerprint profileId: "C05E", deviceId: "0220", inClusters: "0000, 0004, 0003, 0006, 0008, 0005, 0300", outClusters: "0019", manufacturer: "Eaton", model: "Halo_LT01", deviceJoinName: "Halo RL56 Wireless"
}
// UI tile definitions
tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#00A0DC", nextState:"turningOff"
attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn"
attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#00A0DC", nextState:"turningOff"
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn"
}
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
attributeState "level", action:"switch level.setLevel"
}
tileAttribute ("colorName", key: "SECONDARY_CONTROL") {
attributeState "colorName", label:'${currentValue}'
}
}
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
}
controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2700..5000)") {
state "colorTemperature", action:"color temperature.setColorTemperature"
}
valueTile("colorTemp", "device.colorTemperature", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "colorTemperature", label: '${currentValue} K'
}
main(["switch"])
details(["switch", "colorTempSliderControl", "colorTemp", "refresh"])
}
}
// Parse incoming device messages to generate events
def parse(String description) {
log.debug "description is $description"
def event = zigbee.getEvent(description)
if (event) {
if (event.name == "colorTemperature") {
event.unit = "K"
}
sendEvent(event)
}
else {
log.warn "DID NOT PARSE MESSAGE for description : $description"
log.debug zigbee.parseDescriptionAsMap(description)
}
}
def off() {
zigbee.off() + ["delay 1500"] + zigbee.onOffRefresh()
}
def on() {
zigbee.on() + ["delay 1500"] + zigbee.onOffRefresh()
}
def setLevel(value) {
zigbee.setLevel(value) + zigbee.onOffRefresh() + zigbee.levelRefresh()
}
def refresh() {
def cmds = zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh()
// Do NOT config if the device is the Eaton Halo_LT01, it responds with "switch:off" to onOffConfig, and maybe other weird things with the others
if (!((device.getDataValue("manufacturer") == "Eaton") && (device.getDataValue("model") == "Halo_LT01"))) {
cmds = cmds + zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.colorTemperatureConfig()
}
cmds
}
def poll() {
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh()
}
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
return zigbee.levelRefresh()
}
def healthPoll() {
log.debug "healthPoll()"
def cmds = zigbee.onOffRefresh() + zigbee.levelRefresh()
cmds.each{ sendHubCommand(new physicalgraph.device.HubAction(it))}
}
def configureHealthCheck() {
Integer hcIntervalMinutes = 12
if (!hasConfiguredHealthCheck) {
log.debug "Configuring Health Check, Reporting"
unschedule("healthPoll")
runEvery5Minutes("healthPoll")
// Device-Watch allows 2 check-in misses from device
sendEvent(name: "checkInterval", value: hcIntervalMinutes * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
hasConfiguredHealthCheck = true
}
}
def configure() {
log.debug "configure()"
configureHealthCheck()
// Implementation note: for the Eaton Halo_LT01, it responds with "switch:off" to onOffConfig, so be sure this is before the call to onOffRefresh
zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh()
}
def updated() {
log.debug "updated()"
configureHealthCheck()
}
def setColorTemperature(value) {
setGenericName(value)
zigbee.setColorTemperature(value) + ["delay 1500"] + zigbee.colorTemperatureRefresh()
}
//Naming based on the wiki article here: http://en.wikipedia.org/wiki/Color_temperature
def setGenericName(value){
if (value != null) {
def genericName = ""
if (value < 3300) {
genericName = "Soft White"
} else if (value < 4150) {
genericName = "Moonlight"
} else if (value <= 5000) {
genericName = "Cool White"
} else {
genericName = "Daylight"
}
sendEvent(name: "colorName", value: genericName, displayed: false)
}
}

View File

@@ -40,7 +40,7 @@ metadata {
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "on", label: '${name}', action: "switch.off", icon: "st.unknown.zwave.device", backgroundColor: "#79b821"
state "on", label: '${name}', action: "switch.off", icon: "st.unknown.zwave.device", backgroundColor: "#00A0DC"
state "off", label: '${name}', action: "switch.on", icon: "st.unknown.zwave.device", backgroundColor: "#ffffff"
}
standardTile("switchOn", "device.switch", inactiveLabel: false, decoration: "flat") {

View File

@@ -33,7 +33,7 @@ metadata {
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "on", label: '${name}', action: "switch.off", icon: "st.unknown.zwave.device", backgroundColor: "#79b821"
state "on", label: '${name}', action: "switch.off", icon: "st.unknown.zwave.device", backgroundColor: "#00A0DC"
state "off", label: '${name}', action: "switch.on", icon: "st.unknown.zwave.device", backgroundColor: "#ffffff"
}
standardTile("switchOn", "device.switch", inactiveLabel: false, decoration: "flat") {

View File

@@ -41,8 +41,8 @@ metadata {
// UI tile definitions
tiles {
standardTile("contact", "device.contact", width: 2, height: 2) {
state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
state "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#79b821"
state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#e86d13"
state "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#00A0DC"
}
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
state "battery", label:'${currentValue}% battery', unit:""

View File

@@ -39,11 +39,11 @@ metadata {
tiles {
standardTile("toggle", "device.door", width: 2, height: 2) {
state("unknown", label:'${name}', action:"refresh.refresh", icon:"st.doors.garage.garage-open", backgroundColor:"#ffa81e")
state("closed", label:'${name}', action:"door control.open", icon:"st.doors.garage.garage-closed", backgroundColor:"#79b821", nextState:"opening")
state("open", label:'${name}', action:"door control.close", icon:"st.doors.garage.garage-open", backgroundColor:"#ffa81e", nextState:"closing")
state("opening", label:'${name}', icon:"st.doors.garage.garage-opening", backgroundColor:"#ffe71e")
state("closing", label:'${name}', icon:"st.doors.garage.garage-closing", backgroundColor:"#ffe71e")
state("unknown", label:'${name}', action:"refresh.refresh", icon:"st.doors.garage.garage-open", backgroundColor:"#ffffff")
state("closed", label:'${name}', action:"door control.open", icon:"st.doors.garage.garage-closed", backgroundColor:"#00a0dc", nextState:"opening")
state("open", label:'${name}', action:"door control.close", icon:"st.doors.garage.garage-open", backgroundColor:"#e86d13", nextState:"closing")
state("opening", label:'${name}', icon:"st.doors.garage.garage-opening", backgroundColor:"#e86d13")
state("closing", label:'${name}', icon:"st.doors.garage.garage-closing", backgroundColor:"#00a0dc")
}
standardTile("open", "device.door", inactiveLabel: false, decoration: "flat") {

View File

@@ -38,10 +38,10 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name:"toggle", type: "generic", width: 6, height: 4){
tileAttribute ("device.lock", key: "PRIMARY_CONTROL") {
attributeState "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#79b821", nextState:"unlocking"
attributeState "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#00A0DC", nextState:"unlocking"
attributeState "unlocked", label:'unlocked', action:"lock.lock", icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff", nextState:"locking"
attributeState "unknown", label:"unknown", action:"lock.lock", icon:"st.locks.lock.unknown", backgroundColor:"#ffffff", nextState:"locking"
attributeState "locking", label:'locking', icon:"st.locks.lock.locked", backgroundColor:"#79b821"
attributeState "locking", label:'locking', icon:"st.locks.lock.locked", backgroundColor:"#00A0DC"
attributeState "unlocking", label:'unlocking', icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff"
}
}

View File

@@ -51,7 +51,7 @@ metadata {
// tile definitions
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC"
state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
}
valueTile("power", "device.power") {

View File

@@ -38,8 +38,8 @@ metadata {
tiles {
standardTile("motion", "device.motion", width: 2, height: 2) {
state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0")
state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff")
state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC")
state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc")
}
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
state("battery", label:'${currentValue}% battery', unit:"")

View File

@@ -37,8 +37,8 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4){
tileAttribute ("device.contact", key: "PRIMARY_CONTROL") {
attributeState "open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e"
attributeState "closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821"
attributeState "open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#e86d13"
attributeState "closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00a0dc"
}
}
valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {

View File

@@ -32,8 +32,8 @@ metadata {
tiles {
standardTile("sensor", "device.sensor", width: 2, height: 2) {
state("inactive", label:'inactive', icon:"st.unknown.zwave.sensor", backgroundColor:"#ffffff")
state("active", label:'active', icon:"st.unknown.zwave.sensor", backgroundColor:"#53a7c0")
state("inactive", label:'inactive', icon:"st.unknown.zwave.sensor", backgroundColor:"#cccccc")
state("active", label:'active', icon:"st.unknown.zwave.sensor", backgroundColor:"#00A0DC")
}
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
state "battery", label:'${currentValue}% battery', unit:""

View File

@@ -47,7 +47,7 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC"
attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
}
}

View File

@@ -46,7 +46,7 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC"
attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
}
}

View File

@@ -33,7 +33,7 @@ metadata {
tiles {
standardTile("water", "device.water", width: 2, height: 2) {
state "dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff"
state "wet", icon:"st.alarm.water.wet", backgroundColor:"#53a7c0"
state "wet", icon:"st.alarm.water.wet", backgroundColor:"#00A0DC"
}
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
state "battery", label:'${currentValue}% battery', unit:""

View File

@@ -0,0 +1,794 @@
/**
* Gideon
*
* Copyright 2016 Nicola Russo
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
*/
definition(
name: "Gideon Smart Home",
namespace: "gideon.api",
author: "Braindrain Solutions ltd",
description: "Gideon Smart Home SmartApp allows you to connect and control all of your SmartThings devices through the Gideon app, making your SmartThings devices even smarter.",
category: "Family",
iconUrl: "http://s33.postimg.org/t77u7y7v3/logo.png",
iconX2Url: "http://s33.postimg.org/t77u7y7v3/logo.png",
iconX3Url: "http://s33.postimg.org/t77u7y7v3/logo.png",
oauth: [displayName: "Gideon Smart Home API app", displayLink: "gideon.ai"])
preferences {
section("Control these contact sensors...") {
input "contact", "capability.contactSensor", multiple:true, required:false
}
section("Control these switch levels...") {
input "switchlevels", "capability.switchLevel", multiple:true, required:false
}
/* section("Control these thermostats...") {
input "thermostats", "capability.thermostat", multiple:true, required:false
}*/
section("Control the color for these devices...") {
input "colors", "capability.colorControl", multiple:true, required:false
}
section("Control the color temperature for these devices...") {
input "kelvin", "capability.colorTemperature", multiple:true, required:false
}
section("Control these switches...") {
input "switches", "capability.switch", multiple:true, required:false
}
section("Control these smoke alarms...") {
input "smoke_alarms", "capability.smokeDetector", multiple:true, required:false
}
section("Control these window shades...") {
input "shades", "capability.windowShade", multiple:true, required:false
}
section("Control these garage doors...") {
input "garage", "capability.garageDoorControl", multiple:true, required:false
}
section("Control these water sensors...") {
input "water_sensors", "capability.waterSensor", multiple:true, required:false
}
section("Control these motion sensors...") {
input "motions", "capability.motionSensor", multiple:true, required:false
}
section("Control these presence sensors...") {
input "presence_sensors", "capability.presenceSensor", multiple:true, required:false
}
section("Control these outlets...") {
input "outlets", "capability.outlet", multiple:true, required:false
}
section("Control these power meters...") {
input "meters", "capability.powerMeter", multiple:true, required:false
}
section("Control these locks...") {
input "locks", "capability.lock", multiple:true, required:false
}
section("Control these temperature sensors...") {
input "temperature_sensors", "capability.temperatureMeasurement", multiple:true, required:false
}
section("Control these batteries...") {
input "batteries", "capability.battery", multiple:true, required:false
}
}
def installed() {
log.debug "Installed with settings: ${settings}"
initialize()
}
def updated() {
log.debug "Updated with settings: ${settings}"
unsubscribe()
initialize()
}
def initialize() {
}
private device(it, type) {
it ? [id: it.id, label: it.label, type: type] : null
}
//API Mapping
mappings {
path("/getalldevices") {
action: [
GET: "getAllDevices"
]
}
/*
path("/thermostat/setcool/:id/:temp") {
action: [
GET: "setCoolTemp"
]
}
path("/thermostat/setheat/:id/:temp") {
action: [
GET: "setHeatTemp"
]
}
path("/thermostat/setfanmode/:id/:mode") {
action: [
GET: "setFanMode"
]
}
path("/thermostat/setmode/:id/:mode") {
action: [
GET: "setThermostatMode"
]
}
path("/thermostat/:id") {
action: [
GET: "getThermostatStatus"
]
}
*/
path("/light/dim/:id/:dim") {
action: [
GET: "setLevelStatus"
]
}
path("/light/kelvin/:id/:kelvin") {
action: [
GET: "setKelvin"
]
}
path("/colorlight/:id/:hue/:sat") {
action: [
GET: "setColor"
]
}
path("/light/status/:id") {
action: [
GET: "getLightStatus"
]
}
path("/light/on/:id") {
action: [
GET: "turnOnLight"
]
}
path("/light/off/:id") {
action: [
GET: "turnOffLight"
]
}
path("/doorlocks/lock/:id") {
action: [
GET: "lockDoorLock"
]
}
path("/doorlocks/unlock/:id") {
action: [
GET: "unlockDoorLock"
]
}
path("/doorlocks/:id") {
action: [
GET: "getDoorLockStatus"
]
}
path("/contacts/:id") {
action: [
GET: "getContactStatus"
]
}
path("/smoke/:id") {
action: [
GET: "getSmokeStatus"
]
}
path("/shades/open/:id") {
action: [
GET: "openShade"
]
}
path("/shades/preset/:id") {
action: [
GET: "presetShade"
]
}
path("/shades/close/:id") {
action: [
GET: "closeShade"
]
}
path("/shades/:id") {
action: [
GET: "getShadeStatus"
]
}
path("/garage/open/:id") {
action: [
GET: "openGarage"
]
}
path("/garage/close/:id") {
action: [
GET: "closeGarage"
]
}
path("/garage/:id") {
action: [
GET: "getGarageStatus"
]
}
path("/watersensors/:id") {
action: [
GET: "getWaterSensorStatus"
]
}
path("/tempsensors/:id") {
action: [
GET: "getTempSensorsStatus"
]
}
path("/meters/:id") {
action: [
GET: "getMeterStatus"
]
}
path("/batteries/:id") {
action: [
GET: "getBatteryStatus"
]
}
path("/presences/:id") {
action: [
GET: "getPresenceStatus"
]
}
path("/motions/:id") {
action: [
GET: "getMotionStatus"
]
}
path("/outlets/:id") {
action: [
GET: "getOutletStatus"
]
}
path("/outlets/turnon/:id") {
action: [
GET: "turnOnOutlet"
]
}
path("/outlets/turnoff/:id") {
action: [
GET: "turnOffOutlet"
]
}
path("/switches/turnon/:id") {
action: [
GET: "turnOnSwitch"
]
}
path("/switches/turnoff/:id") {
action: [
GET: "turnOffSwitch"
]
}
path("/switches/:id") {
action: [
GET: "getSwitchStatus"
]
}
}
//API Methods
def getAllDevices() {
def locks_list = locks.collect{device(it,"Lock")}
/*def thermo_list = thermostats.collect{device(it,"Thermostat")}*/
def colors_list = colors.collect{device(it,"Color")}
def kelvin_list = kelvin.collect{device(it,"Kelvin")}
def contact_list = contact.collect{device(it,"Contact Sensor")}
def smokes_list = smoke_alarms.collect{device(it,"Smoke Alarm")}
def shades_list = shades.collect{device(it,"Window Shade")}
def garage_list = garage.collect{device(it,"Garage Door")}
def water_sensors_list = water_sensors.collect{device(it,"Water Sensor")}
def presences_list = presence_sensors.collect{device(it,"Presence")}
def motions_list = motions.collect{device(it,"Motion")}
def outlets_list = outlets.collect{device(it,"Outlet")}
def switches_list = switches.collect{device(it,"Switch")}
def switchlevels_list = switchlevels.collect{device(it,"Switch Level")}
def temp_list = temperature_sensors.collect{device(it,"Temperature")}
def meters_list = meters.collect{device(it,"Power Meters")}
def battery_list = batteries.collect{device(it,"Batteries")}
return outlets_list + kelvin_list + colors_list + switchlevels_list + smokes_list + contact_list + water_sensors_list + shades_list + garage_list + locks_list + presences_list + motions_list + switches_list + temp_list + meters_list + battery_list
}
//thermostat
/*
def setCoolTemp() {
def device = thermostats.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
if(device.hasCommand("setCoolingSetpoint")) {
device.setCoolingSetpoint(params.temp.toInteger());
return [result_action: "200"]
}
else {
httpError(510, "Not supported!")
}
}
}
def setHeatTemp() {
def device = thermostats.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
if(device.hasCommand("setHeatingSetpoint")) {
device.setHeatingSetpoint(params.temp.toInteger());
return [result_action: "200"]
}
else {
httpError(510, "Not supported!")
}
}
}
def setFanMode() {
def device = thermostats.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
if(device.hasCommand("setThermostatFanMode")) {
device.setThermostatFanMode(params.mode);
return [result_action: "200"]
}
else {
httpError(510, "Not supported!")
}
}
}
def setThermostatMode() {
def device = thermostats.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
if(device.hasCommand("setThermostatMode")) {
device.setThermostatMode(params.mode);
return [result_action: "200"]
}
else {
httpError(510, "Not supported!")
}
}
}
def getThermostatStatus() {
def device = thermostats.find{ it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
return [ThermostatOperatingState: device.currentValue('thermostatOperatingState'), ThermostatSetpoint: device.currentValue('thermostatSetpoint'),
ThermostatFanMode: device.currentValue('thermostatFanMode'), ThermostatMode: device.currentValue('thermostatMode')]
}
}
*/
//light
def turnOnLight() {
def device = switches.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.on();
return [Device_id: params.id, result_action: "200"]
}
}
def turnOffLight() {
def device = switches.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.off();
return [Device_id: params.id, result_action: "200"]
}
}
def getLightStatus() {
def device = switches.find{ it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
return [Status: device.currentValue('switch'), Dim: getLevelStatus(params.id), Color: getColorStatus(params.id), Kelvin: getKelvinStatus(params.id)]
}
}
//color control
def setColor() {
def device = colors.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
def map = [hue:params.hue.toInteger(), saturation:params.sat.toInteger()]
device.setColor(map);
return [Device_id: params.id, result_action: "200"]
}
}
def getColorStatus(id) {
def device = colors.find { it.id == id }
if (!device) {
return [Color: "none"]
} else {
return [hue: device.currentValue('hue'), saturation: device.currentValue('saturation')]
}
}
//kelvin control
def setKelvin() {
def device = kelvin.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.setColorTemperature(params.kelvin.toInteger());
return [Device_id: params.id, result_action: "200"]
}
}
def getKelvinStatus(id) {
def device = kelvin.find { it.id == id }
if (!device) {
return [kelvin: "none"]
} else {
return [kelvin: device.currentValue('colorTemperature')]
}
}
//switch level
def getLevelStatus() {
def device = switchlevels.find { it.id == params.id }
if (!device) {
[Level: "No dimmer"]
} else {
return [Level: device.currentValue('level')]
}
}
def getLevelStatus(id) {
def device = switchlevels.find { it.id == id }
if (!device) {
[Level: "No dimmer"]
} else {
return [Level: device.currentValue('level')]
}
}
def setLevelStatus() {
def device = switchlevels.find { it.id == params.id }
def level = params.dim
if (!device) {
httpError(404, "Device not found")
} else {
device.setLevel(level.toInteger())
return [result_action: "200", Level: device.currentValue('level')]
}
}
//contact sensors
def getContactStatus() {
def device = contact.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
def args = getTempSensorsStatus(device.id)
return [Device_state: device.currentValue('contact')] + args
}
}
//smoke detectors
def getSmokeStatus() {
def device = smoke_alarms.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
def bat = getBatteryStatus(device.id)
return [Device_state: device.currentValue('smoke')] + bat
}
}
//garage
def getGarageStatus() {
def device = garage.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
return [Device_state: device.currentValue('door')]
}
}
def openGarage() {
def device = garage.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.open();
return [Device_id: params.id, result_action: "200"]
}
}
def closeGarage() {
def device = garage.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.close();
return [Device_id: params.id, result_action: "200"]
}
}
//shades
def getShadeStatus() {
def device = shades.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
return [Device_state: device.currentValue('windowShade')]
}
}
def openShade() {
def device = shades.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.open();
return [Device_id: params.id, result_action: "200"]
}
}
def presetShade() {
def device = shades.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.presetPosition();
return [Device_id: params.id, result_action: "200"]
}
}
def closeShade() {
def device = shades.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.close();
return [Device_id: params.id, result_action: "200"]
}
}
//water sensor
def getWaterSensorStatus() {
def device = water_sensors.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
def bat = getBatteryStatus(device.id)
return [Device_state: device.currentValue('water')] + bat
}
}
//batteries
def getBatteryStatus() {
def device = batteries.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
return [Device_state: device.latestValue("battery")]
}
}
def getBatteryStatus(id) {
def device = batteries.find { it.id == id }
if (!device) {
return []
} else {
return [battery_state: device.latestValue("battery")]
}
}
//LOCKS
def getDoorLockStatus() {
def device = locks.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
def bat = getBatteryStatus(device.id)
return [Device_state: device.currentValue('lock')] + bat
}
}
def lockDoorLock() {
def device = locks.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.lock();
return [Device_id: params.id, result_action: "200"]
}
}
def unlockDoorLock() {
def device = locks.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.unlock();
return [Device_id: params.id, result_action: "200"]
}
}
//PRESENCE
def getPresenceStatus() {
def device = presence_sensors.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
def bat = getBatteryStatus(device.id)
return [Device_state: device.currentValue('presence')] + bat
}
}
//MOTION
def getMotionStatus() {
def device = motions.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
def args = getTempSensorsStatus(device.id)
return [Device_state: device.currentValue('motion')] + args
}
}
//OUTLET
def getOutletStatus() {
def device = outlets.find { it.id == params.id }
if (!device) {
device = switches.find { it.id == params.id }
if(!device) {
httpError(404, "Device not found")
}
}
def watt = getMeterStatus(device.id)
return [Device_state: device.currentValue('switch')] + watt
}
def getMeterStatus() {
def device = meters.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
return [Device_id: device.id, Device_type: device.type, Current_watt: device.currentValue("power")]
}
}
def getMeterStatus(id) {
def device = meters.find { it.id == id }
if (!device) {
return []
} else {
return [Current_watt: device.currentValue("power")]
}
}
def turnOnOutlet() {
def device = outlets.find { it.id == params.id }
if (!device) {
device = switches.find { it.id == params.id }
if(!device) {
httpError(404, "Device not found")
}
}
device.on();
return [Device_id: params.id, result_action: "200"]
}
def turnOffOutlet() {
def device = outlets.find { it.id == params.id }
if (!device) {
device = switches.find { it.id == params.id }
if(!device) {
httpError(404, "Device not found")
}
}
device.off();
return [Device_id: params.id, result_action: "200"]
}
//SWITCH
def getSwitchStatus() {
def device = switches.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
return [Device_state: device.currentValue('switch'), Dim: getLevelStatus(params.id)]
}
}
def turnOnSwitch() {
def device = switches.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.on();
return [Device_id: params.id, result_action: "200"]
}
}
def turnOffSwitch() {
def device = switches.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device.off();
return [Device_id: params.id, result_action: "200"]
}
}
//TEMPERATURE
def getTempSensorsStatus() {
def device = temperature_sensors.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
def bat = getBatteryStatus(device.id)
def scale = [Scale: location.temperatureScale]
return [Device_state: device.currentValue('temperature')] + scale + bat
}
}
def getTempSensorsStatus(id) {
def device = temperature_sensors.find { it.id == id }
if (!device) {
return []
} else {
def bat = getBatteryStatus(device.id)
return [temperature: device.currentValue('temperature')] + bat
}
}

View File

@@ -39,7 +39,7 @@ definition(
* garageDoors | door | open, close | unknown, closed, open, closing, opening
* cameras | image | take | <String>
* thermostats | thermostat | setHeatingSetpoint, | temperature, heatingSetpoint, coolingSetpoint,
* | | setCoolingSetpoint, | thermostatSetpoint, thermostatMode,
* | | setCoolingSetpoint, | thermostatSetpoint, thermostatMode,
* | | off, heat, cool, auto,| thermostatFanMode, thermostatOperatingState
* | | emergencyHeat, |
* | | setThermostatMode, |
@@ -55,7 +55,7 @@ preferences {
input "contactSensors", "capability.contactSensor", title: "Which Contact Sensors", multiple: true, required: false
input "garageDoors", "capability.garageDoorControl", title: "Which Garage Doors?", multiple: true, required: false
input "locks", "capability.lock", title: "Which Locks?", multiple: true, required: false
input "cameras", "capability.videoCapture", title: "Which Cameras?", multiple: true, required: false
input "cameras", "capability.videoCapture", title: "Which Cameras?", multiple: true, required: false
input "motionSensors", "capability.motionSensor", title: "Which Motion Sensors?", multiple: true, required: false
input "presenceSensors", "capability.presenceSensor", title: "Which Presence Sensors", multiple: true, required: false
input "switches", "capability.switch", title: "Which Switches and Lights?", multiple: true, required: false
@@ -66,54 +66,48 @@ preferences {
def getInputs() {
def inputList = []
inputList += contactSensors ?: []
inputList += garageDoors ?: []
inputList += locks ?: []
inputList += cameras ?: []
inputList += motionSensors ?: []
inputList += presenceSensors ?: []
inputList += switches ?: []
inputList += thermostats ?: []
inputList += waterSensors ?: []
inputList += contactSensors?: []
inputList += garageDoors?: []
inputList += locks?: []
inputList += cameras?: []
inputList += motionSensors?: []
inputList += presenceSensors?: []
inputList += switches?: []
inputList += thermostats?: []
inputList += waterSensors?: []
return inputList
}
//API external Endpoints
mappings {
path("/subscriptionURL/:url") {
action:
[
action: [
PUT: "updateEndpointURL"
]
}
path("/connectionId/:connId") {
action:
[
action: [
PUT: "updateConnectionId"
]
}
path("/devices") {
action:
[
action: [
GET: "getDevices"
]
}
path("/devices/:id") {
action:
[
action: [
GET: "getDevice"
]
}
path("/update/:id") {
action:
[
action: [
PUT: "updateDevice"
]
}
path("/subscription/:id") {
action:
[
POST : "registerDeviceChange",
action: [
POST: "registerDeviceChange",
DELETE: "unregisterDeviceChange"
]
}
@@ -145,7 +139,7 @@ def registerSubscriptions() {
def registerChangeHandler(myList) {
myList.each { myDevice ->
def theAtts = myDevice.supportedAttributes
theAtts.each { att ->
theAtts.each {att ->
subscribe(myDevice, att.name, eventHandler)
log.info "Registering ${myDevice.displayName}.${att.name}"
}
@@ -157,7 +151,7 @@ def registerDeviceChange() {
def myDevice = findDevice(params.id)
def theAtts = myDevice.supportedAttributes
try {
theAtts.each { att ->
theAtts.each {att ->
subscribe(myDevice, att.name, eventHandler)
log.info "Registering ${myDevice.displayName}.${att.name}"
}
@@ -186,16 +180,20 @@ def eventHandler(evt) {
def evt_name = evt.name
def evt_device = evt.device
def evt_deviceType = getDeviceType(evt_device);
def deviceInfo
if(evt_deviceType == "thermostat")
{
deviceInfo = [name: evt_device.displayName, id: evt_device.id, status:evt_device.getStatus(), deviceType:evt_deviceType, manufacturer:evt_device.getManufacturerName(), model:evt_device.getModelName(), attributes: deviceAttributeList(evt_device), locationMode: getLocationModeInfo()]
}
else
{
deviceInfo = [name: evt_device.displayName, id: evt_device.id, status:evt_device.getStatus(), deviceType:evt_deviceType, manufacturer:evt_device.getManufacturerName(), model:evt_device.getModelName(), attributes: deviceAttributeList(evt_device)]
}
def params = [
uri : "${state.endpointURL}/${state.connectionId}",
body: [
name : evt_device.displayName,
id : evt_device.id,
deviceType : evt_deviceType,
manufacturer: evt_device.getManufacturerName(),
model : evt_device.getModelName(),
attributes : deviceAttributeList(evt_device)
]
uri: "${state.endpointURL}/${state.connectionId}",
body: [ deviceInfo ]
]
try {
log.trace "POST URI: ${params.uri}"
@@ -230,10 +228,13 @@ def getDevices() {
def deviceData = []
inputs?.each {
def deviceType = getDeviceType(it)
if (deviceType == "thermostat") {
deviceData << [name: it.displayName, id: it.id, deviceType: deviceType, manufacturer: it.getManufacturerName(), model: it.getModelName(), attributes: deviceAttributeList(it), locationMode: getLocationModeInfo()]
} else {
deviceData << [name: it.displayName, id: it.id, deviceType: deviceType, manufacturer: it.getManufacturerName(), model: it.getModelName(), attributes: deviceAttributeList(it)]
if(deviceType == "thermostat")
{
deviceData << [name: it.displayName, id: it.id, status:it.getStatus(), deviceType:deviceType, manufacturer:it.getManufacturerName(), model:it.getModelName(), attributes: deviceAttributeList(it), locationMode: getLocationModeInfo()]
}
else
{
deviceData << [name: it.displayName, id: it.id, status:it.getStatus(), deviceType:deviceType, manufacturer:it.getManufacturerName(), model:it.getModelName(), attributes: deviceAttributeList(it)]
}
}
@@ -246,10 +247,13 @@ def getDevice() {
def it = findDevice(params.id)
def deviceType = getDeviceType(it)
def device
if (deviceType == "thermostat") {
device = [name: it.displayName, id: it.id, deviceType: deviceType, manufacturer: it.getManufacturerName(), model: it.getModelName(), attributes: deviceAttributeList(it), locationMode: getLocationModeInfo()]
} else {
device = [name: it.displayName, id: it.id, deviceType: deviceType, manufacturer: it.getManufacturerName(), model: it.getModelName(), attributes: deviceAttributeList(it)]
if(deviceType == "thermostat")
{
device = [name: it.displayName, id: it.id, status:it.getStatus(), deviceType:deviceType, manufacturer:it.getManufacturerName(), model:it.getModelName(), attributes: deviceAttributeList(it), locationMode: getLocationModeInfo()]
}
else
{
device = [name: it.displayName, id: it.id, status:it.getStatus(), deviceType:deviceType, manufacturer:it.getManufacturerName(), model:it.getModelName(), attributes: deviceAttributeList(it)]
}
log.debug "getDevice, return: ${device}"
return device
@@ -261,18 +265,18 @@ void updateDevice() {
request.JSON.each {
def command = it.key
def value = it.value
if (command) {
if (command){
def commandList = mapDeviceCommands(command, value)
command = commandList[0]
value = commandList[1]
if (command == "setAwayMode") {
log.info "Setting away mode to ${value}"
if (location.modes?.find { it.name == value }) {
if (location.modes?.find {it.name == value}) {
location.setMode(value)
}
} else if (command == "thermostatSetpoint") {
switch (device.currentThermostatMode) {
}else if (command == "thermostatSetpoint"){
switch(device.currentThermostatMode){
case "cool":
log.info "Update: ${device.displayName}, [${command}, ${value}]"
device.setCoolingSetpoint(value)
@@ -286,7 +290,7 @@ void updateDevice() {
httpError(501, "this mode: ${device.currentThermostatMode} does not allow changing thermostat setpoint.")
break
}
} else if (!device) {
}else if (!device) {
log.error "updateDevice, Device not found"
httpError(404, "Device not found")
} else if (!device.hasCommand(command)) {
@@ -296,11 +300,11 @@ void updateDevice() {
if (command == "setColor") {
log.info "Update: ${device.displayName}, [${command}, ${value}]"
device."$command"(hex: value)
} else if (value.isNumber()) {
} else if(value.isNumber()) {
def intValue = value as Integer
log.info "Update: ${device.displayName}, [${command}, ${intValue}(int)]"
device."$command"(intValue)
} else if (value) {
} else if (value){
log.info "Update: ${device.displayName}, [${command}, ${value}]"
device."$command"(value)
} else {
@@ -322,19 +326,28 @@ private getLocationModeInfo() {
//Map each device to a type given it's capabilities
private getDeviceType(device) {
def deviceType
def caps = device.capabilities
log.debug "capabilities: [${device}, ${caps}]"
def capabilities = device.capabilities
log.debug "capabilities: [${device}, ${capabilities}]"
log.debug "supported commands: [${device}, ${device.supportedCommands}]"
caps.each {
switch (it.name.toLowerCase()) {
//Loop through the device capability list to determine the device type.
capabilities.each {capability ->
switch(capability.name.toLowerCase())
{
case "switch":
deviceType = "switch"
if (caps.any { it.name.toLowerCase() == "power meter" }) {
return deviceType
}
if (caps.any { it.name.toLowerCase() == "switch level" }) {
deviceType = "light"
return deviceType
//If the device also contains "Switch Level" capability, identify it as a "light" device.
if (capabilities.any{it.name.toLowerCase() == "switch level"}){
//If the device also contains "Power Meter" capability, identify it as a "dimmerSwitch" device.
if (capabilities.any{it.name.toLowerCase() == "power meter"}){
deviceType = "dimmerSwitch"
return deviceType
} else {
deviceType = "light"
return deviceType
}
}
break
case "contact sensor":
@@ -375,16 +388,16 @@ private findDevice(deviceId) {
//Return a list of device attributes
private deviceAttributeList(device) {
device.supportedAttributes.collectEntries { attribute ->
device.supportedAttributes.collectEntries { attribute->
try {
[(attribute.name): device.currentValue(attribute.name)]
} catch (e) {
[(attribute.name): null]
[ (attribute.name): device.currentValue(attribute.name) ]
} catch(e) {
[ (attribute.name): null ]
}
}
}
//Map device command and value.
//Map device command and value.
//input command and value are from UWP,
//returns resultCommand and resultValue that corresponds with function and value in SmartApps
private mapDeviceCommands(command, value) {
@@ -414,7 +427,7 @@ private mapDeviceCommands(command, value) {
resultCommand = "setSaturation"
resultValue = value
break
case "ct":
case "colorTemperature":
resultCommand = "setColorTemperature"
resultValue = value
break
@@ -451,7 +464,8 @@ private mapDeviceCommands(command, value) {
if (value == 1 || value == "1" || value == "lock") {
resultCommand = "lock"
resultValue = ""
} else if (value == 0 || value == "0" || value == "unlock") {
}
else if (value == 0 || value == "0" || value == "unlock") {
resultCommand = "unlock"
resultValue = ""
}
@@ -460,6 +474,5 @@ private mapDeviceCommands(command, value) {
break
}
return [resultCommand, resultValue]
return [resultCommand,resultValue]
}

View File

@@ -472,8 +472,6 @@ def addBridge() {
log.error "Failed to create Hue Bridge device"
}
}
} else {
log.debug "found ${d.displayName} with id $selectedHue already exists"
}
}
}
@@ -715,6 +713,9 @@ def doDeviceSync(){
log.warn "state.updating failed to clear"
}
if (selectedHue) {
addBridge()
}
convertBulbListToMap()
poll()
ssdpSubscribe()
@@ -1358,7 +1359,7 @@ private void createSwitchEvent(childDevice, setSwitch, setLevel = null) {
private colorPointsForModel(model = null) {
def result = null
switch (model) {
// Gamut A
// Gamut A
case "LLC001": /* Monet, Renoir, Mondriaan (gen II) */
case "LLC005": /* Bloom (gen II) */
case "LLC006": /* Iris (gen III) */
@@ -1370,12 +1371,12 @@ private colorPointsForModel(model = null) {
case "LLC010": /* Hue Living Colors Iris + */
result = [r:[x: 0.704f, y: 0.296f], g:[x: 0.2151f, y: 0.7106f], b:[x: 0.138f, y: 0.08f]];
break
// Gamut C
// Gamut C
case "LLC020": /* Hue Go */
case "LST002": /* Hue LightStrips Plus */
result = [r:[x: 0.692f, y: 0.308f], g:[x: 0.17f, y: 0.7f], b:[x: 0.153f, y: 0.048f]];
break
// Gamut B
// Gamut B
case "LCT001": /* Hue A19 */
case "LCT002": /* Hue BR30 */
case "LCT003": /* Hue GU10 */
@@ -1803,4 +1804,3 @@ def hsvToHex(hue, sat, value = 100){
return "#$r1$g1$b1"
}