summaryrefslogtreecommitdiffstats
path: root/lib/data/data_providers/val_client.dart
blob: 173dbfba514e227bff4a6756bef1c8b3ce0a4759 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import 'package:flutter_ics_homescreen/export.dart';
import 'package:protos/val_api.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("Connecting to KUKSA.val at ${config.hostname}:${config.port}");
    ChannelCredentials creds;
    if (config.useTls && config.caCertificate.isNotEmpty) {
      print("Using TLS");
      if (config.tlsServerName.isNotEmpty) {
        creds = ChannelCredentials.secure(
            certificates: config.caCertificate,
            authority: config.tlsServerName);
      } else {
        creds = ChannelCredentials.secure(certificates: config.caCertificate);
      }
    } else {
      creds = const ChannelCredentials.insecure();
    }
    channel = ClientChannel(config.hostname,
        port: config.port, options: ChannelOptions(credentials: creds));
    stub = VALClient(channel);
  }

  void run() async {
    List<String> signals = VSSPath().getSignalsList();
    Map<String, String> metadata = {};
    if (config.authorization.isNotEmpty) {
      metadata = {'authorization': "Bearer ${config.authorization}"};
    }

    // 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 = signals[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;
          handleSignalUpdate(update.entry);
        }
      }, onError: (stacktrace, errorDescriptor) {
        debugPrint(stacktrace.toString());
      });
    } catch (e) {
      debugPrint(e.toString());
    }
  }

  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(unitStateProvider.notifier).handleSignalUpdate(entry);
  }

  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));
  }

  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);
    }
  }
}