aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorScott Murray <scott.murray@konsulko.com>2023-11-16 07:24:08 +0900
committerScott Murray <scott.murray@konsulko.com>2023-11-16 07:33:36 +0900
commit94b78fd369c318baf1a98d4f510d791ea9f17017 (patch)
treec1f520aa7bb6510bb41124af91d69f55b0afe6b3
parentca2ba809446f2184e50e4b8ebfe607a059c02de6 (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.yaml1
-rw-r--r--lib/core/constants/val_client_helper.dart10
-rw-r--r--lib/data/data_providers/vehicle_notifier.dart152
-rw-r--r--lib/data/data_providers/vss_provider.dart105
-rw-r--r--lib/export.dart1
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