From 06b78cd997b3fcb9cadca54709bb5b7c77ff0d38 Mon Sep 17 00:00:00 2001 From: andrekir Date: Sat, 19 Aug 2023 07:44:54 -0300 Subject: [PATCH] feat: add new module configs --- .../datastore/ModuleConfigRepository.kt | 21 +++ .../mesh/ui/DeviceSettingsFragment.kt | 32 +++- .../config/AmbientLightingConfigItemList.kt | 105 ++++++++++++ .../config/DetectionSensorConfigItemList.kt | 149 ++++++++++++++++++ 4 files changed, 306 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/com/geeksville/mesh/ui/components/config/AmbientLightingConfigItemList.kt create mode 100644 app/src/main/java/com/geeksville/mesh/ui/components/config/DetectionSensorConfigItemList.kt diff --git a/app/src/main/java/com/geeksville/mesh/repository/datastore/ModuleConfigRepository.kt b/app/src/main/java/com/geeksville/mesh/repository/datastore/ModuleConfigRepository.kt index 33a3f8194..bbc00303f 100644 --- a/app/src/main/java/com/geeksville/mesh/repository/datastore/ModuleConfigRepository.kt +++ b/app/src/main/java/com/geeksville/mesh/repository/datastore/ModuleConfigRepository.kt @@ -46,6 +46,9 @@ class ModuleConfigRepository @Inject constructor( if (config.hasCannedMessage()) setCannedMessageConfig(config.cannedMessage) if (config.hasAudio()) setAudioConfig(config.audio) if (config.hasRemoteHardware()) setRemoteHardwareConfig(config.remoteHardware) + if (config.hasNeighborInfo()) setNeighborInfoConfig(config.neighborInfo) + if (config.hasAmbientLighting()) setAmbientLightingConfig(config.ambientLighting) + if (config.hasDetectionSensor()) setDetectionSensorConfig(config.detectionSensor) } private suspend fun setMQTTConfig(config: ModuleConfig.MQTTConfig) { @@ -102,6 +105,24 @@ class ModuleConfigRepository @Inject constructor( } } + private suspend fun setNeighborInfoConfig(config: ModuleConfig.NeighborInfoConfig) { + moduleConfigStore.updateData { preference -> + preference.toBuilder().setNeighborInfo(config).build() + } + } + + private suspend fun setAmbientLightingConfig(config: ModuleConfig.AmbientLightingConfig) { + moduleConfigStore.updateData { preference -> + preference.toBuilder().setAmbientLighting(config).build() + } + } + + private suspend fun setDetectionSensorConfig(config: ModuleConfig.DetectionSensorConfig) { + moduleConfigStore.updateData { preference -> + preference.toBuilder().setDetectionSensor(config).build() + } + } + suspend fun fetchInitialModuleConfig() = moduleConfigStore.data.first() } diff --git a/app/src/main/java/com/geeksville/mesh/ui/DeviceSettingsFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/DeviceSettingsFragment.kt index 322f7f826..d642719dc 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/DeviceSettingsFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/DeviceSettingsFragment.kt @@ -76,10 +76,12 @@ import com.geeksville.mesh.moduleConfig import com.geeksville.mesh.service.MeshService import com.geeksville.mesh.ui.components.PreferenceCategory import com.geeksville.mesh.ui.components.TextDividerPreference +import com.geeksville.mesh.ui.components.config.AmbientLightingConfigItemList import com.geeksville.mesh.ui.components.config.AudioConfigItemList import com.geeksville.mesh.ui.components.config.BluetoothConfigItemList import com.geeksville.mesh.ui.components.config.CannedMessageConfigItemList import com.geeksville.mesh.ui.components.config.ChannelSettingsItemList +import com.geeksville.mesh.ui.components.config.DetectionSensorConfigItemList import com.geeksville.mesh.ui.components.config.DeviceConfigItemList import com.geeksville.mesh.ui.components.config.DisplayConfigItemList import com.geeksville.mesh.ui.components.config.EditDeviceProfileDialog @@ -142,7 +144,9 @@ enum class ModuleDest(val title: String, val route: String) { CANNED_MESSAGE("Canned Message", "canned_message"), AUDIO("Audio", "audio"), REMOTE_HARDWARE("Remote Hardware", "remote_hardware"), - NEIGHBOR_INFO("Neighbor Info", "neighbor_info"); + NEIGHBOR_INFO("Neighbor Info", "neighbor_info"), + AMBIENT_LIGHTING("Ambient Lighting", "ambient_lighting"), + DETECTION_SENSOR("Detection Sensor", "detection_sensor"); } /** @@ -666,6 +670,32 @@ fun RadioConfigNavHost(node: NodeInfo, viewModel: UIViewModel = viewModel()) { } ) } + composable("ambient_lighting") { + AmbientLightingConfigItemList( + ambientLightingConfig = moduleConfig.ambientLighting, + enabled = connected, + focusManager = focusManager, + onSaveClicked = { ambientLightingInput -> + focusManager.clearFocus() + val config = moduleConfig { ambientLighting = ambientLightingInput } + viewModel.setModuleConfig(destNum, config) + moduleConfig = config + } + ) + } + composable("detection_sensor") { + DetectionSensorConfigItemList( + detectionSensorConfig = moduleConfig.detectionSensor, + enabled = connected, + focusManager = focusManager, + onSaveClicked = { detectionSensorInput -> + focusManager.clearFocus() + val config = moduleConfig { detectionSensor = detectionSensorInput } + viewModel.setModuleConfig(destNum, config) + moduleConfig = config + } + ) + } } } diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/AmbientLightingConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/AmbientLightingConfigItemList.kt new file mode 100644 index 000000000..c8f480b5c --- /dev/null +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/AmbientLightingConfigItemList.kt @@ -0,0 +1,105 @@ +package com.geeksville.mesh.ui.components.config + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.material.Divider +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusManager +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.tooling.preview.Preview +import com.geeksville.mesh.ModuleConfigProtos +import com.geeksville.mesh.copy +import com.geeksville.mesh.ui.components.EditTextPreference +import com.geeksville.mesh.ui.components.PreferenceCategory +import com.geeksville.mesh.ui.components.PreferenceFooter +import com.geeksville.mesh.ui.components.SwitchPreference + +@Composable +fun AmbientLightingConfigItemList( + ambientLightingConfig: ModuleConfigProtos.ModuleConfig.AmbientLightingConfig, + enabled: Boolean, + focusManager: FocusManager, + onSaveClicked: (ModuleConfigProtos.ModuleConfig.AmbientLightingConfig) -> Unit, +) { + var ambientLightingInput by remember(ambientLightingConfig) { + mutableStateOf(ambientLightingConfig) + } + + LazyColumn( + modifier = Modifier.fillMaxSize() + ) { + item { PreferenceCategory(text = "Ambient Lighting Config") } + + item { + SwitchPreference(title = "LED state", + checked = ambientLightingInput.ledState, + enabled = enabled, + onCheckedChange = { + ambientLightingInput = ambientLightingInput.copy { ledState = it } + }) + } + item { Divider() } + + item { + EditTextPreference(title = "Current", + value = ambientLightingInput.current, + enabled = enabled, + keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }), + onValueChanged = { + ambientLightingInput = ambientLightingInput.copy { current = it } + }) + } + + item { + EditTextPreference(title = "Red", + value = ambientLightingInput.red, + enabled = enabled, + keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }), + onValueChanged = { ambientLightingInput = ambientLightingInput.copy { red = it } }) + } + + item { + EditTextPreference(title = "Green", + value = ambientLightingInput.green, + enabled = enabled, + keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }), + onValueChanged = { ambientLightingInput = ambientLightingInput.copy { green = it } }) + } + + item { + EditTextPreference(title = "Blue", + value = ambientLightingInput.blue, + enabled = enabled, + keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }), + onValueChanged = { ambientLightingInput = ambientLightingInput.copy { blue = it } }) + } + + item { + PreferenceFooter( + enabled = ambientLightingInput != ambientLightingConfig, + onCancelClicked = { + focusManager.clearFocus() + ambientLightingInput = ambientLightingConfig + }, + onSaveClicked = { onSaveClicked(ambientLightingInput) } + ) + } + } +} + +@Preview(showBackground = true) +@Composable +private fun AmbientLightingConfigPreview() { + AmbientLightingConfigItemList( + ambientLightingConfig = ModuleConfigProtos.ModuleConfig.AmbientLightingConfig.getDefaultInstance(), + enabled = true, + focusManager = LocalFocusManager.current, + onSaveClicked = { }, + ) +} diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/DetectionSensorConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/DetectionSensorConfigItemList.kt new file mode 100644 index 000000000..a3f53b965 --- /dev/null +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/DetectionSensorConfigItemList.kt @@ -0,0 +1,149 @@ +package com.geeksville.mesh.ui.components.config + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.Divider +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusManager +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.tooling.preview.Preview +import com.geeksville.mesh.ModuleConfigProtos +import com.geeksville.mesh.copy +import com.geeksville.mesh.ui.components.EditTextPreference +import com.geeksville.mesh.ui.components.PreferenceCategory +import com.geeksville.mesh.ui.components.PreferenceFooter +import com.geeksville.mesh.ui.components.SwitchPreference + +@Composable +fun DetectionSensorConfigItemList( + detectionSensorConfig: ModuleConfigProtos.ModuleConfig.DetectionSensorConfig, + enabled: Boolean, + focusManager: FocusManager, + onSaveClicked: (ModuleConfigProtos.ModuleConfig.DetectionSensorConfig) -> Unit, +) { + var detectionSensorInput by remember(detectionSensorConfig) { + mutableStateOf(detectionSensorConfig) + } + + LazyColumn( + modifier = Modifier.fillMaxSize() + ) { + item { PreferenceCategory(text = "Detection Sensor Config") } + + item { + SwitchPreference(title = "Detection Sensor enabled", + checked = detectionSensorInput.enabled, + enabled = enabled, + onCheckedChange = { + detectionSensorInput = detectionSensorInput.copy { this.enabled = it } + }) + } + item { Divider() } + + item { + EditTextPreference(title = "Minimum broadcast (seconds)", + value = detectionSensorInput.minimumBroadcastSecs, + enabled = enabled, + keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }), + onValueChanged = { + detectionSensorInput = detectionSensorInput.copy { minimumBroadcastSecs = it } + }) + } + + item { + EditTextPreference(title = "State broadcast (seconds)", + value = detectionSensorInput.stateBroadcastSecs, + enabled = enabled, + keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }), + onValueChanged = { + detectionSensorInput = detectionSensorInput.copy { stateBroadcastSecs = it } + }) + } + + item { + SwitchPreference(title = "Send bell with alert message", + checked = detectionSensorInput.sendBell, + enabled = enabled, + onCheckedChange = { + detectionSensorInput = detectionSensorInput.copy { sendBell = it } + }) + } + item { Divider() } + + item { + EditTextPreference(title = "Friendly name", + value = detectionSensorInput.name, + maxSize = 19, // name max_size:20 + enabled = enabled, + isError = false, + keyboardOptions = KeyboardOptions.Default.copy( + keyboardType = KeyboardType.Text, imeAction = ImeAction.Done + ), + keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }), + onValueChanged = { + detectionSensorInput = detectionSensorInput.copy { name = it } + }) + } + + item { + EditTextPreference(title = "GPIO pin to monitor", + value = detectionSensorInput.monitorPin, + enabled = enabled, + keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }), + onValueChanged = { + detectionSensorInput = detectionSensorInput.copy { monitorPin = it } + }) + } + + item { + SwitchPreference(title = "Detection is triggered on HIGH (1)", + checked = detectionSensorInput.detectionTriggeredHigh, + enabled = enabled, + onCheckedChange = { + detectionSensorInput = detectionSensorInput.copy { detectionTriggeredHigh = it } + }) + } + item { Divider() } + + item { + SwitchPreference(title = "Use INPUT_PULLUP mode", + checked = detectionSensorInput.usePullup, + enabled = enabled, + onCheckedChange = { + detectionSensorInput = detectionSensorInput.copy { usePullup = it } + }) + } + item { Divider() } + + item { + PreferenceFooter( + enabled = detectionSensorInput != detectionSensorConfig, + onCancelClicked = { + focusManager.clearFocus() + detectionSensorInput = detectionSensorConfig + }, + onSaveClicked = { onSaveClicked(detectionSensorInput) } + ) + } + } +} + +@Preview(showBackground = true) +@Composable +private fun DetectionSensorConfigPreview() { + DetectionSensorConfigItemList( + detectionSensorConfig = ModuleConfigProtos.ModuleConfig.DetectionSensorConfig.getDefaultInstance(), + enabled = true, + focusManager = LocalFocusManager.current, + onSaveClicked = { }, + ) +}