mirror of
https://github.com/home-assistant/android
synced 2024-09-18 23:52:51 +00:00
Add power sensors: Interactive, Doze, Power Save (#885)
* Add power sensors * Fix state translation to allow the sensors to be binary
This commit is contained in:
parent
aee090144b
commit
ba127fd5bd
|
@ -8,6 +8,7 @@ import android.content.IntentFilter
|
|||
import android.media.AudioManager
|
||||
import android.net.wifi.WifiManager
|
||||
import android.os.Build
|
||||
import android.os.PowerManager
|
||||
import android.telephony.TelephonyManager
|
||||
import io.homeassistant.companion.android.common.dagger.AppComponent
|
||||
import io.homeassistant.companion.android.common.dagger.Graph
|
||||
|
@ -39,6 +40,24 @@ open class HomeAssistantApplication : Application(), GraphComponentAccessor {
|
|||
}
|
||||
)
|
||||
|
||||
// This will cause interactive and power save to update upon a state change
|
||||
registerReceiver(
|
||||
sensorReceiver, IntentFilter().apply {
|
||||
addAction(Intent.ACTION_SCREEN_OFF)
|
||||
addAction(Intent.ACTION_SCREEN_ON)
|
||||
addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)
|
||||
}
|
||||
)
|
||||
|
||||
// Update doze mode immediately on supported devices
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
registerReceiver(
|
||||
sensorReceiver, IntentFilter().apply {
|
||||
addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// This will trigger an update any time the wifi state has changed
|
||||
registerReceiver(
|
||||
sensorReceiver,
|
||||
|
|
|
@ -17,13 +17,15 @@ data class SensorWithAttributes(
|
|||
val attributes = attributes.map { it.name to it.value }.toMap()
|
||||
val state = when (sensor.stateType) {
|
||||
"" -> ""
|
||||
"boolean" -> sensor.state.toBoolean()
|
||||
"float" -> sensor.state.toFloat()
|
||||
"int" -> sensor.state.toInt()
|
||||
"string" -> sensor.state
|
||||
"number" -> sensor.state.toFloat()
|
||||
else -> throw IllegalArgumentException("State is of unknown type: ${sensor.stateType}")
|
||||
}
|
||||
return SensorRegistration(
|
||||
sensor.id,
|
||||
sensor.state,
|
||||
state,
|
||||
sensor.type,
|
||||
sensor.icon,
|
||||
attributes,
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
package io.homeassistant.companion.android.sensors
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Context.POWER_SERVICE
|
||||
import android.os.Build
|
||||
import android.os.PowerManager
|
||||
import androidx.annotation.RequiresApi
|
||||
import io.homeassistant.companion.android.R
|
||||
|
||||
class PowerSensorManager : SensorManager {
|
||||
companion object {
|
||||
private const val TAG = "PowerSensors"
|
||||
private const val packageName = "io.homeassistant.companion.android"
|
||||
|
||||
private val interactiveDevice = SensorManager.BasicSensor(
|
||||
"is_interactive",
|
||||
"binary_sensor",
|
||||
R.string.basic_sensor_name_interactive,
|
||||
R.string.sensor_description_interactive
|
||||
)
|
||||
private val doze = SensorManager.BasicSensor(
|
||||
"is_idle",
|
||||
"binary_sensor",
|
||||
R.string.basic_sensor_name_doze,
|
||||
R.string.sensor_description_doze
|
||||
)
|
||||
private val powerSave = SensorManager.BasicSensor(
|
||||
"power_save",
|
||||
"binary_sensor",
|
||||
R.string.basic_sensor_name_power_save,
|
||||
R.string.sensor_description_power_save
|
||||
)
|
||||
}
|
||||
|
||||
override val enabledByDefault: Boolean
|
||||
get() = false
|
||||
override val name: Int
|
||||
get() = R.string.sensor_name_power
|
||||
|
||||
override val availableSensors: List<SensorManager.BasicSensor>
|
||||
get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
listOf(interactiveDevice, doze, powerSave)
|
||||
} else {
|
||||
listOf(interactiveDevice, powerSave)
|
||||
}
|
||||
|
||||
override fun requiredPermissions(): Array<String> {
|
||||
return emptyArray()
|
||||
}
|
||||
|
||||
override fun requestSensorUpdate(
|
||||
context: Context
|
||||
) {
|
||||
val powerManager = context.getSystemService(POWER_SERVICE) as PowerManager
|
||||
updateInteractive(context, powerManager)
|
||||
updatePowerSave(context, powerManager)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
updateDoze(context, powerManager)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateInteractive(context: Context, powerManager: PowerManager) {
|
||||
|
||||
if (!isEnabled(context, interactiveDevice.id))
|
||||
return
|
||||
|
||||
val interactiveState = powerManager.isInteractive
|
||||
val icon = if (interactiveState) "mdi:cellphone" else "mdi:cellphone-off"
|
||||
|
||||
onSensorUpdated(
|
||||
context,
|
||||
interactiveDevice,
|
||||
interactiveState,
|
||||
icon,
|
||||
mapOf()
|
||||
)
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.M)
|
||||
private fun updateDoze(context: Context, powerManager: PowerManager) {
|
||||
|
||||
if (!isEnabled(context, doze.id))
|
||||
return
|
||||
|
||||
val dozeState = powerManager.isDeviceIdleMode
|
||||
val icon = if (dozeState) "mdi:sleep" else "mdi:sleep-off"
|
||||
|
||||
onSensorUpdated(
|
||||
context,
|
||||
doze,
|
||||
dozeState,
|
||||
icon,
|
||||
mapOf(
|
||||
"ignoring_battery_optizimations" to powerManager.isIgnoringBatteryOptimizations(packageName)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun updatePowerSave(context: Context, powerManager: PowerManager) {
|
||||
|
||||
if (!isEnabled(context, powerSave.id))
|
||||
return
|
||||
|
||||
val powerSaveState = powerManager.isPowerSaveMode
|
||||
val icon = "mdi:battery-plus"
|
||||
|
||||
onSensorUpdated(
|
||||
context,
|
||||
powerSave,
|
||||
powerSaveState,
|
||||
icon,
|
||||
mapOf()
|
||||
)
|
||||
}
|
||||
}
|
|
@ -71,8 +71,10 @@ interface SensorManager {
|
|||
sensor.id = basicSensor.id
|
||||
sensor.state = state.toString()
|
||||
sensor.stateType = when (state) {
|
||||
is Boolean -> "boolean"
|
||||
is Int -> "int"
|
||||
is Number -> "float"
|
||||
is String -> "string"
|
||||
is Number -> "number"
|
||||
else -> throw IllegalArgumentException("Unknown Sensor State Type")
|
||||
}
|
||||
sensor.type = basicSensor.type
|
||||
|
|
|
@ -32,6 +32,7 @@ class SensorReceiver : BroadcastReceiver() {
|
|||
NetworkSensorManager(),
|
||||
NextAlarmManager(),
|
||||
PhoneStateSensorManager(),
|
||||
PowerSensorManager(),
|
||||
PressureSensorManager(),
|
||||
ProximitySensorManager(),
|
||||
StepsSensorManager(),
|
||||
|
|
|
@ -154,6 +154,13 @@ like to connect to:</string>
|
|||
<string name="sensor_description_location_zone">Import existing Home Assistant zones as geofences for zone based tracking.</string>
|
||||
<string name="sensor_description_next_alarm">The date and time of the next scheduled alarm, any app or manufacturer can override the default behavior. The package attribute will tell you which app set the next scheduled alarm.</string>
|
||||
<string name="sensor_description_none">No description</string>
|
||||
<string name="sensor_description_interactive">Whether or not the device is in an interactive state</string>
|
||||
<string name="sensor_description_doze">Whether or not the device is in Doze mode</string>
|
||||
<string name="sensor_description_power_save">Whether or not the device is in Power Save mode</string>
|
||||
<string name="sensor_name_power">Power Sensors</string>
|
||||
<string name="basic_sensor_name_power_save">Power Save</string>
|
||||
<string name="basic_sensor_name_interactive">Interactive</string>
|
||||
<string name="basic_sensor_name_doze">Doze Mode</string>
|
||||
<string name="basic_sensor_name_activity">Detected Activity</string>
|
||||
<string name="basic_sensor_name_geolocation">Geocoded Location</string>
|
||||
<string name="basic_sensor_name_location_background">Background Location</string>
|
||||
|
|
Loading…
Reference in a new issue