Connected Smoke Alarms

I took an existing app, copied it, edited it and published it to myself. I then associated the app with my device.

I am still learning this myself so I totally understand your position. You just have to play with it until you get what you want out of it. Trial and error seems to be the way to go here. The best part is, no matter how bad you muck it up you just can’t break it.

Does your custom device show up in the Damage and Danger dashboard tab?

Sorry for digging up an older thread, but I might be missing something.

I have the First Alert relay connected using the common and normally closed wires to the Schlage terminals. I added the Schlage sensor to my hub, but there doesn’t seem to be a Schlage specific device type anymore. I think this is why I have trouble getting it to report correctly. No matter what I try, the sensor always reports ‘open’. Can someone who has this working correctly share their entire device type script?

The device type I am using below. It the standard Z-Wave Door./Window Sensor with a few modifications to make it display more like a smoke detector. I am using the Kidde relay so may not work the same but as soon as I hook the wires to the Schlage it shows as closed. The only time it shows as open is when the alarms are going off or I have knocked one of the wire loose.


  • Z-Wave Door/Window Sensor
  • Author: SmartThings
  • Date: 2013-11-3

// for the UI
metadata {
// Automatically generated. Make future change here.
definition (name: “Smoke Alarms (Schlage Sensor)”, namespace: “custom”, author: “bwesterdahl”) {
capability "Contact Sensor"
capability "Sensor"
capability “Battery”

	fingerprint deviceId: "0x2001", inClusters: "0x30,0x80,0x84,0x70,0x85,0x86,0x72"

// simulator metadata
simulator {
	// status messages
	status "open":  "command: 2001, payload: FF"
	status "closed": "command: 2001, payload: 00"

// UI tile definitions
tiles {
	standardTile("contact", "", width: 2, height: 2) {
		state "open", label: 'FIRE', icon: "st.particulate.particulate.particulate", backgroundColor: "#cc0000"
		state "closed", label: 'NO SMOKE', icon: "st.Home.home2", backgroundColor: "#79b821"
    valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
		state "battery", label:'${currentValue}% battery', unit:""

	main "contact"
	details(["contact", "battery"])


def parse(String description) {
def result = null
if (description.startsWith(“Err”)) {
result = createEvent(descriptionText:description)
} else if (description == “updated”) {
if (!state.MSR) {
result = [
response(zwave.wakeUpV1.wakeUpIntervalSet(seconds:4*3600, nodeid:zwaveHubNodeId)),
} else {
def cmd = zwave.parse(description, [0x20: 1, 0x25: 1, 0x30: 1, 0x31: 5, 0x80: 1, 0x84: 1, 0x71: 3, 0x9C: 1])
if (cmd) {
result = zwaveEvent(cmd)
return result

def sensorValueEvent(value) {
if (value) {
createEvent(name: “contact”, value: “open”, descriptionText: “$device.displayName smoke was detected!”)
} else {
createEvent(name: “contact”, value: “closed”, descriptionText: “$device.displayName smoke is clear”)

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd)

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd)

def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd)

def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv1.SensorBinaryReport cmd)

def zwaveEvent(physicalgraph.zwave.commands.sensoralarmv1.SensorAlarmReport cmd)

def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd)
def result = []
if (cmd.notificationType == 0x06 && cmd.event == 0x16) {
result << sensorValueEvent(1)
} else if (cmd.notificationType == 0x06 && cmd.event == 0x17) {
result << sensorValueEvent(0)
} else if (cmd.notificationType == 0x07) {
if (cmd.v1AlarmType == 0x07) { // special case for nonstandard messages from Monoprice door/window sensors
result << sensorValueEvent(cmd.v1AlarmLevel)
} else if (cmd.event == 0x01 || cmd.event == 0x02) {
result << sensorValueEvent(1)
} else if (cmd.event == 0x03) {
result << createEvent(descriptionText: “$device.displayName covering was removed”, isStateChange: true)
result << response(zwave.wakeUpV1.wakeUpIntervalSet(seconds:4*3600, nodeid:zwaveHubNodeId))
if(!state.MSR) result << response(zwave.manufacturerSpecificV2.manufacturerSpecificGet())
} else if (cmd.event == 0x05 || cmd.event == 0x06) {
result << createEvent(descriptionText: “$device.displayName detected glass breakage”, isStateChange: true)
} else if (cmd.event == 0x07) {
if(!state.MSR) result << response(zwave.manufacturerSpecificV2.manufacturerSpecificGet())
result << createEvent(name: “motion”, value: “active”, descriptionText:"$device.displayName detected motion")
} else if (cmd.notificationType) {
def text = “Notification $cmd.notificationType: event ${([cmd.event] + cmd.eventParameter).join(”, ")}"
result << createEvent(name: “notification$cmd.notificationType”, value: “$cmd.event”, descriptionText: text, displayed: false)
} else {
def value = cmd.v1AlarmLevel == 255 ? “active” : cmd.v1AlarmLevel ?: "inactive"
result << createEvent(name: “alarm $cmd.v1AlarmType”, value: value, displayed: false)

def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
def result = [createEvent(descriptionText: “${device.displayName} woke up”, isStateChange: false)]
if (!state.lastbat || (new Date().time) - state.lastbat > 5360601000) {
result << response(zwave.batteryV1.batteryGet())
result << response(“delay 1200”)
if (!state.MSR) {
result << response(zwave.wakeUpV1.wakeUpIntervalSet(seconds:4
3600, nodeid:zwaveHubNodeId))
result << response(zwave.manufacturerSpecificV2.manufacturerSpecificGet())
result << response(“delay 1200”)
result << response(zwave.wakeUpV1.wakeUpNoMoreInformation())

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 {
map.value = cmd.batteryLevel
state.lastbat = new Date().time
[createEvent(map), response(zwave.wakeUpV1.wakeUpNoMoreInformation())]

def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
def result = []

def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
log.debug "msr: $msr"
updateDataValue("MSR", msr)


result << createEvent(descriptionText: "$device.displayName MSR: $msr", isStateChange: false)


def zwaveEvent(physicalgraph.zwave.Command cmd) {
createEvent(descriptionText: “$device.displayName: $cmd”, displayed: false)

def retypeBasedOnMSR() {
switch (state.MSR) {
case “0086-0002-002D”:
log.debug(“Changing device type to Z-Wave Water Sensor”)
setDeviceType(“Z-Wave Water Sensor”)
case “011F-0001-0001”: // Schlage motion
case “014A-0001-0001”: // Ecolink motion
case “0060-0001-0002”: // Everspring SP814
case “0060-0001-0003”: // Everspring HSP02
log.debug(“Changing device type to Z-Wave Motion Sensor”)
setDeviceType(“Z-Wave Motion Sensor”)



@trotsky40, thanks for your time posting your device type. Unfortunately it didn’t make a difference. I am beginning to think I got a defective relay. I tried 2 different Schlage sensors, so I don’t think it’s the sensor.

I have received a couple of emails about how the wiring for the relay/door sensor works. Hope this helps:


I’m going to resurrect this topic and ask a question of some of the devs here: @wackware @pstuart @scottinpollock

Is it possible to take the code above and modify it to show up as a smoke alarm type in the app? I would like it to show up under the Damage & Danger option.

I’m currently doing the exact same wiring in my house with an Ecolink sensor, which I believe is the same as a Schlage sensor if I recall.

@Ben, you might want to look at this thread for use in the blog or even the store. This is a VERY good option for people that have hardwired smoke alarms already (which is pretty much all new construction in the past few years and most in the past 15 years). And, often new construction has even more smoke detectors than normal - we have 7 in our house, for example. Given that there are no hard-wired zwave options right now, leaving on the pricey Nest Protect, I really think this is a great option for customers, thanks to the great work of @trotsky40.

And we are up and running! :slight_smile: Thanks, @trotsky40. This received a high wife approval factor today since it involved safety. Although, the three smoke alarm test runs were not met with high approval by anyone in the house (two or four legged).

brainlees, did you get it to show in Damage & Danger? I have altered the device type to make it show there.

I just added the Smoke Detector capability as per the ZWave detector device type has:
capability “Smoke Detector”

This made it capable of being added to the Damage & Danger dashboard and has worked in my testing very well. I hope that helps.

Thanks, @KLabs! I like it when it is easy! That worked perfectly.

No problem, @brianlees. Glad I could contribute something helpful.

I finally finished my connected smoke alarm project this evening when Kidde relay arrived. Thanks to all the posters who shared their project!

I did not have an easy way to install a junction box, which is the main reason I delayed in doing this. Then last week I had a brain wave to try and see if I can use a broken smoke alarm I had laying around. The result is in the picture below :smile:. I used a Peq open/close sensor, which seem to be exactly the same as the SmartThings sensor. I de-soldered the reed switch from the sensor and soldered on three wires, which connected to the Kidde relay common, NC and NO. So it’s not quite as simple as the Schlage that folks were using.

I had to Dremel everything out of the donor smoke detector and it was still a pretty tight fit. I can probably free up a little space by shortening the wires from the Kidde relay. But for the moment everything is in there and working. I replaced the original smoke detector connector with a re-purposed PC hard drive power connector male / female set, so I can unplug it from the ceiling for future battery changes or if I want to move it.

As noted in other posts, I changed the device code to make it a smoke detector device. I also rewrote a bit of the device code to emit smoke events instead of open / close events. This allows me to integrate perfectly in the Damage & Danger section in the dashboard, and add rules for being notified, turning on lights, unlocking doors, etc.

I don’t know why one of the alarm manufactures don’t come out with a hardwired alarm that you can connect into the existing interconnect wires. E.g. if the wired Nest allowed connection and monitoring of the interconnect wiring, I would not have bothered to go to all this trouble.


@trotsky40, @chrisb, @solardave1, @pizzinini, @kg4fku, @KLabs, @Dan999

Tagging everyone that might use this setup. I tested recently and I’m not receiving texts nor are the lights coming on, but the logs show that it is registering smoke/clear. I wanted to see if anyone else is having the issue. Support is confused by this setup at the moment (haven’t seen it before) and they can’t support it.

So, I’m turning to the community to verify what’s going on out there and if I’m the only one having issues or not.

What I found was that adding the “Smoke Detector” capability and then setting it up through the Damage and Danger section doesn’t actually work even though it looks like it does. As long as I treat it like a door sensor and use apps like “Notify Me When…” It works as expected.

Will potentially switch back to that. Working with support now. I think that it is just not reporting the correct info when it is tripped. If we could see the zwave smoke detector device type code, I think we could figure it out. The detector is a boolean device, just like a contact sensor. So, we just need to swap out the bits to make the contact sensor report the same as a smoke detector.

I know I’m over-simplifying it, but it should be fairly straightforward?

My setup has been working fine. I have the smoke alarm set up through Damage & Danger and I’ve always received a text and push notification when I test any of the connected smoke alarms. I just tested it again to make sure things still work (kids had to get up anyway :smiley:)

If I remember correctly, I modified a Z-Wave device type to simply send SmartThings smoke events instead of on / off events when the contact switch opens / closes. I seem to recall looking at the Z-Wave smoke alarm code and sending out those events. I used a PEQ sensor, which has temperature and battery status, so I started with the SmartThings open / close sensor. (Device type code)

I don’t think it should be necessary to mess with the device level bits. If the device emits the correct SmartThings events, things should work.

1 Like

The way I understand the platform is as follows. The capabilities of a device defines what commands and events the device will support. It also makes that device show up in SmartApps when they look for capability=xyz. So defining the smoke detector capability will make it show up in the Damage & Danger section SmartApps. If you then install the SmartApp, it will subscribe to the smoke detector events. But if your actual device never emits those events, the SmartApp event handlers will never be triggered. So therefor your device type must also emit those events.

I posted a link above to my device type. The main change I made, was to emit smoke detected and cleared events instead of open / closed events. This seems to work perfectly with the existing D&D SmartApps.

I also removed the contact sensor capability and added the smoke detector capability. The code below (from the device type) essentially intercepts the open / close events and emits the expected smoke events to make the internal SmartApps fire correctly.

private Map getContactResult(value) {
log.debug 'Contact Status'

def val=""
def descriptionText=""
if (value == "open") 
	val = "detected"
    descriptionText = "$device.displayName detected smoke"
else if (value == "closed") 
	val = "clear"
    descriptionText = "$device.displayName smoke is cleared"
return [
	name: 'smoke',
	value: val,
	descriptionText: descriptionText



@Dan999 - Can you post your entire device type? Would like to test this one…but will have to wait until the family is out since they don’t approve of the repeated smoke detector tests…neither do the cats! :smile:

I posted a link a few posts back. It is a modification of the SmartThings open/close sensor. If your sensor is different, it may not work, but I’m guessing it probably will. If it doesn’t work, you should be able to easily use the snippet above to emit “smoke” events, with values “detected” or “clear” based on your contact senor being “open” or “closed”. I wired mine up such that open = detected, and closed = clear. If your relay is wired differently to the contact sensor, then swap the open / closed events.

While I was getting all this to work on my desk, I used the magnet that came with the contact switch to open and close the reed switch without having to hook up a smoke alarm. If your sensor is accessible, you may be able to trigger it that way without creating a disturbance in the force :smile:

Good point. I could go down to the basement with the magnet. Much quicker and a happier family. I already know the relay part works with the alarms themselves.