diff options
-rw-r--r-- | app-config/config.yaml | 1 | ||||
-rw-r--r-- | lib/core/constants/val_client_helper.dart | 10 | ||||
-rw-r--r-- | lib/data/data_providers/vehicle_notifier.dart | 152 | ||||
-rw-r--r-- | lib/data/data_providers/vss_provider.dart | 105 | ||||
-rw-r--r-- | lib/export.dart | 1 |
5 files changed, 145 insertions, 124 deletions
diff --git a/app-config/config.yaml b/app-config/config.yaml index 138fe4b..dd3ae08 100644 --- a/app-config/config.yaml +++ b/app-config/config.yaml @@ -1,2 +1,3 @@ hostname: localhost port: 55556 +use_tls: false diff --git a/lib/core/constants/val_client_helper.dart b/lib/core/constants/val_client_helper.dart index 0d7a284..02912b0 100644 --- a/lib/core/constants/val_client_helper.dart +++ b/lib/core/constants/val_client_helper.dart @@ -1,10 +1,10 @@ import 'package:protos/protos.dart'; class ValClientHelper { - final ClientChannel channel; final VALClient stub; + final String authorization; - ValClientHelper({required this.channel, required this.stub}); + ValClientHelper({required this.stub, required this.authorization}); void setUint32(String path, int value, [bool actuator = true]) async { var dp = Datapoint()..uint32 = value; @@ -50,9 +50,9 @@ class ValClientHelper { var request = SetRequest(); request.updates.add(update); Map<String, String> metadata = {}; - // if (config.authorization.isNotEmpty) { - // metadata = {'authorization': "Bearer ${config.authorization}"}; - // } + if (authorization.isNotEmpty) { + metadata = {'authorization': "Bearer ${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 b12cbfd..012e5dc 100644 --- a/lib/data/data_providers/vehicle_notifier.dart +++ b/lib/data/data_providers/vehicle_notifier.dart @@ -4,10 +4,28 @@ 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; void updateSpeed(double newValue) { @@ -123,33 +141,141 @@ class VehicleNotifier extends StateNotifier<Vehicle> { } } - void startListen() async { - String hostName = 'localhost'; - int port = 8080; + Future<KuksaConfig> readConfig() async { + String hostname = KuksaConfig.defaultHostname; + int port = KuksaConfig.defaultPort; + bool use_tls = false; + String ca_path = KuksaConfig.defaultCaCertPath; + List<int> ca_cert = []; + String tls_server_name = ""; + 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']; + hostname = yamlMap['hostname']; } if (yamlMap.containsKey('port')) { port = yamlMap['port']; } + + if (yamlMap.containsKey('use-tls')) { + var value = yamlMap['use-tls']; + if (value is bool) + use_tls = value; + } + + if (use_tls) { + if (yamlMap.containsKey('ca-certificate')) { + ca_path = yamlMap['ca-certificate']; + } + + if (yamlMap.containsKey('tls-server-name')) { + tls_server_name = 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) + use_tls = value; + } + //debugPrint("Use TLS = $use_tls"); + + if (use_tls) { + if (yamlMap.containsKey('ca-certificate')) { + ca_path = yamlMap['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"); + + if (yamlMap.containsKey('tls-server-name')) { + tls_server_name = 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: use_tls, + ca_certificate: ca_cert, + tls_server_name: tls_server_name + ); + } + + 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 = ChannelCredentials.insecure(); + } channel = ClientChannel( - hostName, - port: port, - options: const ChannelOptions( - credentials: ChannelCredentials.insecure(), - ), + config.hostname, + port: config.port, + options: ChannelOptions(credentials: creds) ); - - debugPrint('Start Listen on port: $port'); + debugPrint('Start Listen on port: ${config.port}'); stub = VALClient(channel); List<String> fewSignals = VSSPath().getSignalsList(); var request = SubscribeRequest(); @@ -183,7 +309,7 @@ class VehicleNotifier extends StateNotifier<Vehicle> { } void setChildLock({required String side}) { - var helper = ValClientHelper(channel: channel, stub: stub); + var helper = ValClientHelper(stub: stub, authorization: authorization); try { switch (side) { case 'left': @@ -218,7 +344,7 @@ class VehicleNotifier extends StateNotifier<Vehicle> { } void setHVACMode({required String mode}) { - var helper = ValClientHelper(channel: channel, stub: stub); + var helper = ValClientHelper(stub: stub, authorization: authorization); try { switch (mode) { case 'airCondition': diff --git a/lib/data/data_providers/vss_provider.dart b/lib/data/data_providers/vss_provider.dart deleted file mode 100644 index ca02de6..0000000 --- a/lib/data/data_providers/vss_provider.dart +++ /dev/null @@ -1,105 +0,0 @@ -import 'package:flutter_ics_homescreen/export.dart'; -import 'package:protos/protos.dart'; - -class VSS { - static handleSignalUpdates( - EntryUpdate update, - ) { - //final ref = ProviderContainer().read(vehicleStateProvider); - switch (update.entry.path) { - case VSSPath.vehicleSpeed: - if (update.entry.value.hasFloat()) { - //print(ref); - } - break; - // case VSSPath.vehicleInsideTemperature: - // if (update.entry.value.hasFloat()) { - // ref - // .read(vehicleInsideTemperature.notifier) - // .update((state) => state = update.entry.value.float); - // } - // break; - // case VSSPath.vehicleOutsideTemperature: - // if (update.entry.value.hasFloat()) { - // ref - // .read(vehicleOutSideTemperature.notifier) - // .update((state) => state = update.entry.value.float); - // } - // break; - // case VSSPath.vehicleRange: - // if (update.entry.value.hasInt32()) { - // ref - // .read(vehicleRange.notifier) - // .update((state) => state = update.entry.value.uint32); - // } - // break; - // case VSSPath.vehicleFuelLevel: - // if (update.entry.value.hasInt32()) { - // ref - // .read(vehicleFuelLevel.notifier) - // .update((state) => state = update.entry.value.uint32); - // } - // break; - // case VSSPath.vehicleMediaVolume: - // if (update.entry.value.hasInt32()) { - // ref - // .read(vehicleMediaVolume.notifier) - // .update((state) => state = update.entry.value.uint32); - // } - // break; - // case VSSPath.vehicleIsChildLockActiveLeft: - // if (update.entry.value.hasBool_12()) { - // ref - // .read(vehicleIsChildLockActiveLeft.notifier) - // .update((state) => state = update.entry.value.bool_12); - // } - // break; - // case VSSPath.vehicleIsChildLockActiveRight: - // if (update.entry.value.hasBool_12()) { - // ref - // .read(vehicleIsChildLockActiveRight.notifier) - // .update((state) => state = update.entry.value.bool_12); - // } - // break; - // case VSSPath.vehicleEngineSpeed: - // if (update.entry.value.hasFloat()) { - // ref - // .read(vehicleEngineSpeed.notifier) - // .update((state) => state = update.entry.value.float); - // } - // break; - // case VSSPath.vehicleFrontLeftTire: - // if (update.entry.value.hasFloat()) { - // ref - // .read(vehicleFrontLeftTire.notifier) - // .update((state) => state = update.entry.value.float); - // } - // break; - // case VSSPath.vehicleFrontRightTire: - // if (update.entry.value.hasFloat()) { - // ref - // .read(vehicleFrontRightTire.notifier) - // .update((state) => state = update.entry.value.float); - // } - // break; - // case VSSPath.vehicleRearLeftTire: - // if (update.entry.value.hasFloat()) { - // ref - // .read(vehicleRearLeftTire.notifier) - // .update((state) => state = update.entry.value.float); - // } - // break; - // case VSSPath.vehicleRearRightTire: - // if (update.entry.value.hasFloat()) { - // ref - // .read(vehicleRearRightTire.notifier) - // .update((state) => state = update.entry.value.float); - // } - // break; - - default: - debugPrint("ERROR: Unexpected path ${update.entry.path}"); - break; - } - } -} diff --git a/lib/export.dart b/lib/export.dart index 08dff4f..20aa850 100644 --- a/lib/export.dart +++ b/lib/export.dart @@ -1,7 +1,6 @@ export 'data/data_providers/app.dart'; export 'data/data_providers/app_provider.dart'; export 'presentation/router/routes/routes.dart'; -export 'data/data_providers/vss_provider.dart'; export 'data/theme/theme.dart'; //Models |