Allow sensors to have custom settings (#939)

* Allow sensors to have custom settings

* Add toggle to only grab one BSSID at a time

* Change keyboard logic to string or number to simplify it

* Review comments

* Review comments
This commit is contained in:
Daniel Shokouhi 2020-09-17 20:35:08 -07:00 committed by GitHub
parent 005b759a28
commit e652696f1d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 137 additions and 4 deletions

View file

@ -14,6 +14,7 @@ import io.homeassistant.companion.android.database.authentication.Authentication
import io.homeassistant.companion.android.database.sensor.Attribute
import io.homeassistant.companion.android.database.sensor.Sensor
import io.homeassistant.companion.android.database.sensor.SensorDao
import io.homeassistant.companion.android.database.sensor.Setting
import io.homeassistant.companion.android.database.widget.ButtonWidgetDao
import io.homeassistant.companion.android.database.widget.ButtonWidgetEntity
import io.homeassistant.companion.android.database.widget.StaticWidgetDao
@ -26,11 +27,12 @@ import io.homeassistant.companion.android.database.widget.TemplateWidgetEntity
Attribute::class,
Authentication::class,
Sensor::class,
Setting::class,
ButtonWidgetEntity::class,
StaticWidgetEntity::class,
TemplateWidgetEntity::class
],
version = 10
version = 11
)
abstract class AppDatabase : RoomDatabase() {
abstract fun authenticationDao(): AuthenticationDao
@ -65,7 +67,8 @@ abstract class AppDatabase : RoomDatabase() {
MIGRATION_6_7,
MIGRATION_7_8,
MIGRATION_8_9,
MIGRATION_9_10
MIGRATION_9_10,
MIGRATION_10_11
)
.build()
}
@ -194,5 +197,11 @@ abstract class AppDatabase : RoomDatabase() {
}
}
}
private val MIGRATION_10_11 = object : Migration(10, 11) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("CREATE TABLE IF NOT EXISTS `sensor_settings` (`sensor_id` TEXT NOT NULL, `name` TEXT NOT NULL, `value` TEXT NOT NULL, `value_type` TEXT NOT NULL DEFAULT 'string', PRIMARY KEY(`sensor_id`, `name`))")
}
}
}
}

View file

