Okay...I thought you meant that you were using both for yourself.
So, for the ST presence sensor, there's a driver that has Enable and disable like a normal switch.
import groovy.json.JsonOutput
/**
*
* ST Arrival Sensor (Advanced)
*
* Copyright 2019 Ryan Casler
* Developed from LLWarrenP's "Arrival Sensor HA with Disable"
*
* 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.0"
}
/*
* Change Log:
* 2019-3-13 - (1.0) Initial release
*/
metadata {
definition (name: "ST Arrival Sensor (Advanced)", namespace: "ryan780", author: "ryan780") {
capability "Tone"
capability "Actuator"
capability "Presence Sensor"
capability "Sensor"
capability "Battery"
capability "Configuration"
capability "Switch"
attribute "enabled", "string"
command "enable"
command "disable"
command "toggle"
command "disableDelayedEnable", ["minutes"]
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
input name: "logEnable", type: "bool", title: "Enable debug logging", defaultValue: true
}
}
}
def updated() {
startTimer()
log.info "updated..."
log.warn "debug logging is: ${logEnable == true}"
if (logEnable) runIn(1800, logsOff)
}
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 logsOff() {
log.warn "debug logging disabled..."
device.updateSetting("logEnable", [value: "false", type: "bool"])
}
def configure() {
def cmds = zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020) + zigbee.batteryConfig(20, 20, 0x01)
if (logEnable) log.debug "configure -- cmds: ${cmds}"
return cmds
}
def beep() {
if (logEnable) 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
]
if (logEnable) 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) {
if (logEnable) log.debug "Sensor is present"
startTimer()
} else if (!present) {
if (logEnable) 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
if (logEnable) 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)
if (logEnable)log.debug "Creating presence event: ${device.displayName} ${eventMap.name} is ${eventMap.value} with status ${device.currentValue("enabled")}"
sendEvent(eventMap)
}
}
private startTimer() {
if (logEnable)log.debug "Scheduling periodic timer"
runEvery1Minute("checkPresenceCallback")
}
private stopTimer() {
if (logEnable)log.debug "Stopping periodic timer"
unschedule()
}
def checkPresenceCallback() {
def timeSinceLastCheckin = (now() - state.lastCheckin) / 1000
def theCheckInterval = (checkInterval ? checkInterval as int : 2) * 60
if (logEnable)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
if (logEnable)log.debug "Setting sensor presence to ${settings.enabledMode}"
sendEvent(name: "switch", value: "on", isStateChange: true)
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
if (logEnable)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
if (logEnable)log.debug "Setting sensor presence to ${settings.disabledMode}"
sendEvent(name: "switch", value: "off", isStateChange: true)
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
if (logEnable)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)
}
def disableDelayedEnable(delay) {
unschedule()
disable()
myDelay=(delay.toInteger())*60
runIn(myDelay, enable)
}
def on(){
enable()
}
def off(){
disable()
}
When disabled you can have the presence be whatever you choose in the driver. If you're using life 360 for your other presence, that's going to be a little tougher since that uses a built in app and driver that no one but hubitat staff has access to. You best bet might be to look at Combined Presence. it's a Cobra app. That way, you can control what state the virtual presence sensor you create is in manually. That's the only way I can think to accomplish what you want. Not a clean method to be sure. Might just be easier to get a powerbank to charge your phone up.
I have to say, when I first read your post and read "left my phone at home" i thought at first you were joking. The thought of leaving home without my phone has become almost unthinkable. lol