diff options
Diffstat (limited to 'lib/data')
-rw-r--r-- | lib/data/data_providers/app_config_provider.dart | 162 | ||||
-rw-r--r-- | lib/data/data_providers/app_provider.dart | 17 | ||||
-rw-r--r-- | lib/data/data_providers/audio_notifier.dart | 129 | ||||
-rw-r--r-- | lib/data/data_providers/hybrid_notifier.dart | 42 | ||||
-rw-r--r-- | lib/data/data_providers/val_client.dart | 118 | ||||
-rw-r--r-- | lib/data/data_providers/vehicle_notifier.dart | 253 | ||||
-rw-r--r-- | lib/data/models/audio.dart | 35 | ||||
-rw-r--r-- | lib/data/models/hybrid.dart | 2 | ||||
-rw-r--r-- | lib/data/models/vehicle.dart | 139 |
9 files changed, 543 insertions, 354 deletions
diff --git a/lib/data/data_providers/app_config_provider.dart b/lib/data/data_providers/app_config_provider.dart new file mode 100644 index 0000000..7e0ddc6 --- /dev/null +++ b/lib/data/data_providers/app_config_provider.dart @@ -0,0 +1,162 @@ +import 'dart:io'; +import 'package:flutter/foundation.dart'; +import 'package:flutter_ics_homescreen/core/constants/constants.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:yaml/yaml.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 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}); + + static KuksaConfig defaultConfig() { + return KuksaConfig( + hostname: KuksaConfig.defaultHostname, + port: KuksaConfig.defaultPort, + authorization: "", + use_tls: false, + ca_certificate: [], + tls_server_name: ""); + } +} + +class AppConfig { + final bool disableBkgAnimation; + final bool randomHybridAnimation; + final KuksaConfig kuksaConfig; + + static String configFilePath = '/etc/xdg/AGL/ics-homescreen.yaml'; + + AppConfig({required this.disableBkgAnimation, required this.randomHybridAnimation, required this.kuksaConfig}); + + static KuksaConfig parseKuksaConfig(YamlMap kuksaMap) { + try { + String hostname = KuksaConfig.defaultHostname; + if (kuksaMap.containsKey('hostname')) { + hostname = kuksaMap['hostname']; + } + + int port = KuksaConfig.defaultPort; + if (kuksaMap.containsKey('port')) { + port = kuksaMap['port']; + } + + String token = ""; + if (kuksaMap.containsKey('authorization')) { + String s = kuksaMap['authorization']; + if (s.isNotEmpty) { + if (s.startsWith("/")) { + debugPrint("Reading authorization token $s"); + try { + token = File(s).readAsStringSync(); + } on Exception catch (_) { + print("ERROR: Could not read authorization token file $token"); + token = ""; + } + } else { + token = s; + } + } + } + //debugPrint("authorization = $token"); + + bool use_tls = false; + if (kuksaMap.containsKey('use-tls')) { + var value = kuksaMap['use-tls']; + if (value is bool) use_tls = value; + } + //debugPrint("Use TLS = $use_tls"); + + List<int> ca_cert = []; + String ca_path = KuksaConfig.defaultCaCertPath; + if (kuksaMap.containsKey('ca-certificate')) { + ca_path = kuksaMap['ca-certificate']; + } + try { + ca_cert = File(ca_path).readAsBytesSync(); + } on Exception catch (_) { + print("ERROR: Could not read CA certificate file $ca_path"); + ca_cert = []; + } + //debugPrint("CA cert = $ca_cert"); + + String tls_server_name = ""; + if (kuksaMap.containsKey('tls-server-name')) { + tls_server_name = kuksaMap['tls_server_name']; + } + + return KuksaConfig( + hostname: hostname, + port: port, + authorization: token, + use_tls: use_tls, + ca_certificate: ca_cert, + tls_server_name: tls_server_name); + } on Exception catch (_) { + return KuksaConfig.defaultConfig(); + } + } +} + +final appConfigProvider = Provider((ref) { + final configFile = File(AppConfig.configFilePath); + try { + print("Reading configuration ${AppConfig.configFilePath}"); + String content = configFile.readAsStringSync(); + final dynamic yamlMap = loadYaml(content); + + KuksaConfig kuksaConfig; + if (yamlMap.containsKey('kuksa')) { + kuksaConfig = AppConfig.parseKuksaConfig(yamlMap['kuksa']); + } else { + kuksaConfig = KuksaConfig( + hostname: KuksaConfig.defaultHostname, + port: KuksaConfig.defaultPort, + authorization: "", + use_tls: false, + ca_certificate: [], + tls_server_name: ""); + } + + bool disableBkgAnimation = disableBkgAnimationDefault; + if (yamlMap.containsKey('disable-bg-animation')) { + var value = yamlMap['disable-bg-animation']; + if (value is bool) { + disableBkgAnimation = value; + } + } + + bool randomHybridAnimation = randomHybridAnimationDefault; + if (yamlMap.containsKey('random-hybrid-animation')) { + var value = yamlMap['random-hybrid-animation']; + if (value is bool) { + randomHybridAnimation = value; + } + } + + return AppConfig( + disableBkgAnimation: disableBkgAnimation, + randomHybridAnimation: randomHybridAnimation, + kuksaConfig: kuksaConfig); + } on Exception catch (_) { + return AppConfig( + disableBkgAnimation: false, + randomHybridAnimation: false, + kuksaConfig: KuksaConfig.defaultConfig()); + } +}); diff --git a/lib/data/data_providers/app_provider.dart b/lib/data/data_providers/app_provider.dart index fb0a447..cfda370 100644 --- a/lib/data/data_providers/app_provider.dart +++ b/lib/data/data_providers/app_provider.dart @@ -4,6 +4,7 @@ import 'package:flutter_ics_homescreen/data/data_providers/time_notifier.dart'; import 'package:flutter_ics_homescreen/data/data_providers/units_notifier.dart'; import 'package:flutter_ics_homescreen/data/data_providers/audio_notifier.dart'; import 'package:flutter_ics_homescreen/data/data_providers/users_notifier.dart'; +import 'package:flutter_ics_homescreen/data/data_providers/val_client.dart'; import 'package:flutter_ics_homescreen/export.dart'; import '../models/users.dart'; @@ -36,9 +37,15 @@ enum AppState { } final appProvider = StateProvider<AppState>((ref) => AppState.splash); -final vehicleProvider = StateNotifierProvider<VehicleNotifier, Vehicle>((ref) { - return VehicleNotifier(const Vehicle.initial()); + +final valClientProvider = Provider((ref) { + KuksaConfig config = ref.watch(appConfigProvider).kuksaConfig; + return ValClient(config: config, ref: ref); }); + +final vehicleProvider = + NotifierProvider<VehicleNotifier, Vehicle>(VehicleNotifier.new); + final signalsProvider = StateNotifierProvider<SignalNotifier, Signals>((ref) { return SignalNotifier(const Signals.initial()); }); @@ -46,9 +53,9 @@ final signalsProvider = StateNotifierProvider<SignalNotifier, Signals>((ref) { final unitStateProvider = StateNotifierProvider<UnitsNotifier, Units>((ref) { return UnitsNotifier(const Units.initial()); }); -final audioStateProvider = StateNotifierProvider<AudioNotifier, Audio>((ref) { - return AudioNotifier(const Audio.initial()); -}); + +final audioStateProvider = + NotifierProvider<AudioNotifier, Audio>(AudioNotifier.new); final usersProvider = StateNotifierProvider<UsersNotifier, Users>((ref) { return UsersNotifier(Users.initial()); diff --git a/lib/data/data_providers/audio_notifier.dart b/lib/data/data_providers/audio_notifier.dart index 1f8c1a9..32ab409 100644 --- a/lib/data/data_providers/audio_notifier.dart +++ b/lib/data/data_providers/audio_notifier.dart @@ -1,22 +1,131 @@ import 'package:flutter_ics_homescreen/export.dart'; +import 'package:protos/protos.dart'; -class AudioNotifier extends StateNotifier<Audio> { - AudioNotifier(super.state); +class AudioNotifier extends Notifier<Audio> { + @override + Audio build() { + return Audio.initial(); + } void resetToDefaults() { - state = state.copyWith(treble: 5.0, bass: 5.0, rearFront: 5.0); + state = state.copyWith(balance: 5.0, fade: 5.0, treble: 5.0, bass: 5.0); + var valClient = ref.read(valClientProvider); + int value = (state.balance * 20).toInt() - 100; + valClient.setInt32( + VSSPath.vehicleMediaBalance, + value, + true, + ); + value = (state.fade * 20).toInt() - 100; + valClient.setInt32( + VSSPath.vehicleMediaFade, + value, + true, + ); + value = (state.treble * 20).toInt() - 100; + valClient.setInt32( + VSSPath.vehicleMediaTreble, + value, + true, + ); + value = (state.bass * 20).toInt() - 100; + valClient.setInt32( + VSSPath.vehicleMediaBass, + value, + true, + ); } - void setTreble(double newVal) { - state = state.copyWith(treble: newVal); + bool handleSignalsUpdate(EntryUpdate update) { + bool handled = true; + switch (update.entry.path) { + case VSSPath.vehicleMediaVolume: + if (update.entry.value.hasUint32()) { + double value = update.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; + state = state.copyWith(balance: value); + } + break; + case VSSPath.vehicleMediaFade: + if (update.entry.value.hasInt32()) { + double value = (update.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; + state = state.copyWith(treble: value); + } + break; + case VSSPath.vehicleMediaBass: + if (update.entry.value.hasInt32()) { + double value = (update.entry.value.int32 + 100) / 20.0; + state = state.copyWith(bass: value); + } + break; + default: + handled = false; + } + return handled; } - void setBass(double newVal) { - state = state.copyWith(bass: newVal); + void setVolume(double newValue) { + state = state.copyWith(volume: newValue); + var valClient = ref.read(valClientProvider); + valClient.setUint32( + VSSPath.vehicleMediaVolume, + newValue.toInt(), + true, + ); } - void setRearFront(double newVal) { - state = state.copyWith(rearFront: newVal); + void setBalance(double newValue) { + state = state.copyWith(balance: newValue); + int value = (newValue * 20).toInt() - 100; + var valClient = ref.read(valClientProvider); + valClient.setInt32( + VSSPath.vehicleMediaBalance, + value, + true, + ); + } + + void setFade(double newValue) { + state = state.copyWith(fade: newValue); + int value = (newValue * 20).toInt() - 100; + var valClient = ref.read(valClientProvider); + valClient.setInt32( + VSSPath.vehicleMediaFade, + value, + true, + ); } -} + void setTreble(double newValue) { + state = state.copyWith(treble: newValue); + int value = (newValue * 20).toInt() - 100; + var valClient = ref.read(valClientProvider); + valClient.setInt32( + VSSPath.vehicleMediaTreble, + value, + true, + ); + } + + void setBass(double newValue) { + state = state.copyWith(bass: newValue); + int value = (newValue * 20).toInt() - 100; + var valClient = ref.read(valClientProvider); + valClient.setInt32( + VSSPath.vehicleMediaBass, + value, + true, + ); + } +} diff --git a/lib/data/data_providers/hybrid_notifier.dart b/lib/data/data_providers/hybrid_notifier.dart index 3668f61..7381f5c 100644 --- a/lib/data/data_providers/hybrid_notifier.dart +++ b/lib/data/data_providers/hybrid_notifier.dart @@ -1,6 +1,6 @@ // ignore_for_file: unused_local_variable -import '../../export.dart'; +import 'package:flutter_ics_homescreen/export.dart'; class HybridNotifier extends StateNotifier<Hybrid> { HybridNotifier(super.state); @@ -9,38 +9,44 @@ class HybridNotifier extends StateNotifier<Hybrid> { switch (hybridState) { case HybridState.idle: state = state.copyWith( - topArrowState: ArrowState.blue, - leftArrowState: ArrowState.blue, - rightArrowState: ArrowState.blue, - batteryState: BatteryState.white, + hybridState: hybridState, + topArrowState: ArrowState.blue, + leftArrowState: ArrowState.blue, + rightArrowState: ArrowState.blue, + batteryState: BatteryState.white, ); break; case HybridState.engineOutput: state = state.copyWith( - topArrowState: ArrowState.red, - leftArrowState: ArrowState.red, - rightArrowState: ArrowState.blue, - batteryState: BatteryState.red, + hybridState: hybridState, + topArrowState: ArrowState.red, + leftArrowState: ArrowState.red, + rightArrowState: ArrowState.blue, + batteryState: BatteryState.red, ); break; case HybridState.regenerativeBreaking: state = state.copyWith( + hybridState: hybridState, topArrowState: ArrowState.blue, leftArrowState: ArrowState.blue, rightArrowState: ArrowState.green, - batteryState: BatteryState.green); - + batteryState: BatteryState.green + ); break; - case HybridState.baterryOutput: + case HybridState.batteryOutput: state = state.copyWith( + hybridState: hybridState, topArrowState: ArrowState.blue, leftArrowState: ArrowState.blue, rightArrowState: ArrowState.yellow, - batteryState: BatteryState.yellow); + batteryState: BatteryState.yellow + ); break; default: + state = state.copyWith(hybridState: hybridState); + break; } - state = state.copyWith(hybridState: hybridState); } void updateHybridState(double speed, double engineSpeed, bool brake) { @@ -55,25 +61,23 @@ class HybridNotifier extends StateNotifier<Hybrid> { // Variable for storing the average value of RPM double avgRpm = 0.0; - if (speed == 0 && engineSpeed == 0) { // Set idle state. currentState = HybridState.idle; } else if (engineSpeed > 0 && speed > 0) { - // Set stan na engine output state.. + // Set engine output state.. currentState = HybridState.engineOutput; } else if (speed < 0 && brake) { - // Set regenerative breaking state + // Set regenerative breaking state currentState = HybridState.regenerativeBreaking; } else if (speed > 0 && engineSpeed <= 0) { // Set battery output state - currentState = HybridState.baterryOutput; + currentState = HybridState.batteryOutput; } // Update hybrid state if (currentState != previousState) { - //state = state.copyWith(hybridState: currentState); setHybridState(currentState); } } diff --git a/lib/data/data_providers/val_client.dart b/lib/data/data_providers/val_client.dart new file mode 100644 index 0000000..28bb480 --- /dev/null +++ b/lib/data/data_providers/val_client.dart @@ -0,0 +1,118 @@ +import 'package:flutter_ics_homescreen/export.dart'; +import 'package:protos/protos.dart'; + +class ValClient { + final KuksaConfig config; + final Ref ref; + late ClientChannel channel; + late VALClient stub; + late String authorization; + + ValClient({required this.config, required this.ref}) { + debugPrint("Using ${config.hostname}:${config.port}"); + 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); + } + + void startListen() async { + List<String> fewSignals = VSSPath().getSignalsList(); + var request = SubscribeRequest(); + Map<String, String> metadata = {}; + if (config.authorization.isNotEmpty) { + metadata = {'authorization': "Bearer ${config.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()); + }); + } catch (e) { + debugPrint(e.toString()); + } + } + + bool handleSignalsUpdate(EntryUpdate update) { + if (ref.read(vehicleProvider.notifier).handleSignalsUpdate(update)) { + return true; + } + return ref.read(audioStateProvider.notifier).handleSignalsUpdate(update); + } + + void setUint32(String path, int value, [bool actuator = true]) async { + var dp = Datapoint()..uint32 = value; + set(path, dp, actuator); + } + + void setInt32(String path, int value, [bool actuator = true]) async { + var dp = Datapoint()..int32 = value; + set(path, dp, actuator); + } + + void setBool(String path, bool value, [bool actuator = true]) async { + var dp = Datapoint()..bool_12 = value; + set(path, dp, actuator); + } + + void setString(String path, String value, [bool actuator = true]) async { + var dp = Datapoint()..string = value; + set(path, dp, actuator); + } + + void setFloat(String path, double value, [bool actuator = true]) async { + var dp = Datapoint()..float = value; + set(path, dp, actuator); + } + + void setDouble(String path, double value, [bool actuator = true]) async { + var dp = Datapoint()..double_18 = value; + set(path, dp, actuator); + } + + void set(String path, Datapoint dp, bool actuator) async { + var entry = DataEntry()..path = path; + var update = EntryUpdate(); + if (actuator) { + entry.actuatorTarget = dp; + update.fields.add(Field.FIELD_ACTUATOR_TARGET); + } else { + entry.value = dp; + update.fields.add(Field.FIELD_VALUE); + } + update.entry = entry; + var request = SetRequest(); + request.updates.add(update); + Map<String, String> metadata = {}; + if (config.authorization.isNotEmpty) { + metadata = {'authorization': "Bearer ${config.authorization}"}; + } + await stub.set(request, options: CallOptions(metadata: metadata)); + } +} 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, diff --git a/lib/data/models/audio.dart b/lib/data/models/audio.dart index 69df18b..65490f9 100644 --- a/lib/data/models/audio.dart +++ b/lib/data/models/audio.dart @@ -5,52 +5,59 @@ import 'package:flutter_ics_homescreen/export.dart'; @immutable class Audio { final double volume; + final double balance; + final double fade; final double treble; final double bass; - final double rearFront; const Audio({ required this.volume, + required this.balance, + required this.fade, required this.treble, required this.bass, - required this.rearFront, }); const Audio.initial() : volume = 5.0, + balance = 5.0, + fade = 5.0, treble = 5.0, - bass = 5.0, - rearFront = 5.0; + bass = 5.0; Audio copyWith({ double? volume, + double? balance, + double? fade, double? treble, double? bass, - double? rearFront, }) { return Audio( volume: volume ?? this.volume, + balance: balance ?? this.balance, + fade: fade ?? this.fade, treble: treble ?? this.treble, bass: bass ?? this.bass, - rearFront: rearFront ?? this.rearFront, ); } Map<String, dynamic> toMap() { return { 'volume': volume, + 'balance': balance, + 'fade': fade, 'treble': treble, 'bass': bass, - 'rearFront': rearFront, }; } factory Audio.fromMap(Map<String, dynamic> map) { return Audio( volume: map['volume']?.toDouble() ?? 0.0, + balance: map['balance']?.toDouble() ?? 0.0, + fade: map['fade']?.toDouble() ?? 0.0, treble: map['treble']?.toDouble() ?? 0.0, bass: map['bass']?.toDouble() ?? 0.0, - rearFront: map['rearFront']?.toDouble() ?? 0.0, ); } @@ -60,7 +67,7 @@ class Audio { @override String toString() { - return 'Audio(volume: $volume, treble: $treble, bass: $bass, rearFront: $rearFront)'; + return 'Audio(volume: $volume, balance: $balance, fade: $fade, treble: $treble, bass: $bass)'; } @override @@ -69,16 +76,18 @@ class Audio { return other is Audio && other.volume == volume && + other.balance == balance && + other.fade == fade && other.treble == treble && - other.bass == bass && - other.rearFront == rearFront; + other.bass == bass; } @override int get hashCode { return volume.hashCode ^ + balance.hashCode ^ + fade.hashCode ^ treble.hashCode ^ - bass.hashCode ^ - rearFront.hashCode; + bass.hashCode; } } diff --git a/lib/data/models/hybrid.dart b/lib/data/models/hybrid.dart index d567f14..5746033 100644 --- a/lib/data/models/hybrid.dart +++ b/lib/data/models/hybrid.dart @@ -2,7 +2,7 @@ enum HybridState { idle, engineOutput, regenerativeBreaking, - baterryOutput, + batteryOutput, } enum ArrowState { blue, red, green, yellow } diff --git a/lib/data/models/vehicle.dart b/lib/data/models/vehicle.dart index 2dea928..ad76620 100644 --- a/lib/data/models/vehicle.dart +++ b/lib/data/models/vehicle.dart @@ -10,7 +10,6 @@ class Vehicle { final double outsideTemperature; final int range; final int fuelLevel; - final int mediaVolume; final bool isChildLockActiveLeft; final bool isChildLockActiveRight; final int frontLeftTire; @@ -27,27 +26,26 @@ class Vehicle { final bool temperatureSynced; const Vehicle( - this.speed, - this.engineSpeed, - this.insideTemperature, - this.outsideTemperature, - this.range, - this.fuelLevel, - this.mediaVolume, - this.isChildLockActiveLeft, - this.isChildLockActiveRight, - this.frontLeftTire, - this.frontRightTire, - this.rearLeftTire, - this.rearRightTire, - this.isAirConditioningActive, - this.isFrontDefrosterActive, - this.isRearDefrosterActive, - this.isRecirculationActive, - this.fanSpeed, - this.driverTemperature, - this.passengerTemperature, - this.temperatureSynced, + this.speed, + this.engineSpeed, + this.insideTemperature, + this.outsideTemperature, + this.range, + this.fuelLevel, + this.isChildLockActiveLeft, + this.isChildLockActiveRight, + this.frontLeftTire, + this.frontRightTire, + this.rearLeftTire, + this.rearRightTire, + this.isAirConditioningActive, + this.isFrontDefrosterActive, + this.isRearDefrosterActive, + this.isRecirculationActive, + this.fanSpeed, + this.driverTemperature, + this.passengerTemperature, + this.temperatureSynced, ); const Vehicle.initial() @@ -57,7 +55,6 @@ class Vehicle { outsideTemperature = 0, range = 0, fuelLevel = 0, - mediaVolume = 50, isChildLockActiveLeft = false, isChildLockActiveRight = true, frontLeftTire = 33, @@ -80,7 +77,6 @@ class Vehicle { outsideTemperature = 32.0, range = 21, fuelLevel = 49, - mediaVolume = 50, isChildLockActiveLeft = false, isChildLockActiveRight = true, frontLeftTire = 33, @@ -96,51 +92,49 @@ class Vehicle { passengerTemperature = 26, temperatureSynced = true; - Vehicle copyWith( - {double? speed, - double? engineSpeed, - double? insideTemperature, - double? outsideTemperature, - int? range, - int? fuelLevel, - int? mediaVolume, - bool? isChildLockActiveLeft, - bool? isChildLockActiveRight, - int? frontLeftTire, - int? frontRightTire, - int? rearLeftTire, - int? rearRightTire, - bool? isAirConditioningActive, - bool? isFrontDefrosterActive, - bool? isRearDefrosterActive, - bool? isRecirculationActive, - int? fanSpeed, - int? driverTemperature, - int? passengerTemperature, - bool? temperatureSynced, + Vehicle copyWith({ + double? speed, + double? engineSpeed, + double? insideTemperature, + double? outsideTemperature, + int? range, + int? fuelLevel, + bool? isChildLockActiveLeft, + bool? isChildLockActiveRight, + int? frontLeftTire, + int? frontRightTire, + int? rearLeftTire, + int? rearRightTire, + bool? isAirConditioningActive, + bool? isFrontDefrosterActive, + bool? isRearDefrosterActive, + bool? isRecirculationActive, + int? fanSpeed, + int? driverTemperature, + int? passengerTemperature, + bool? temperatureSynced, }) { return Vehicle( - speed ?? this.speed, - engineSpeed ?? this.engineSpeed, - insideTemperature ?? this.insideTemperature, - outsideTemperature ?? this.outsideTemperature, - range ?? this.range, - fuelLevel ?? this.fuelLevel, - mediaVolume ?? this.mediaVolume, - isChildLockActiveLeft ?? this.isChildLockActiveLeft, - isChildLockActiveRight ?? this.isChildLockActiveRight, - frontLeftTire ?? this.frontLeftTire, - frontRightTire ?? this.frontRightTire, - rearLeftTire ?? this.rearLeftTire, - rearRightTire ?? this.rearRightTire, - isAirConditioningActive ?? this.isAirConditioningActive, - isFrontDefrosterActive ?? this.isFrontDefrosterActive, - isRearDefrosterActive ?? this.isRearDefrosterActive, - isRecirculationActive ?? this.isRecirculationActive, - fanSpeed ?? this.fanSpeed, - driverTemperature ?? this.driverTemperature, - passengerTemperature ?? this.passengerTemperature, - temperatureSynced ?? this.temperatureSynced, + speed ?? this.speed, + engineSpeed ?? this.engineSpeed, + insideTemperature ?? this.insideTemperature, + outsideTemperature ?? this.outsideTemperature, + range ?? this.range, + fuelLevel ?? this.fuelLevel, + isChildLockActiveLeft ?? this.isChildLockActiveLeft, + isChildLockActiveRight ?? this.isChildLockActiveRight, + frontLeftTire ?? this.frontLeftTire, + frontRightTire ?? this.frontRightTire, + rearLeftTire ?? this.rearLeftTire, + rearRightTire ?? this.rearRightTire, + isAirConditioningActive ?? this.isAirConditioningActive, + isFrontDefrosterActive ?? this.isFrontDefrosterActive, + isRearDefrosterActive ?? this.isRearDefrosterActive, + isRecirculationActive ?? this.isRecirculationActive, + fanSpeed ?? this.fanSpeed, + driverTemperature ?? this.driverTemperature, + passengerTemperature ?? this.passengerTemperature, + temperatureSynced ?? this.temperatureSynced, ); } @@ -152,7 +146,6 @@ class Vehicle { 'outsideTemperature': outsideTemperature, 'range': range, 'fuelLevel': fuelLevel, - 'mediaVolume': mediaVolume, 'isChildLockActiveLeft': isChildLockActiveLeft, 'isChildLockActiveRight': isChildLockActiveRight, 'frontLeftTire': frontLeftTire, @@ -178,7 +171,6 @@ class Vehicle { map['outsideTemperature']?.toDouble() ?? 0.0, map['range']?.toInt() ?? 0, map['fuelLevel']?.toDouble() ?? 0.0, - map['mediaVolume']?.toInt() ?? 0, map['isChildLockActiveLeft'] ?? false, map['isChildLockActiveRight'] ?? false, map['frontLeftTire']?.toInt() ?? 0, @@ -203,7 +195,7 @@ class Vehicle { @override String toString() { - return 'Vehicle(speed: $speed, insideTemperature: $insideTemperature, outsideTemperature: $outsideTemperature, range: $range, fuelLevel: $fuelLevel, mediaVolume: $mediaVolume, isChildLockActiveLeft: $isChildLockActiveLeft, isChildLockActiveRight: $isChildLockActiveRight, engineSpeed: $engineSpeed, frontLeftTire: $frontLeftTire, frontRightTire: $frontRightTire, rearLeftTire: $rearLeftTire, rearRightTire: $rearRightTire, isAirConditioningActive: $isAirConditioningActive, isFrontDefrosterActive: $isFrontDefrosterActive, isRearDefrosterActive: $isRearDefrosterActive, isRecirculationActive: $isRecirculationActive,fanSpeed:$fanSpeed,driverTemperature:$driverTemperature, passengerTemperature:$passengerTemperature)'; + return 'Vehicle(speed: $speed, insideTemperature: $insideTemperature, outsideTemperature: $outsideTemperature, range: $range, fuelLevel: $fuelLevel, isChildLockActiveLeft: $isChildLockActiveLeft, isChildLockActiveRight: $isChildLockActiveRight, engineSpeed: $engineSpeed, frontLeftTire: $frontLeftTire, frontRightTire: $frontRightTire, rearLeftTire: $rearLeftTire, rearRightTire: $rearRightTire, isAirConditioningActive: $isAirConditioningActive, isFrontDefrosterActive: $isFrontDefrosterActive, isRearDefrosterActive: $isRearDefrosterActive, isRecirculationActive: $isRecirculationActive,fanSpeed:$fanSpeed,driverTemperature:$driverTemperature, passengerTemperature:$passengerTemperature)'; } @override @@ -216,7 +208,6 @@ class Vehicle { other.outsideTemperature == outsideTemperature && other.range == range && other.fuelLevel == fuelLevel && - other.mediaVolume == mediaVolume && other.isChildLockActiveLeft == isChildLockActiveLeft && other.isChildLockActiveRight == isChildLockActiveRight && other.engineSpeed == engineSpeed && @@ -241,7 +232,6 @@ class Vehicle { outsideTemperature.hashCode ^ range.hashCode ^ fuelLevel.hashCode ^ - mediaVolume.hashCode ^ isChildLockActiveLeft.hashCode ^ isChildLockActiveRight.hashCode ^ engineSpeed.hashCode ^ @@ -258,9 +248,4 @@ class Vehicle { passengerTemperature.hashCode ^ temperatureSynced.hashCode; } -// } -// / class VehicleNotifier extends StateNotifier<Vehicle> { -// // VehicleNotifier() : super(Vehicle()); - -// // } } |