Made a Water Leak Sensor

I’ll do it right now. Thanks.

Nope. No change. :sob:

I have no more ideas. I made the same water sensor. hmmmm

This is the correct code? I’m not missing some addition am I?

https://github.com/jdeltoft/SmartThings/blob/master/devicetype.monoprice.waterleak/devicetype.monoprice.waterleak.groovy

I’m using the same one and just for curiosity sake I compared the above and what I have installed and they matched.

Le sigh…thanks for checking. I appreciate it very much.

Try the following:

  1. Remove the Monoprice sensors from ST. Make sure you do a Zwave exclude.
  2. Delete the custom device handler.
  3. Re-add one of the Monoprice sensors - if you have one you haven’t tried to add yet, even better.
  4. I believe ST will add it with a generic Zwave DH IIRC. If so, see if the open/close is working.

Are you seeing lights on the sensors at all?

I’ve re-added one of the sensors, and the open/close function is working as should.

There is a short “blip” of the red light on the sensor when both opening or closing the connection. I also get a text notice stating that the “door” was opened (set up as an open/close sensor just to make sure it is completely functioning in case I need to re-purpose it).

Oh my…I am a colossal twonk. I’ve been tinkering with this all day, and had been using the “Z-wave Water Sensor” from the grouping of Z-Wave device lists.

For whatever reason (mostly out of desperation), I scrolled down the list to the very bottom and saw this:

I tried using this as the device type, and Bob’s your uncle. It WORKS!

Thank you so very much to everyone for trying to help me diagnose the issue. I really appreciate your expertise, and am regretful that I’ve wasted your time.

Cheers!

2 Likes

So here’s one code that you can use, infact if you install this code BEFORE you pair your Monoprice Motion Sensor it will automatically identify it as the Monoprice Door/Window Sensor used as a Water Sensor. Note, this only supports the Monoprice Z-Wave and NOT the Z-Wave Plus devices. Will update the code once I get around to it:

/**
 *  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.
 *
 *  Modified by RBoy
 *  Generic Z-Wave Door/Window sensor adapter to work as a Water Sensor
 *
 *  Date: 2016-9-23
 */

metadata {
	definition (name: "Z-Wave Door/Window Sensor Used As Water Sensor", namespace: "rboy", author: "RBoy") {
		capability "Water Sensor"
		capability "Sensor"
		capability "Battery"

		fingerprint deviceId: '0x2001', inClusters: '0x71,0x85,0x80,0x72,0x30,0x86,0x84'
        fingerprint type:"2001", mfr:"0109", prod:"2001", model:"0102", cc:"71,85,80,72,30,86,84", deviceJoinName: "Monoprice Z-Wave Door/Window Sensor Used as Water Sensor"
	}

	simulator {
		status "dry": "command: 3003, payload: 00"
		status "wet": "command: 3003, payload: FF"
	}
	
	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"
		}
		valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
			state "battery", label:'${currentValue}% battery', unit:""
		}

		main "water"
		details(["water", "battery"])
	}
}

def parse(String description) {
	def result = null
	if (description.startsWith("Err")) {
	    result = createEvent(descriptionText:description)
	} else {
		def cmd = zwave.parse(description, [0x20: 1, 0x30: 1, 0x31: 5, 0x80: 1, 0x84: 1, 0x71: 3, 0x9C: 1])
		if (cmd) {
			result = zwaveEvent(cmd)
		} else {
			result = createEvent(value: description, descriptionText: description, isStateChange: false)
		}
	}
    log.trace result
	return result
}

def sensorValueEvent(value) {
    log.trace "SensorValueEvent: $value"
	def eventValue = value ? "wet" : "dry"
	createEvent(name: "water", value: eventValue, descriptionText: "$device.displayName is $eventValue")
}

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)
{
    log.trace "NotificationReport: $cmd"
	def result = []
	if (cmd.notificationType == 0x05) {
		result << sensorValueEvent(cmd.event <= 2 ? 255 : 0)
	} else if (cmd.notificationType == 0x04) {
		if (cmd.event <= 0x02) {
			result << createEvent(descriptionText: "$device.displayName detected overheat", isStateChange: true)
		} else if (cmd.event <= 0x04) {
			result << createEvent(descriptionText: "$device.displayName detected rapid temperature rise", isStateChange: true)
		} else {
			result << createEvent(descriptionText: "$device.displayName detected low temperature", isStateChange: true)
		}
	} else if (cmd.notificationType == 0x07) {
		if (cmd.event == 0x03) {
			result << createEvent(descriptionText: "$device.displayName covering was removed", isStateChange: true)
			result << response(zwave.wakeUpV1.wakeUpIntervalSet(seconds:4*3600, nodeid:zwaveHubNodeId))
		} else if (cmd.event == 254) {
            result << sensorValueEvent(!cmd.v1AlarmLevel)
        }
	} 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 result = [createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)]
	if (!state.lastbat || (new Date().time) - state.lastbat > 53*60*60*1000) {
		result << response(zwave.batteryV1.batteryGet())
	} else {
		result << response(zwave.wakeUpV1.wakeUpNoMoreInformation())
	}
	result
}

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.sensormultilevelv5.SensorMultilevelReport cmd)
{
	def map = [ displayed: true, value: cmd.scaledSensorValue.toString() ]
	switch (cmd.sensorType) {
		case 1:
			map.name = "temperature"
			map.unit = cmd.scale == 1 ? "F" : "C"
			break;
		case 5:
			map.name = "humidity"
			map.value = cmd.scaledSensorValue.toInteger().toString()
			map.unit = cmd.scale == 0 ? "%" : ""
			break;
	}
	createEvent(map)
}

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

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)

	if (msr == "0086-0002-002D") {  // Aeon Water Sensor needs to have wakeup interval set
		result << response(zwave.wakeUpV1.wakeUpIntervalSet(seconds:4*3600, nodeid:zwaveHubNodeId))
	}
	result << createEvent(descriptionText: "$device.displayName MSR: $msr", isStateChange: false)
	result
}

It’s the reason why I get in a habit of adding the word “custom” in front of the name. That way I know not only it’s at the bottom but the word custom is there. Awesome that you got it sorted out and working.

That’s a great idea, Ray! I appreciate you chiming in!

1 Like

I have a few of the GoControl door sensors on my doors and was considering upgrading them to the Monorprice recessed door sensors.

Does anyone know if I can use the GoControl sensors for this hack?? Also, do the originals who did this hack have any insight into how they held up long term??

I’m using a couple of the GoControls and they also work with the water sensor DTH.

Good to know! So you basically just screwed 2 wires into the unused port, left the other ends of the wires separate, and when water connects the circuit it goes from dry to wet?

Yes. Mine still working (I hope) since it hasn’t gotten wet since last testing.

yup. Drilled a hole on the shell near the screw terminal and ran my wires through it. One jsut have the wires dangling into my sump pit and the other has the wires coiled around a wooden dowl that lays on the ground.

Mine are going strong on original batteries a year later. I just tested them last week (unannounced and immediately got a worried text from the wife).

Awesome, I want to set up a bunch around the house and maybe get a water main valve that turns off automatically if they are activated.

Problem is, I am going to need one in every bathroom, kitchen sinks plus W/D, and hot water heater. That is like 9 of them…

#automationwoes