summaryrefslogtreecommitdiffstats
path: root/lib/data/data_providers/vehicle_notifier.dart
diff options
context:
space:
mode:
authorScott Murray <scott.murray@konsulko.com>2023-12-17 15:48:21 -0500
committerJan-Simon Moeller <jsmoeller@linuxfoundation.org>2023-12-18 13:28:28 +0000
commit4ae68f5be11d110f2df10d54377d970921e30a21 (patch)
treeb37b5cb3c6964fbaeaa95edc1edeb44d615912e9 /lib/data/data_providers/vehicle_notifier.dart
parentdda6c8502a3fa1e50654c4cca934b4b846bbca98 (diff)
Implement audio settings
Changes: - Rework KUKSA.val "VAL" gRPC API implementation to separate it from the vehicle model + notifier, and more easily allow using it from other notifiers. - Move volume handling from the vehicle model + notifier to the audio set for clarity. - Wire up the new VSS audio signals in the audio notifier. The "rearFront" variable naming has been changed to "fade" in several places to match expected terminology. - Add a balance slider to the audio settings page. - Change the min/max labels on the fade slider to be Text instead of Icon's since we do not have the equivalent to use with the balance slider, and text seems like it'd be what you would want for any potential future internationalization. - Rework configuration file to be usable from anywhere via a RiverPod Provider instead of tied to the vehicle notifier code, and shifted the background and hybrid animation flags to be handled with it. This change removes the built-in asset with defaults in favor of maintaining the defaults for the ICS environment in the AppConfig and KuksaConfig classes, with a goal of avoiding the need for using async methods in the config provider. - Change some notifiers from using StateNotifier to the RiverPod 2.0 Notifier class for improved flexibility. The other notifiers will be updated in future work. - Added select's to several ref.watches in the new hybrid animation code to avoid unnecessary repaints. - Fix several spelling issues in method and parameter names across the codebase. Bug-AGL: SPEC-5001 Change-Id: Iefae417fa870405d659303497d96e519e6b6d1de Signed-off-by: Scott Murray <scott.murray@konsulko.com>
Diffstat (limited to 'lib/data/data_providers/vehicle_notifier.dart')
-rw-r--r--lib/data/data_providers/vehicle_notifier.dart253
1 files changed, 24 insertions, 229 deletions
diff --git a/lib/data/data_providers/vehicle_notifier.dart b/lib/data/data_providers/vehicle_notifier.dart
index 3a385a3..78c5328 100644
--- a/lib/data/data_providers/vehicle_notifier.dart
+++ b/lib/data/data_providers/vehicle_notifier.dart
@@ -3,43 +3,20 @@
import 'dart:async';
import 'package:flutter_ics_homescreen/export.dart';
-import 'package:flutter/services.dart';
import 'package:protos/protos.dart';
-class KuksaConfig {
- final String hostname;
- final int port;
- final String authorization;
- final bool use_tls;
- final List<int> ca_certificate;
- final String tls_server_name;
-
- static String configFilePath = '/etc/xdg/AGL/ics-homescreen.yaml';
- static String defaultHostname = 'localhost';
- static int defaultPort = 55555;
- static String defaultCaCertPath = '/etc/kuksa-val/CA.pem';
-
- KuksaConfig(
- {required this.hostname,
- required this.port,
- required this.authorization,
- required this.use_tls,
- required this.ca_certificate,
- required this.tls_server_name});
-}
-
-class VehicleNotifier extends StateNotifier<Vehicle> {
- VehicleNotifier(super.state);
-
- late ClientChannel channel;
- late String authorization;
- late VALClient stub;
+class VehicleNotifier extends Notifier<Vehicle> {
+ @override
+ Vehicle build() {
+ return Vehicle.initial();
+ }
void updateSpeed(double newValue) {
state = state.copyWith(speed: newValue);
}
- void handleSignalsUpdate(EntryUpdate update) {
+ bool handleSignalsUpdate(EntryUpdate update) {
+ bool handled = true;
switch (update.entry.path) {
case VSSPath.vehicleSpeed:
if (update.entry.value.hasFloat()) {
@@ -66,11 +43,6 @@ class VehicleNotifier extends StateNotifier<Vehicle> {
state = state.copyWith(fuelLevel: update.entry.value.uint32);
}
break;
- case VSSPath.vehicleMediaVolume:
- if (update.entry.value.hasUint32()) {
- state = state.copyWith(mediaVolume: update.entry.value.uint32);
- }
- break;
case VSSPath.vehicleIsChildLockActiveLeft:
if (update.entry.value.hasBool_12()) {
state =
@@ -108,7 +80,6 @@ class VehicleNotifier extends StateNotifier<Vehicle> {
state = state.copyWith(rearRightTire: update.entry.value.uint32);
}
break;
-
case VSSPath.vehicleIsAirConditioningActive:
if (update.entry.value.hasBool_12()) {
state = state.copyWith(
@@ -142,8 +113,7 @@ class VehicleNotifier extends StateNotifier<Vehicle> {
fanSpeed = 3;
else if (value > 33)
fanSpeed = 2;
- else if (value > 0)
- fanSpeed = 1;
+ else if (value > 0) fanSpeed = 1;
state = state.copyWith(fanSpeed: fanSpeed);
}
break;
@@ -158,183 +128,18 @@ class VehicleNotifier extends StateNotifier<Vehicle> {
state.copyWith(passengerTemperature: update.entry.value.int32);
}
break;
- // default:
- // debugPrint("ERROR: Unexpected path ${update.entry.path}");
- // break;
- }
- }
-
- Future<KuksaConfig> readConfig() async {
- String hostname = KuksaConfig.defaultHostname;
- int port = KuksaConfig.defaultPort;
- bool useTls = false;
- String caPath = KuksaConfig.defaultCaCertPath;
- List<int> caCert = [];
- String tlsServerName = "";
- String token = "";
-
- // Read build time configuration from bundle
- try {
- var data = await rootBundle.loadString('app-config/config.yaml');
- final dynamic yamlMap = loadYaml(data);
-
- if (yamlMap.containsKey('hostname')) {
- hostname = yamlMap['hostname'];
- }
-
- if (yamlMap.containsKey('port')) {
- port = yamlMap['port'];
- }
-
- if (yamlMap.containsKey('use-tls')) {
- var value = yamlMap['use-tls'];
- if (value is bool) {
- useTls = value;
- }
- }
-
- if (useTls) {
- if (yamlMap.containsKey('ca-certificate')) {
- caPath = yamlMap['ca-certificate'];
- }
-
- if (yamlMap.containsKey('tls-server-name')) {
- tlsServerName = yamlMap['tls_server_name'];
- }
- }
-
- if (yamlMap.containsKey('authorization')) {
- token = yamlMap['authorization'];
- }
- } catch (e) {
- //debugPrint('ERROR: Could not read from file: $configFile');
- debugPrint(e.toString());
- }
-
- // Try reading from configuration file in /etc
- final configFile = File(KuksaConfig.configFilePath);
- try {
- print("Reading configuration ${KuksaConfig.configFilePath}");
- String content = await configFile.readAsString();
- final dynamic yamlMap = loadYaml(content);
-
- if (yamlMap.containsKey('hostname')) {
- hostname = yamlMap['hostname'];
- }
-
- if (yamlMap.containsKey('port')) {
- port = yamlMap['port'];
- }
-
- if (yamlMap.containsKey('use-tls')) {
- var value = yamlMap['use-tls'];
- if (value is bool) {
- useTls = value;
- }
- }
- //debugPrint("Use TLS = $use_tls");
-
- if (useTls) {
- if (yamlMap.containsKey('ca-certificate')) {
- caPath = yamlMap['ca-certificate'];
- }
- try {
- caCert = File(caPath).readAsBytesSync();
- } on Exception catch (_) {
- print("ERROR: Could not read CA certificate file $caPath");
- caCert = [];
- }
- //debugPrint("CA cert = $ca_cert");
-
- if (yamlMap.containsKey('tls-server-name')) {
- tlsServerName = yamlMap['tls_server_name'];
- }
- }
-
- if (yamlMap.containsKey('authorization')) {
- token = yamlMap['authorization'];
- }
- if (token.isNotEmpty) {
- if (token.startsWith("/")) {
- debugPrint("Reading authorization token $token");
- String tokenFile = token;
- try {
- token = await File(tokenFile).readAsString();
- } on Exception catch (_) {
- print("ERROR: Could not read authorization token file $token");
- token = "";
- }
- }
- }
- //debugPrint("authorization = $token");
- } catch (e) {
- debugPrint('WARNING: Could not read from file: $configFile');
- //debugPrint(e.toString());
- }
- return KuksaConfig(
- hostname: hostname,
- port: port,
- authorization: token,
- use_tls: useTls,
- ca_certificate: caCert,
- tls_server_name: tlsServerName);
- }
-
- void startListen() async {
- KuksaConfig config = await readConfig();
- ChannelCredentials creds;
- if (config.use_tls && config.ca_certificate.isNotEmpty) {
- print("Using TLS");
- if (config.tls_server_name.isNotEmpty) {
- creds = ChannelCredentials.secure(
- certificates: config.ca_certificate,
- authority: config.tls_server_name);
- } else {
- creds = ChannelCredentials.secure(certificates: config.ca_certificate);
- }
- } else {
- creds = const ChannelCredentials.insecure();
- }
- channel = ClientChannel(config.hostname,
- port: config.port, options: ChannelOptions(credentials: creds));
- debugPrint('Start Listen on port: ${config.port}');
- stub = VALClient(channel);
- authorization = config.authorization;
- List<String> fewSignals = VSSPath().getSignalsList();
- var request = SubscribeRequest();
- Map<String, String> metadata = {};
- if (authorization.isNotEmpty) {
- metadata = {'authorization': "Bearer ${authorization}"};
- }
- for (int i = 0; i < fewSignals.length; i++) {
- var entry = SubscribeEntry();
- entry.path = fewSignals[i];
- entry.fields.add(Field.FIELD_PATH);
- entry.fields.add(Field.FIELD_VALUE);
- request.entries.add(entry);
- }
- try {
- var responseStream = stub.subscribe(request, options: CallOptions(metadata: metadata));
- responseStream.listen((value) async {
- for (var update in value.updates) {
- if (!(update.hasEntry() && update.entry.hasPath())) continue;
- handleSignalsUpdate(update);
- }
- }, onError: (stacktrace, errorDescriptor) {
- debugPrint(stacktrace.toString());
- state = const Vehicle.initialForDebug();
- });
- } catch (e) {
- debugPrint(e.toString());
+ default:
+ handled = false;
}
+ return handled;
}
void setChildLock({required String side}) async {
- var helper = ValClientHelper(stub: stub, authorization: authorization);
+ var valClient = ref.read(valClientProvider);
try {
switch (side) {
case 'left':
- helper.setBool(
+ valClient.setBool(
VSSPath.vehicleIsChildLockActiveLeft,
!state.isChildLockActiveLeft,
false,
@@ -343,7 +148,7 @@ class VehicleNotifier extends StateNotifier<Vehicle> {
isChildLockActiveLeft: !state.isChildLockActiveLeft);
break;
case 'right':
- helper.setBool(
+ valClient.setBool(
VSSPath.vehicleIsChildLockActiveRight,
!state.isChildLockActiveRight,
false,
@@ -360,22 +165,12 @@ class VehicleNotifier extends StateNotifier<Vehicle> {
}
}
- void setVolume(double newVal) {
- state = state.copyWith(mediaVolume: newVal.toInt());
- var helper = ValClientHelper(stub: stub, authorization: authorization);
- helper.setUint32(
- VSSPath.vehicleMediaVolume,
- newVal.toInt(),
- true,
- );
- }
-
void setTemperature({required Side side, required int value}) {
- var helper = ValClientHelper(stub: stub, authorization: authorization);
+ var valClient = ref.read(valClientProvider);
try {
switch (side) {
case Side.left:
- helper.setInt32(
+ valClient.setInt32(
VSSPath.vehicleDriverTemperature,
value,
true,
@@ -383,7 +178,7 @@ class VehicleNotifier extends StateNotifier<Vehicle> {
state = state.copyWith(driverTemperature: value);
break;
case Side.right:
- helper.setInt32(
+ valClient.setInt32(
VSSPath.vehiclePassengerTemperature,
value,
true,
@@ -419,8 +214,8 @@ class VehicleNotifier extends StateNotifier<Vehicle> {
default:
break;
}
- var helper = ValClientHelper(stub: stub, authorization: authorization);
- helper.setUint32(
+ var valClient = ref.read(valClientProvider);
+ valClient.setUint32(
VSSPath.vehicleFanSpeed,
targetFanSpeed,
true,
@@ -429,11 +224,11 @@ class VehicleNotifier extends StateNotifier<Vehicle> {
}
void setHVACMode({required String mode}) {
- var helper = ValClientHelper(stub: stub, authorization: authorization);
+ var valClient = ref.read(valClientProvider);
try {
switch (mode) {
case 'airCondition':
- helper.setBool(
+ valClient.setBool(
VSSPath.vehicleIsAirConditioningActive,
!state.isAirConditioningActive,
true,
@@ -442,7 +237,7 @@ class VehicleNotifier extends StateNotifier<Vehicle> {
isAirConditioningActive: !state.isAirConditioningActive);
break;
case 'frontDefrost':
- helper.setBool(
+ valClient.setBool(
VSSPath.vehicleIsFrontDefrosterActive,
!state.isFrontDefrosterActive,
true,
@@ -451,7 +246,7 @@ class VehicleNotifier extends StateNotifier<Vehicle> {
isFrontDefrosterActive: !state.isFrontDefrosterActive);
break;
case 'rearDefrost':
- helper.setBool(
+ valClient.setBool(
VSSPath.vehicleIsRearDefrosterActive,
!state.isRearDefrosterActive,
true,
@@ -460,7 +255,7 @@ class VehicleNotifier extends StateNotifier<Vehicle> {
isRearDefrosterActive: !state.isRearDefrosterActive);
break;
case 'recirculation':
- helper.setBool(
+ valClient.setBool(
VSSPath.vehicleIsRecirculationActive,
!state.isRecirculationActive,
true,