@ -17,12 +17,22 @@ interface SensorDao {
@Query("SELECT * FROM Sensors WHERE id = :id")
fun getFull(id: String): SensorWithAttributes?
@Transaction
@Query("SELECT * FROM sensor_settings WHERE sensor_id = :id")
fun getSettings(id: String): List<Setting>
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun add(sensor: Sensor)
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun add(attribute: Attribute)
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun add(setting: Setting)
@Query("DELETE FROM sensor_settings WHERE sensor_id = :sensorId AND name = :settingName")
fun removeSetting(sensorId: String, settingName: String)
@Update
fun update(sensor: Sensor)

View file

@ -0,0 +1,14 @@
package io.homeassistant.companion.android.database.sensor
import androidx.room.Embedded
import androidx.room.Relation
data class SensorWithSettings(
@Embedded
val sensor: Sensor,
@Relation(
parentColumn = "id",
entityColumn = "sensor_id"
)
val settings: List<Setting>
)

View file

@ -0,0 +1,16 @@
package io.homeassistant.companion.android.database.sensor
import androidx.room.ColumnInfo
import androidx.room.Entity
@Entity(tableName = "sensor_settings", primaryKeys = ["sensor_id", "name"])
data class Setting(
@ColumnInfo(name = "sensor_id")
val sensorId: String,
@ColumnInfo(name = "name")
val name: String,
@ColumnInfo(name = "value")
var value: String,
@ColumnInfo(name = "value_type")
var valueType: String
)

View file

@ -7,6 +7,8 @@ import android.net.wifi.WifiManager
import android.os.Build
import android.util.Log
import io.homeassistant.companion.android.R
import io.homeassistant.companion.android.database.AppDatabase
import io.homeassistant.companion.android.database.sensor.Setting
import okhttp3.Call
import okhttp3.Callback
import okhttp3.OkHttpClient
@ -70,6 +72,7 @@ class NetworkSensorManager : SensorManager {
R.string.basic_sensor_name_public_ip,
R.string.sensor_description_public_ip
)
private const val GET_CURRENT_BSSID = "get_current_bssid"
}
override val enabledByDefault: Boolean
@ -174,7 +177,27 @@ class NetworkSensorManager : SensorManager {
conInfo = wifiManager.connectionInfo
}
val bssid = if (conInfo!!.bssid == null) "<not connected>" else conInfo.bssid
var bssid = if (conInfo!!.bssid == null) "<not connected>" else conInfo.bssid
val settingName = "replace_$bssid"
val sensorDao = AppDatabase.getInstance(context).sensorDao()
val sensorSettings = sensorDao.getSettings(bssidState.id)
val getCurrentBSSID = sensorSettings?.firstOrNull { it.name == GET_CURRENT_BSSID }?.value ?: "false"
val currentSetting = sensorSettings?.firstOrNull { it.name == settingName }?.value ?: ""
if (getCurrentBSSID == "true") {
if (currentSetting == "") {
sensorDao.add(Setting(bssidState.id, GET_CURRENT_BSSID, "false", "toggle"))
sensorDao.add(Setting(bssidState.id, settingName, bssid, "string"))
}
} else {
if (currentSetting != "")
bssid = currentSetting
else
sensorDao.removeSetting(bssidState.id, settingName)
sensorDao.add(Setting(bssidState.id, GET_CURRENT_BSSID, "false", "toggle"))
}
val icon = if (bssid != "<not connected>") "mdi:wifi" else "mdi:wifi-off"
onSensorUpdated(
context,

View file

@ -3,6 +3,8 @@ package io.homeassistant.companion.android.sensors
import android.content.pm.PackageManager
import android.os.Bundle
import android.os.Handler
import android.text.InputType
import androidx.preference.EditTextPreference
import androidx.preference.Preference
import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceFragmentCompat
@ -13,6 +15,7 @@ import io.homeassistant.companion.android.common.dagger.GraphComponentAccessor
import io.homeassistant.companion.android.database.AppDatabase
import io.homeassistant.companion.android.database.sensor.Sensor
import io.homeassistant.companion.android.database.sensor.SensorDao
import io.homeassistant.companion.android.database.sensor.Setting
class SensorDetailFragment(
private val sensorManager: SensorManager,
@ -92,6 +95,7 @@ class SensorDetailFragment(
val sensorDao = AppDatabase.getInstance(requireContext()).sensorDao()
val fullData = sensorDao.getFull(basicSensor.id)
val sensorSettings = sensorDao.getSettings(basicSensor.id)
if (fullData?.sensor == null)
return
val sensorData = fullData.sensor
@ -147,6 +151,57 @@ class SensorDetailFragment(
} else
it.isVisible = false
}
findPreference<PreferenceCategory>("sensor_settings")?.let {
if (sensorData.enabled && !sensorSettings.isNullOrEmpty()) {
sensorSettings.forEach { setting ->
val key = "setting_${setting.name}"
if (setting.valueType == "toggle") {
val pref = findPreference(key) ?: SwitchPreference(requireContext())
pref.key = key
pref.title = setting.name
pref.isChecked = setting.value == "true"
pref.isIconSpaceReserved = false
pref.setOnPreferenceChangeListener { _, newState ->
val isEnabled = newState as Boolean
sensorDao.add(Setting(basicSensor.id, setting.name, isEnabled.toString(), "toggle"))
return@setOnPreferenceChangeListener true
}
if (!it.contains(pref))
it.addPreference(pref)
} else if (setting.valueType == "string" || setting.valueType == "number") {
val pref = findPreference(key) ?: EditTextPreference(requireContext())
pref.key = key
pref.title = setting.name
if (setting.value != "")
pref.summary = setting.value
else
pref.summary = pref.text
pref.isIconSpaceReserved = false
pref.setOnBindEditTextListener { fieldType ->
if (setting.valueType == "number")
fieldType.inputType = InputType.TYPE_CLASS_NUMBER
}
if (pref.text != null)
sensorDao.add(
Setting(
basicSensor.id,
setting.name,
pref.text,
setting.valueType
)
)
if (!it.contains(pref))
it.addPreference(pref)
}
}
it.isVisible = true
} else
it.isVisible = false
}
}
private fun updateSensorEntity(

View file

@ -208,7 +208,7 @@ like to connect to:</string>
<string name="sensor_description_volume_call">Volume level for calls on the device</string>
<string name="sensor_description_volume_music">Volume level for music on the device</string>
<string name="sensor_description_volume_ring">Volume level for the ringer on the device</string>
<string name="sensor_description_wifi_bssid">The mac address of the currently connected WiFi access point</string>
<string name="sensor_description_wifi_bssid">The mac address of the currently connected WiFi access point. Enabling the "get_current_bssid" toggle will create a new setting allowing you to rename the state sent back to Home Assistant for the chosen mac address. The toggle will default to off after the current BSSID is stored, so you will need to enable it once for each BSSID you wish to rename. You can also clear out the value to remove the setting in the next update.</string>
<string name="sensor_description_wifi_connection">The name of the network the device is currently connected to</string>
<string name="sensor_description_wifi_frequency">The frequency band of the connected network</string>
<string name="sensor_description_wifi_ip">The current IP address of the device on the network</string>
@ -242,6 +242,7 @@ like to connect to:</string>
<string name="sensor_name_volume_call">Volume Level Call</string>
<string name="sensor_name_volume_music">Volume Level Music</string>
<string name="sensor_name_volume_ring">Volume Level Ringer</string>
<string name="sensor_settings">Sensor Settings</string>
<string name="sensor_summary">Use this to manage what sensors are enabled/disabled.</string>
<string name="sensor_title">Manage Sensors</string>
<string name="sensors">Sensors</string>

View file

@ -36,4 +36,9 @@
app:key="attributes"
app:title="@string/attributes"
app:iconSpaceReserved="false"/>
<androidx.preference.PreferenceCategory
app:key="sensor_settings"
app:title="@string/sensor_settings"
app:iconSpaceReserved="false"/>
</androidx.preference.PreferenceScreen>