mirror of
https://github.com/home-assistant/android
synced 2024-09-18 23:52:51 +00:00
Geofencing Improvements (#1048)
* Send an event when we enter or exit a zone * Add more event data * Change event name, update geofence registration logic, add zone entity ID to event * Track geofence registration * Remove geofences as needed, ignore updates within 5 seconds unless geofence event * Reset variable when sending location * Review comments
This commit is contained in:
parent
6cf4b41d92
commit
48afca5427
|
@ -9,6 +9,7 @@ import android.location.Location
|
|||
import android.os.Build
|
||||
import android.os.PowerManager
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.ContextCompat.getSystemService
|
||||
import com.google.android.gms.location.Geofence
|
||||
import com.google.android.gms.location.GeofencingEvent
|
||||
|
@ -72,6 +73,8 @@ class LocationSensorManager : BroadcastReceiver(), SensorManager {
|
|||
|
||||
private var lastLocationSend = 0L
|
||||
private var lastUpdateLocation = ""
|
||||
|
||||
private var geofenceRegistered = false
|
||||
}
|
||||
|
||||
@Inject
|
||||
|
@ -122,6 +125,11 @@ class LocationSensorManager : BroadcastReceiver(), SensorManager {
|
|||
isBackgroundLocationSetup = false
|
||||
isZoneLocationSetup = false
|
||||
}
|
||||
if (backgroundEnabled && !zoneEnabled && isZoneLocationSetup) {
|
||||
removeGeofenceUpdateRequests()
|
||||
isZoneLocationSetup = false
|
||||
Log.d(TAG, "Removing geofence update requests")
|
||||
}
|
||||
if (backgroundEnabled && !isBackgroundLocationSetup) {
|
||||
isBackgroundLocationSetup = true
|
||||
requestLocationUpdates()
|
||||
|
@ -143,9 +151,14 @@ class LocationSensorManager : BroadcastReceiver(), SensorManager {
|
|||
|
||||
fusedLocationProviderClient.removeLocationUpdates(backgroundIntent)
|
||||
|
||||
removeGeofenceUpdateRequests()
|
||||
}
|
||||
|
||||
private fun removeGeofenceUpdateRequests() {
|
||||
val geofencingClient = LocationServices.getGeofencingClient(latestContext)
|
||||
val zoneIntent = getLocationUpdateIntent(true)
|
||||
geofencingClient.removeGeofences(zoneIntent)
|
||||
geofenceRegistered = false
|
||||
}
|
||||
|
||||
private fun requestLocationUpdates() {
|
||||
|
@ -170,6 +183,11 @@ class LocationSensorManager : BroadcastReceiver(), SensorManager {
|
|||
return
|
||||
}
|
||||
|
||||
if (geofenceRegistered) {
|
||||
Log.w(TAG, "Not registering for zones as we already have")
|
||||
return
|
||||
}
|
||||
|
||||
Log.d(TAG, "Registering for zone based location updates")
|
||||
|
||||
try {
|
||||
|
@ -204,12 +222,48 @@ class LocationSensorManager : BroadcastReceiver(), SensorManager {
|
|||
|
||||
private fun handleGeoUpdate(intent: Intent) {
|
||||
Log.d(TAG, "Received geofence update.")
|
||||
if (!isEnabled(latestContext, zoneLocation.id)) {
|
||||
isZoneLocationSetup = false
|
||||
Log.w(TAG, "Unregistering geofences as zone tracking is disabled and intent was received")
|
||||
removeGeofenceUpdateRequests()
|
||||
return
|
||||
}
|
||||
val geofencingEvent = GeofencingEvent.fromIntent(intent)
|
||||
if (geofencingEvent.hasError()) {
|
||||
Log.e(TAG, "Error getting geofence broadcast status code: ${geofencingEvent.errorCode}")
|
||||
return
|
||||
}
|
||||
|
||||
val validGeofencingEvents = listOf(Geofence.GEOFENCE_TRANSITION_ENTER, Geofence.GEOFENCE_TRANSITION_EXIT)
|
||||
if (geofencingEvent.geofenceTransition in validGeofencingEvents) {
|
||||
val zoneStatusEvent = when (geofencingEvent.geofenceTransition) {
|
||||
Geofence.GEOFENCE_TRANSITION_ENTER -> "android.zone_entered"
|
||||
Geofence.GEOFENCE_TRANSITION_EXIT -> "android.zone_exited"
|
||||
else -> ""
|
||||
}
|
||||
val zoneAttr = mapOf(
|
||||
"accuracy" to geofencingEvent.triggeringLocation.accuracy,
|
||||
"altitude" to geofencingEvent.triggeringLocation.altitude,
|
||||
"bearing" to geofencingEvent.triggeringLocation.bearing,
|
||||
"latitude" to geofencingEvent.triggeringLocation.latitude,
|
||||
"longitude" to geofencingEvent.triggeringLocation.longitude,
|
||||
"provider" to geofencingEvent.triggeringLocation.provider,
|
||||
"time" to geofencingEvent.triggeringLocation.time,
|
||||
"vertical_accuracy" to if (Build.VERSION.SDK_INT >= 26) geofencingEvent.triggeringLocation.verticalAccuracyMeters.toInt() else 0,
|
||||
"zone" to geofencingEvent.triggeringGeofences[0].requestId
|
||||
)
|
||||
runBlocking {
|
||||
try {
|
||||
integrationUseCase.fireEvent(zoneStatusEvent, zoneAttr as Map<String, Any>)
|
||||
Log.d(TAG, "Event sent to Home Assistant")
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Unable to send event to Home Assistant", e)
|
||||
Toast.makeText(latestContext, R.string.zone_event_failure, Toast.LENGTH_LONG)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val sensorDao = AppDatabase.getInstance(latestContext).sensorDao()
|
||||
val sensorSettings = sensorDao.getSettings(zoneLocation.id)
|
||||
val minAccuracy = sensorSettings
|
||||
|
@ -224,11 +278,11 @@ class LocationSensorManager : BroadcastReceiver(), SensorManager {
|
|||
)
|
||||
requestSingleAccurateLocation()
|
||||
} else {
|
||||
sendLocationUpdate(geofencingEvent.triggeringLocation)
|
||||
sendLocationUpdate(geofencingEvent.triggeringLocation, "", true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun sendLocationUpdate(location: Location, name: String = "") {
|
||||
private fun sendLocationUpdate(location: Location, name: String = "", geofenceUpdate: Boolean = false) {
|
||||
Log.d(
|
||||
TAG, "Last Location: " +
|
||||
"\nCoords:(${location.latitude}, ${location.longitude})" +
|
||||
|
@ -256,6 +310,11 @@ class LocationSensorManager : BroadcastReceiver(), SensorManager {
|
|||
Log.d(TAG, "Duplicate location received, not sending to HA")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if (now < lastLocationSend + 5000 && !geofenceUpdate) {
|
||||
Log.d(TAG, "New location update not possible within 5 seconds, not sending to HA")
|
||||
return
|
||||
}
|
||||
}
|
||||
lastLocationSend = now
|
||||
lastUpdateLocation = updateLocation.gps.contentToString()
|
||||
|
@ -304,6 +363,7 @@ class LocationSensorManager : BroadcastReceiver(), SensorManager {
|
|||
.build()
|
||||
)
|
||||
}
|
||||
geofenceRegistered = true
|
||||
return geofencingRequestBuilder.build()
|
||||
}
|
||||
|
||||
|
|
|
@ -77,6 +77,7 @@ to your home internet.</string>
|
|||
<string name="connected_to_home_assistant">Connected to Home Assistant</string>
|
||||
<string name="create_template">Create Template</string>
|
||||
<string name="database_event_failure">Unable to send migration failure event to Home Assistant</string>
|
||||
<string name="zone_event_failure">Unable to send zone event to Home Assistant</string>
|
||||
<string name="database_migration_failed">Database migration failed, all sensor and widget data has been reset. Please re-enable your sensors and recreate your widgets.</string>
|
||||
<string name="developer_tools">Developer Tools</string>
|
||||
<string name="device_class">Device Class</string>
|
||||
|
|
Loading…
Reference in a new issue