diff --git a/app/src/main/java/io/homeassistant/companion/android/bluetooth/ble/IBeaconMonitor.kt b/app/src/main/java/io/homeassistant/companion/android/bluetooth/ble/IBeaconMonitor.kt index b9502508b..c72fe7041 100644 --- a/app/src/main/java/io/homeassistant/companion/android/bluetooth/ble/IBeaconMonitor.kt +++ b/app/src/main/java/io/homeassistant/companion/android/bluetooth/ble/IBeaconMonitor.kt @@ -4,33 +4,34 @@ import android.content.Context import io.homeassistant.companion.android.sensors.BluetoothSensorManager import io.homeassistant.companion.android.sensors.SensorWorker import org.altbeacon.beacon.Beacon +import kotlin.math.abs import kotlin.math.round const val MAX_SKIPPED_UPDATED = 10 data class IBeacon( - var uuid: String, - var major: String, - var minor: String, - var distance: Double, - var rssi: Double, + override val uuid: String, + override val major: String, + override val minor: String, + val distance: Double, + val rssi: Double, var skippedUpdated: Int, -) +) : IBeaconNameFormat class IBeaconMonitor { lateinit var sensorManager: BluetoothSensorManager var beacons: List = listOf() - fun sort(tmp: Collection): Collection { + private fun sort(tmp: Collection): Collection { return tmp.sortedBy { it.distance } } fun setBeacons(context: Context, newBeacons: Collection) { var requireUpdate = false - var tmp: Map = linkedMapOf() + val tmp = mutableMapOf() for (existingBeacon in beacons) { existingBeacon.skippedUpdated++ - tmp += Pair(name(existingBeacon.uuid, existingBeacon.major, existingBeacon.minor), existingBeacon) + tmp += existingBeacon.name to existingBeacon } for (newBeacon in newBeacons) { val uuid = newBeacon.id1.toString() @@ -38,10 +39,12 @@ class IBeaconMonitor { val minor = newBeacon.id3.toString() val distance = round(newBeacon.distance * 100) / 100 val rssi = newBeacon.runningAverageRssi - if (!tmp.contains(name(uuid, major, minor))) { // we found a new beacon + + val beacon = IBeacon(uuid, major, minor, distance, rssi, 0) + if (beacon.name !in tmp) { // we found a new beacon requireUpdate = true } - tmp += Pair(name(uuid, major, minor), IBeacon(uuid, major, minor, distance, rssi, 0)) + tmp += beacon.name to beacon } val sorted = sort(tmp.values).toMutableList() if (requireUpdate) { @@ -58,13 +61,13 @@ class IBeaconMonitor { sendUpdate(context, sorted) return } - beacons.forEachIndexed foreach@{ i, existingBeacon -> + for ((i, existingBeacon) in beacons.withIndex()) { if (i < sorted.size) { - if (name(sorted[i].uuid, sorted[i].major, sorted[i].minor) != name(existingBeacon.uuid, existingBeacon.major, existingBeacon.minor) || // the distance order switched - kotlin.math.abs(sorted[i].distance - existingBeacon.distance) > 0.5 // the distance difference is greater than 0.5m + if (sorted[i].name != existingBeacon.name || // the distance order switched + abs(sorted[i].distance - existingBeacon.distance) > 0.5 // the distance difference is greater than 0.5m ) { requireUpdate = true - return@foreach + break } } } diff --git a/app/src/main/java/io/homeassistant/companion/android/bluetooth/ble/IBeaconNameFormat.kt b/app/src/main/java/io/homeassistant/companion/android/bluetooth/ble/IBeaconNameFormat.kt index 54c40677d..1674b7b01 100755 --- a/app/src/main/java/io/homeassistant/companion/android/bluetooth/ble/IBeaconNameFormat.kt +++ b/app/src/main/java/io/homeassistant/companion/android/bluetooth/ble/IBeaconNameFormat.kt @@ -1,5 +1,9 @@ package io.homeassistant.companion.android.bluetooth.ble -fun name(uuid: T, major: T, minor: T): String { - return "${uuid}_${major}_$minor" +interface IBeaconNameFormat { + val uuid: String + val major: String + val minor: String } + +val IBeaconNameFormat.name get() = "${uuid}_${major}_$minor" diff --git a/app/src/main/java/io/homeassistant/companion/android/bluetooth/ble/IBeaconTransmitter.kt b/app/src/main/java/io/homeassistant/companion/android/bluetooth/ble/IBeaconTransmitter.kt index 64e13d2c2..9054ed02e 100644 --- a/app/src/main/java/io/homeassistant/companion/android/bluetooth/ble/IBeaconTransmitter.kt +++ b/app/src/main/java/io/homeassistant/companion/android/bluetooth/ble/IBeaconTransmitter.kt @@ -1,9 +1,9 @@ package io.homeassistant.companion.android.bluetooth.ble data class IBeaconTransmitter( - var uuid: String, - var major: String, - var minor: String, + override var uuid: String, + override var major: String, + override var minor: String, var transmitting: Boolean = false, var transmitRequested: Boolean = false, var state: String, @@ -13,4 +13,4 @@ data class IBeaconTransmitter( var restartRequired: Boolean = false, val manufacturer: Int = 0x004c, val beaconLayout: String = "m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24" -) +) : IBeaconNameFormat diff --git a/app/src/main/java/io/homeassistant/companion/android/sensors/BluetoothSensorManager.kt b/app/src/main/java/io/homeassistant/companion/android/sensors/BluetoothSensorManager.kt index 021b27a84..5aa828232 100644 --- a/app/src/main/java/io/homeassistant/companion/android/sensors/BluetoothSensorManager.kt +++ b/app/src/main/java/io/homeassistant/companion/android/sensors/BluetoothSensorManager.kt @@ -18,7 +18,6 @@ import io.homeassistant.companion.android.database.AppDatabase import io.homeassistant.companion.android.database.sensor.SensorSetting import io.homeassistant.companion.android.database.sensor.SensorSettingType import java.util.UUID -import kotlin.collections.ArrayList import io.homeassistant.companion.android.common.R as commonR class BluetoothSensorManager : SensorManager { @@ -345,7 +344,7 @@ class BluetoothSensorManager : SensorManager { if (state != "") state else lastState, icon, mapOf( - "id" to name(bleTransmitterDevice.uuid, bleTransmitterDevice.major, bleTransmitterDevice.minor), + "id" to bleTransmitterDevice.name, "Transmitting power" to bleTransmitterDevice.transmitPowerSetting, "Advertise mode" to bleTransmitterDevice.advertiseModeSetting, "Measured power" to bleTransmitterDevice.measuredPowerSetting, @@ -366,7 +365,7 @@ class BluetoothSensorManager : SensorManager { val attr = mutableMapOf() if (BluetoothUtils.isOn(context) && monitoringManager.isMonitoring()) { for (beacon: IBeacon in beaconMonitoringDevice.beacons) { - attr += Pair(name(beacon.uuid, beacon.major, beacon.minor), beacon.distance) + attr += beacon.name to beacon.distance } } diff --git a/app/src/main/java/io/homeassistant/companion/android/settings/sensor/SensorSettingsViewModel.kt b/app/src/main/java/io/homeassistant/companion/android/settings/sensor/SensorSettingsViewModel.kt index d0ad7de7a..ca5fcfe31 100644 --- a/app/src/main/java/io/homeassistant/companion/android/settings/sensor/SensorSettingsViewModel.kt +++ b/app/src/main/java/io/homeassistant/companion/android/settings/sensor/SensorSettingsViewModel.kt @@ -2,7 +2,6 @@ package io.homeassistant.companion.android.settings.sensor import android.app.Application import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.AndroidViewModel @@ -28,7 +27,8 @@ class SensorSettingsViewModel @Inject constructor( } private var sensorsList = emptyList() - var sensors = mutableStateListOf() + var sensors by mutableStateOf>(emptyMap()) + private set var searchQuery: String? = null var sensorFilter by mutableStateOf(SensorFilter.ALL) @@ -55,10 +55,9 @@ class SensorSettingsViewModel @Inject constructor( private fun filterSensorsList() { val app = getApplication() - sensors.clear() - - SensorReceiver.MANAGERS.filter { it.hasSensor(app.applicationContext) }.forEach { manager -> - sensors.addAll( + sensors = SensorReceiver.MANAGERS + .filter { it.hasSensor(app.applicationContext) } + .flatMap { manager -> manager.getAvailableSensors(app.applicationContext) .filter { sensor -> ( @@ -75,7 +74,7 @@ class SensorSettingsViewModel @Inject constructor( ) } .mapNotNull { sensor -> sensorsList.firstOrNull { it.id == sensor.id } } - ) - } + } + .associateBy { it.id } } } diff --git a/app/src/main/java/io/homeassistant/companion/android/settings/sensor/views/SensorListView.kt b/app/src/main/java/io/homeassistant/companion/android/settings/sensor/views/SensorListView.kt index d4955c579..3933b7138 100644 --- a/app/src/main/java/io/homeassistant/companion/android/settings/sensor/views/SensorListView.kt +++ b/app/src/main/java/io/homeassistant/companion/android/settings/sensor/views/SensorListView.kt @@ -38,7 +38,7 @@ fun SensorListView( val listEntries = managers.associateWith { manager -> manager.getAvailableSensors(context) .filter { basicSensor -> - viewModel.sensors.any { basicSensor.id == it.id } + basicSensor.id in viewModel.sensors } .sortedBy { context.getString(it.name) } } @@ -76,7 +76,7 @@ fun SensorListView( ) { basicSensor -> SensorRow( basicSensor = basicSensor, - dbSensor = viewModel.sensors.firstOrNull { it.id == basicSensor.id }, + dbSensor = viewModel.sensors[basicSensor.id], onSensorClicked = onSensorClicked ) } diff --git a/common/src/main/java/io/homeassistant/companion/android/common/data/integration/impl/entities/CheckRateLimits.kt b/common/src/main/java/io/homeassistant/companion/android/common/data/integration/impl/entities/CheckRateLimits.kt index 974726539..eaa42008a 100644 --- a/common/src/main/java/io/homeassistant/companion/android/common/data/integration/impl/entities/CheckRateLimits.kt +++ b/common/src/main/java/io/homeassistant/companion/android/common/data/integration/impl/entities/CheckRateLimits.kt @@ -3,7 +3,7 @@ package io.homeassistant.companion.android.common.data.integration.impl.entities import com.fasterxml.jackson.annotation.JsonProperty data class CheckRateLimits( - var target: String, + val target: String, @JsonProperty("rateLimits") - var rateLimits: RateLimitResponse + val rateLimits: RateLimitResponse ) diff --git a/common/src/main/java/io/homeassistant/companion/android/common/data/integration/impl/entities/RateLimitResponse.kt b/common/src/main/java/io/homeassistant/companion/android/common/data/integration/impl/entities/RateLimitResponse.kt index f0a3dabaf..7672b56e4 100644 --- a/common/src/main/java/io/homeassistant/companion/android/common/data/integration/impl/entities/RateLimitResponse.kt +++ b/common/src/main/java/io/homeassistant/companion/android/common/data/integration/impl/entities/RateLimitResponse.kt @@ -3,12 +3,12 @@ package io.homeassistant.companion.android.common.data.integration.impl.entities import com.fasterxml.jackson.annotation.JsonProperty data class RateLimitResponse( - var attempts: Int, - var successful: Int, - var errors: Int, - var total: Int, - var maximum: Int, - var remaining: Int, + val attempts: Int, + val successful: Int, + val errors: Int, + val total: Int, + val maximum: Int, + val remaining: Int, @JsonProperty("resetsAt") - var resetsAt: String + val resetsAt: String ) diff --git a/common/src/main/java/io/homeassistant/companion/android/common/data/integration/impl/entities/RegisterDeviceRequest.kt b/common/src/main/java/io/homeassistant/companion/android/common/data/integration/impl/entities/RegisterDeviceRequest.kt index 31e8c6ca4..cf0d4705d 100644 --- a/common/src/main/java/io/homeassistant/companion/android/common/data/integration/impl/entities/RegisterDeviceRequest.kt +++ b/common/src/main/java/io/homeassistant/companion/android/common/data/integration/impl/entities/RegisterDeviceRequest.kt @@ -6,14 +6,14 @@ import com.fasterxml.jackson.annotation.JsonInclude data class RegisterDeviceRequest( var appId: String?, var appName: String?, - var appVersion: String?, - var deviceName: String?, - var manufacturer: String?, - var model: String?, + val appVersion: String?, + val deviceName: String?, + val manufacturer: String?, + val model: String?, var osName: String?, - var osVersion: String?, + val osVersion: String?, var supportsEncryption: Boolean?, - var appData: Map?, + val appData: Map?, // Added in HA 0.104.0 var deviceId: String? ) diff --git a/common/src/main/java/io/homeassistant/companion/android/common/data/integration/impl/entities/RegisterDeviceResponse.kt b/common/src/main/java/io/homeassistant/companion/android/common/data/integration/impl/entities/RegisterDeviceResponse.kt index d47cf987d..0ef5cd781 100644 --- a/common/src/main/java/io/homeassistant/companion/android/common/data/integration/impl/entities/RegisterDeviceResponse.kt +++ b/common/src/main/java/io/homeassistant/companion/android/common/data/integration/impl/entities/RegisterDeviceResponse.kt @@ -1,8 +1,8 @@ package io.homeassistant.companion.android.common.data.integration.impl.entities data class RegisterDeviceResponse( - var cloudhookUrl: String?, - var remoteUiUrl: String?, - var secret: String?, - var webhookId: String + val cloudhookUrl: String?, + val remoteUiUrl: String?, + val secret: String?, + val webhookId: String ) diff --git a/common/src/main/java/io/homeassistant/companion/android/common/data/websocket/impl/entities/GetConfigResponse.kt b/common/src/main/java/io/homeassistant/companion/android/common/data/websocket/impl/entities/GetConfigResponse.kt index a299a0535..b638efa7f 100644 --- a/common/src/main/java/io/homeassistant/companion/android/common/data/websocket/impl/entities/GetConfigResponse.kt +++ b/common/src/main/java/io/homeassistant/companion/android/common/data/websocket/impl/entities/GetConfigResponse.kt @@ -12,7 +12,7 @@ data class GetConfigResponse( val timeZone: String, val components: List, val version: String, - var cloudhookUrl: String?, // only when using webhook - var remoteUiUrl: String?, // only when using webhook + val cloudhookUrl: String?, // only when using webhook + val remoteUiUrl: String?, // only when using webhook val entities: Map>? // only on core >= 2022.6 when using webhook ) diff --git a/common/src/main/java/io/homeassistant/companion/android/database/authentication/Authentication.kt b/common/src/main/java/io/homeassistant/companion/android/database/authentication/Authentication.kt index 7133d25d8..55883d4e8 100644 --- a/common/src/main/java/io/homeassistant/companion/android/database/authentication/Authentication.kt +++ b/common/src/main/java/io/homeassistant/companion/android/database/authentication/Authentication.kt @@ -7,11 +7,11 @@ import androidx.room.PrimaryKey @Entity(tableName = "Authentication_List") data class Authentication( @PrimaryKey - var host: String, + val host: String, @ColumnInfo(name = "Username") val username: String, @ColumnInfo(name = "Password") - var password: String + val password: String ) diff --git a/common/src/main/java/io/homeassistant/companion/android/database/notification/NotificationDao.kt b/common/src/main/java/io/homeassistant/companion/android/database/notification/NotificationDao.kt index fa8b085b3..cbb040f7c 100644 --- a/common/src/main/java/io/homeassistant/companion/android/database/notification/NotificationDao.kt +++ b/common/src/main/java/io/homeassistant/companion/android/database/notification/NotificationDao.kt @@ -8,9 +8,6 @@ import androidx.room.Query @Dao interface NotificationDao { - @Query("SELECT * FROM notification_history WHERE id = :id") - fun get(id: Int): NotificationItem? - @Insert(onConflict = OnConflictStrategy.REPLACE) fun add(notification: NotificationItem) diff --git a/common/src/main/java/io/homeassistant/companion/android/database/sensor/Attribute.kt b/common/src/main/java/io/homeassistant/companion/android/database/sensor/Attribute.kt index 0eaa2800f..7545a6615 100644 --- a/common/src/main/java/io/homeassistant/companion/android/database/sensor/Attribute.kt +++ b/common/src/main/java/io/homeassistant/companion/android/database/sensor/Attribute.kt @@ -10,7 +10,7 @@ data class Attribute( @ColumnInfo(name = "name") val name: String, @ColumnInfo(name = "value") - var value: String, + val value: String, @ColumnInfo(name = "value_type") - var valueType: String + val valueType: String ) diff --git a/common/src/main/java/io/homeassistant/companion/android/database/sensor/Sensor.kt b/common/src/main/java/io/homeassistant/companion/android/database/sensor/Sensor.kt index a6e46670a..1a11c3ec0 100644 --- a/common/src/main/java/io/homeassistant/companion/android/database/sensor/Sensor.kt +++ b/common/src/main/java/io/homeassistant/companion/android/database/sensor/Sensor.kt @@ -8,36 +8,35 @@ import androidx.room.PrimaryKey data class Sensor( @PrimaryKey @ColumnInfo(name = "id") - var id: String, + val id: String, @ColumnInfo(name = "enabled") var enabled: Boolean, @ColumnInfo(name = "registered", defaultValue = "NULL") var registered: Boolean? = null, @ColumnInfo(name = "state") - var state: String, + val state: String, @ColumnInfo(name = "last_sent_state", defaultValue = "NULL") var lastSentState: String? = null, @ColumnInfo(name = "last_sent_icon", defaultValue = "NULL") var lastSentIcon: String? = null, @ColumnInfo(name = "state_type") - var stateType: String = "", + val stateType: String = "", @ColumnInfo(name = "type") - var type: String = "", + val type: String = "", @ColumnInfo(name = "icon") - var icon: String = "", + val icon: String = "", @ColumnInfo(name = "name") - var name: String = "", + val name: String = "", @ColumnInfo(name = "device_class") - var deviceClass: String? = null, + val deviceClass: String? = null, @ColumnInfo(name = "unit_of_measurement") - var unitOfMeasurement: String? = null, + val unitOfMeasurement: String? = null, @ColumnInfo(name = "state_class") - var stateClass: String? = null, + val stateClass: String? = null, @ColumnInfo(name = "entity_category") - var entityCategory: String? = null, + val entityCategory: String? = null, @ColumnInfo(name = "core_registration") var coreRegistration: String? = null, @ColumnInfo(name = "app_registration") var appRegistration: String? = null - ) diff --git a/common/src/main/java/io/homeassistant/companion/android/database/sensor/SensorWithAttributes.kt b/common/src/main/java/io/homeassistant/companion/android/database/sensor/SensorWithAttributes.kt index 27645e8bf..56f5b2eb1 100644 --- a/common/src/main/java/io/homeassistant/companion/android/database/sensor/SensorWithAttributes.kt +++ b/common/src/main/java/io/homeassistant/companion/android/database/sensor/SensorWithAttributes.kt @@ -19,7 +19,7 @@ data class SensorWithAttributes( ) { fun toSensorRegistration(basicSensor: SensorManager.BasicSensor): SensorRegistration { var objectMapper: ObjectMapper? = null - val attributes = attributes.map { + val attributes = attributes.associate { val attributeValue = when (it.valueType) { "listboolean", "listfloat", "listlong", "listint", "liststring" -> { if (objectMapper == null) objectMapper = jacksonObjectMapper() @@ -41,7 +41,7 @@ data class SensorWithAttributes( else -> throw IllegalArgumentException("Attribute: ${it.name} is of unknown type: ${it.valueType}") } it.name to attributeValue - }.toMap() + } val state = when (sensor.stateType) { "" -> "" "boolean" -> sensor.state.toBoolean() diff --git a/wear/src/main/java/io/homeassistant/companion/android/data/SimplifiedEntity.kt b/wear/src/main/java/io/homeassistant/companion/android/data/SimplifiedEntity.kt index 4775b0ddc..f3c4c25f2 100644 --- a/wear/src/main/java/io/homeassistant/companion/android/data/SimplifiedEntity.kt +++ b/wear/src/main/java/io/homeassistant/companion/android/data/SimplifiedEntity.kt @@ -1,9 +1,9 @@ package io.homeassistant.companion.android.data data class SimplifiedEntity( - var entityId: String, - var friendlyName: String = entityId, - var icon: String = "" + val entityId: String, + val friendlyName: String = entityId, + val icon: String = "" ) { constructor(entityString: String) : this( entityString.split(",")[0],