Geo Fencing


#1

I am interested if there is a way to use geo fencing (my cell phone location) to sense when I get to the my drive. What I am looking for initially is a means to a: open the garage door, b: turn on lights, etc.

Ideas?


#2

The only officially supported location service is Life 360.

I wouldn't use that to open a garage door though, too risky that it might fire off when you're not actually there. I use Google Assistant to open the garage door when I get a few doors down from home.


#3

Life 360 integration works great, however I'd be wary with opening the garage door automatically.


#4

What type of phone are you using? iPhone? Droid?


#5

Life360. Make sure you set it up to refresh


#6

I use a combined system with a couple apps like Locative which talks to MakerAPI which in turn uses a virtual presence device. I also use the native Life360 integration and a ST Fob as well as a WiFi check for the phones static address.

I then use a custom app to create a combined presence check with a threshold variable. If the collection of presence detection methods listed above reach the set threshold the presence event is thrown and another unified virtual presence device is set.

This method has completely eliminated false events for the phone’s unreliable GPS.


#7

We have droids. I do have Google home. So far I haven't looked into using it to operate my relays from my Hubduino connection.


#8

I use a combination of three things:

  1. [RELEASE] iPhone WiFi Presence Sensor
  2. Alexa app geofencing for presence
  3. [RELEASE] Combined Presence

#9

I modified your combined presence app. It now incorporates a threshold variable and the WiFi Presence sensor, which when present = skip threshold, when not present = check the threshold.

You rejected the PR, so just in case anyone wants it...

parent

/**
 *  Combined Presence
 *
 *  Copyright 2019 Joel Wetzel
 *
 *  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.
 *
 */


definition(
    name: "Combined Presence",
    namespace: "joelwetzel",
    author: "Joel Wetzel",
    description: "An app for Habitat to combine the values of presence sensors.",
    category: "Convenience",
	iconUrl: "",
    iconX2Url: "",
    iconX3Url: "")


preferences {
     page name: "mainPage", title: "", install: true, uninstall: true
}


def installed() {
    log.debug "Installed with settings: ${settings}"
    initialize()
}


def updated() {
    log.debug "Updated with settings: ${settings}"
    unsubscribe()
    initialize()
}


def initialize() {
    log.info "There are ${childApps.size()} child apps"
    childApps.each { child ->
    	log.info "Child app: ${child.label}"
    }
}


def installCheck() {         
	state.appInstalled = app.getInstallationState()
	
	if (state.appInstalled != 'COMPLETE') {
		section{paragraph "Please hit 'Done' to install '${app.label}' parent app "}
  	}
  	else {
    	log.info "Parent Installed OK"
  	}
}


def getImage(type) {
    def loc = "<img src=https://raw.githubusercontent.com/bptworld/Hubitat/master/resources/images/"
    if(type == "Blank") return "${loc}blank.png height=35 width=5}>"
}


def getFormat(type, myText=""){
	if(type == "header-green") return "<div style='color:#ffffff;font-weight: bold;background-color:#81BC00;border: 1px solid;box-shadow: 2px 3px #A9A9A9'>${myText}</div>"
    if(type == "line") return "\n<hr style='background-color:#1A77C9; height: 1px; border: 0;'></hr>"
	if(type == "title") return "<h2 style='color:#1A77C9;font-weight: bold'>${myText}</h2>"
}


def display(){
	section() {
		paragraph getFormat("line")
		paragraph "<div style='color:#1A77C9;text-align:center'>Combined Presence - @joelwetzel<br><a href='https://github.com/joelwetzel/' target='_blank'>Click here for more Hubitat apps/drivers on my GitHub!</a></div>"
	}       
}


def mainPage() {
    dynamicPage(name: "mainPage") {
    	installCheck()
		
		if (state.appInstalled == 'COMPLETE') {
			section(getFormat("title", "${app.label}")) {
				paragraph "Combine two or more presence sensors to control an output Virtual Presence Sensor.  It uses a boolean-OR to combine them."
			}
  			section("<b>Bindings:</b>") {
				app(name: "anyOpenApp", appName: "Combined Presence Instance", namespace: "joelwetzel", title: "<b>Add a new combined presence</b>", multiple: true)
			}
			section("<b>General</b>") {
       			label title: "Enter a name for parent app (optional)", required: false
 			}
			display()
		}
	}
}

And the Child

/**
 *  Combined Presence Instance
 *
 *	Author: Joel Wetzel, Doug Beard
 *
 *  Original Copyright below, this work has been heavily modified with really only the original concept remaining.
 * 
 *  Copyright 2019 Joel Wetzel
 *
 *  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.
 *
 */


