mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-08 05:31:56 +00:00
ICP-1075, ICP-1215 Separate ZSMOKE from ZCOMBO and default detector DTH (assume supports smoke+CO if no explicit fingerprint), set initial states to clear
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
.st-ignore
|
||||||
|
README.md
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# Z-wave Basic Smoke Alarm
|
||||||
|
|
||||||
|
Cloud Execution
|
||||||
|
|
||||||
|
Works with:
|
||||||
|
|
||||||
|
* [First Alert Smoke Detector (ZSMOKE)](https://www.smartthings.com/products/first-alert-smoke-detector)
|
||||||
|
|
||||||
|
## Table of contents
|
||||||
|
|
||||||
|
* [Capabilities](#capabilities)
|
||||||
|
* [Health](#device-health)
|
||||||
|
* [Battery](#battery-specification)
|
||||||
|
* [Troubleshooting](#troubleshooting)
|
||||||
|
|
||||||
|
## Capabilities
|
||||||
|
|
||||||
|
* **Smoke Detector** - measure smoke and optionally carbon monoxide levels
|
||||||
|
* **Sensor** - detects sensor events
|
||||||
|
* **Battery** - defines device uses a battery
|
||||||
|
* **Health Check** - indicates ability to get device health notifications
|
||||||
|
|
||||||
|
## Device Health
|
||||||
|
|
||||||
|
First Alert Smoke Detector (ZSMOKE) is a Z-wave sleepy device and checks in every 1 hour.
|
||||||
|
Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*60 + 2)mins = 122 mins.
|
||||||
|
|
||||||
|
* __122min__ checkInterval
|
||||||
|
|
||||||
|
## Battery Specification
|
||||||
|
|
||||||
|
Two AA 1.5V batteries are required.
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link:
|
||||||
|
* [First Alert Smoke Detector (ZSMOKE) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/207150556-First-Alert-Smoke-Detector-ZSMOKE-)
|
||||||
@@ -0,0 +1,181 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2015 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 Basic Smoke Alarm", namespace: "smartthings", author: "SmartThings") {
|
||||||
|
capability "Smoke Detector"
|
||||||
|
capability "Sensor"
|
||||||
|
capability "Battery"
|
||||||
|
capability "Health Check"
|
||||||
|
|
||||||
|
fingerprint deviceId: "0xA100", inClusters: "0x20,0x80,0x70,0x85,0x71,0x72,0x86"
|
||||||
|
fingerprint mfr:"0138", prod:"0001", model:"0001", deviceJoinName: "First Alert Smoke Detector"
|
||||||
|
}
|
||||||
|
|
||||||
|
simulator {
|
||||||
|
status "smoke": "command: 7105, payload: 01 FF"
|
||||||
|
status "clear": "command: 7105, payload: 01 00"
|
||||||
|
status "test": "command: 7105, payload: 0C FF"
|
||||||
|
status "battery 100%": "command: 8003, payload: 64"
|
||||||
|
status "battery 5%": "command: 8003, payload: 05"
|
||||||
|
}
|
||||||
|
|
||||||
|
tiles (scale: 2){
|
||||||
|
multiAttributeTile(name:"smoke", type: "lighting", width: 6, height: 4){
|
||||||
|
tileAttribute ("device.smoke", key: "PRIMARY_CONTROL") {
|
||||||
|
attributeState("clear", label:"clear", icon:"st.alarm.smoke.clear", backgroundColor:"#ffffff")
|
||||||
|
attributeState("detected", label:"SMOKE", icon:"st.alarm.smoke.smoke", backgroundColor:"#e86d13")
|
||||||
|
attributeState("tested", label:"TEST", icon:"st.alarm.smoke.test", backgroundColor:"#e86d13")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
||||||
|
state "battery", label:'${currentValue}% battery', unit:""
|
||||||
|
}
|
||||||
|
|
||||||
|
main "smoke"
|
||||||
|
details(["smoke", "battery"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def installed() {
|
||||||
|
// Device checks in every hour, this interval allows us to miss one check-in notification before marking offline
|
||||||
|
sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||||
|
|
||||||
|
def cmds = []
|
||||||
|
createSmokeEvents("smokeClear", cmds)
|
||||||
|
cmds.each { cmd -> sendEvent(cmd) }
|
||||||
|
}
|
||||||
|
|
||||||
|
def updated() {
|
||||||
|
// Device checks in every hour, this interval allows us to miss one check-in notification before marking offline
|
||||||
|
sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||||
|
}
|
||||||
|
|
||||||
|
def parse(String description) {
|
||||||
|
def results = []
|
||||||
|
if (description.startsWith("Err")) {
|
||||||
|
results << createEvent(descriptionText:description, displayed:true)
|
||||||
|
} else {
|
||||||
|
def cmd = zwave.parse(description, [ 0x80: 1, 0x84: 1, 0x71: 2, 0x72: 1 ])
|
||||||
|
if (cmd) {
|
||||||
|
zwaveEvent(cmd, results)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.debug "'$description' parsed to ${results.inspect()}"
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
def createSmokeEvents(name, results) {
|
||||||
|
def text = null
|
||||||
|
switch (name) {
|
||||||
|
case "smoke":
|
||||||
|
text = "$device.displayName smoke was detected!"
|
||||||
|
// these are displayed:false because the composite event is the one we want to see in the app
|
||||||
|
results << createEvent(name: "smoke", value: "detected", descriptionText: text)
|
||||||
|
break
|
||||||
|
case "tested":
|
||||||
|
text = "$device.displayName was tested"
|
||||||
|
results << createEvent(name: "smoke", value: "tested", descriptionText: text)
|
||||||
|
break
|
||||||
|
case "smokeClear":
|
||||||
|
text = "$device.displayName smoke is clear"
|
||||||
|
results << createEvent(name: "smoke", value: "clear", descriptionText: text)
|
||||||
|
name = "clear"
|
||||||
|
break
|
||||||
|
case "testClear":
|
||||||
|
text = "$device.displayName test cleared"
|
||||||
|
results << createEvent(name: "smoke", value: "clear", descriptionText: text)
|
||||||
|
name = "clear"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def zwaveEvent(physicalgraph.zwave.commands.alarmv2.AlarmReport cmd, results) {
|
||||||
|
if (cmd.zwaveAlarmType == physicalgraph.zwave.commands.alarmv2.AlarmReport.ZWAVE_ALARM_TYPE_SMOKE) {
|
||||||
|
if (cmd.zwaveAlarmEvent == 3) {
|
||||||
|
createSmokeEvents("tested", results)
|
||||||
|
} else {
|
||||||
|
createSmokeEvents((cmd.zwaveAlarmEvent == 1 || cmd.zwaveAlarmEvent == 2) ? "smoke" : "smokeClear", results)
|
||||||
|
}
|
||||||
|
} else switch(cmd.alarmType) {
|
||||||
|
case 1:
|
||||||
|
createSmokeEvents(cmd.alarmLevel ? "smoke" : "smokeClear", results)
|
||||||
|
break
|
||||||
|
case 12: // test button pressed
|
||||||
|
createSmokeEvents(cmd.alarmLevel ? "tested" : "testClear", results)
|
||||||
|
break
|
||||||
|
case 13: // sent every hour -- not sure what this means, just a wake up notification?
|
||||||
|
if (cmd.alarmLevel == 255) {
|
||||||
|
results << createEvent(descriptionText: "$device.displayName checked in", isStateChange: false)
|
||||||
|
} else {
|
||||||
|
results << createEvent(descriptionText: "$device.displayName code 13 is $cmd.alarmLevel", isStateChange:true, displayed:false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear smoke in case they pulled batteries and we missed the clear msg
|
||||||
|
if(device.currentValue("smoke") != "clear") {
|
||||||
|
createSmokeEvents("smokeClear", results)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check battery if we don't have a recent battery event
|
||||||
|
if (!state.lastbatt || (now() - state.lastbatt) >= 48*60*60*1000) {
|
||||||
|
results << response(zwave.batteryV1.batteryGet())
|
||||||
|
}
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
results << createEvent(displayed: true, descriptionText: "Alarm $cmd.alarmType ${cmd.alarmLevel == 255 ? 'activated' : cmd.alarmLevel ?: 'deactivated'}".toString())
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SensorBinary and SensorAlarm aren't tested, but included to preemptively support future smoke alarms
|
||||||
|
//
|
||||||
|
def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv2.SensorBinaryReport cmd, results) {
|
||||||
|
if (cmd.sensorType == physicalgraph.zwave.commandclasses.SensorBinaryV2.SENSOR_TYPE_SMOKE) {
|
||||||
|
createSmokeEvents(cmd.sensorValue ? "smoke" : "smokeClear", results)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def zwaveEvent(physicalgraph.zwave.commands.sensoralarmv1.SensorAlarmReport cmd, results) {
|
||||||
|
if (cmd.sensorType == 1) {
|
||||||
|
createSmokeEvents(cmd.sensorState ? "smoke" : "smokeClear", results)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd, results) {
|
||||||
|
results << createEvent(descriptionText: "$device.displayName woke up", isStateChange: false)
|
||||||
|
if (!state.lastbatt || (now() - state.lastbatt) >= 56*60*60*1000) {
|
||||||
|
results << response(zwave.batteryV1.batteryGet(), "delay 2000", zwave.wakeUpV1.wakeUpNoMoreInformation())
|
||||||
|
} else {
|
||||||
|
results << response(zwave.wakeUpV1.wakeUpNoMoreInformation())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd, results) {
|
||||||
|
def map = [ name: "battery", unit: "%", isStateChange: true ]
|
||||||
|
state.lastbatt = now()
|
||||||
|
if (cmd.batteryLevel == 0xFF) {
|
||||||
|
map.value = 1
|
||||||
|
map.descriptionText = "$device.displayName battery is low!"
|
||||||
|
} else {
|
||||||
|
map.value = cmd.batteryLevel
|
||||||
|
}
|
||||||
|
results << createEvent(map)
|
||||||
|
}
|
||||||
|
|
||||||
|
def zwaveEvent(physicalgraph.zwave.Command cmd, results) {
|
||||||
|
def event = [ displayed: false ]
|
||||||
|
event.linkText = device.label ?: device.name
|
||||||
|
event.descriptionText = "$event.linkText: $cmd"
|
||||||
|
results << createEvent(event)
|
||||||
|
}
|
||||||
@@ -21,8 +21,6 @@ metadata {
|
|||||||
|
|
||||||
attribute "alarmState", "string"
|
attribute "alarmState", "string"
|
||||||
|
|
||||||
fingerprint deviceId: "0xA100", inClusters: "0x20,0x80,0x70,0x85,0x71,0x72,0x86"
|
|
||||||
fingerprint mfr:"0138", prod:"0001", model:"0001", deviceJoinName: "First Alert Smoke Detector"
|
|
||||||
fingerprint mfr:"0138", prod:"0001", model:"0002", deviceJoinName: "First Alert Smoke Detector and Carbon Monoxide Alarm (ZCOMBO)"
|
fingerprint mfr:"0138", prod:"0001", model:"0002", deviceJoinName: "First Alert Smoke Detector and Carbon Monoxide Alarm (ZCOMBO)"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,6 +55,10 @@ metadata {
|
|||||||
def installed() {
|
def installed() {
|
||||||
// Device checks in every hour, this interval allows us to miss one check-in notification before marking offline
|
// Device checks in every hour, this interval allows us to miss one check-in notification before marking offline
|
||||||
sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||||
|
|
||||||
|
def cmds = []
|
||||||
|
createSmokeOrCOEvents("allClear", cmds) // allClear to set inital states for smoke and CO
|
||||||
|
cmds.each { cmd -> sendEvent(cmd) }
|
||||||
}
|
}
|
||||||
|
|
||||||
def updated() {
|
def updated() {
|
||||||
@@ -105,6 +107,12 @@ def createSmokeOrCOEvents(name, results) {
|
|||||||
results << createEvent(name: "carbonMonoxide", value: "clear", descriptionText: text, displayed: false)
|
results << createEvent(name: "carbonMonoxide", value: "clear", descriptionText: text, displayed: false)
|
||||||
name = "clear"
|
name = "clear"
|
||||||
break
|
break
|
||||||
|
case "allClear":
|
||||||
|
text = "$device.displayName all clear"
|
||||||
|
results << createEvent(name: "smoke", value: "clear", descriptionText: text, displayed: false)
|
||||||
|
results << createEvent(name: "carbonMonoxide", value: "clear", displayed: false)
|
||||||
|
name = "clear"
|
||||||
|
break
|
||||||
case "testClear":
|
case "testClear":
|
||||||
text = "$device.displayName test cleared"
|
text = "$device.displayName test cleared"
|
||||||
results << createEvent(name: "smoke", value: "clear", descriptionText: text, displayed: false)
|
results << createEvent(name: "smoke", value: "clear", descriptionText: text, displayed: false)
|
||||||
|
|||||||
Reference in New Issue
Block a user