The gocontrol motion sensor also detects temp!


#8

Hi John, I took your modifications and tweaked it a bit further by adding a "Temperature Adjustment" feature in preferences.

    /**
 *  Generic Z-Wave Motion Sensor
 *
 *  Author: SmartThings with modifications by John Lord, copy & pasted Temperature adjust code by Jimxenus
 *  Date: 2013-11-25, 6-10-2015, 11-1-2015
 */

metadata {
    // Automatically generated. Make future change here.
    definition (name: "Go Control Z-Wave Motion Sensor w/Temperature adjust", namespace: "smartthings", author: "SmartThings") {
        capability "Motion Sensor"
        capability "Sensor"
        capability "Battery"
       capability "Temperature Measurement"
      
    }

    simulator {
        status "inactive": "command: 3003, payload: 00"
        status "active": "command: 3003, payload: FF"
    }
    
    preferences {
        input 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: "Temperature Offset", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false
    }

    tiles {
        standardTile("motion", "device.motion", width: 2, height: 2) {
            state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0")
            state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff")
        }
        valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
            state("battery", label:'${currentValue}% battery', unit:"")
        }
        valueTile("temperature", "device.temperature") {
            state("temperature", label:'${currentValue}°', unit:"F",
                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"]
                ]
            )
        }
        
        main "motion"
        details(["motion", "battery", "temperature"])
    }
}

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

def sensorValueEvent(Short value) {
    if (value) {
        createEvent(name: "motion", value: "active", descriptionText: "$device.displayName detected motion")
    } else {
        createEvent(name: "motion", value: "inactive", descriptionText: "$device.displayName motion has stopped")
    }
}

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 == 0x07) {
        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 << sensorValueEvent(1)
        }
    } 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())
        result << response("delay 1200")
    }
    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:
            // temperature
            def cmdScale = cmd.scale == 1 ? "F" : "C"
            def preValue = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision)
            def value = preValue as float
            if (tempOffset) {
                def offset = tempOffset as float
                map.value = value + offset as float
                map.value = map.value.round()
            }
            else {
                map.value = value as float
                map.value = map.value.round()
            }    
            map.unit = getTemperatureScale()
            map.name = "temperature"
            break;
        case 3:
            map.name = "illuminance"
            map.value = cmd.scaledSensorValue.toInteger().toString()
            map.unit = "lux"
            break;
        case 5:
            map.name = "humidity"
            map.value = cmd.scaledSensorValue.toInteger().toString()
            map.unit = cmd.scale == 0 ? "%" : ""
            break;
        case 0x1E:
            map.name = "loudness"
            map.unit = cmd.scale == 1 ? "dBA" : "dB"
            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)

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

(Kevin) #9

I have one of the GoControl WAPIRZ-1 variants and the temperature readings are becoming sporadic. Over the past 3 days, it sent 10 temp readings in a one hour window then nothing the rest of the time. It does report motion as expected and battery level every hour. Also reports tamper alarm=255 every few minutes even though case is closed.


(I got a hair cut from Alexa) #10

I've noticed the same thing. I put mine outside at the front door under the roof overhang, which of course is not recommended. The motion sensor seems to work ok when people show up on my porch, but if the temperature gets low like freezing, the temperature sensor starts getting WAY off like 32F turns into (minus) -21F


(Ray) #11

The ecolink motion spec for temp Operating Temperature: 32° - 120°F (0° - 49°C). So anything 32f and lower will be way off for sure.


(Kevin) #12

Thanks for the feedback; I have mine inside. I'm not seeing radical temperature swings, just lack of reporting temperature for many hours or days. Right now going on 40 hours with no temperature report.


(Ray) #13

Possible there is no temp changed in that room?


(I got a hair cut from Alexa) #14

Thanks Ray, that totally explains it. Hey, do you know if there is a way to mute the temp sensor so it's not filling up my activity feed with junk? :wink:


(Ray) #15

Funny you asked. There are a couple of sensors I don't need to know the temp so I changed it to the genetic ST z-wave motion sensor device type in IDE. This way I am not flooded with activity also for local processing.


(Devesh Batra) #16

