mirror of
https://github.com/home-assistant/android
synced 2024-10-02 22:34:46 +00:00
Add daily floors sensor for Wear OS3 devices (#3005)
* Add daily floors sensor for Wear OS3 devices * Do a compatibility check for sensor availability in health services * Print more logs and attempt to send latest data, update more getAvailableSensor methods * Process review comments * Process more review comments, use actual time in millis * Clear out available sensors when updating with new list * Log the capabilities in case we need to troubleshoot later * Review comment * Missed one additional review comment * Return immediately instead of storing a list
This commit is contained in:
parent
e01246ae28
commit
affc60178e
|
@ -196,7 +196,7 @@ class ActivitySensorManager : BroadcastReceiver(), SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_activity
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(activity, sleepConfidence, sleepSegment)
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ class GeocodeSensorManager : SensorManager {
|
|||
get() = false
|
||||
override val name: Int
|
||||
get() = commonR.string.sensor_name_geolocation
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(geocodedLocation)
|
||||
}
|
||||
|
||||
|
|
|
@ -654,7 +654,7 @@ class LocationSensorManager : LocationSensorManagerBase() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return if (DisabledLocationHandler.hasGPS(context)) {
|
||||
listOf(singleAccurateLocation, backgroundLocation, zoneLocation, highAccuracyMode, highAccuracyUpdateInterval)
|
||||
} else {
|
||||
|
|
|
@ -134,7 +134,7 @@ class BluetoothSensorManager : SensorManager {
|
|||
get() = false
|
||||
override val name: Int
|
||||
get() = commonR.string.sensor_name_bluetooth
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(bluetoothConnection, bluetoothState, bleTransmitter, beaconMonitor)
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ class DevicePolicyManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = R.string.sensor_name_device_policy
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(isWorkProfile)
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ class DisplaySensorManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_display_sensors
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(screenBrightness, screenOffTimeout)
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ class DynamicColorSensorManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_dynamic_color
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(accentColorSensor)
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ class KeyguardSensorManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_keyguard
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return when {
|
||||
(Build.VERSION.SDK_INT >= 23) -> listOf(deviceLocked, deviceSecure, keyguardLocked, keyguardSecure)
|
||||
(Build.VERSION.SDK_INT >= 22) -> listOf(deviceLocked, keyguardLocked, keyguardSecure)
|
||||
|
|
|
@ -32,7 +32,7 @@ class LastAppSensorManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_last_app
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(last_used)
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ class LastRebootSensorManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_last_reboot
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(lastRebootSensor)
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ class LightSensorManager : SensorManager, SensorEventListener {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_light
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(lightSensor)
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ class MobileDataManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_mobile_data
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(mobileDataState, mobileDataRoaming)
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ class NotificationSensorManager : NotificationListenerService(), SensorManager {
|
|||
}
|
||||
override val name: Int
|
||||
get() = commonR.string.sensor_name_last_notification
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(lastNotification, lastRemovedNotification, activeNotificationCount, mediaSession)
|
||||
}
|
||||
override val enabledByDefault: Boolean
|
||||
|
|
|
@ -57,7 +57,7 @@ class PhoneStateSensorManager : SensorManager {
|
|||
override fun hasSensor(context: Context): Boolean {
|
||||
return context.packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
|
||||
}
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1)
|
||||
listOf(phoneState, sim_1, sim_2)
|
||||
else listOf(phoneState)
|
||||
|
|
|
@ -41,7 +41,7 @@ class PressureSensorManager : SensorManager, SensorEventListener {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_pressure
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(pressureSensor)
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ class ProximitySensorManager : SensorManager, SensorEventListener {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_proximity
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(proximitySensor)
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ class QuestSensorManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_quest
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(
|
||||
headsetMounted
|
||||
)
|
||||
|
|
|
@ -66,7 +66,7 @@ class StorageSensorManager : SensorManager {
|
|||
get() = false
|
||||
override val name: Int
|
||||
get() = commonR.string.sensor_name_storage
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(storageSensor, externalStorage)
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ class TimeZoneManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_time_zone
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(currentTimeZone)
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ class TrafficStatsManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_traffic_stats
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return if (hasCellular) {
|
||||
listOf(rxBytesMobile, txBytesMobile, rxBytesTotal, txBytesTotal)
|
||||
} else listOf(rxBytesTotal, txBytesTotal)
|
||||
|
|
|
@ -17,6 +17,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
|||
import io.homeassistant.companion.android.common.bluetooth.BluetoothUtils
|
||||
import io.homeassistant.companion.android.common.data.integration.IntegrationRepository
|
||||
import io.homeassistant.companion.android.common.sensors.NetworkSensorManager
|
||||
import io.homeassistant.companion.android.common.sensors.SensorManager
|
||||
import io.homeassistant.companion.android.common.util.DisabledLocationHandler
|
||||
import io.homeassistant.companion.android.database.sensor.SensorDao
|
||||
import io.homeassistant.companion.android.database.sensor.SensorSetting
|
||||
|
@ -75,10 +76,17 @@ class SensorDetailViewModel @Inject constructor(
|
|||
private val _permissionSnackbar = MutableSharedFlow<PermissionSnackbar>()
|
||||
var permissionSnackbar = _permissionSnackbar.asSharedFlow()
|
||||
|
||||
val sensorManager = SensorReceiver.MANAGERS
|
||||
.find { it.getAvailableSensors(getApplication()).any { sensor -> sensor.id == sensorId } }
|
||||
val basicSensor = sensorManager?.getAvailableSensors(getApplication())
|
||||
?.find { it.id == sensorId }
|
||||
val sensorManager: SensorManager? = runBlocking {
|
||||
SensorReceiver.MANAGERS
|
||||
.find {
|
||||
it.getAvailableSensors(getApplication()).any { sensor -> sensor.id == sensorId }
|
||||
}
|
||||
}
|
||||
|
||||
val basicSensor: SensorManager.BasicSensor? = runBlocking {
|
||||
sensorManager?.getAvailableSensors(getApplication())
|
||||
?.find { it.id == sensorId }
|
||||
}
|
||||
|
||||
var sensor by mutableStateOf<SensorWithAttributes?>(null)
|
||||
private set
|
||||
|
@ -133,7 +141,11 @@ class SensorDetailViewModel @Inject constructor(
|
|||
if ((fineLocation || coarseLocation) &&
|
||||
!DisabledLocationHandler.isLocationEnabled(getApplication())
|
||||
) {
|
||||
val sensorName = basicSensor?.let { getApplication<Application>().getString(basicSensor.name) }.orEmpty()
|
||||
val sensorName = basicSensor?.let {
|
||||
getApplication<Application>().getString(
|
||||
basicSensor.name
|
||||
)
|
||||
}.orEmpty()
|
||||
locationPermissionRequests.value = LocationPermissionsDialog(block = true, sensors = arrayOf(sensorName))
|
||||
return
|
||||
} else {
|
||||
|
|
|
@ -15,7 +15,6 @@ import androidx.fragment.app.viewModels
|
|||
import com.google.android.material.composethemeadapter.MdcTheme
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.homeassistant.companion.android.R
|
||||
import io.homeassistant.companion.android.sensors.SensorReceiver
|
||||
import io.homeassistant.companion.android.settings.sensor.views.SensorListView
|
||||
import io.homeassistant.companion.android.common.R as commonR
|
||||
|
||||
|
@ -93,7 +92,6 @@ class SensorSettingsFragment : Fragment() {
|
|||
MdcTheme {
|
||||
SensorListView(
|
||||
viewModel = viewModel,
|
||||
managers = SensorReceiver.MANAGERS.sortedBy { getString(it.name) },
|
||||
onSensorClicked = { sensor ->
|
||||
parentFragmentManager
|
||||
.beginTransaction()
|
||||
|
|
|
@ -7,6 +7,7 @@ import androidx.compose.runtime.setValue
|
|||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import io.homeassistant.companion.android.common.sensors.SensorManager
|
||||
import io.homeassistant.companion.android.database.sensor.Sensor
|
||||
import io.homeassistant.companion.android.database.sensor.SensorDao
|
||||
import io.homeassistant.companion.android.sensors.SensorReceiver
|
||||
|
@ -30,6 +31,9 @@ class SensorSettingsViewModel @Inject constructor(
|
|||
var sensors by mutableStateOf<Map<String, Sensor>>(emptyMap())
|
||||
private set
|
||||
|
||||
var allSensors by mutableStateOf<Map<SensorManager, List<SensorManager.BasicSensor>>>(emptyMap())
|
||||
private set
|
||||
|
||||
var searchQuery: String? = null
|
||||
var sensorFilter by mutableStateOf(SensorFilter.ALL)
|
||||
private set
|
||||
|
@ -44,17 +48,22 @@ class SensorSettingsViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
fun setSensorsSearchQuery(query: String? = "") {
|
||||
searchQuery = query
|
||||
filterSensorsList()
|
||||
viewModelScope.launch {
|
||||
searchQuery = query
|
||||
filterSensorsList()
|
||||
}
|
||||
}
|
||||
|
||||
fun setSensorFilterChoice(filter: SensorFilter) {
|
||||
sensorFilter = filter
|
||||
filterSensorsList()
|
||||
viewModelScope.launch {
|
||||
sensorFilter = filter
|
||||
filterSensorsList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun filterSensorsList() {
|
||||
private suspend fun filterSensorsList() {
|
||||
val app = getApplication<Application>()
|
||||
val managers = SensorReceiver.MANAGERS.sortedBy { app.getString(it.name) }
|
||||
sensors = SensorReceiver.MANAGERS
|
||||
.filter { it.hasSensor(app.applicationContext) }
|
||||
.flatMap { manager ->
|
||||
|
@ -76,5 +85,13 @@ class SensorSettingsViewModel @Inject constructor(
|
|||
.mapNotNull { sensor -> sensorsList.firstOrNull { it.id == sensor.id } }
|
||||
}
|
||||
.associateBy { it.id }
|
||||
|
||||
allSensors = managers.associateWith { manager ->
|
||||
manager.getAvailableSensors(app)
|
||||
.filter { basicSensor ->
|
||||
sensors.containsKey(basicSensor.id)
|
||||
}
|
||||
.sortedBy { app.getString(it.name) }.distinct()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,20 +31,11 @@ import io.homeassistant.companion.android.common.R as commonR
|
|||
@Composable
|
||||
fun SensorListView(
|
||||
viewModel: SensorSettingsViewModel,
|
||||
managers: List<SensorManager>,
|
||||
onSensorClicked: (String) -> Unit
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val listEntries = managers.associateWith { manager ->
|
||||
manager.getAvailableSensors(context)
|
||||
.filter { basicSensor ->
|
||||
basicSensor.id in viewModel.sensors
|
||||
}
|
||||
.sortedBy { context.getString(it.name) }
|
||||
}
|
||||
|
||||
LazyColumn {
|
||||
listEntries.forEach { (manager, currentSensors) ->
|
||||
viewModel.allSensors.forEach { (manager, currentSensors) ->
|
||||
stickyHeader(
|
||||
key = manager.id()
|
||||
) {
|
||||
|
@ -80,7 +71,7 @@ fun SensorListView(
|
|||
onSensorClicked = onSensorClicked
|
||||
)
|
||||
}
|
||||
if (currentSensors.any() && manager.id() != listEntries.keys.last().id()) {
|
||||
if (currentSensors.any() && manager.id() != viewModel.allSensors.keys.last().id()) {
|
||||
item {
|
||||
Divider()
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ import android.widget.ImageView
|
|||
import android.widget.Toast
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
|
@ -711,7 +712,9 @@ class WebViewActivity : BaseActivity(), io.homeassistant.companion.android.webvi
|
|||
|
||||
SensorWorker.start(this)
|
||||
WebsocketManager.start(this)
|
||||
checkAndWarnForDisabledLocation()
|
||||
lifecycleScope.launch {
|
||||
checkAndWarnForDisabledLocation()
|
||||
}
|
||||
changeLog.showChangeLog(this, false)
|
||||
}
|
||||
|
||||
|
@ -721,7 +724,7 @@ class WebViewActivity : BaseActivity(), io.homeassistant.companion.android.webvi
|
|||
presenter.setAppActive(false)
|
||||
}
|
||||
|
||||
private fun checkAndWarnForDisabledLocation() {
|
||||
private suspend fun checkAndWarnForDisabledLocation() {
|
||||
var showLocationDisabledWarning = false
|
||||
var settingsWithLocationPermissions = mutableListOf<String>()
|
||||
if (!DisabledLocationHandler.isLocationEnabled(this) && presenter.isSsidUsed()) {
|
||||
|
@ -980,10 +983,12 @@ class WebViewActivity : BaseActivity(), io.homeassistant.companion.android.webvi
|
|||
windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
override fun onPictureInPictureModeChanged(
|
||||
isInPictureInPictureMode: Boolean,
|
||||
newConfig: Configuration
|
||||
) {
|
||||
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
|
||||
if (exoPlayerView.visibility != View.VISIBLE) {
|
||||
if (isInPictureInPictureMode) {
|
||||
(decor.getChildAt(3) as FrameLayout).layoutParams.height =
|
||||
|
|
|
@ -17,7 +17,7 @@ class ActivitySensorManager : BroadcastReceiver(), SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_activity
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf()
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ class GeocodeSensorManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_geolocation
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf()
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ class LocationSensorManager : LocationSensorManagerBase(), SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_location
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf()
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ class AppSensorManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_app_sensor
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return when {
|
||||
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) ->
|
||||
listOf(
|
||||
|
|
|
@ -138,7 +138,7 @@ class AudioSensorManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_audio
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
val allSupportedSensors = listOf(
|
||||
audioSensor, audioState, headphoneState, micMuted, speakerphoneState,
|
||||
musicActive, volAlarm, volCall, volMusic, volRing, volNotification, volSystem,
|
||||
|
|
|
@ -103,7 +103,7 @@ class BatterySensorManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_battery
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(
|
||||
batteryLevel,
|
||||
batteryState,
|
||||
|
|
|
@ -32,7 +32,7 @@ class DNDSensorManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_dnd
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(dndSensor)
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ class LastUpdateManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_last_update
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(lastUpdate)
|
||||
}
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ class NetworkSensorManager : SensorManager {
|
|||
get() = false
|
||||
override val name: Int
|
||||
get() = commonR.string.sensor_name_network
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
val list = listOf(
|
||||
wifiConnection,
|
||||
bssidState,
|
||||
|
|
|
@ -38,7 +38,7 @@ class NextAlarmManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_alarm
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(nextAlarm)
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ class PowerSensorManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_power
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
listOf(interactiveDevice, doze, powerSave)
|
||||
} else {
|
||||
|
|
|
@ -99,7 +99,7 @@ interface SensorManager {
|
|||
*/
|
||||
fun requestSensorUpdate(context: Context)
|
||||
|
||||
fun getAvailableSensors(context: Context): List<BasicSensor>
|
||||
suspend fun getAvailableSensors(context: Context): List<BasicSensor>
|
||||
|
||||
/**
|
||||
* Check if the user's device supports this type of sensor
|
||||
|
|
|
@ -39,7 +39,7 @@ class StepsSensorManager : SensorManager, SensorEventListener {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_steps
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(stepsSensor)
|
||||
}
|
||||
|
||||
|
|
|
@ -947,4 +947,6 @@
|
|||
<string name="sensor_name_health_services">Health Services</string>
|
||||
<string name="sensor_name_heart_rate">Heart Rate</string>
|
||||
<string name="sensor_description_heart_rate">Current heart rate in beats per minute, an attribute also exists for the reported accuracy from the sensor</string>
|
||||
<string name="sensor_name_daily_floors">Daily Floors</string>
|
||||
<string name="sensor_description_daily_floors">The total number floors climbed over a day, where the previous day ends and a new day begins at 12:00 AM local time</string>
|
||||
</resources>
|
||||
|
|
|
@ -10,7 +10,6 @@ import dagger.hilt.android.AndroidEntryPoint
|
|||
import io.homeassistant.companion.android.home.views.LoadHomePage
|
||||
import io.homeassistant.companion.android.onboarding.OnboardingActivity
|
||||
import io.homeassistant.companion.android.onboarding.integration.MobileAppIntegrationActivity
|
||||
import io.homeassistant.companion.android.sensors.SensorReceiver
|
||||
import io.homeassistant.companion.android.sensors.SensorWorker
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -47,15 +46,7 @@ class HomeActivity : ComponentActivity(), HomeView {
|
|||
super.onResume()
|
||||
SensorWorker.start(this)
|
||||
|
||||
initAllSensors()
|
||||
}
|
||||
|
||||
private fun initAllSensors() {
|
||||
for (manager in SensorReceiver.MANAGERS) {
|
||||
for (basicSensor in manager.getAvailableSensors(this)) {
|
||||
manager.isEnabled(this, basicSensor.id)
|
||||
}
|
||||
}
|
||||
mainViewModel.initAllSensors()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
|
|
|
@ -10,6 +10,7 @@ import androidx.compose.runtime.snapshots.SnapshotStateList
|
|||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import io.homeassistant.companion.android.HomeAssistantApplication
|
||||
import io.homeassistant.companion.android.common.data.integration.Entity
|
||||
import io.homeassistant.companion.android.common.data.integration.domain
|
||||
import io.homeassistant.companion.android.common.data.websocket.WebSocketState
|
||||
|
@ -23,6 +24,7 @@ import io.homeassistant.companion.android.database.wear.FavoriteCaches
|
|||
import io.homeassistant.companion.android.database.wear.FavoriteCachesDao
|
||||
import io.homeassistant.companion.android.database.wear.FavoritesDao
|
||||
import io.homeassistant.companion.android.database.wear.getAllFlow
|
||||
import io.homeassistant.companion.android.sensors.SensorReceiver
|
||||
import io.homeassistant.companion.android.sensors.SensorWorker
|
||||
import io.homeassistant.companion.android.util.RegistriesDataHandler
|
||||
import kotlinx.coroutines.async
|
||||
|
@ -108,6 +110,8 @@ class MainViewModel @Inject constructor(
|
|||
|
||||
val sensors = sensorsDao.getAllFlow().collectAsState()
|
||||
|
||||
var availableSensors = emptyList<SensorManager.BasicSensor>()
|
||||
|
||||
private fun loadSettings() {
|
||||
viewModelScope.launch {
|
||||
if (!homePresenter.isConnected()) {
|
||||
|
@ -291,6 +295,26 @@ class MainViewModel @Inject constructor(
|
|||
SensorWorker.start(getApplication())
|
||||
}
|
||||
|
||||
fun updateAllSensors(sensorManager: SensorManager) {
|
||||
availableSensors = emptyList()
|
||||
viewModelScope.launch {
|
||||
val context = getApplication<HomeAssistantApplication>().applicationContext
|
||||
availableSensors = sensorManager
|
||||
.getAvailableSensors(context)
|
||||
.sortedBy { context.getString(it.name) }.distinct()
|
||||
}
|
||||
}
|
||||
|
||||
fun initAllSensors() {
|
||||
viewModelScope.launch {
|
||||
for (manager in SensorReceiver.MANAGERS) {
|
||||
for (basicSensor in manager.getAvailableSensors(getApplication())) {
|
||||
manager.isEnabled(getApplication(), basicSensor.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getAreaForEntity(entityId: String): AreaRegistryResponse? =
|
||||
RegistriesDataHandler.getAreaForEntity(entityId, areaRegistry, deviceRegistry, entityRegistry)
|
||||
|
||||
|
|
|
@ -222,8 +222,10 @@ fun LoadHomePage(
|
|||
val sensorManager = getSensorManagers().first { sensorManager ->
|
||||
sensorManager.id() == sensorManagerId
|
||||
}
|
||||
mainViewModel.updateAllSensors(sensorManager)
|
||||
SensorManagerUi(
|
||||
allSensors = mainViewModel.sensors.value,
|
||||
allAvailSensors = mainViewModel.availableSensors,
|
||||
sensorManager = sensorManager,
|
||||
) { sensorId, isEnabled ->
|
||||
mainViewModel.enableDisableSensor(sensorManager, sensorId, isEnabled)
|
||||
|
|
|
@ -1,39 +1,38 @@
|
|||
package io.homeassistant.companion.android.home.views
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Devices
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.wear.compose.material.CircularProgressIndicator
|
||||
import androidx.wear.compose.material.PositionIndicator
|
||||
import androidx.wear.compose.material.Scaffold
|
||||
import androidx.wear.compose.material.ScalingLazyListState
|
||||
import androidx.wear.compose.material.rememberScalingLazyListState
|
||||
import io.homeassistant.companion.android.common.R
|
||||
import io.homeassistant.companion.android.common.sensors.SensorManager
|
||||
import io.homeassistant.companion.android.database.sensor.Sensor
|
||||
import io.homeassistant.companion.android.theme.WearAppTheme
|
||||
import io.homeassistant.companion.android.util.batterySensorManager
|
||||
import io.homeassistant.companion.android.util.sensorList
|
||||
import io.homeassistant.companion.android.views.ListHeader
|
||||
import io.homeassistant.companion.android.views.ThemeLazyColumn
|
||||
|
||||
@Composable
|
||||
fun SensorManagerUi(
|
||||
allSensors: List<Sensor>?,
|
||||
allAvailSensors: List<SensorManager.BasicSensor>?,
|
||||
sensorManager: SensorManager,
|
||||
onSensorClicked: (String, Boolean) -> Unit,
|
||||
) {
|
||||
val scalingLazyListState: ScalingLazyListState = rememberScalingLazyListState()
|
||||
val context = LocalContext.current
|
||||
val availableSensors by remember {
|
||||
mutableStateOf(
|
||||
sensorManager
|
||||
.getAvailableSensors(context)
|
||||
.sortedBy { context.getString(it.name) }
|
||||
)
|
||||
}
|
||||
WearAppTheme {
|
||||
Scaffold(
|
||||
positionIndicator = {
|
||||
|
@ -49,21 +48,38 @@ fun SensorManagerUi(
|
|||
ListHeader(id = sensorManager.name)
|
||||
}
|
||||
val currentSensors = allSensors?.filter { sensor ->
|
||||
availableSensors.firstOrNull { availableSensor ->
|
||||
allAvailSensors?.firstOrNull { availableSensor ->
|
||||
sensor.id == availableSensor.id
|
||||
} != null
|
||||
}
|
||||
|
||||
items(availableSensors.size, { availableSensors[it].id }) { index ->
|
||||
val basicSensor = availableSensors[index]
|
||||
val sensor = currentSensors?.firstOrNull { sensor ->
|
||||
sensor.id == basicSensor.id
|
||||
if (allAvailSensors?.isEmpty() == true) {
|
||||
item {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(vertical = 32.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center
|
||||
) {
|
||||
ListHeader(id = R.string.loading)
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
allAvailSensors?.size?.let { int ->
|
||||
items(int, { allAvailSensors[it].id }) { index ->
|
||||
val basicSensor = allAvailSensors[index]
|
||||
val sensor = currentSensors?.firstOrNull { sensor ->
|
||||
sensor.id == basicSensor.id
|
||||
}
|
||||
SensorUi(
|
||||
sensor = sensor,
|
||||
manager = sensorManager,
|
||||
basicSensor = basicSensor,
|
||||
) { sensorId, enabled -> onSensorClicked(sensorId, enabled) }
|
||||
}
|
||||
}
|
||||
SensorUi(
|
||||
sensor = sensor,
|
||||
manager = sensorManager,
|
||||
basicSensor = basicSensor,
|
||||
) { sensorId, enabled -> onSensorClicked(sensorId, enabled) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,6 +92,7 @@ private fun PreviewSensorManagerUI() {
|
|||
CompositionLocalProvider {
|
||||
SensorManagerUi(
|
||||
allSensors = listOf(),
|
||||
allAvailSensors = sensorList,
|
||||
sensorManager = batterySensorManager
|
||||
) { _, _ -> }
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import io.homeassistant.companion.android.common.R
|
|||
import io.homeassistant.companion.android.common.sensors.SensorManager
|
||||
import io.homeassistant.companion.android.database.sensor.Sensor
|
||||
import io.homeassistant.companion.android.util.batterySensorManager
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
@Composable
|
||||
fun SensorUi(
|
||||
|
@ -96,11 +97,12 @@ fun SensorUi(
|
|||
@Preview(device = Devices.WEAR_OS_LARGE_ROUND)
|
||||
@Composable
|
||||
private fun PreviewSensorUI() {
|
||||
val context = LocalContext.current
|
||||
CompositionLocalProvider {
|
||||
SensorUi(
|
||||
sensor = null,
|
||||
manager = batterySensorManager,
|
||||
basicSensor = batterySensorManager.getAvailableSensors(LocalContext.current).first()
|
||||
basicSensor = runBlocking { batterySensorManager.getAvailableSensors(context).first() }
|
||||
) { _, _ -> }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ class BedtimeModeSensorManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_bedtime_mode
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(bedtimeMode)
|
||||
}
|
||||
|
||||
|
|
|
@ -3,18 +3,27 @@ package io.homeassistant.companion.android.sensors
|
|||
import android.Manifest
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.os.SystemClock
|
||||
import android.util.Log
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.health.services.client.HealthServices
|
||||
import androidx.health.services.client.HealthServicesClient
|
||||
import androidx.health.services.client.PassiveListenerCallback
|
||||
import androidx.health.services.client.PassiveMonitoringClient
|
||||
import androidx.health.services.client.data.DataPointContainer
|
||||
import androidx.health.services.client.data.DataType
|
||||
import androidx.health.services.client.data.DeltaDataType
|
||||
import androidx.health.services.client.data.ExerciseType
|
||||
import androidx.health.services.client.data.IntervalDataPoint
|
||||
import androidx.health.services.client.data.PassiveListenerConfig
|
||||
import androidx.health.services.client.data.PassiveMonitoringCapabilities
|
||||
import androidx.health.services.client.data.UserActivityInfo
|
||||
import androidx.health.services.client.data.UserActivityState
|
||||
import io.homeassistant.companion.android.common.sensors.SensorManager
|
||||
import io.homeassistant.companion.android.database.AppDatabase
|
||||
import kotlinx.coroutines.guava.await
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.time.Instant
|
||||
import io.homeassistant.companion.android.common.R as commonR
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.R)
|
||||
|
@ -31,16 +40,29 @@ class HealthServicesSensorManager : SensorManager {
|
|||
entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
updateType = SensorManager.BasicSensor.UpdateType.INTENT
|
||||
)
|
||||
private val dailyFloors = SensorManager.BasicSensor(
|
||||
"daily_floors",
|
||||
"sensor",
|
||||
commonR.string.sensor_name_daily_floors,
|
||||
commonR.string.sensor_description_daily_floors,
|
||||
"mdi:stairs",
|
||||
unitOfMeasurement = "floors",
|
||||
entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
updateType = SensorManager.BasicSensor.UpdateType.INTENT
|
||||
)
|
||||
}
|
||||
|
||||
private lateinit var latestContext: Context
|
||||
private var healthClient: HealthServicesClient? = null
|
||||
private var passiveMonitoringClient: PassiveMonitoringClient? = null
|
||||
private var passiveMonitoringCapabilities: PassiveMonitoringCapabilities? = null
|
||||
private var passiveListenerConfig: PassiveListenerConfig? = null
|
||||
private var callBackRegistered = false
|
||||
private var dataTypesRegistered = emptySet<DataType<*, *>>()
|
||||
private var activityStateRegistered = false
|
||||
|
||||
override fun docsLink(): String {
|
||||
return "https://companion.home-assistant.io/docs/wear-os/#sensors"
|
||||
return "https://companion.home-assistant.io/docs/wear-os/sensors#health-services"
|
||||
}
|
||||
override val enabledByDefault: Boolean
|
||||
get() = false
|
||||
|
@ -48,8 +70,22 @@ class HealthServicesSensorManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_health_services
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(userActivityState)
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
latestContext = context
|
||||
if (healthClient == null)
|
||||
healthClient = HealthServices.getClient(latestContext)
|
||||
if (passiveMonitoringClient == null)
|
||||
passiveMonitoringClient = healthClient?.passiveMonitoringClient
|
||||
if (passiveMonitoringCapabilities == null) {
|
||||
passiveMonitoringCapabilities = passiveMonitoringClient?.getCapabilitiesAsync()?.await()
|
||||
Log.d(TAG, "Supported capabilities: $passiveMonitoringCapabilities")
|
||||
}
|
||||
|
||||
val supportedSensors = mutableListOf(userActivityState)
|
||||
|
||||
if (passiveMonitoringCapabilities?.supportedDataTypesPassiveMonitoring?.contains(DataType.FLOORS_DAILY) == true)
|
||||
supportedSensors += dailyFloors
|
||||
return supportedSensors
|
||||
}
|
||||
|
||||
override fun requiredPermissions(sensorId: String): Array<String> {
|
||||
|
@ -62,22 +98,37 @@ class HealthServicesSensorManager : SensorManager {
|
|||
|
||||
override fun requestSensorUpdate(context: Context) {
|
||||
latestContext = context
|
||||
updateUserActivityState()
|
||||
updateHealthServices()
|
||||
}
|
||||
|
||||
private fun updateUserActivityState() {
|
||||
if (!isEnabled(latestContext, userActivityState.id)) {
|
||||
passiveMonitoringClient?.clearPassiveListenerCallbackAsync()
|
||||
callBackRegistered = false
|
||||
private fun updateHealthServices() {
|
||||
val activityStateEnabled = isEnabled(latestContext, userActivityState.id)
|
||||
val dailyFloorEnabled = isEnabled(latestContext, dailyFloors.id)
|
||||
|
||||
if (!activityStateEnabled && !dailyFloorEnabled) {
|
||||
clearHealthServicesCallBack()
|
||||
return
|
||||
}
|
||||
|
||||
if (healthClient == null) healthClient = HealthServices.getClient(latestContext)
|
||||
if (passiveMonitoringClient == null) passiveMonitoringClient = healthClient?.passiveMonitoringClient
|
||||
|
||||
val dataTypes = mutableSetOf<DataType<*, *>>()
|
||||
if (dailyFloorEnabled)
|
||||
dataTypes += DataType.FLOORS_DAILY
|
||||
|
||||
passiveListenerConfig = PassiveListenerConfig.builder()
|
||||
.setShouldUserActivityInfoBeRequested(isEnabled(latestContext, userActivityState.id))
|
||||
.setShouldUserActivityInfoBeRequested(activityStateEnabled)
|
||||
.setDataTypes(dataTypes)
|
||||
.build()
|
||||
|
||||
if (dataTypesRegistered != dataTypes || activityStateRegistered != activityStateEnabled) {
|
||||
clearHealthServicesCallBack()
|
||||
}
|
||||
|
||||
activityStateRegistered = activityStateEnabled
|
||||
dataTypesRegistered = dataTypes
|
||||
|
||||
val passiveListenerCallback: PassiveListenerCallback = object : PassiveListenerCallback {
|
||||
override fun onUserActivityInfoReceived(info: UserActivityInfo) {
|
||||
Log.d(TAG, "User activity state: ${info.userActivityState.name}")
|
||||
|
@ -90,21 +141,61 @@ class HealthServicesSensorManager : SensorManager {
|
|||
UserActivityState.USER_ACTIVITY_EXERCISE -> "exercise"
|
||||
else -> "unknown"
|
||||
},
|
||||
when (info.userActivityState) {
|
||||
UserActivityState.USER_ACTIVITY_EXERCISE -> "mdi:run"
|
||||
UserActivityState.USER_ACTIVITY_ASLEEP -> "mdi:sleep"
|
||||
UserActivityState.USER_ACTIVITY_PASSIVE -> "mdi:human-handsdown"
|
||||
else -> userActivityState.statelessIcon
|
||||
},
|
||||
getActivityIcon(info),
|
||||
mapOf(
|
||||
"time" to info.stateChangeTime,
|
||||
"exercise_type" to info.exerciseInfo?.exerciseType?.name
|
||||
)
|
||||
),
|
||||
forceUpdate = info.userActivityState == UserActivityState.USER_ACTIVITY_EXERCISE
|
||||
)
|
||||
|
||||
SensorWorker.start(latestContext)
|
||||
}
|
||||
|
||||
override fun onNewDataPointsReceived(dataPoints: DataPointContainer) {
|
||||
Log.d(TAG, "New data point received: ${dataPoints.dataTypes}")
|
||||
val floorsDaily = dataPoints.getData(DataType.FLOORS_DAILY)
|
||||
val bootInstant =
|
||||
Instant.ofEpochMilli(System.currentTimeMillis() - SystemClock.elapsedRealtime())
|
||||
var latest = 0
|
||||
var lastIndex = 0
|
||||
|
||||
dataPoints.dataTypes.forEachIndexed { _, dataType ->
|
||||
|
||||
if (dataType is DeltaDataType<*, *>) {
|
||||
val data = dataPoints.getData(dataType)
|
||||
data.forEachIndexed { indexPoint, dataPoint ->
|
||||
if (dataPoint is IntervalDataPoint) {
|
||||
val endTime = dataPoint.getEndInstant(bootInstant)
|
||||
Log.d(
|
||||
TAG,
|
||||
"Data for ${dataType.name} index: $indexPoint with value: ${dataPoint.value} end time: ${endTime.toEpochMilli()}"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (floorsDaily.isNotEmpty()) {
|
||||
floorsDaily.forEachIndexed { index, intervalDataPoint ->
|
||||
val endTime = intervalDataPoint.getEndInstant(bootInstant)
|
||||
Log.d(TAG, "Daily Floors data index: $index with value: ${intervalDataPoint.value} end time: ${endTime.toEpochMilli()}")
|
||||
if (endTime.toEpochMilli() > latest) {
|
||||
latest = endTime.toEpochMilli().toInt()
|
||||
lastIndex = index
|
||||
}
|
||||
}
|
||||
onSensorUpdated(
|
||||
latestContext,
|
||||
dailyFloors,
|
||||
floorsDaily[lastIndex].value,
|
||||
dailyFloors.statelessIcon,
|
||||
mapOf()
|
||||
)
|
||||
|
||||
SensorWorker.start(latestContext)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPermissionLost() {
|
||||
val sensorDao = AppDatabase.getInstance(latestContext).sensorDao()
|
||||
runBlocking {
|
||||
|
@ -116,6 +207,11 @@ class HealthServicesSensorManager : SensorManager {
|
|||
Log.e(TAG, "onRegistrationFailed: ", throwable)
|
||||
callBackRegistered = false
|
||||
}
|
||||
|
||||
override fun onRegistered() {
|
||||
Log.d(TAG, "Health services callback successfully registered for the following data types: ${passiveListenerConfig!!.dataTypes} User Activity Info: ${passiveListenerConfig!!.shouldUserActivityInfoBeRequested} Health Events: ${passiveListenerConfig!!.healthEventTypes}")
|
||||
callBackRegistered = true
|
||||
}
|
||||
}
|
||||
|
||||
if (!callBackRegistered) {
|
||||
|
@ -124,6 +220,61 @@ class HealthServicesSensorManager : SensorManager {
|
|||
passiveListenerCallback
|
||||
)
|
||||
}
|
||||
|
||||
// Assume the callback is registered to avoid making multiple requests
|
||||
callBackRegistered = true
|
||||
}
|
||||
|
||||
private fun clearHealthServicesCallBack() {
|
||||
passiveMonitoringClient?.clearPassiveListenerCallbackAsync()
|
||||
callBackRegistered = false
|
||||
}
|
||||
|
||||
private fun getActivityIcon(info: UserActivityInfo): String {
|
||||
return when (info.userActivityState) {
|
||||
UserActivityState.USER_ACTIVITY_EXERCISE -> {
|
||||
when (info.exerciseInfo?.exerciseType) {
|
||||
ExerciseType.ALPINE_SKIING, ExerciseType.SKIING -> "mdi:skiing"
|
||||
ExerciseType.WEIGHTLIFTING, ExerciseType.BARBELL_SHOULDER_PRESS, ExerciseType.BENCH_PRESS -> "mdi:weight-lifter"
|
||||
ExerciseType.BIKING, ExerciseType.BIKING_STATIONARY, ExerciseType.MOUNTAIN_BIKING -> "mdi:bike"
|
||||
ExerciseType.SWIMMING_POOL, ExerciseType.SWIMMING_OPEN_WATER -> "mdi:swim"
|
||||
ExerciseType.BASEBALL -> "mdi:baseball"
|
||||
ExerciseType.BASKETBALL -> "mdi:basketball"
|
||||
ExerciseType.FOOTBALL_AMERICAN -> "mdi:football"
|
||||
ExerciseType.FOOTBALL_AUSTRALIAN -> "mdi:football-australian"
|
||||
ExerciseType.SOCCER -> "mdi:soccer"
|
||||
ExerciseType.SKATING, ExerciseType.INLINE_SKATING -> "mdi:skate"
|
||||
ExerciseType.ROLLER_SKATING -> "mdi:roller-skate"
|
||||
ExerciseType.SCUBA_DIVING -> "mdi:diving-scuba"
|
||||
ExerciseType.SAILING -> "mdi:sail-boat"
|
||||
ExerciseType.RUGBY -> "mdi:rugby"
|
||||
ExerciseType.ROWING, ExerciseType.ROWING_MACHINE -> "mdi:rowing"
|
||||
ExerciseType.RACQUETBALL -> "mdi:racquetball"
|
||||
ExerciseType.HORSE_RIDING -> "mdi:horse-human"
|
||||
ExerciseType.ICE_HOCKEY, ExerciseType.ROLLER_HOCKEY -> "mdi:hockey-sticks"
|
||||
ExerciseType.GYMNASTICS -> "mdi:gymnastics"
|
||||
ExerciseType.DANCING -> "mdi:dance-ballroom"
|
||||
ExerciseType.CRICKET -> "mdi:cricket"
|
||||
ExerciseType.JUMP_ROPE -> "mdi:jump-rope"
|
||||
ExerciseType.JUMPING_JACK -> "mdi:human-handsdown"
|
||||
ExerciseType.SNOWBOARDING -> "mdi:snowboard"
|
||||
ExerciseType.MEDITATION -> "mdi:meditation"
|
||||
ExerciseType.SURFING -> "mdi:surfing"
|
||||
ExerciseType.TENNIS -> "mdi:tennis"
|
||||
ExerciseType.TABLE_TENNIS -> "mdi:table-tennis"
|
||||
ExerciseType.VOLLEYBALL -> "mdi:volleyball"
|
||||
ExerciseType.HANDBALL -> "mdi:handball"
|
||||
ExerciseType.YOGA -> "mdi:yoga"
|
||||
ExerciseType.WATER_POLO -> "mdi:water-polo"
|
||||
ExerciseType.STAIR_CLIMBING, ExerciseType.STAIR_CLIMBING_MACHINE -> "mdi:stairs"
|
||||
ExerciseType.PARA_GLIDING -> "mdi:paragliding"
|
||||
ExerciseType.GOLF -> "mdi:golf"
|
||||
else -> "mdi:run"
|
||||
}
|
||||
}
|
||||
UserActivityState.USER_ACTIVITY_PASSIVE -> "mdi:human-handsdown"
|
||||
UserActivityState.USER_ACTIVITY_ASLEEP -> "mdi:sleep"
|
||||
else -> userActivityState.statelessIcon
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ class HeartRateSensorManager : SensorManager, SensorEventListener {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_heart_rate
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(heartRate)
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ class OnBodySensorManager : SensorManager, SensorEventListener {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_on_body
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(onBodySensor)
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ class TheaterModeSensorManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_theater_mode
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(theaterMode)
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ class WetModeSensorManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_wet_mode
|
||||
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
override suspend fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(
|
||||
wetModeSensor
|
||||
)
|
||||
|
|
|
@ -31,3 +31,5 @@ val playPreviewEntityScene2 = Entity("scene.second", "on", mapOf("friendly_name"
|
|||
val playPreviewEntityScene3 = Entity("scene.third", "on", mapOf("friendly_name" to "Goodbye"), calendar, calendar, mapOf())
|
||||
|
||||
val batterySensorManager = BatterySensorManager()
|
||||
|
||||
val sensorList = listOf(BatterySensorManager.isChargingState)
|
||||
|
|
Loading…
Reference in a new issue