United security pressure mat

This one:

How did you attach the wires to the sensor. Mine have a problem of staying connected. Did you solder them, tape them? Photos would be great!

The open/close sensor I used has two metal posts that have screws on top so all I did was insert them and then tightened the screws. I would take a picture but it is outside and installed already. Maybe I’ll get to it tomorrow, but trust me if you have the same sensor you will quickly see the posts and know what to do. If you don’t have this then a soldering iron should do the trick.

1 Like

Brilliant, I had no idea those were screws! Thanks for you help :slight_smile:

So I’ve got this all set up, after fighting with the inclusion process for a few minutes and realizing that (somehow) the behavior is screwy unless you actually put the plastic cover back ON the sensor (for me, it would turn red when I pressed the mat, but then stay on forever and not report any status)

My question: Since it wants to report in the Open position and change to Closed when it’s triggered, how are you guys attaching triggers and notifications to it without creating a “Door” object to attach it to? The issue with making a door, of course, is that it will always report as Open and make other automations such as to arm the alarm when all the doors are closed simply fail. Presumably anything that checks which doors are open/closed can have its list of checkable doors modified, but it still seems as though a custom (or maybe already available in the developer console) device type that behaves as a momentary switch would be more ideal? I havent tried re-assigning it yet, I’m curious what all of you have done?

I wrote a custom device call pressure mat that is the same as the door device but with new icon and message for stepped on and empty. Then I wrote a smart app that does something when stepped on, which is reverse logic from the existing built in open door app. I then took a picture of my mat and used it to override the icon so it looks like a mat. The device code is:

/**
 *  Z-Wave Pressure Mat Sensor
 *
 *  Author: SmartThings - edited by KW
 *  Date: 2013-11-3
 */

// for the UI
metadata {
	// Automatically generated. Make future change here.
	definition (name: "Z-Wave Pressure Mat Sensor", namespace: "kewashi", author: "Ken Washington") {
		capability "Contact Sensor"
		capability "Sensor"
		capability "Battery"
		capability "Configuration"

		fingerprint deviceId: "0x2001", inClusters: "0x30,0x71,0x72,0x86,0x85,0x84,0x80,0x70,0xEF,0x20"
		// fingerprint deviceId: "0x2001", inClusters: "0x30,0x80,0x84,0x85,0x86,0x72"
		// fingerprint deviceId: "0x07", inClusters: "0x30"
		// fingerprint deviceId: "0x0701", inClusters: "0x5E,0x86,0x72,0x98", outClusters: "0x5A,0x82"
	}

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

	// UI tile definitions
    // switch colors for mat
	tiles {
		standardTile("contact", "device.contact", width: 2, height: 2, canChangeBackground: true) {
			state "open", label: 'empty', icon: "st.custom.buttons.a", backgroundColor: "#79b821"
			state "closed", label: 'stepped on', icon: "st.custom.buttons.b", backgroundColor: "#ffa81e"
			// state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
			// state "closed", label: '${name}', icon: "st.contact.contact.closed", 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 106")) {
		if (!state.sec) {
			log.debug description
		} else {
			result = createEvent(
				descriptionText: "This sensor failed to complete the network security key exchange. If you are unable to control it via SmartThings, you must remove it from your network and add it again.",
				eventType: "ALERT",
				name: "secureInclusion",
				value: "failed",
				isStateChange: true,
			)
		}
	} else if (description != "updated") {
		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)
		}
	}
	log.debug "parsed '$description' to $result"
	return result
}

def updated() {
	def cmds = []
	if (!state.MSR) {
		cmds = [
			zwave.manufacturerSpecificV2.manufacturerSpecificGet().format(),
			"delay 1200",
			zwave.wakeUpV1.wakeUpNoMoreInformation().format()
		]
	} else if (!state.lastbat) {
		cmds = []
	} else {
		cmds = [zwave.wakeUpV1.wakeUpNoMoreInformation().format()]
	}
	response(cmds)
}

def configure() {
	delayBetween([
		zwave.manufacturerSpecificV2.manufacturerSpecificGet().format(),
		batteryGetCommand()
	], 6000)
}

def sensorValueEvent(value) {
	if (value) {
		createEvent(name: "contact", value: "open", descriptionText: "$device.displayName is empty")
	} else {
		createEvent(name: "contact", value: "closed", descriptionText: "$device.displayName is stepped on")
	}
}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd)
{
	sensorValueEvent(cmd.value)
}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd)
{
	sensorValueEvent(cmd.value)
}

def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd)
{
	sensorValueEvent(cmd.value)
}

def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv1.SensorBinaryReport cmd)
{
	sensorValueEvent(cmd.sensorValue)
}

def zwaveEvent(physicalgraph.zwave.commands.sensoralarmv1.SensorAlarmReport cmd)
{
	sensorValueEvent(cmd.sensorState)
}

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)
	}
	result
}