I have a couple of these motion sensors that are not reporting temp. Is there an updated device type that i can use to get the temp reading ?

thanks


(Ray) #17

I use the device type in this post and the temp is reporting fine. Not sure about battery but it's working fine since November.

You can also try @RBoy device type. It's not free but you get really good tech support. He also has device type for other devices as well so do a forum search for his devices.


(www.rboyapps.com - Make your home your butler!) #18

Based on the documentation here:
http://www.nortekcontrol.com/pdf/manuals/WAPIRZ_install.pdf

My custom device type for the monoprice should work with the WAPIRZ-1 motion sensor. It looks like they are made off the same design


(www.rboyapps.com - Make your home your butler!) #19

Quoting from the device documentation:

Every rise or drop of 1 degree will trigger a notifi cation to the Hub

Possible your room temp isnt' changing much?


(I got a hair cut from Alexa) #20

That's a great point RBoy. It doesn't seem to show up in the notify unless there's a change. Mine kept flip flopping between 69 and 71 degrees every time the furnace kicked in and later stopped. I added a little code to the standard z-wave driver to accommodate the hysteresis and only report if there was a bigger than 2 degree jump from the last report. It quieted down the reports.


(Kevin) #21

Mine seems to report small changes when it's being "chatty" example... 3am:67.0, nothing for 9 hours then 66.7,67,66.7,67. Sometimes it seems to transmit every 30 minutes. Other times I thought maybe it was sending temp at times it detected motion, but then I see a lot of temp readings 2am-4am without motion. :confused:


(sd@oe.ca) #22

First off, John Lord, THANK YOU! Your script is the first one of many that actually returns a battery level for me for the gocontrol motion detectors that I have.

Unfortunately for the life of me I can't seem to get the code to run in Celsius instead of Fahrenheit. I've changed the unit:"C", map.unit = cmd.scale == 1 ? "F" : "C" to map.unit = cmd.scale == 1 ? "C" : "F" but nothing seems to work, the motion detectors still report Fahrenheit on the tile (setting off my air conditioner prematurely :-p)

Incidentally, the hub is set up to be in Celsius and the script appears to ignore that.

Any idea what I am missing here?

Thanks in advance!


(John Lord) #23

Have you tried just converting it mathematically? It's What I had to do with my scale to display pounds instead of kilograms


(sd@oe.ca) #24

I guess I need to understand where the base variable is controlled. If I change the tile label it will look good, but my IFTTT routines, and others will be calculating on Fahrenheit still, no? Where exactly in your code would I put the TempC = ((TempF - 32) × 5 / 9) so that it reports the same to anything that calls on it?

Cheers,

C


(John Lord) #25

this part: def cmdScale = cmd.scale == 1 ? "F" : "C"
you can't just swap the f and the c. that's actually a java shortcut method of doing an if statement.
similar to this: if (cmd.scale==1 {
cmdScale="F"}
else{cmdScale = "C"}
you could replace that whole line with cmdScale = "C"

however look here: def value = preValue as float

it creates a value as a float then assigns prevalue to it. You can change prevalue here. I'm not sure where the scaling is supposed to take place since the function is built-in somehow to groovy, but if it's not working correctly then simply hardcode it to be value=((preValue-32) * 5 / 9). I'm pretty sure you'll also have to do this separately for the tile though. This will force it to return celsius on the z-wave polling.
first though i would simply try hardcoding cmdScale to "C" though. It may be all you need to do.


(sd@oe.ca) #26

Thanks, yes, that was the first thing I tried (swapping the "F" : "C" to "C" : "F" unfortunately it did nothing to the tile.

What is odd is if I look at the event logs for the detector, it is showing valid Celsius figures, infact the tile temperature is not changing on my android nor is the current state changing on graph-na02-useast1.api.smartthings.com, but the events on both are showing accurate Celsius updates.

Thoroughly confused now.


(John Lord) #27

the underlying code supports c or f but the tile doesn't. You will have to change the unit to "C" there. I'm not sure if that will change currentvalue automatically but at the least you will need to modify the color gradients to represent celsius. The app i based this on wasn't region-aware.