diff options
author | Scott Murray <scott.murray@konsulko.com> | 2024-01-04 20:13:01 -0500 |
---|---|---|
committer | Scott Murray <scott.murray@konsulko.com> | 2024-01-04 20:20:16 -0500 |
commit | 31438c5081e8ee5b520787a6e64b9372ec678886 (patch) | |
tree | 3c2fd4d08d0ad5070ade0f6111fe5961ed39a8da /lib/data/data_providers | |
parent | 5588d1d26f1be968af6809e43507d7be0fadf434 (diff) |
Configurable units fixes
Notable changes:
- Add pressure unit to the units model.
- Add tire pressure unit configuration page under settings.
- Rework the VSS client, provider, and the associated handling in
the vehicle and audio state providers to make the signal updating
code reusable for processing the result of VAL API get commands.
- Add logic to get the initial values of the used VSS signals so
the initial application state looks sane in demo scenarios.
- Add VSS signal support to the units provider so that changes will
be pushed out for e.g. IC use.
- Fix pressure unit use in various widgets.
- Fix up range calculation for dashboard to correctly account for
units and the incoming VSS value being in meters.
- Fix some unit naming inconsistencies around capitalization.
Bug-AGL: SPEC-5031, SPEC-5032
Change-Id: I33ac735dfbe35283bd30c92aa157cbdb7af1837c
Signed-off-by: Scott Murray <scott.murray@konsulko.com>
Diffstat (limited to 'lib/data/data_providers')
-rw-r--r-- | lib/data/data_providers/app_provider.dart | 6 | ||||
-rw-r--r-- | lib/data/data_providers/audio_notifier.dart | 24 | ||||
-rw-r--r-- | lib/data/data_providers/units_notifier.dart | 65 | ||||
-rw-r--r-- | lib/data/data_providers/val_client.dart | 47 | ||||
-rw-r--r-- | lib/data/data_providers/vehicle_notifier.dart | 87 |
5 files changed, 156 insertions, 73 deletions
diff --git a/lib/data/data_providers/app_provider.dart b/lib/data/data_providers/app_provider.dart index 3d00d4c..ee6d29e 100644 --- a/lib/data/data_providers/app_provider.dart +++ b/lib/data/data_providers/app_provider.dart @@ -40,6 +40,7 @@ enum AppState { weather, distanceUnit, tempUnit, + pressureUnit, clock, date, time, @@ -78,9 +79,8 @@ final signalsProvider = StateNotifierProvider<SignalNotifier, Signals>((ref) { return SignalNotifier(const Signals.initial()); }); -final unitStateProvider = StateNotifierProvider<UnitsNotifier, Units>((ref) { - return UnitsNotifier(const Units.initial()); -}); +final unitStateProvider = + NotifierProvider<UnitsNotifier, Units>(UnitsNotifier.new); final audioStateProvider = NotifierProvider<AudioStateNotifier, AudioState>(AudioStateNotifier.new); diff --git a/lib/data/data_providers/audio_notifier.dart b/lib/data/data_providers/audio_notifier.dart index a601095..76b34a7 100644 --- a/lib/data/data_providers/audio_notifier.dart +++ b/lib/data/data_providers/audio_notifier.dart @@ -36,36 +36,36 @@ class AudioStateNotifier extends Notifier<AudioState> { ); } - bool handleSignalsUpdate(EntryUpdate update) { + bool handleSignalUpdate(DataEntry entry) { bool handled = true; - switch (update.entry.path) { + switch (entry.path) { case VSSPath.vehicleMediaVolume: - if (update.entry.value.hasUint32()) { - double value = update.entry.value.uint32.toDouble(); + if (entry.value.hasUint32()) { + double value = entry.value.uint32.toDouble(); state = state.copyWith(volume: value); } break; case VSSPath.vehicleMediaBalance: - if (update.entry.value.hasInt32()) { - double value = (update.entry.value.int32 + 100) / 20.0; + if (entry.value.hasInt32()) { + double value = (entry.value.int32 + 100) / 20.0; state = state.copyWith(balance: value); } break; case VSSPath.vehicleMediaFade: - if (update.entry.value.hasInt32()) { - double value = (update.entry.value.int32 + 100) / 20.0; + if (entry.value.hasInt32()) { + double value = (entry.value.int32 + 100) / 20.0; state = state.copyWith(fade: value); } break; case VSSPath.vehicleMediaTreble: - if (update.entry.value.hasInt32()) { - double value = (update.entry.value.int32 + 100) / 20.0; + if (entry.value.hasInt32()) { + double value = (entry.value.int32 + 100) / 20.0; state = state.copyWith(treble: value); } break; case VSSPath.vehicleMediaBass: - if (update.entry.value.hasInt32()) { - double value = (update.entry.value.int32 + 100) / 20.0; + if (entry.value.hasInt32()) { + double value = (entry.value.int32 + 100) / 20.0; state = state.copyWith(bass: value); } break; diff --git a/lib/data/data_providers/units_notifier.dart b/lib/data/data_providers/units_notifier.dart index f7c25aa..26b79da 100644 --- a/lib/data/data_providers/units_notifier.dart +++ b/lib/data/data_providers/units_notifier.dart @@ -1,13 +1,72 @@ -import '../../export.dart'; +import 'package:flutter_ics_homescreen/export.dart'; +import 'package:protos/val-api.dart'; -class UnitsNotifier extends StateNotifier<Units> { - UnitsNotifier(super.state); +class UnitsNotifier extends Notifier<Units> { + @override + Units build() { + return const Units.initial(); + } + + bool handleSignalUpdate(DataEntry entry) { + bool handled = true; + switch (entry.path) { + case VSSPath.vehicleHmiDistanceUnit: + if (entry.value.hasString()) { + String value = entry.value.string; + DistanceUnit unit = DistanceUnit.kilometers; + if (value != "KILOMETERS") unit = DistanceUnit.miles; + state = state.copyWith(distanceUnit: unit); + } + break; + case VSSPath.vehicleHmiTemperatureUnit: + if (entry.value.hasString()) { + String value = entry.value.string; + TemperatureUnit unit = TemperatureUnit.celsius; + if (value != "C") unit = TemperatureUnit.fahrenheit; + state = state.copyWith(temperatureUnit: unit); + } + break; + case VSSPath.vehicleHmiPressureUnit: + if (entry.value.hasString()) { + String value = entry.value.string; + PressureUnit unit = PressureUnit.kilopascals; + if (value != "KPA") unit = PressureUnit.psi; + state = state.copyWith(pressureUnit: unit); + } + break; + default: + handled = false; + } + return handled; + } void setDistanceUnit(DistanceUnit unit) { state = state.copyWith(distanceUnit: unit); + var valClient = ref.read(valClientProvider); + valClient.setString( + VSSPath.vehicleHmiDistanceUnit, + unit == DistanceUnit.kilometers ? "KILOMETERS" : "MILES", + true, + ); } void setTemperatureUnit(TemperatureUnit unit) { state = state.copyWith(temperatureUnit: unit); + var valClient = ref.read(valClientProvider); + valClient.setString( + VSSPath.vehicleHmiTemperatureUnit, + unit == TemperatureUnit.celsius ? "C" : "F", + true, + ); + } + + void setPressureUnit(PressureUnit unit) { + state = state.copyWith(pressureUnit: unit); + var valClient = ref.read(valClientProvider); + valClient.setString( + VSSPath.vehicleHmiPressureUnit, + unit == PressureUnit.kilopascals ? "KPA" : "PSI", + true, + ); } } diff --git a/lib/data/data_providers/val_client.dart b/lib/data/data_providers/val_client.dart index db962ee..5e7339c 100644 --- a/lib/data/data_providers/val_client.dart +++ b/lib/data/data_providers/val_client.dart @@ -29,15 +29,21 @@ class ValClient { } void run() async { - List<String> fewSignals = VSSPath().getSignalsList(); - var request = SubscribeRequest(); + List<String> signals = VSSPath().getSignalsList(); Map<String, String> metadata = {}; if (config.authorization.isNotEmpty) { metadata = {'authorization': "Bearer ${config.authorization}"}; } - for (int i = 0; i < fewSignals.length; i++) { + + // Initialize signal states + for (int i = 0; i < signals.length; i++) { + get(signals[i]); + } + + var request = SubscribeRequest(); + for (int i = 0; i < signals.length; i++) { var entry = SubscribeEntry(); - entry.path = fewSignals[i]; + entry.path = signals[i]; entry.fields.add(Field.FIELD_PATH); entry.fields.add(Field.FIELD_VALUE); request.entries.add(entry); @@ -48,7 +54,7 @@ class ValClient { responseStream.listen((value) async { for (var update in value.updates) { if (!(update.hasEntry() && update.entry.hasPath())) continue; - handleSignalsUpdate(update); + handleSignalUpdate(update.entry); } }, onError: (stacktrace, errorDescriptor) { debugPrint(stacktrace.toString()); @@ -58,11 +64,14 @@ class ValClient { } } - bool handleSignalsUpdate(EntryUpdate update) { - if (ref.read(vehicleProvider.notifier).handleSignalsUpdate(update)) { + bool handleSignalUpdate(DataEntry entry) { + if (ref.read(vehicleProvider.notifier).handleSignalUpdate(entry)) { + return true; + } + if (ref.read(audioStateProvider.notifier).handleSignalUpdate(entry)) { return true; } - return ref.read(audioStateProvider.notifier).handleSignalsUpdate(update); + return ref.read(unitStateProvider.notifier).handleSignalUpdate(entry); } void setUint32(String path, int value, [bool actuator = true]) async { @@ -114,4 +123,26 @@ class ValClient { } await stub.set(request, options: CallOptions(metadata: metadata)); } + + void get(String path) async { + var entry = EntryRequest()..path = path; + entry.fields.add(Field.FIELD_VALUE); + var request = GetRequest(); + request.entries.add(entry); + Map<String, String> metadata = {}; + if (config.authorization.isNotEmpty) { + metadata = {'authorization': "Bearer ${config.authorization}"}; + } + debugPrint("Getting {path} value"); + var response = + await stub.get(request, options: CallOptions(metadata: metadata)); + if (response.hasError()) { + debugPrint("Get request had error {response.error().reason}"); + return; + } + for (var entry in response.entries) { + if (!entry.hasPath()) continue; + handleSignalUpdate(entry); + } + } } diff --git a/lib/data/data_providers/vehicle_notifier.dart b/lib/data/data_providers/vehicle_notifier.dart index 6fafb8c..fb2de19 100644 --- a/lib/data/data_providers/vehicle_notifier.dart +++ b/lib/data/data_providers/vehicle_notifier.dart @@ -15,99 +15,93 @@ class VehicleNotifier extends Notifier<Vehicle> { state = state.copyWith(speed: newValue); } - bool handleSignalsUpdate(EntryUpdate update) { + bool handleSignalUpdate(DataEntry entry) { bool handled = true; - switch (update.entry.path) { + switch (entry.path) { case VSSPath.vehicleSpeed: - if (update.entry.value.hasFloat()) { - state = state.copyWith(speed: update.entry.value.float); + if (entry.value.hasFloat()) { + state = state.copyWith(speed: entry.value.float); } break; case VSSPath.vehicleInsideTemperature: - if (update.entry.value.hasFloat()) { - state = state.copyWith(insideTemperature: update.entry.value.float); + if (entry.value.hasFloat()) { + state = state.copyWith(insideTemperature: entry.value.float); } break; case VSSPath.vehicleOutsideTemperature: - if (update.entry.value.hasFloat()) { - state = state.copyWith(outsideTemperature: update.entry.value.float); + if (entry.value.hasFloat()) { + state = state.copyWith(outsideTemperature: entry.value.float); } break; case VSSPath.vehicleRange: - if (update.entry.value.hasUint32()) { - state = state.copyWith(range: update.entry.value.uint32); + if (entry.value.hasUint32()) { + state = state.copyWith(range: entry.value.uint32); } break; case VSSPath.vehicleFuelLevel: - if (update.entry.value.hasUint32()) { - state = state.copyWith(fuelLevel: update.entry.value.uint32); + if (entry.value.hasUint32()) { + state = state.copyWith(fuelLevel: entry.value.uint32); } break; case VSSPath.vehicleIsChildLockActiveLeft: - if (update.entry.value.hasBool_12()) { - state = - state.copyWith(isChildLockActiveLeft: update.entry.value.bool_12); + if (entry.value.hasBool_12()) { + state = state.copyWith(isChildLockActiveLeft: entry.value.bool_12); } break; case VSSPath.vehicleIsChildLockActiveRight: - if (update.entry.value.hasBool_12()) { - state = state.copyWith( - isChildLockActiveRight: update.entry.value.bool_12); + if (entry.value.hasBool_12()) { + state = state.copyWith(isChildLockActiveRight: entry.value.bool_12); } break; case VSSPath.vehicleEngineSpeed: - if (update.entry.value.hasFloat()) { - state = state.copyWith(engineSpeed: update.entry.value.float); + if (entry.value.hasFloat()) { + state = state.copyWith(engineSpeed: entry.value.float); } break; case VSSPath.vehicleFrontLeftTire: - if (update.entry.value.hasUint32()) { - state = state.copyWith(frontLeftTire: update.entry.value.uint32); + if (entry.value.hasUint32()) { + state = state.copyWith(frontLeftTire: entry.value.uint32); } break; case VSSPath.vehicleFrontRightTire: - if (update.entry.value.hasUint32()) { - state = state.copyWith(frontRightTire: update.entry.value.uint32); + if (entry.value.hasUint32()) { + state = state.copyWith(frontRightTire: entry.value.uint32); } break; case VSSPath.vehicleRearLeftTire: - if (update.entry.value.hasUint32()) { - state = state.copyWith(rearLeftTire: update.entry.value.uint32); + if (entry.value.hasUint32()) { + state = state.copyWith(rearLeftTire: entry.value.uint32); } break; case VSSPath.vehicleRearRightTire: - if (update.entry.value.hasUint32()) { - state = state.copyWith(rearRightTire: update.entry.value.uint32); + if (entry.value.hasUint32()) { + state = state.copyWith(rearRightTire: entry.value.uint32); } break; case VSSPath.vehicleIsAirConditioningActive: - if (update.entry.value.hasBool_12()) { - state = state.copyWith( - isAirConditioningActive: update.entry.value.bool_12); + if (entry.value.hasBool_12()) { + state = state.copyWith(isAirConditioningActive: entry.value.bool_12); } break; case VSSPath.vehicleIsFrontDefrosterActive: - if (update.entry.value.hasBool_12()) { - state = state.copyWith( - isFrontDefrosterActive: update.entry.value.bool_12); + if (entry.value.hasBool_12()) { + state = state.copyWith(isFrontDefrosterActive: entry.value.bool_12); } break; case VSSPath.vehicleIsRearDefrosterActive: - if (update.entry.value.hasBool_12()) { - state = - state.copyWith(isRearDefrosterActive: update.entry.value.bool_12); + if (entry.value.hasBool_12()) { + state = state.copyWith(isRearDefrosterActive: entry.value.bool_12); } break; case VSSPath.vehicleIsRecirculationActive: - if (update.entry.value.hasBool_12()) { - state = - state.copyWith(isRecirculationActive: update.entry.value.bool_12); + if (entry.value.hasBool_12()) { + state = state.copyWith(isRecirculationActive: entry.value.bool_12); } break; case VSSPath.vehicleFanSpeed: - if (update.entry.value.hasUint32()) { + if (entry.value.hasUint32()) { // Convert 0-100 to local 0-3 setting - var value = update.entry.value.uint32; + var value = entry.value.uint32; var fanSpeed = 0; if (value > 66) fanSpeed = 3; @@ -118,14 +112,13 @@ class VehicleNotifier extends Notifier<Vehicle> { } break; case VSSPath.vehicleDriverTemperature: - if (update.entry.value.hasInt32()) { - state = state.copyWith(driverTemperature: update.entry.value.int32); + if (entry.value.hasInt32()) { + state = state.copyWith(driverTemperature: entry.value.int32); } break; case VSSPath.vehiclePassengerTemperature: - if (update.entry.value.hasInt32()) { - state = - state.copyWith(passengerTemperature: update.entry.value.int32); + if (entry.value.hasInt32()) { + state = state.copyWith(passengerTemperature: entry.value.int32); } break; default: |