My v4 tags have been some of the most reliable things I've bought for this integration. I just replace the battery every month and don't think about it after that.
The only issue I had so far is:
It sits as present and suddenly middle of night it goes to not present and 1m later changes back to present. So can't really use it.
yeah, like I've already mentioned they go away, then return during the morning back up.
Not much can be done about this ATM.
All my presence related rules have constraints that prevent those events from effecting anything important.
Thanks
It's only a success if you actually wanted your wife to come home.
That said, I have been experiencing this issue all along...
I assure everyone I was in bed when this happened..
presence | present | Steve's Fob has arrived | DEVICE | 2019-03-06 12:54:06.334 AM EST | ||
---|---|---|---|---|---|---|
presence | not present | Steve's Fob has departed | DEVICE | 2019-03-06 12:47:45.202 AM EST |
I spun up a test fob whilst troubleshooting the Zigbee issues. It sits in a closet in an adjacent room.. Notice the time correlation for todays event?
presence | present | Test Fob has arrived | DEVICE | 2019-03-06 12:52:04.719 AM EST | ||
---|---|---|---|---|---|---|
presence | not present | Test Fob has departed | DEVICE | 2019-03-06 12:47:45.421 AM EST |
This fob never leaves the closet, yet it appears that it has quite the social life...
presence | present | Test Fob has arrived | DEVICE | 2019-02-10 09:43:16.067 PM EST | ||
---|---|---|---|---|---|---|
presence | not present | Test Fob has departed | DEVICE | 2019-02-10 07:23:06.574 PM EST | ||
presence | present | Test Fob has arrived | DEVICE | 2019-02-10 05:34:14.080 PM EST | ||
presence | not present | Test Fob has departed | DEVICE | 2019-02-10 04:13:49.915 PM EST | ||
presence | present | Test Fob has arrived | DEVICE | 2019-02-10 02:34:32.242 PM EST |
I have another fob that lives in my carry bag with my iPads and laptop...
presence | present | Steve's Work Bag Fob has arrived | DEVICE | 2019-03-06 12:52:05.170 AM EST | ||
---|---|---|---|---|---|---|
presence | not present | Steve's Work Bag Fob has departed | DEVICE | 2019-03-06 12:47:44.671 AM EST |
Again with the same correlation as the other events. Its almost as if the hub stopped processing Zigbee events, only from fobs though. This one however, aside from todays event, has been rock solid.
These are my only misbehaving Zigbee devices.
Presence Central has the facility to βdelayβ leaving or arriving if you want to have a look.
I had to add this because I have an app that screams if the presence sensors in the cars leave after midnight.
WAF is not high when the house screams at 3am
Andy
@Somel
what do you have your arrival sensor Presence timeout set at?
@mike.maxwell
could you add longer or ability for a custom Presence timeout to the DH?
mine is set to the max 5 minutes and I rarely (but looking through the logs occasionally) have the random depart and arrive.
Default value?! 2min....
By the way what does this feature really do?! What happens on no selection?!
10 minute and 15 minute options will be in 2.0.7, also added the Tone capability (beep)
Can I create a dashboard tile with the attribute?!
Beep is the command published by the tone capability, Tone has no attributes, and I do not know if Tone is published in the dashboard.
This is the amount of time from last sensor check in to the departed event. If the device comes back online before the timeout expires, no events are generated.
LMAO
@mike.maxwell
just curious
so if "no selection" is selected on the presence timeout does it just use the default timeout?
Yes, default is 2 minutes.
I hope the changes doesn't screw up the presence, from day 1 (I started with HE in July 2018) I never had any issues with HE and presence, I only saw that behavior of going not present randomly when I was with ST combined with one of 2 other events, the internet dropped or the sensor was routed through a bulb. I never seen my presence changed when the hub is doing backup or any other events like the one I mentioned for ST. My presence has been so good that I wanted to have 1 minute timeout.
adding beep, verifying battery reports work and adding a few more timeout options isn't going to effect the base functionality, that section in the driver wasn't touched.
This is awesome, thanks Mike!
There's a driver I found in the ST forum that might be of help to some folks. The driver allows you to disable reading the presence from the fob and set it manually by a command of Disable. I've set it up so the fob is "disabled" when I'm not in away mode and when in away mode, it "enables" 5 minutes later (via RM). It also supports the beep function.
import groovy.json.JsonOutput
/**
*
* Arrival Sensor HA with Disable
*
* Copyright 2018 Warren Poschman
*
* 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.
*
*/
def dthVersion() {
return "1.1"
}
/*
* Change Log:
* 2018-7-29 - (1.1) Improved tracking and added user options to force mode upon enable / disable
* 2018-7-26 - (1.0) Initial release
* 2018-7-24 - (0.1) Debug release
*/
metadata {
definition (name: "Arrival Sensor HA with Disable", namespace: "LLWarrenP", author: "LLWarrenP") {
capability "Tone"
capability "Actuator"
capability "Presence Sensor"
capability "Sensor"
capability "Battery"
capability "Configuration"
capability "Health Check"
attribute "enabled", "string"
command "enable"
command "disable"
command "toggle"
fingerprint inClusters: "0000,0001,0003,000F,0020", outClusters: "0003,0019",
manufacturer: "SmartThings", model: "tagv4", deviceJoinName: "Arrival Sensor"
}
preferences {
section {
image(name: 'educationalcontent', multiple: true, images: [
"http://cdn.device-gse.smartthings.com/Arrival/Arrival1.png",
"http://cdn.device-gse.smartthings.com/Arrival/Arrival2.png"
])
}
section {
input "checkInterval", "enum", title: "Presence timeout (minutes)", description: "Tap to set",
defaultValue:"2", options: ["2", "3", "5"], displayDuringSetup: false
}
section {
input "disabledMode", "enum", title: "When disabling sensor, set presence to:", description: "Tap to set",
defaultValue:"auto", options: ["auto", "present", "not present"], displayDuringSetup: false
input "enabledMode", "enum", title: "When enabling sensor, set presence to:", description: "Tap to set",
defaultValue:"auto", options: ["auto", "present", "not present"], displayDuringSetup: false
}
}
}
def updated() {
startTimer()
}
def installed() {
// Arrival sensors only goes OFFLINE when Hub is off
sendEvent(name: "DeviceWatch-Enroll", value: JsonOutput.toJson([protocol: "zigbee", scheme:"untracked"]), displayed: false)
}
def configure() {
def cmds = zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020) + zigbee.batteryConfig(20, 20, 0x01)
log.debug "configure -- cmds: ${cmds}"
return cmds
}
def beep() {
log.debug "Sending Identify command to beep the sensor for 5 seconds"
return zigbee.command(0x0003, 0x00, "0500")
}
def parse(String description) {
state.lastCheckin = now()
handlePresenceEvent(true)
if (description?.startsWith('read attr -')) {
handleReportAttributeMessage(description)
}
return []
}
private handleReportAttributeMessage(String description) {
def descMap = zigbee.parseDescriptionAsMap(description)
if (descMap.clusterInt == 0x0001 && descMap.attrInt == 0x0020) {
handleBatteryEvent(Integer.parseInt(descMap.value, 16))
}
}
/**
* Create battery event from reported battery voltage.
*
* @param volts Battery voltage in .1V increments
*/
private handleBatteryEvent(volts) {
def descriptionText
if (volts == 0 || volts == 255) {
log.debug "Ignoring invalid value for voltage (${volts/10}V)"
}
else {
def batteryMap = [28:100, 27:100, 26:100, 25:90, 24:90, 23:70,
22:70, 21:50, 20:50, 19:30, 18:30, 17:15, 16:1, 15:0]
def minVolts = 15
def maxVolts = 28
if (volts < minVolts)
volts = minVolts
else if (volts > maxVolts)
volts = maxVolts
def value = batteryMap[volts]
if (value != null) {
def linkText = getLinkText(device)
descriptionText = '{{ linkText }} battery was {{ value }}'
def eventMap = [
name: 'battery',
value: value,
descriptionText: descriptionText,
translatable: true
]
log.debug "Creating battery event for voltage=${volts/10}V: ${linkText} ${eventMap.name} is ${eventMap.value}%"
sendEvent(eventMap)
}
}
}
private handlePresenceEvent(present) {
def wasPresent = device.currentState("presence")?.value == "present"
if (!wasPresent && present) {
log.debug "Sensor is present"
startTimer()
} else if (!present) {
log.debug "Sensor is not present"
stopTimer()
}
def linkText = getLinkText(device)
def descriptionText
def enabledStatus = ""
if ( present )
descriptionText = "{{ linkText }} has arrived"
else
descriptionText = "{{ linkText }} has left"
if ((device.currentValue("enabled") == "disabled-present") || (device.currentValue("enabled") == "disabled-not present")) {
// Device is disabled so we won't generate a presence event but instead just track the status behind the scenes by generating an enabled event
log.debug "${linkText} is ${device.currentValue("enabled")}: not creating presence event"
enabledStatus = "disabled-"
enabledStatus = enabledStatus.concat(present ? "present" : "not present")
if (device.currentValue("enabled") != enabledStatus) sendEvent(name: "enabled", value: enabledStatus, isStateChange: true)
}
else {
// Device is enabled so we will generate a presence event and an enabled event
def eventMap = [
name: "presence",
value: present ? "present" : "not present",
linkText: linkText,
descriptionText: descriptionText,
translatable: true
]
enabledStatus = "enabled-"
enabledStatus = enabledStatus.concat(present ? "present" : "not present")
if (device.currentValue("enabled") != enabledStatus) sendEvent(name: "enabled", value: enabledStatus, isStateChange: true)
log.debug "Creating presence event: ${device.displayName} ${eventMap.name} is ${eventMap.value} with status ${device.currentValue("enabled")}"
sendEvent(eventMap)
}
}
private startTimer() {
log.debug "Scheduling periodic timer"
runEvery1Minute("checkPresenceCallback")
}
private stopTimer() {
log.debug "Stopping periodic timer"
unschedule()
}
def checkPresenceCallback() {
def timeSinceLastCheckin = (now() - state.lastCheckin) / 1000
def theCheckInterval = (checkInterval ? checkInterval as int : 2) * 60
log.debug "Sensor checked in ${timeSinceLastCheckin} seconds ago"
if (timeSinceLastCheckin >= theCheckInterval) {
handlePresenceEvent(false)
}
}
def toggle() {
// Button pressed, toggle the enabled state (which also tracks the current presence)
if ((device.currentValue("enabled") == "enabled-present") || (device.currentValue("enabled") == "enabled-not present"))
disable()
else
enable()
}
def enable() {
// Force presence per user settings
log.debug "Setting sensor presence to ${settings.enabledMode}"
if (settings.enabledMode && (settings.enabledMode != "auto")) {
stopTimer()
sendEvent(name: "presence", value: settings.enabledMode, translatable: true)
}
else if (settings.enabledMode && (settings.enabledMode == "auto"))
startTimer()
// Enable the device and update the enabled status to reflect the new status
log.debug "Enabling ${getLinkText(device)}"
if (device.currentValue("presence") == "present")
sendEvent(name: "enabled", value: "enabled-present", isStateChange: true)
else if (device.currentValue("presence") == "not present")
sendEvent(name: "enabled", value: "enabled-not present", isStateChange: true)
}
def disable() {
// Force presence per user settings
log.debug "Setting sensor presence to ${settings.disabledMode}"
if (settings.disabledMode && (settings.disabledMode != "auto")) {
stopTimer()
sendEvent(name: "presence", value: settings.disabledMode, translatable: true)
}
else if (settings.disabledMode && (settings.disabledMode == "auto"))
startTimer()
// Disable the device and update the enabled status to reflect the new status
log.debug "Disabling ${getLinkText(device)}"
state.updatePresence = false
if (device.currentValue("presence") == "present")
sendEvent(name: "enabled", value: "disabled-present", isStateChange: true)
else if (device.currentValue("presence") == "not present")
sendEvent(name: "enabled", value: "disabled-not present", isStateChange: true)
}
I didn't even have to make any modifications to this one...it worked directly from ST.
Thanks Ryan,
This is a great find and would be nice if @mike.maxwell could incorporate such feature on the HE Driver just for a reason of support.
This could help the "ghosts leaves" to disappear when at home.
Question though if it is disabled how does it know that it has left the house?
I'm guessing that you use other rules besides the fob to know if you have left the house correct?