mirror of
https://github.com/home-assistant/android
synced 2024-10-15 20:43:06 +00:00
Add Beacon Monitor (#2472)
* Add BLE Beacon Monitoring Sensor * Fix on/off toggle * Add on/off commands * Fix commands * Add all beacons to attributtes * Add Kalman Filter * Improve performance * More settings * cleanup * Fix linter errors * Update description * Show monitoring state in sensor * Add missing permissions * Fix permissions * Fix Bluetooth state of Android 12 * Use instance instead of singelton * Use runBlocking for updateLastSendState * Use own scope for beacon manager * Use new notification commands * fix rebase * use null instead of empty string * return if sensor is disabled
This commit is contained in:
parent
647d6c4533
commit
d0016e530e
|
@ -12,6 +12,7 @@
|
|||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
package io.homeassistant.companion.android.bluetooth.ble
|
||||
|
||||
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.round
|
||||
|
||||
const val MAX_SKIPPED_UPDATED = 10
|
||||
|
||||
data class IBeacon(
|
||||
var uuid: String,
|
||||
var distance: Double,
|
||||
var rssi: Double,
|
||||
var skippedUpdated: Int,
|
||||
)
|
||||
|
||||
class IBeaconMonitor {
|
||||
lateinit var sensorManager: BluetoothSensorManager
|
||||
var beacons: List<IBeacon> = listOf()
|
||||
|
||||
fun sort(tmp: Collection<IBeacon>): Collection<IBeacon> {
|
||||
return tmp.sortedBy { it.distance }
|
||||
}
|
||||
|
||||
fun setBeacons(context: Context, newBeacons: Collection<Beacon>) {
|
||||
var requireUpdate = false
|
||||
var tmp: Map<String, IBeacon> = linkedMapOf()
|
||||
for (existingBeacon in beacons) {
|
||||
existingBeacon.skippedUpdated++
|
||||
tmp += Pair(existingBeacon.uuid, existingBeacon)
|
||||
}
|
||||
for (newBeacon in newBeacons) {
|
||||
val uuid = newBeacon.id1.toString()
|
||||
val distance = round(newBeacon.distance * 100) / 100
|
||||
val rssi = newBeacon.runningAverageRssi
|
||||
if (!tmp.contains(uuid)) { // we found a new beacon
|
||||
requireUpdate = true
|
||||
}
|
||||
tmp += Pair(uuid, IBeacon(uuid, distance, rssi, 0))
|
||||
}
|
||||
val sorted = sort(tmp.values).toMutableList()
|
||||
if (requireUpdate) {
|
||||
sendUpdate(context, sorted)
|
||||
return
|
||||
}
|
||||
for (i in sorted.indices.reversed()) {
|
||||
if (sorted[i].skippedUpdated > MAX_SKIPPED_UPDATED) { // a old beacon expired
|
||||
sorted.removeAt(i)
|
||||
requireUpdate = true
|
||||
}
|
||||
}
|
||||
if (requireUpdate) {
|
||||
sendUpdate(context, sorted)
|
||||
return
|
||||
}
|
||||
assert(sorted.count() == beacons.count())
|
||||
beacons.forEachIndexed foreach@{ i, existingBeacon ->
|
||||
if (sorted[i].uuid != existingBeacon.uuid || // the distance order switched
|
||||
kotlin.math.abs(sorted[i].distance - existingBeacon.distance) > 0.5 // the distance difference is greater than 0.5m
|
||||
) {
|
||||
requireUpdate = true
|
||||
return@foreach
|
||||
}
|
||||
}
|
||||
if (requireUpdate) {
|
||||
sendUpdate(context, sorted)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
private fun sendUpdate(context: Context, tmp: List<IBeacon>) {
|
||||
beacons = tmp
|
||||
sensorManager!!.updateBeaconMonitoringSensor(context)
|
||||
SensorWorker.start(context)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package io.homeassistant.companion.android.bluetooth.ble
|
||||
|
||||
import org.altbeacon.beacon.service.RssiFilter
|
||||
import kotlin.math.pow
|
||||
|
||||
class KalmanFilter : RssiFilter {
|
||||
companion object {
|
||||
var maxIterations = 10
|
||||
var rssiMultiplier: Double = 1.05
|
||||
}
|
||||
|
||||
private var predictedValue: Double = 0.0
|
||||
private var numIterations: Int = 0
|
||||
|
||||
override fun addMeasurement(rssi: Int) {
|
||||
if (numIterations == 0) {
|
||||
predictedValue = rssi.toDouble()
|
||||
}
|
||||
if (numIterations < maxIterations) {
|
||||
numIterations++
|
||||
} else {
|
||||
numIterations = maxIterations
|
||||
}
|
||||
|
||||
val delta: Double = rssi.toDouble() - predictedValue
|
||||
val gain: Double = 1.0 / (rssiMultiplier.pow(kotlin.math.abs(rssi.toDouble())) + numIterations)
|
||||
predictedValue += gain * delta
|
||||
}
|
||||
|
||||
override fun noMeasurementsAvailable(): Boolean {
|
||||
return numIterations == 0
|
||||
}
|
||||
|
||||
override fun calculateRssi(): Double {
|
||||
return predictedValue
|
||||
}
|
||||
|
||||
override fun getMeasurementCount(): Int {
|
||||
return numIterations
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package io.homeassistant.companion.android.bluetooth.ble
|
||||
|
||||
import android.content.Context
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import org.altbeacon.beacon.BeaconManager
|
||||
import org.altbeacon.beacon.BeaconParser
|
||||
import org.altbeacon.beacon.Region
|
||||
|
||||
class MonitoringManager {
|
||||
private lateinit var beaconManager: BeaconManager
|
||||
private lateinit var region: Region
|
||||
var scanPeriod: Long = 1100
|
||||
var scanInterval: Long = 500
|
||||
|
||||
private val scope: CoroutineScope = CoroutineScope(Dispatchers.Main + Job())
|
||||
|
||||
private fun buildRegion(): Region {
|
||||
return Region("all-beacons", null, null, null)
|
||||
}
|
||||
|
||||
fun isMonitoring(): Boolean {
|
||||
return this::beaconManager.isInitialized && beaconManager.isAnyConsumerBound
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun startMonitoring(context: Context, haMonitor: IBeaconMonitor) {
|
||||
if (isMonitoring()) {
|
||||
return
|
||||
}
|
||||
if (!this::beaconManager.isInitialized) {
|
||||
beaconManager = BeaconManager.getInstanceForApplication(context)
|
||||
|
||||
// find iBeacons
|
||||
beaconManager.beaconParsers.add(
|
||||
BeaconParser()
|
||||
.setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24")
|
||||
)
|
||||
|
||||
BeaconManager.setRssiFilterImplClass(KalmanFilter::class.java)
|
||||
}
|
||||
if (!beaconManager.isAnyConsumerBound) {
|
||||
beaconManager.foregroundScanPeriod = scanPeriod
|
||||
beaconManager.foregroundBetweenScanPeriod = scanInterval
|
||||
beaconManager.backgroundScanPeriod = scanPeriod
|
||||
beaconManager.backgroundBetweenScanPeriod = scanInterval
|
||||
|
||||
region = buildRegion()
|
||||
scope.launch(Dispatchers.Main) {
|
||||
beaconManager.getRegionViewModel(region).rangedBeacons.observeForever { beacons ->
|
||||
haMonitor.setBeacons(
|
||||
context,
|
||||
beacons
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
beaconManager.startRangingBeacons(region)
|
||||
haMonitor.sensorManager.updateBeaconMonitoringSensor(context)
|
||||
}
|
||||
|
||||
fun stopMonitoring(context: Context, haMonitor: IBeaconMonitor) {
|
||||
if (isMonitoring()) {
|
||||
beaconManager.stopRangingBeacons(region)
|
||||
haMonitor.sensorManager.updateBeaconMonitoringSensor(context)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -153,6 +153,7 @@ class MessagingManager @Inject constructor(
|
|||
const val COMMAND_VOLUME_LEVEL = "command_volume_level"
|
||||
const val COMMAND_BLUETOOTH = "command_bluetooth"
|
||||
const val COMMAND_BLE_TRANSMITTER = "command_ble_transmitter"
|
||||
const val COMMAND_BEACON_MONITOR = "command_beacon_monitor"
|
||||
const val COMMAND_SCREEN_ON = "command_screen_on"
|
||||
const val COMMAND_MEDIA = "command_media"
|
||||
const val COMMAND_UPDATE_SENSORS = "command_update_sensors"
|
||||
|
@ -230,6 +231,7 @@ class MessagingManager @Inject constructor(
|
|||
COMMAND_VOLUME_LEVEL,
|
||||
COMMAND_BLUETOOTH,
|
||||
COMMAND_BLE_TRANSMITTER,
|
||||
COMMAND_BEACON_MONITOR,
|
||||
COMMAND_HIGH_ACCURACY_MODE,
|
||||
COMMAND_ACTIVITY,
|
||||
COMMAND_WEBVIEW,
|
||||
|
@ -407,6 +409,19 @@ class MessagingManager @Inject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
COMMAND_BEACON_MONITOR -> {
|
||||
if (!jsonData[COMMAND].isNullOrEmpty() && jsonData[COMMAND] in ENABLE_COMMANDS)
|
||||
handleDeviceCommands(jsonData)
|
||||
else {
|
||||
mainScope.launch {
|
||||
Log.d(
|
||||
TAG,
|
||||
"Invalid beacon monitor command received, posting notification to device"
|
||||
)
|
||||
sendNotification(jsonData)
|
||||
}
|
||||
}
|
||||
}
|
||||
COMMAND_HIGH_ACCURACY_MODE -> {
|
||||
if ((!jsonData[COMMAND].isNullOrEmpty() && jsonData[COMMAND] in ENABLE_COMMANDS) ||
|
||||
(
|
||||
|
@ -783,6 +798,12 @@ class MessagingManager @Inject constructor(
|
|||
SensorWorker.start(context)
|
||||
}
|
||||
}
|
||||
COMMAND_BEACON_MONITOR -> {
|
||||
if (command == TURN_OFF)
|
||||
BluetoothSensorManager.enableDisableBeaconMonitor(context, false)
|
||||
if (command == TURN_ON)
|
||||
BluetoothSensorManager.enableDisableBeaconMonitor(context, true)
|
||||
}
|
||||
COMMAND_HIGH_ACCURACY_MODE -> {
|
||||
when (command) {
|
||||
TURN_OFF -> LocationSensorManager.setHighAccuracyModeSetting(context, false)
|
||||
|
|
|
@ -3,7 +3,11 @@ package io.homeassistant.companion.android.sensors
|
|||
import android.Manifest
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import io.homeassistant.companion.android.bluetooth.ble.IBeacon
|
||||
import io.homeassistant.companion.android.bluetooth.ble.IBeaconMonitor
|
||||
import io.homeassistant.companion.android.bluetooth.ble.IBeaconTransmitter
|
||||
import io.homeassistant.companion.android.bluetooth.ble.KalmanFilter
|
||||
import io.homeassistant.companion.android.bluetooth.ble.MonitoringManager
|
||||
import io.homeassistant.companion.android.bluetooth.ble.TransmitterManager
|
||||
import io.homeassistant.companion.android.common.bluetooth.BluetoothDevice
|
||||
import io.homeassistant.companion.android.common.bluetooth.BluetoothUtils
|
||||
|
@ -12,6 +16,7 @@ import io.homeassistant.companion.android.common.sensors.SensorManager
|
|||
import io.homeassistant.companion.android.database.AppDatabase
|
||||
import io.homeassistant.companion.android.database.sensor.SensorSetting
|
||||
import io.homeassistant.companion.android.database.sensor.SensorSettingType
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.util.UUID
|
||||
import kotlin.collections.ArrayList
|
||||
import io.homeassistant.companion.android.common.R as commonR
|
||||
|
@ -33,6 +38,11 @@ class BluetoothSensorManager : SensorManager {
|
|||
const val BLE_TRANSMIT_MEDIUM = "medium"
|
||||
const val BLE_TRANSMIT_LOW = "low"
|
||||
const val BLE_TRANSMIT_ULTRA_LOW = "ultraLow"
|
||||
private const val SETTING_BEACON_MONITOR_ENABLED = "beacon_monitor_enabled"
|
||||
private const val SETTING_BEACON_MONITOR_SCAN_PERIOD = "beacon_monitor_scan_period"
|
||||
private const val SETTING_BEACON_MONITOR_SCAN_INTERVAL = "beacon_monitor_scan_interval"
|
||||
private const val SETTING_BEACON_MONITOR_FILTER_ITERATIONS = "beacon_monitor_filter_iterations"
|
||||
private const val SETTING_BEACON_MONITOR_FILTER_RSSI_MULTIPLIER = "beacon_monitor_filter_rssi_multiplier"
|
||||
|
||||
private const val DEFAULT_BLE_TRANSMIT_POWER = "ultraLow"
|
||||
private const val DEFAULT_BLE_ADVERTISE_MODE = "lowPower"
|
||||
|
@ -41,7 +51,13 @@ class BluetoothSensorManager : SensorManager {
|
|||
private const val DEFAULT_MEASURED_POWER_AT_1M = -59
|
||||
private var priorBluetoothStateEnabled = false
|
||||
|
||||
private const val DEFAULT_BEACON_MONITOR_SCAN_PERIOD = "1100"
|
||||
private const val DEFAULT_BEACON_MONITOR_SCAN_INTERVAL = "500"
|
||||
private const val DEFAULT_BEACON_MONITOR_FILTER_ITERATIONS = "10"
|
||||
private const val DEFAULT_BEACON_MONITOR_FILTER_RSSI_MULTIPLIER = "1.05"
|
||||
|
||||
private var bleTransmitterDevice = IBeaconTransmitter("", "", "", transmitPowerSetting = "", measuredPowerSetting = 0, advertiseModeSetting = "", transmitting = false, state = "", restartRequired = false)
|
||||
private var beaconMonitoringDevice = IBeaconMonitor()
|
||||
val bluetoothConnection = SensorManager.BasicSensor(
|
||||
"bluetooth_connection",
|
||||
"sensor",
|
||||
|
@ -71,6 +87,17 @@ class BluetoothSensorManager : SensorManager {
|
|||
updateType = SensorManager.BasicSensor.UpdateType.INTENT
|
||||
)
|
||||
|
||||
val monitoringManager = MonitoringManager()
|
||||
val beaconMonitor = SensorManager.BasicSensor(
|
||||
"beacon_monitor",
|
||||
"sensor",
|
||||
commonR.string.basic_sensor_name_bluetooth_ble_beacon_monitor,
|
||||
commonR.string.sensor_description_bluetooth_ble_beacon_monitor,
|
||||
"mdi:bluetooth",
|
||||
entityCategory = SensorManager.ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
updateType = SensorManager.BasicSensor.UpdateType.CUSTOM
|
||||
)
|
||||
|
||||
fun enableDisableBLETransmitter(context: Context, transmitEnabled: Boolean) {
|
||||
val sensorDao = AppDatabase.getInstance(context).sensorDao()
|
||||
val sensorEntity = sensorDao.get(bleTransmitter.id)
|
||||
|
@ -84,6 +111,21 @@ class BluetoothSensorManager : SensorManager {
|
|||
}
|
||||
sensorDao.add(SensorSetting(bleTransmitter.id, SETTING_BLE_TRANSMIT_ENABLED, transmitEnabled.toString(), SensorSettingType.TOGGLE))
|
||||
}
|
||||
|
||||
fun enableDisableBeaconMonitor(context: Context, monitorEnabled: Boolean) {
|
||||
val sensorDao = AppDatabase.getInstance(context).sensorDao()
|
||||
val sensorEntity = sensorDao.get(beaconMonitor.id)
|
||||
val sensorEnabled = (sensorEntity != null && sensorEntity.enabled)
|
||||
if (!sensorEnabled)
|
||||
return
|
||||
|
||||
if (monitorEnabled) {
|
||||
monitoringManager.startMonitoring(context, beaconMonitoringDevice)
|
||||
} else {
|
||||
monitoringManager.stopMonitoring(context, beaconMonitoringDevice)
|
||||
}
|
||||
sensorDao.add(SensorSetting(beaconMonitor.id, SETTING_BEACON_MONITOR_ENABLED, monitorEnabled.toString(), SensorSettingType.TOGGLE))
|
||||
}
|
||||
}
|
||||
|
||||
override fun docsLink(): String {
|
||||
|
@ -94,7 +136,7 @@ class BluetoothSensorManager : SensorManager {
|
|||
override val name: Int
|
||||
get() = commonR.string.sensor_name_bluetooth
|
||||
override fun getAvailableSensors(context: Context): List<SensorManager.BasicSensor> {
|
||||
return listOf(bluetoothConnection, bluetoothState, bleTransmitter)
|
||||
return listOf(bluetoothConnection, bluetoothState, bleTransmitter, beaconMonitor)
|
||||
}
|
||||
|
||||
override fun requiredPermissions(sensorId: String): Array<String> {
|
||||
|
@ -106,6 +148,22 @@ class BluetoothSensorManager : SensorManager {
|
|||
Manifest.permission.BLUETOOTH_CONNECT
|
||||
)
|
||||
}
|
||||
(sensorId == beaconMonitor.id && Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) -> {
|
||||
arrayOf(
|
||||
Manifest.permission.BLUETOOTH,
|
||||
Manifest.permission.BLUETOOTH_ADMIN,
|
||||
Manifest.permission.ACCESS_FINE_LOCATION,
|
||||
Manifest.permission.ACCESS_BACKGROUND_LOCATION,
|
||||
Manifest.permission.ACCESS_COARSE_LOCATION,
|
||||
)
|
||||
}
|
||||
(sensorId == beaconMonitor.id && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) -> {
|
||||
arrayOf(
|
||||
Manifest.permission.BLUETOOTH,
|
||||
Manifest.permission.BLUETOOTH_SCAN,
|
||||
Manifest.permission.ACCESS_FINE_LOCATION,
|
||||
)
|
||||
}
|
||||
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) -> {
|
||||
arrayOf(
|
||||
Manifest.permission.BLUETOOTH,
|
||||
|
@ -122,6 +180,8 @@ class BluetoothSensorManager : SensorManager {
|
|||
updateBluetoothConnectionSensor(context)
|
||||
updateBluetoothState(context)
|
||||
updateBLESensor(context)
|
||||
updateBeaconMonitoringDevice(context)
|
||||
updateBeaconMonitoringSensor(context)
|
||||
}
|
||||
|
||||
private fun updateBluetoothConnectionSensor(context: Context) {
|
||||
|
@ -222,6 +282,31 @@ class BluetoothSensorManager : SensorManager {
|
|||
bleTransmitterDevice.transmitRequested = transmitActive
|
||||
}
|
||||
|
||||
private fun updateBeaconMonitoringDevice(context: Context) {
|
||||
if (!isEnabled(context, beaconMonitor.id)) {
|
||||
return
|
||||
}
|
||||
|
||||
beaconMonitoringDevice.sensorManager = this
|
||||
|
||||
val monitoringActive = getSetting(context, beaconMonitor, SETTING_BEACON_MONITOR_ENABLED, SensorSettingType.TOGGLE, "true").toBoolean()
|
||||
val scanPeriod = getSetting(context, beaconMonitor, SETTING_BEACON_MONITOR_SCAN_PERIOD, SensorSettingType.NUMBER, DEFAULT_BEACON_MONITOR_SCAN_PERIOD).toLongOrNull() ?: DEFAULT_BEACON_MONITOR_SCAN_PERIOD.toLong()
|
||||
val scanInterval = getSetting(context, beaconMonitor, SETTING_BEACON_MONITOR_SCAN_INTERVAL, SensorSettingType.NUMBER, DEFAULT_BEACON_MONITOR_SCAN_INTERVAL).toLongOrNull() ?: DEFAULT_BEACON_MONITOR_SCAN_INTERVAL.toLong()
|
||||
KalmanFilter.maxIterations = getSetting(context, beaconMonitor, SETTING_BEACON_MONITOR_FILTER_ITERATIONS, SensorSettingType.NUMBER, DEFAULT_BEACON_MONITOR_FILTER_ITERATIONS).toIntOrNull() ?: DEFAULT_BEACON_MONITOR_FILTER_ITERATIONS.toInt()
|
||||
KalmanFilter.rssiMultiplier = getSetting(context, beaconMonitor, SETTING_BEACON_MONITOR_FILTER_RSSI_MULTIPLIER, SensorSettingType.NUMBER, DEFAULT_BEACON_MONITOR_FILTER_RSSI_MULTIPLIER).toDoubleOrNull() ?: DEFAULT_BEACON_MONITOR_FILTER_RSSI_MULTIPLIER.toDouble()
|
||||
|
||||
var restart = monitoringManager.isMonitoring() &&
|
||||
(monitoringManager.scanPeriod != scanPeriod || monitoringManager.scanInterval != scanInterval)
|
||||
monitoringManager.scanPeriod = scanPeriod
|
||||
monitoringManager.scanInterval = scanInterval
|
||||
|
||||
if (!isEnabled(context, beaconMonitor.id) || ! monitoringActive || restart) {
|
||||
monitoringManager.stopMonitoring(context, beaconMonitoringDevice)
|
||||
} else {
|
||||
monitoringManager.startMonitoring(context, beaconMonitoringDevice)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateBLESensor(context: Context) {
|
||||
// get device details from settings
|
||||
updateBLEDevice(context)
|
||||
|
@ -261,6 +346,37 @@ class BluetoothSensorManager : SensorManager {
|
|||
)
|
||||
}
|
||||
|
||||
fun updateBeaconMonitoringSensor(context: Context) {
|
||||
if (!isEnabled(context, beaconMonitor.id)) {
|
||||
return
|
||||
}
|
||||
|
||||
val icon = if (monitoringManager.isMonitoring()) "mdi:bluetooth" else "mdi:bluetooth-off"
|
||||
|
||||
var state = if (!BluetoothUtils.isOn(context)) "Bluetooth is turned off" else if (monitoringManager.isMonitoring()) "Monitoring" else "Stopped"
|
||||
|
||||
var attr: Map<String, Any?> = mapOf()
|
||||
if (BluetoothUtils.isOn(context) && monitoringManager.isMonitoring()) {
|
||||
for (beacon: IBeacon in beaconMonitoringDevice.beacons) {
|
||||
attr += Pair(beacon.uuid, beacon.distance)
|
||||
}
|
||||
}
|
||||
|
||||
// reset the last_sent_state of the sensor so it won't skip the update of attributes
|
||||
val sensorDao = AppDatabase.getInstance(context).sensorDao()
|
||||
runBlocking {
|
||||
sensorDao.updateLastSentStateAndIcon(beaconMonitor.id, null, null)
|
||||
}
|
||||
|
||||
onSensorUpdated(
|
||||
context,
|
||||
beaconMonitor,
|
||||
state,
|
||||
icon,
|
||||
attr
|
||||
)
|
||||
}
|
||||
|
||||
private fun checkNameAddress(bt: BluetoothDevice): String {
|
||||
return if (bt.address != bt.name) "${bt.address} (${bt.name})" else bt.address
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
<string name="basic_sensor_name_battery_state">Battery State</string>
|
||||
<string name="basic_sensor_name_battery_temperature">Battery Temperature</string>
|
||||
<string name="basic_sensor_name_bluetooth_ble_emitter">BLE Transmitter</string>
|
||||
<string name="basic_sensor_name_bluetooth_ble_beacon_monitor">Beacon Monitor</string>
|
||||
<string name="basic_sensor_name_bluetooth_state">Bluetooth State</string>
|
||||
<string name="basic_sensor_name_bluetooth">Bluetooth Connection</string>
|
||||
<string name="basic_sensor_name_call_number">Call Number</string>
|
||||
|
@ -467,6 +468,7 @@
|
|||
<string name="sensor_description_battery_state">The current charging state of the battery</string>
|
||||
<string name="sensor_description_battery_temperature">The current battery temperature</string>
|
||||
<string name="sensor_description_bluetooth_ble_emitter">Send BLE iBeacon with configured interval, used to track presence around house, e.g. together with roomassistant, esp32-mqtt-room or espresence projects.\n\nWarning: this can affect battery life, particularly if the \"Transmitter power\" setting is set to High or \"Advertise Mode\" is set to Low latency.\nSettings allow for specifying:\n- \"UUID\" (standard UUID format), \"Major\" and \"Minor\" (should be 0 - 65535), to tailor identifiers and groups\n- \"Transmitter Power\" and \"Advertise Mode\" to help to preserve battery life (use lowest values if possible)#n - \"Measured Power\" to specify power measured at 1m (initial default -59)\n\nNote:\nAdditionally a separate setting exists (\"Enable Transmitter\") to stop or start transmitting.</string>
|
||||
<string name="sensor_description_bluetooth_ble_beacon_monitor">Scans for iBeacons and shows the IDs of nearby beacons and their distance in meters.\n\nWarning: this can affect battery life, especially with a short \"Scan Interval\".\n\nSettings allow for specifying:\n- \"Filter Iterations\" (should be 1 - 100, default: 10), higher values will result in more stable measurements but also less responsiveness.\n- \"Filter RSSI Multiplier\" (should be 1.0 - 2.0, default: 1.05), can be used to archive more stable measurements when beacons are farther away. This will also affect responsiveness.\n - \"Scan Interval\" (default: 500) milliseconds between scans. Shorter intervals will drain the battery more quickly.\n - \"Scan Period\" (default: 1100) milliseconds to scan for beacons. Most beacons will send a signal every second so this value should be at least 1100ms.\n\nNote:\nAdditionally a separate setting exists (\"Enable Beacon Monitor\") to stop or start scanning.</string>
|
||||
<string name="sensor_description_bluetooth_connection">Information about currently connected Bluetooth devices</string>
|
||||
<string name="sensor_description_bluetooth_state">Whether Bluetooth is enabled on the device</string>
|
||||
<string name="sensor_description_call_number">The cell number of the incoming or outgoing call</string>
|
||||
|
@ -587,6 +589,11 @@
|
|||
<string name="sensor_setting_ble_transmit_power_title">Transmitter power</string>
|
||||
<string name="sensor_setting_ble_transmit_power_ultraLow_label">Ultra Low</string>
|
||||
<string name="sensor_setting_ble_uuid_title">UUID</string>
|
||||
<string name="sensor_setting_beacon_monitor_enabled_title">Enable Beacon Monitor</string>
|
||||
<string name="sensor_setting_beacon_monitor_scan_period_title">Scan Period</string>
|
||||
<string name="sensor_setting_beacon_monitor_scan_interval_title">Scan Interval</string>
|
||||
<string name="sensor_setting_beacon_monitor_filter_iterations_title">Filter Iterations</string>
|
||||
<string name="sensor_setting_beacon_monitor_filter_rssi_multiplier_title">Filter RSSI Multiplier</string>
|
||||
<string name="sensor_setting_geocode_minimum_accuracy_title">Minimum Accuracy</string>
|
||||
<string name="sensor_setting_lastreboot_deadband_title">Deadband</string>
|
||||
<string name="sensor_setting_lastupdate_add_new_intent_title">Add New Intent</string>
|
||||
|
|
Loading…
Reference in a new issue