Compare commits
14 Commits
production
...
user147497
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a92e3f728 | ||
|
|
3d67448aa5 | ||
|
|
224747408b | ||
|
|
4bc177f638 | ||
|
|
97970cd0f0 | ||
|
|
4e1a2c4004 | ||
|
|
94320f74cb | ||
|
|
3745a305c2 | ||
|
|
0b73e5c4de | ||
|
|
85352ad7f4 | ||
|
|
e6d4e3e529 | ||
|
|
1e2f1feff8 | ||
|
|
2419b977fd | ||
|
|
ab754469be |
@@ -171,12 +171,10 @@ private Map parseReportAttributeMessage(String description) {
|
||||
private Map parseCustomMessage(String description) {
|
||||
Map resultMap = [:]
|
||||
if (description?.startsWith('temperature: ')) {
|
||||
// log.debug "${description}"
|
||||
// def value = zigbee.parseHATemperatureValue(description, "temperature: ", getTemperatureScale())
|
||||
// log.debug "split: " + description.split(": ")
|
||||
def value = Double.parseDouble(description.split(": ")[1])
|
||||
// log.debug "${value}"
|
||||
resultMap = makeTemperatureResult(convertTemperature(value))
|
||||
def tempData = description.split(": ")[1].split(" ")
|
||||
def scale = (tempData.length > 1) ? tempData[1] : "C"
|
||||
def value = Double.parseDouble(tempData[0])
|
||||
resultMap = makeTemperatureResult(convertTemperature(value, scale))
|
||||
}
|
||||
return resultMap
|
||||
}
|
||||
@@ -282,18 +280,19 @@ private def convertTemperatureHex(value) {
|
||||
def celsius = Integer.parseInt(value, 16).shortValue() / 100
|
||||
// log.debug "celsius: ${celsius}"
|
||||
|
||||
return convertTemperature(celsius)
|
||||
return convertTemperature(celsius, "C")
|
||||
}
|
||||
|
||||
private def convertTemperature(celsius) {
|
||||
// log.debug "convertTemperature()"
|
||||
|
||||
if(getTemperatureScale() == "C"){
|
||||
return celsius
|
||||
private def convertTemperature(value, scale = "C") {
|
||||
if(getTemperatureScale() == scale){
|
||||
return Math.round(value * 100) / 100
|
||||
} else {
|
||||
def fahrenheit = Math.round(celsiusToFahrenheit(celsius) * 100) /100
|
||||
// log.debug "converted to F: ${fahrenheit}"
|
||||
return fahrenheit
|
||||
if (scale == "C") {
|
||||
// Celsius to Fahrenheit
|
||||
return Math.round(celsiusToFahrenheit(value) * 100) /100
|
||||
}
|
||||
// Fahrenheit to Celsius
|
||||
return Math.round(fahrenheitToCelsius(value) * 100) /100
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* eZEX Temp & Humidity Sensor (AC Type)
|
||||
*
|
||||
* Copyright 2019 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 physicalgraph.zigbee.zcl.DataType
|
||||
|
||||
metadata {
|
||||
definition(name: "eZEX Temp & Humidity Sensor", namespace: "smartthings", author: "SmartThings", mnmn:"SmartThings", vid:"generic-humidity") {
|
||||
capability "Configuration"
|
||||
capability "Temperature Measurement"
|
||||
capability "Relative Humidity Measurement"
|
||||
capability "Sensor"
|
||||
|
||||
fingerprint profileId: "0104", inClusters: "0000,0003,0402,0405,0500", outClusters: "0019", model: "E282-KR0B0Z1-HA", deviceJoinName: "eZEX Temperature & Humidity Sensor (AC Type)"
|
||||
}
|
||||
|
||||
|
||||
preferences {
|
||||
input title: "Temperature Offset", description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter \"-5\". If 3 degrees too cold, enter \"+3\".", displayDuringSetup: false, type: "paragraph", element: "paragraph"
|
||||
input "tempOffset", "number", title: "Degrees", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false
|
||||
input title: "Humidity Offset", description: "This feature allows you to correct any humidity variations by selecting an offset. Ex: If your sensor consistently reports a humidity that's 6% higher then a similiar calibrated sensor, you'd enter \"-6\".", displayDuringSetup: false, type: "paragraph", element: "paragraph"
|
||||
input "humidityOffset", "number", title: "Humidity Offset in Percent", description: "Adjust humidity by this percentage", range: "*..*", displayDuringSetup: false
|
||||
}
|
||||
|
||||
tiles(scale: 2) {
|
||||
multiAttributeTile(name: "temperature", type: "generic", width: 6, height: 4, canChangeIcon: true) {
|
||||
tileAttribute("device.temperature", key: "PRIMARY_CONTROL") {
|
||||
attributeState "temperature", label: '${currentValue}°',
|
||||
backgroundColors: [
|
||||
[value: 31, color: "#153591"],
|
||||
[value: 44, color: "#1e9cbb"],
|
||||
[value: 59, color: "#90d2a7"],
|
||||
[value: 74, color: "#44b621"],
|
||||
[value: 84, color: "#f1d801"],
|
||||
[value: 95, color: "#d04e00"],
|
||||
[value: 96, color: "#bc2323"]
|
||||
]
|
||||
}
|
||||
}
|
||||
valueTile("humidity", "device.humidity", inactiveLabel: false, width: 2, height: 2) {
|
||||
state "humidity", label: '${currentValue}% humidity', unit: ""
|
||||
}
|
||||
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
||||
state "default", action: "refresh.refresh", icon: "st.secondary.refresh"
|
||||
}
|
||||
|
||||
main "temperature", "humidity"
|
||||
details(["temperature", "humidity", "refresh"])
|
||||
}
|
||||
}
|
||||
|
||||
def parse(String description) {
|
||||
log.debug "description: $description"
|
||||
|
||||
// getEvent will handle temperature and humidity
|
||||
Map map = zigbee.getEvent(description)
|
||||
if (!map) {
|
||||
Map descMap = zigbee.parseDescriptionAsMap(description)
|
||||
if (descMap?.clusterInt == zigbee.TEMPERATURE_MEASUREMENT_CLUSTER && descMap.commandInt == 0x07) {
|
||||
if (descMap.data[0] == "00") {
|
||||
log.debug "TEMP REPORTING CONFIG RESPONSE: $descMap"
|
||||
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||
} else {
|
||||
log.warn "TEMP REPORTING CONFIG FAILED- error code: ${descMap.data[0]}"
|
||||
}
|
||||
}
|
||||
} else if (map.name == "temperature") {
|
||||
if (tempOffset) {
|
||||
map.value = (int) map.value + (int) tempOffset
|
||||
}
|
||||
map.descriptionText = temperatureScale == 'C' ? '{{ device.displayName }} was {{ value }}°C' : '{{ device.displayName }} was {{ value }}°F'
|
||||
map.translatable = true
|
||||
} else if (map.name == "humidity") {
|
||||
if (humidityOffset) {
|
||||
map.value = (int) map.value + (int) humidityOffset
|
||||
}
|
||||
}
|
||||
|
||||
log.debug "Parse returned $map"
|
||||
return map ? createEvent(map) : [:]
|
||||
}
|
||||
|
||||
/**
|
||||
* PING is used by Device-Watch in attempt to reach the Device
|
||||
* */
|
||||
def ping() {
|
||||
return refresh()
|
||||
}
|
||||
|
||||
def refresh() {
|
||||
log.debug "refresh temperature, humidity"
|
||||
return zigbee.readAttribute(zigbee.RELATIVE_HUMIDITY_CLUSTER, 0x0000) +
|
||||
zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000)
|
||||
}
|
||||
|
||||
def configure() {
|
||||
// Device-Watch allows 2 check-in misses from device + ping (plus 1 min lag time)
|
||||
sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||
|
||||
log.debug "Configuring Reporting and Bindings."
|
||||
|
||||
// temperature minReportTime 30 seconds, maxReportTime 1 hour. Reporting interval if no activity
|
||||
return refresh() +
|
||||
zigbee.configureReporting(zigbee.RELATIVE_HUMIDITY_CLUSTER, 0x0000, DataType.UINT16, 30, 3600, 100) +
|
||||
zigbee.configureReporting(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000, DataType.UINT16, 30, 3600, 100)
|
||||
}
|
||||
@@ -171,9 +171,9 @@ def ping() {
|
||||
def refresh() {
|
||||
log.debug "Refreshing Temperature and Battery"
|
||||
def refreshCmds = zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000) +
|
||||
zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020)
|
||||
zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020) + zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER, zigbee.ATTRIBUTE_IAS_ZONE_STATUS) + zigbee.enrollResponse()
|
||||
|
||||
return refreshCmds + zigbee.enrollResponse()
|
||||
return refreshCmds
|
||||
}
|
||||
|
||||
def configure() {
|
||||
@@ -182,7 +182,7 @@ def configure() {
|
||||
sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"])
|
||||
|
||||
log.debug "Configuring Reporting, IAS CIE, and Bindings."
|
||||
def cmds = refresh() + zigbee.iasZoneConfig(30, 60 * 5) + zigbee.batteryConfig() + zigbee.temperatureConfig(30, 60 * 30)
|
||||
def cmds = refresh() + zigbee.iasZoneConfig(30, 60 * 5) + zigbee.batteryConfig() + zigbee.temperatureConfig(30, 60 * 30) + zigbee.enrollResponse()
|
||||
if(getDataValue("manufacturer") == "Ecolink") {
|
||||
cmds += configureEcolink()
|
||||
}
|
||||
|
||||
@@ -292,6 +292,8 @@ def poll() {
|
||||
else {
|
||||
log.warn "No response from TWC API"
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
def parseAlertTime(s) {
|
||||
|
||||
@@ -56,9 +56,10 @@ metadata {
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B05, 1000, FEDC", outClusters: "000A, 0019", manufacturer: "Aurora", model: "FWGU10Bulb50AU", deviceJoinName: "Aurora Smart Dimmable GU10"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B05, 1000, FEDC", outClusters: "000A, 0019", manufacturer: "Smarthome", model: "S111-201A", deviceJoinName: "Leedarson Dimmable White Bulb A19"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 1000", outClusters: "0019", manufacturer: "innr", model: "RB 265", deviceJoinName: "Innr Smart Bulb White"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 1000", outClusters: "0019", manufacturer: "innr", model: "RB 245", deviceJoinName: "Innr Smart Candle Warm white"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 1000", outClusters: "0019", manufacturer: "innr", model: "RB 245", deviceJoinName: "Innr Smart Candle Warm White"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 1000", outClusters: "0019", manufacturer: "innr", model: "RS 225", deviceJoinName: "Innr Smart Spot White"
|
||||
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "E11-N13", deviceJoinName: "Sengled Element Classic"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "E11-N14", deviceJoinName: "Sengled Element Classic"
|
||||
}
|
||||
|
||||
tiles(scale: 2) {
|
||||
|
||||
28
devicetypes/smartthings/zwave-mouse-trap.src/README.md
Normal file
28
devicetypes/smartthings/zwave-mouse-trap.src/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Z-Wave Mouse Trap
|
||||
|
||||
Local Execution
|
||||
|
||||
* [Capabilities](#capabilities)
|
||||
* [Health](#device-health)
|
||||
* [Troubleshooting](#Troubleshooting)
|
||||
|
||||
## Capabilities
|
||||
|
||||
* **Sensor** - detects sensor events
|
||||
* **Battery** - defines that the device has a battery
|
||||
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
|
||||
* **Health Check** - indicates ability to get device health notifications
|
||||
* **Refresh** - _refresh()_ command for status updates
|
||||
* **Pest Control** - indicates ability to get mouse trap notifications
|
||||
|
||||
## Device Health
|
||||
|
||||
Z-Wave Mouse Trap is a Z-Wave sleepy device and checks in every 12 hours.
|
||||
Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2 * 12 * 60 * 60 + 2 * 60) sek. = 1442 mins.
|
||||
|
||||
* __1442min__ checkInterval
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range.
|
||||
Pairing needs to be tried again by placing the device closer to the hub.
|
||||
@@ -0,0 +1,208 @@
|
||||
/**
|
||||
* Copyright 2019 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.
|
||||
*
|
||||
*/
|
||||
metadata {
|
||||
definition(name: "Z-Wave Mouse Trap", namespace: "smartthings", author: "SmartThings", mnmn: "SmartThings", vid: "generic-pestcontrol-1", runLocally: false, executeCommandsLocally: false) {
|
||||
capability "Sensor"
|
||||
capability "Battery"
|
||||
capability "Configuration"
|
||||
capability "Health Check"
|
||||
capability "Pest Control"
|
||||
//capability "pestControl", enum: idle, trapArmed, trapRearmRequired, pestDetected, pestExterminated
|
||||
|
||||
//zw:S type:0701 mfr:021F prod:0003 model:0104 ver:3.49 zwv:4.38 lib:06 cc:5E,86,72,5A,73,80,71,30,85,59,84,70 role:06 ff:8C13 ui:8C13
|
||||
fingerprint mfr: "021F", prod: "0003", model: "0104", deviceJoinName: "Dome Mouser"
|
||||
}
|
||||
|
||||
tiles(scale: 2) {
|
||||
multiAttributeTile(name: "pestControl", type: "generic", width: 6, height: 4) {
|
||||
tileAttribute("device.pestControl", key: "PRIMARY_CONTROL") {
|
||||
attributeState("idle", label: 'IDLE', icon: "st.contact.contact.open", backgroundColor: "#00FF00")
|
||||
attributeState("trapRearmRequired", label: 'TRAP RE-ARM REQUIRED', icon: "st.contact.contact.open", backgroundColor: "#00A0DC")
|
||||
attributeState("trapArmed", label: 'TRAP ARMED', icon: "st.contact.contact.open", backgroundColor: "#FF6600")
|
||||
attributeState("pestDetected", label: 'PEST DETECTED', icon: "st.contact.contact.open", backgroundColor: "#FF6600")
|
||||
attributeState("pestExterminated", label: 'PEST EXTERMINATED', icon: "st.contact.contact.closed", backgroundColor: "#FF0000")
|
||||
}
|
||||
}
|
||||
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
||||
state "battery", label: '${currentValue}% battery', unit: ""
|
||||
}
|
||||
standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
||||
state "configure", label: '', action: "configuration.configure", icon: "st.secondary.configure"
|
||||
}
|
||||
main "pestControl"
|
||||
details(["pestControl", "battery", "configure"])
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PING is used by Device-Watch in attempt to reach the Device
|
||||
* */
|
||||
def ping() {
|
||||
log.debug "ping() called"
|
||||
}
|
||||
|
||||
def parse(String description) {
|
||||
def result = []
|
||||
log.debug "desc: $description"
|
||||
def cmd = zwave.parse(description)
|
||||
if (cmd) {
|
||||
result = zwaveEvent(cmd)
|
||||
}
|
||||
log.debug "parsed '$description' to $result"
|
||||
return result
|
||||
}
|
||||
|
||||
def installed() {
|
||||
log.debug "installed()"
|
||||
// Device-Watch simply pings if no device events received for 24h 2min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 24 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
initialize()
|
||||
}
|
||||
|
||||
def updated() {
|
||||
log.debug "updated()"
|
||||
// Device-Watch simply pings if no device events received for 24h 2min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 24 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
|
||||
def initialize() {
|
||||
log.debug "initialize()"
|
||||
def cmds = []
|
||||
cmds << zwave.batteryV1.batteryGet().format()
|
||||
cmds << getConfigurationCommands()
|
||||
sendHubCommand(cmds)
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) {
|
||||
// ignore, to prevent override of NotificationReport
|
||||
[]
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv1.SensorBinaryReport cmd) {
|
||||
// ignore, to prevent override of SensorBinaryReport
|
||||
[]
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) {
|
||||
log.debug "Event: ${cmd.event}, Notification type: ${cmd.notificationType}"
|
||||
def result = []
|
||||
def value
|
||||
def description
|
||||
if (cmd.notificationType == 0x07) {
|
||||
//notificationType == 0x07 (Home Security)
|
||||
switch (cmd.event) {
|
||||
case 0x00:
|
||||
value = "idle"
|
||||
description = "Trap cleared"
|
||||
break
|
||||
case 0x07:
|
||||
value = "pestExterminated"
|
||||
description = "Pest exterminated"
|
||||
break
|
||||
default:
|
||||
log.debug "Not handled event type: ${cmd.event}"
|
||||
break
|
||||
}
|
||||
result = createEvent(name: "pestControl", value: value, descriptionText: description)
|
||||
} else if (cmd.notificationType == 0x13) {
|
||||
//notificationType == 0x13 (Pest Control)
|
||||
switch (cmd.event) {
|
||||
case 0x00:
|
||||
value = "idle"
|
||||
description = "Trap cleared"
|
||||
break
|
||||
case 0x02:
|
||||
value = "trapArmed"
|
||||
description = "Trap armed"
|
||||
break
|
||||
case 0x04:
|
||||
value = "trapRearmRequired"
|
||||
description = "Trap re-arm required"
|
||||
break
|
||||
case 0x06:
|
||||
value = "pestDetected"
|
||||
description = "Pest detected"
|
||||
break
|
||||
case 0x08:
|
||||
value = "pestExterminated"
|
||||
description = "Pest exterminated"
|
||||
break
|
||||
default:
|
||||
log.debug "Not handled event type: ${cmd.event}"
|
||||
break
|
||||
}
|
||||
result = createEvent(name: "pestControl", value: value, descriptionText: description)
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd) {
|
||||
log.debug "WakeUpNotification ${cmd}"
|
||||
def event = createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)
|
||||
def cmds = []
|
||||
|
||||
if (device.currentValue("pestControl") == null) { // In case our initial request didn't make it
|
||||
cmds << getConfigurationCommands()
|
||||
}
|
||||
if (!state.lastbat || now() - state.lastbat > (12 * 60 * 60 + 6 * 60) * 1000 /*milliseconds*/) {
|
||||
cmds << zwave.batteryV1.batteryGet().format()
|
||||
} else {
|
||||
// If we check the battery state we will send NoMoreInfo in the handler for BatteryReport so that we definitely get the report
|
||||
cmds << zwave.wakeUpV1.wakeUpNoMoreInformation().format()
|
||||
}
|
||||
[event, response(cmds)]
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
|
||||
def map = [name: "battery", unit: "%"]
|
||||
if (cmd.batteryLevel == 0xFF) {
|
||||
map.value = 1
|
||||
map.descriptionText = "${device.displayName} has a low battery"
|
||||
map.isStateChange = true
|
||||
} else {
|
||||
log.debug "Battery report: $cmd"
|
||||
map.value = cmd.batteryLevel
|
||||
}
|
||||
state.lastbat = now()
|
||||
[createEvent(map), response(zwave.wakeUpV1.wakeUpNoMoreInformation())]
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.Command cmd) {
|
||||
createEvent(descriptionText: "$device.displayName: $cmd", displayed: true)
|
||||
}
|
||||
|
||||
def configure() {
|
||||
log.debug "config"
|
||||
response(getConfigurationCommands())
|
||||
}
|
||||
|
||||
def getConfigurationCommands() {
|
||||
log.debug "getConfigurationCommands"
|
||||
def cmds = []
|
||||
cmds << zwave.notificationV3.notificationGet(notificationType: 0x13).format()
|
||||
// The wake-up interval is set in seconds, and is 43,200 seconds (12 hours) by default.
|
||||
cmds << zwave.wakeUpV2.wakeUpIntervalSet(seconds: 12 * 3600, nodeid: zwaveHubNodeId).format()
|
||||
|
||||
// BASIC_SET Level, default: 255
|
||||
cmds << zwave.configurationV1.configurationSet(parameterNumber: 1, size: 1, configurationValue: [255]).format()
|
||||
// Set Firing Mode, default: 2 (Burst fire)
|
||||
cmds << zwave.configurationV1.configurationSet(parameterNumber: 2, size: 1, configurationValue: [2]).format()
|
||||
// This parameter defines how long the Mouser will fire continuously before it starts to burst-fire, default: 360 seconds
|
||||
cmds << zwave.configurationV1.configurationSet(parameterNumber: 3, size: 2, configurationValue: [360]).format()
|
||||
// Enable/Disable LED Alarm, default: 1 (enabled)
|
||||
cmds << zwave.configurationV1.configurationSet(parameterNumber: 4, size: 1, configurationValue: [1]).format()
|
||||
// LED Alarm Duration, default: 0 hours
|
||||
cmds << zwave.configurationV1.configurationSet(parameterNumber: 5, size: 1, configurationValue: [0]).format()
|
||||
cmds
|
||||
}
|
||||
222
smartapps/shaneshuford/gear-watch.src/gear-watch.groovy
Normal file
222
smartapps/shaneshuford/gear-watch.src/gear-watch.groovy
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Shanes Webservice Test
|
||||
* Copyright 2017 Shane
|
||||
*/
|
||||
|
||||
//Apollo Spock, we have lift off... wait what?
|
||||
definition(
|
||||
name: "Gear Watch",
|
||||
namespace: "shaneshuford",
|
||||
author: "Shane",
|
||||
description: "Gear Watch",
|
||||
category: "",
|
||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
|
||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
|
||||
iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
|
||||
oauth: true
|
||||
)
|
||||
|
||||
preferences(oauthPage: "pageOne") {
|
||||
page(name: "pageOne", title: "Gear Devices:", nextPage: "selectActions", install: false, uninstall: true) {
|
||||
section("Choose devices to control with watch") {
|
||||
input "switches", "capability.switch", title: "Which Switches?", required: false, multiple: true
|
||||
input "locks", "capability.lock", title: "Which Locks?", required: false, multiple: true
|
||||
//input "lights", "capability.light", title: "Which Lights?", required: false, multiple: true
|
||||
//input "levels", "capability.switchLevel", title: "Which level switches?", required: false, multiple: true
|
||||
//input "motion", "capability.motionSensor", title: "Which Motion Sensors?", required: false, multiple: true
|
||||
}
|
||||
}
|
||||
page(name: "selectActions")
|
||||
}
|
||||
|
||||
def selectActions() {
|
||||
dynamicPage(name: "selectActions", title: "Gear Actions/Routines", install: true, uninstall: true) {
|
||||
// get the available actions
|
||||
def actions = location.helloHome?.getPhrases()*.label
|
||||
if (actions) {
|
||||
// sort them alphabetically
|
||||
actions.sort()
|
||||
section("Choose routines to execute with watch:") {
|
||||
log.trace actions
|
||||
input "action", "enum", title: "Select an routines to execute", options: actions, required: false, multiple: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def installed() {}
|
||||
def updated() {}
|
||||
|
||||
mappings {
|
||||
|
||||
//Switches
|
||||
path("/switches") {
|
||||
action: [
|
||||
GET: "listSwitches"
|
||||
]
|
||||
}
|
||||
path("/switches/:id") {
|
||||
action: [
|
||||
GET: "showSwitch"
|
||||
]
|
||||
}
|
||||
path("/switches/:id/:command") {
|
||||
action: [
|
||||
GET: "updateSwitch"
|
||||
]
|
||||
}
|
||||
path("/switches/:id/:command/:value") {
|
||||
action: [
|
||||
GET: "setSwitchLevel"
|
||||
]
|
||||
}
|
||||
|
||||
//Locks
|
||||
path("/locks") {
|
||||
action: [
|
||||
GET: "listLocks"
|
||||
]
|
||||
}
|
||||
path("/locks/:id") {
|
||||
action: [
|
||||
GET: "showLock"
|
||||
]
|
||||
}
|
||||
path("/locks/:id/:command") {
|
||||
action: [
|
||||
GET: "updateLock"
|
||||
]
|
||||
}
|
||||
|
||||
//Routines
|
||||
path("/routines/:name") {
|
||||
action: [
|
||||
GET: "executeRoutine"
|
||||
]
|
||||
}
|
||||
path("/routines") {
|
||||
action: [
|
||||
GET: "listRoutines"
|
||||
]
|
||||
}
|
||||
|
||||
path("/version") {
|
||||
action: [
|
||||
GET: "smartAppVersion"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
//version
|
||||
def smartAppVersion(){
|
||||
[version: "1.0.1"]
|
||||
}
|
||||
|
||||
//switches
|
||||
def listSwitches() {
|
||||
switches.collect{device(it,"switch")}
|
||||
}
|
||||
|
||||
def showSwitch() {
|
||||
show(switches, "switch")
|
||||
}
|
||||
|
||||
def updateSwitch() {
|
||||
update(switches)
|
||||
}
|
||||
|
||||
def setSwitchLevel(){
|
||||
setlevel(switches)
|
||||
}
|
||||
|
||||
//Locks
|
||||
def listLocks() {
|
||||
locks.collect{device(it,"lock")}
|
||||
}
|
||||
def showLock() {
|
||||
show(locks, "lock")
|
||||
}
|
||||
def updateLock() {
|
||||
update(locks)
|
||||
}
|
||||
|
||||
//Routines
|
||||
def listRoutines() {
|
||||
def actions = location.helloHome?.getPhrases()*.label
|
||||
return actions
|
||||
}
|
||||
def executeRoutine(){
|
||||
def name = params.name
|
||||
location.helloHome?.execute(name)
|
||||
def resp = []
|
||||
resp << [ok: "executed"]
|
||||
return resp
|
||||
}
|
||||
|
||||
//in the future...
|
||||
def deviceHandler(evt) {}
|
||||
|
||||
private void setlevel(devices){
|
||||
def command = params.command
|
||||
|
||||
if(command)
|
||||
{
|
||||
def device = devices.find { it.id == params.id }
|
||||
if(!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
if(command == "level")
|
||||
{
|
||||
device.setLevel(params.value as int)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private update(devices) {
|
||||
def command = params.command
|
||||
|
||||
if (command){
|
||||
def device = devices.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
if(command == "toggle"){
|
||||
if(device.currentValue('switch') == "on"){
|
||||
device.off();
|
||||
[status: "off"]}
|
||||
else{
|
||||
device.on();
|
||||
[status: "on"]}
|
||||
}else{
|
||||
device."$command"()
|
||||
if(command == "on" || command == "off")
|
||||
{
|
||||
[status: command]
|
||||
}
|
||||
else if(command == "lock" || command == "unlock")
|
||||
{
|
||||
[status: command + "ed"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private show(devices, type) {
|
||||
def device = devices.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
def attributeName = type == "motionSensor" ? "motion" : type
|
||||
def s = device.currentState(attributeName)
|
||||
[id: device.id, label: device.displayName, level: it.currentValue("level"), value: s?.value, unitTime: s?.date?.time, type: type]
|
||||
}
|
||||
}
|
||||
|
||||
private device(it, type) {
|
||||
def attributeName = type == "motionSensor" ? "motion" : type
|
||||
def s = it.currentState(attributeName)
|
||||
it ? [id: it.id, label: it.label, level: it.currentValue("level"), value: s?.value, type: type] : null
|
||||
}
|
||||
Reference in New Issue
Block a user