Skip to content

Commit

Permalink
Ensure when sensors are disabled they aren't still polling. (#752)
Browse files Browse the repository at this point in the history
  • Loading branch information
JBassett committed Aug 14, 2020
1 parent 3432461 commit 2e5ee34
Show file tree
Hide file tree
Showing 16 changed files with 343 additions and 252 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,37 @@ class GeocodeSensorManager : SensorManager {

companion object {
private const val TAG = "GeocodeSM"
private val geocodedLocation = SensorManager.BasicSensor(
"geocoded_location",
"sensor",
"Geocoded Location"
)
}

override val name: String
get() = "Geolocation Sensors"
override val availableSensors: List<SensorManager.BasicSensor>
get() = listOf(geocodedLocation)

override fun requiredPermissions(): Array<String> {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION)
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION
)
} else {
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)
}
}

override fun getSensorRegistrations(context: Context): List<SensorRegistration<Any>> {
return listOf(getGeocodedLocation(context))
override fun getSensorData(
context: Context,
sensorId: String
): SensorRegistration<Any> {
return when (sensorId) {
geocodedLocation.id -> getGeocodedLocation(context)
else -> throw IllegalArgumentException("Unknown sensorId: $sensorId")
}
}

private fun getGeocodedLocation(context: Context): SensorRegistration<Any> {
Expand Down Expand Up @@ -63,13 +79,10 @@ class GeocodeSensorManager : SensorManager {
)
}.orEmpty()

return SensorRegistration(
"geocoded_location",
return geocodedLocation.toSensorRegistration(
address?.getAddressLine(0) ?: "Unknown",
"sensor",
"mdi:map",
attributes,
"Geocoded Location"
attributes
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,16 @@ class LocationBroadcastReceiver : BroadcastReceiver(), SensorManager {
const val ACTION_PROCESS_GEO =
"io.homeassistant.companion.android.background.PROCESS_GEOFENCE"

const val ID_BACKGROUND_LOCATION = "location_background"
const val ID_ZONE_LOCATION = "location_zone"

val backgroundLocation = SensorManager.BasicSensor(
"location_background",
"",
"Background Location"
)
val zoneLocation = SensorManager.BasicSensor(
"zone_background",
"",
"Zone Location"
)
internal const val TAG = "LocBroadcastReceiver"

fun restartLocationTracking(context: Context) {
Expand Down Expand Up @@ -94,9 +101,9 @@ class LocationBroadcastReceiver : BroadcastReceiver(), SensorManager {
try {
removeAllLocationUpdateRequests(context)

if (sensorDao.get(ID_BACKGROUND_LOCATION)?.enabled == true)
if (sensorDao.get(backgroundLocation.id)?.enabled == true)
requestLocationUpdates(context)
if (sensorDao.get(ID_ZONE_LOCATION)?.enabled == true)
if (sensorDao.get(zoneLocation.id)?.enabled == true)
requestZoneUpdates(context)
} catch (e: Exception) {
Log.e(TAG, "Issue setting up location tracking", e)
Expand Down Expand Up @@ -292,32 +299,38 @@ class LocationBroadcastReceiver : BroadcastReceiver(), SensorManager {
override val name: String
get() = "Location Sensors"

override val availableSensors: List<SensorManager.BasicSensor>
get() = listOf(backgroundLocation, zoneLocation)

override fun requiredPermissions(): Array<String> {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION)
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION
)
} else {
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)
}
}

override fun getSensorRegistrations(context: Context): List<SensorRegistration<Any>> {
return listOf<SensorRegistration<Any>>(
SensorRegistration(
ID_BACKGROUND_LOCATION,
"",
"",
"mdi:map",
mapOf(),
"Background Location"
),
SensorRegistration(
ID_ZONE_LOCATION,
"",
"",
"mdi:map",
mapOf(),
"Zone Based Location"
)
)
override fun getSensorData(
context: Context,
sensorId: String
): SensorRegistration<Any> {
return when (sensorId) {
zoneLocation.id ->
zoneLocation.toSensorRegistration(
"",
"mdi:map",
mapOf()
)
backgroundLocation.id ->
backgroundLocation.toSensorRegistration(
"",
"mdi:map",
mapOf()
)
else -> throw IllegalArgumentException("Unknown sensorId: $sensorId")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class MobileAppIntegrationFragment : Fragment(), MobileAppIntegrationView {

zoneTracking = findViewById<SwitchCompat>(R.id.location_zone).apply {
setOnCheckedChangeListener { _, isChecked ->
updateSensorDao(LocationBroadcastReceiver.ID_ZONE_LOCATION, isChecked)
updateSensorDao(LocationBroadcastReceiver.zoneLocation.id, isChecked)
}
isEnabled = hasLocationPermission
isChecked = hasLocationPermission
Expand All @@ -102,7 +102,7 @@ class MobileAppIntegrationFragment : Fragment(), MobileAppIntegrationView {

backgroundTracking = findViewById<SwitchCompat>(R.id.location_background).apply {
setOnCheckedChangeListener { _, isChecked ->
updateSensorDao(LocationBroadcastReceiver.ID_BACKGROUND_LOCATION, isChecked)
updateSensorDao(LocationBroadcastReceiver.backgroundLocation.id, isChecked)
}
isEnabled = hasLocationPermission
isChecked = hasLocationPermission && isIgnoringBatteryOptimizations()
Expand All @@ -121,7 +121,7 @@ class MobileAppIntegrationFragment : Fragment(), MobileAppIntegrationView {

callTracking = findViewById<SwitchCompat>(R.id.call_tracking).apply {
setOnCheckedChangeListener { _, isChecked ->
updateSensorDao(PhoneStateSensorManager.ID_PHONE, isChecked)
updateSensorDao(PhoneStateSensorManager.phoneState.id, isChecked)
}
isEnabled = hasPhoneStatePermission
isChecked = hasPhoneStatePermission
Expand Down Expand Up @@ -185,7 +185,7 @@ class MobileAppIntegrationFragment : Fragment(), MobileAppIntegrationView {
zoneTracking.isEnabled = true
zoneTrackingSummary.isEnabled = true
zoneTracking.isChecked = true
updateSensorDao(LocationBroadcastReceiver.ID_ZONE_LOCATION, true)
updateSensorDao(LocationBroadcastReceiver.zoneLocation.id, true)

backgroundTracking.isEnabled = true
backgroundTrackingSummary.isEnabled = true
Expand All @@ -204,7 +204,7 @@ class MobileAppIntegrationFragment : Fragment(), MobileAppIntegrationView {
callTracking.isEnabled = true
callTracking.isChecked = true
callTrackingSummary.isEnabled = true
updateSensorDao(PhoneStateSensorManager.ID_PHONE, true)
updateSensorDao(PhoneStateSensorManager.phoneState.id, true)
} else {
callTracking.isEnabled = false
callTrackingSummary.isEnabled = false
Expand All @@ -215,7 +215,7 @@ class MobileAppIntegrationFragment : Fragment(), MobileAppIntegrationView {
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == BACKGROUND_REQUEST && isIgnoringBatteryOptimizations()) {
zoneTracking.isChecked = true
updateSensorDao(LocationBroadcastReceiver.ID_BACKGROUND_LOCATION, true)
updateSensorDao(LocationBroadcastReceiver.backgroundLocation.id, true)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,63 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.BatteryManager
import android.util.Log
import io.homeassistant.companion.android.domain.integration.SensorRegistration

class BatterySensorManager : SensorManager {

companion object {
const val TAG = "BatterySensor"
private const val TAG = "BatterySensor"
private val batteryLevel = SensorManager.BasicSensor(
"battery_level",
"sensor",
"Battery Level",
"battery",
"%"
)
private val batteryState = SensorManager.BasicSensor(
"battery_state",
"sensor",
"Battery State",
"battery"
)
}

override val name: String
get() = "Battery Sensors"
override val availableSensors: List<SensorManager.BasicSensor>
get() = listOf(batteryLevel, batteryState)

override fun requiredPermissions(): Array<String> {
return emptyArray()
}

override fun getSensorRegistrations(context: Context): List<SensorRegistration<Any>> {
return context.registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))?.let {
val retVal = ArrayList<SensorRegistration<Any>>()

getBatteryLevelSensor(it)?.let { sensor ->
retVal.add(sensor)
override fun getSensorData(
context: Context,
sensorId: String
): SensorRegistration<Any> {
val intent = context.registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
if (intent != null) {
return when (sensorId) {
batteryLevel.id -> getBatteryLevelSensor(intent)
batteryState.id -> getBatteryStateSensor(intent)
else -> throw IllegalArgumentException("Unknown sensorId: $sensorId")
}

getBatteryStateSensor(it)?.let { sensor ->
retVal.add(sensor)
}

return@let retVal
} ?: listOf()
}
throw RuntimeException("Unable to get battery state.")
}

private fun getBatteryPercentage(level: Int, scale: Int): Int {
private fun getBatteryPercentage(intent: Intent): Int {
val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
return (level.toFloat() / scale.toFloat() * 100.0f).toInt()
}

private fun getBatteryIcon(percentage: Int, isCharging: Boolean = false, chargerType: String? = null, chargingStatus: String? = null): String {
private fun getBatteryIcon(
percentage: Int,
isCharging: Boolean = false,
chargerType: String? = null,
chargingStatus: String? = null
): String {
var batteryIcon = "mdi:battery"

if (chargingStatus == "unknown") {
Expand All @@ -65,70 +85,44 @@ class BatterySensorManager : SensorManager {
return batteryIcon
}

private fun getBatteryLevelSensor(intent: Intent): SensorRegistration<Any>? {
val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)

if (level == -1 || scale == -1) {
Log.e(TAG, "Issue getting battery level!")
return null
}

val percentage: Int = getBatteryPercentage(level, scale)
private fun getBatteryLevelSensor(intent: Intent): SensorRegistration<Any> {

val percentage: Int = getBatteryPercentage(intent)
val isCharging = getIsCharging(intent)
val chargerType = getChargerType(intent)
val chargingStatus = getChargingStatus(intent)

return SensorRegistration(
"battery_level",
return batteryLevel.toSensorRegistration(
percentage,
"sensor",
getBatteryIcon(percentage, isCharging, chargerType, chargingStatus),
mapOf(),
"Battery Level",
"battery",
"%"
mapOf()
)
}

private fun getBatteryStateSensor(intent: Intent): SensorRegistration<Any>? {
val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
val status: Int = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1)

if (level == -1 || scale == -1 || status == -1) {
Log.e(TAG, "Issue getting battery state!")
return null
}
private fun getBatteryStateSensor(intent: Intent): SensorRegistration<Any> {

val percentage: Int = getBatteryPercentage(intent)
val isCharging = getIsCharging(intent)
val chargerType = getChargerType(intent)
val chargingStatus = getChargingStatus(intent)
val batteryHealth = getBatteryHealth(intent)

val percentage: Int = getBatteryPercentage(level, scale)

return SensorRegistration(
"battery_state",
return batteryState.toSensorRegistration(
chargingStatus,
"sensor",
getBatteryIcon(percentage, isCharging, chargerType, chargingStatus),
mapOf(
"is_charging" to isCharging,
"charger_type" to chargerType,
"battery_health" to batteryHealth
),
"Battery State",
"battery"
)
)
}

private fun getIsCharging(intent: Intent): Boolean {
val status: Int = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1)

return status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL
status == BatteryManager.BATTERY_STATUS_FULL
}

private fun getChargerType(intent: Intent): String {
Expand Down

0 comments on commit 2e5ee34

Please sign in to comment.