definition(
    name: "Combined Presence Instance",
	parent: "joelwetzel:Combined Presence",
    namespace: "joelwetzel",
    author: "Doug Beard",
    description: "This will set a virtual presence sensor to the logical-OR of all the input sensors",
    category: "Safety & Security",
	iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
    iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")


def inputSensors = [
		name:				"inputSensors",
		type:				"capability.presenceSensor",
		title:				"Input Sensors",
		//description:		"",
		multiple:			true,
		required:			true
	]

def wifiPresenceSensor = [
		name:				"wifiSensor",
		type:				"capability.presenceSensor",
		title:				"WiFi Sensor",
		//description:		"",
		multiple:			false,
		required:			false
	]


def outputSensor = [
		name:				"outputSensor",
		type:				"capability.presenceSensor",
		title:				"Output Sensor",
		//description:		"",
		multiple:			false,
		required:			true
	]

def thresholdInput = [
		name:				"threshold",
		type:				"int",
		title:				"Departure Threshold",
		//description:		"",
		multiple:			false,
		required:			true
	]

def thresholdArrivalInput = [
		name:				"arrivalthreshold",
		type:				"int",
		title:				"Arrival Threshold",
		//description:		"",
		multiple:			false,
		required:			true
	]


preferences {
	page(name: "mainPage", title: "<b>Presence Sensors:</b>", install: true, uninstall: true) {
		section("") {
			input inputSensors
			input outputSensor
			input thresholdInput
			input thresholdArrivalInput
			input wifiPresenceSensor
		}
		
		
		section("") {
            input "isDebug", "bool", title: "Enable Debug Logging", required: false, multiple: false, defaultValue: false, submitOnChange: true
        }
	}
}


def installed() {
	log.info "Installed with settings: ${settings}"

	initialize()
}


def updated() {
	log.info "Updated with settings: ${settings}"

	unsubscribe()
	initialize()
}



def initialize() {
	subscribe(inputSensors, "presence.present", presenceChangedHandler)
	subscribe(inputSensors, "presence.not present", presenceChangedHandler)
	if (wifiSensor){
		subscribe(wifiSensor, "presence.not present", wifiPresenceChangedHandler)
	}
	app.updateLabel("Combined Presence for ${outputSensor.displayName}")
}

def wifiPresenceChangedHandler(evt) {
	sendEvent(name:"Presence Changed", value: "$evt.device - $evt.value", displayed:false, isStateChange: false)
	switch(evt.value){
		case "not present":
			int count = 0
			inputSensors.each { inputSensor ->
				if (inputSensor.currentValue("presence") == "not present") {
					ifDebug("${inputSensor.label} not present")
					count++
				}
			}
			ifDebug("$count sensors not present")
			if (count >= Integer.parseInt(threshold)){
				ifDebug("Threshold met setting not present")
				sendEvent(name:"Threshold", value: "$threshold met", displayed:false, isStateChange: false)
				outputSensor.departed()
				sendEvent(name:"Combined Presence", value: "departed", displayed:false, isStateChange: false)
			}	
				break
		case "present":
			ifDebug("WiFi Present, skip threshold check")
			sendEvent(name:"Combined Presence", value: "arrived", displayed:false, isStateChange: false)
		
			outputSensor.arrived()	
	}
}


def presenceChangedHandler(evt) {
	sendEvent(name:"Presence Changed", value: "$evt.device - $evt.value", displayed:false, isStateChange: false)
	switch(evt.value){
		case "not present":
			int count = 0
			inputSensors.each { inputSensor ->
				if (inputSensor.currentValue("presence") == "not present") {
					ifDebug("${inputSensor.label} not present")
					count++
				}
			}
			ifDebug("$count sensors not present")
			if (count >= Integer.parseInt(threshold)){
				ifDebug("Threshold met setting not present")
				sendEvent(name:"Threshold", value: "$threshold met", displayed:false, isStateChange: false)
				outputSensor.departed()
				sendEvent(name:"Combined Presence", value: "departed", displayed:false, isStateChange: false)
			}	
				break
		case "present":
			int count = 0
			inputSensors.each { inputSensor ->
				if (inputSensor.currentValue("presence") == "present") {
					sendEvent(name:"Arrival Threshold", value: "$arrivalthreshold met", displayed:false, isStateChange: false)
					ifDebug("${inputSensor.label} present")
					count++
				}
			}
			ifDebug("$count sensors present")
			if (count >= Integer.parseInt(arrivalthreshold)){
				ifDebug("Threshold met setting present")
				outputSensor.arrived()	
				sendEvent(name:"Combined Presence", value: "arrived", displayed:false, isStateChange: false)

			}	
				break
	}
}

private ifDebug(msg)     
{  
    if (msg && isDebug)  log.debug "Combined Presence for $outputSensor.displayName: " + msg  
}

#10

@doug

Hey man,

Trying to install this and the "parent:" is causing issues. Is this a child app for the Combined Presence or was this the proposed merge code?


#11

Hmmm, what I originally posted was just the child app.
Do you have the parent already installed? I don't believe I made any additions to it.
You also need to be sure to install the wifi presence driver.

Just in case I've posted my copy of the parent app, in the above posting.

Hope that helps.