diff options
author | Scott Murray <scott.murray@konsulko.com> | 2023-11-16 07:24:08 +0900 |
---|---|---|
committer | Scott Murray <scott.murray@konsulko.com> | 2023-11-16 07:33:36 +0900 |
commit | 94b78fd369c318baf1a98d4f510d791ea9f17017 (patch) | |
tree | c1f520aa7bb6510bb41124af91d69f55b0afe6b3 | |
parent | ca2ba809446f2184e50e4b8ebfe607a059c02de6 (diff) |
Update Kuksa databroker configuration scheme
Rework Kuksa databroker configuration to also read a configuration
yaml file from /etc/xdg/AGL/ics-homescreen.yaml at runtime to allow
overriding the built-in default configuration. The latter is left
as is with the addition of an explicit disabling of TLS, to still
match the internal test setup at ICS. The AGL build will supply
a runtime configuration that enables TLS and an authorization token.
Additionally:
- the ValClientHelper constructor has been changed to take the
stub and authorization token as arguments to allow authorization
with the VAL API requests. The channel argument has been
removed since it is not used, only the stub is.
- the apparently unused vss_provider.dart source file has been
removed to avoid potential confusion.
Bug-AGL: SPEC-4969
Change-Id: Ic7b867eaf565ef22f2e70df0afe7b5272b604d04
Signed-off-by: Scott Murray <scott.murray@konsulko.com>
-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 |