def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
{
	def event = createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)
	def cmds = []
	if (!state.MSR) {
		cmds << zwave.wakeUpV1.wakeUpIntervalSet(seconds:4*3600, nodeid:zwaveHubNodeId).format()
		cmds << zwave.manufacturerSpecificV2.manufacturerSpecificGet().format()
		cmds << "delay 1200"
	}
	if (!state.lastbat || now() - state.lastbat > 53*60*60*1000) {
		cmds << batteryGetCommand()
	} else {
		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 {
		map.value = cmd.batteryLevel
	}
	state.lastbat = now()
	[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)

	retypeBasedOnMSR()

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

	if (msr == "011A-0601-0901") {  // Enerwave motion doesn't always get the associationSet that the hub sends on join
		result << response(zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId))
	} else if (!device.currentState("battery")) {
		if(msr == "0086-0102-0059") state.sec = 1
		result << response(batteryGetCommand())
	}

	result
}

def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
	def encapsulatedCommand = cmd.encapsulatedCommand([0x20: 1, 0x85: 2, 0x70: 1])
	// log.debug "encapsulated: $encapsulatedCommand"
	if (encapsulatedCommand) {
		state.sec = 1
		zwaveEvent(encapsulatedCommand)
	}
}

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

def batteryGetCommand() {
	def cmd = zwave.batteryV1.batteryGet()
	if (state.sec) {
		cmd = zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd)
	}
	cmd.format()
}

def retypeBasedOnMSR() {
	switch (state.MSR) {
		case "0086-0002-002D":
			log.debug("Changing device type to Z-Wave Water Sensor")
			setDeviceType("Z-Wave Water Sensor")
			break
		case "011F-0001-0001":  // Schlage motion
		case "014A-0001-0001":  // Ecolink motion
		case "0060-0001-0002":  // Everspring SP814
		case "0060-0001-0003":  // Everspring HSP02
		case "011A-0601-0901":  // Enerwave ZWN-BPC
			log.debug("Changing device type to Z-Wave Motion Sensor")
			setDeviceType("Z-Wave Motion Sensor")
			break
		
	}
}
12 Likes

Fantastic ideas and use cases mentioned her for Pressure Mats, as stated by @JDRoberts they would be a blessing for wheelchair users like my grandparents who im considering installing ST aspects for so my family can keep an eye on them as they are getting older and more vulnerable now.

does anyone have any out of the box use cases for these, i like the idea of using them in a sofa to indicate someone is in the room either watching tv or relaxing etc - be great for a cinema room if you could pause a film when you stand up and it resumes when you sit back down whilst your home is in movie mode etc :slight_smile:

2 Likes

Lots more interesting use case ideas in the smart chair topic:

1 Like

Just reading that as it happens :wink: thanks a lot as always mate.

1 Like

Any chance this is the EcoLink? I wondered what those were for as nothing in the booklet. So I can pair up a mat with a sensor like rather than the battery?

Oh my, what a rabbit hole I’ve fallen into.
I started this forum session on one topic, and ended up here a few topics later.
There are so many cool things that can be done.
Somebody please stop it! Let me get caught up. lol

1 Like

I am sorry, that is simply not possible. Now go build your HA dreams

2 Likes

Well, you’ve got the name for it! :first_quarter_moon_with_face::last_quarter_moon_with_face:

1 Like

Thank you so much for this! I have a disabled daughter who likes to get out of bed and is not all that stable! This has saved her from more than one fall!

1 Like

This is BY FAR, my favorite Smart Home hack to date. Thank you so much for the share!!!

I wanted to inquire about the default “Open” state of this set up, and if there is any possible way that the default state could be set (or coded) to be read by SmartThings as Closed?

The reason being, for the longest time I actually used this as part of my SmartThings security “Smart Home Monitor”. This was great because I could get notified, or say, trip my camera to record, if someone walked up to my door but didn’t knock, the postman left a package but didn’t knock (BEST use ever), or (heaven forbid) someone tried to break into my house and obviously didn’t want to knock lol.

However, because the default state is open, SmartThings would constantly remind me something like “Your home is safe, but the Front Door Mat was left open”. Or it would false triggereturn a security alert. I can’t remember the specifics because I removed it from my “Smart Home Monitor” as it rendered the Smart Home Monitor completely uselessatisfied.

Don’t get me wrong, I completely understand WHY it is in a default state of open and when someone or something steps or lands on it it closes… but has anyone wished or felt that there would be a benefit from it being reversed? Maybe this can be done by some code… I am no coder, but would be willing to donate if someone wished to try to tackle this.

Thanks!!

3 Likes

When I created a “panic button” from a doorbell button and a door sensor like he is using, I just flip flopped the open and closed in the code here:

// report open and closed events are swapped so that createEvent open is closed, and closed is open
// this reversal lets the alarm system function properly

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

2 Likes

For anyone interested, I created an icon that better matches the ones that SmartThings uses. It has a transparent background so the colors and text still show up.

3 Likes

So I think I found the code in the Device Handler starting at around 96 below but when I tried to swap the values, it seems to have no effect. Any suggestions?

def sensorValueEvent(value) {
if (value) {
createEvent(name: “contact”, value: “open”, descriptionText: “$device.displayName is empty”)
} else {
createEvent(name: “contact”, value: “closed”, descriptionText: “$device.displayName is stepped on”)
}
}

Maybe there was more I did. :wink:
So you changed the code, saved it, and published/for me
backed out of the device display on your phone/tablet and came back in…
and it didn’t change function.
I’ll look some more in the code.

hmm, I don’t think I did this but I opened up SmartTiles and nothing changed there either.