kuksa-vss-init: rework into agl-vss-helper
[AGL/meta-agl-demo.git] / recipes-demo / agl-vss-helper / files / agl-vss-helper.py
1 #!/usr/bin/env python3
2 # Copyright (c) 2022 Aakash Solanki, tech2aks@gmail.com
3 # Copyright (c) 2024 Scott Murray <scott.murray@konsulko.com>
4 #
5 # SPDX-License-Identifier: MIT
6
7 import sys
8 from pathlib import Path
9 import yaml
10 import asyncio
11 import concurrent.futures
12 from kuksa_client.grpc.aio import VSSClient
13 from kuksa_client.grpc import Datapoint
14 from systemd.daemon import notify
15
16 # Defaults
17 hostname = "localhost"
18 port = 55555
19 config_filename = "/etc/xdg/AGL/agl-vss-helper.yaml"
20 token_filename = "/etc/xdg/AGL/agl-vss-helper/agl-vss-helper.token"
21 ca_cert_filename = "/etc/kuksa-val/CA.pem"
22 tls_server_name = "localhost"
23 verbose = False
24
25 async def main():
26     client = VSSClient(hostname,
27                        port,
28                        root_certificates=Path(ca_cert_filename),
29                        tls_server_name=tls_server_name,
30                        token=token,
31                        ensure_startup_connection=True)
32     await client.connect()
33     print(f"Connected to KUKSA.val databroker at {hostname}:{port}")
34     if "initialize" in config and isinstance(config["initialize"], list):
35         for entry in config["initialize"]:
36             if "signal" in entry and "value" in entry:
37                 if verbose:
38                     print(f"Setting {entry['signal']} to {entry['value']}")
39                 await client.set_current_values({ entry["signal"] : Datapoint(entry["value"]) })
40
41     notify("READY=1")
42
43     if "mock" in config and isinstance(config["mock"], list):
44         if len(config["mock"]) != 0:
45             print(f"Mocking actuators:")
46             for signal in config["mock"]:
47                 print(f"  {signal}")
48             async for updates in client.subscribe_target_values(config["mock"]):
49                 for signal in updates:
50                     if updates[signal] is not None:
51                         if verbose:
52                             print(f"Actuating {signal} to {updates[signal].value}")
53                         await client.set_current_values({ signal : Datapoint(updates[signal].value) })
54
55
56 #
57 # Initialization
58 #
59
60 try:
61     config_file = open(config_filename, "r")
62     config = yaml.safe_load(config_file)
63 except yaml.YAMLError as exc:
64     print(f"Could not parse configuration: ${exc}")
65 except:
66     print(f"Could not read configuration")
67
68 if "verbose" in config and isinstance(config["verbose"], bool):
69     verbose = config["verbose"]
70 if "hostname" in config and isinstance(config["hostname"], string):
71     hostname = config["hostname"]
72 if "port" in config and isinstance(config["port"], int):
73     port = config["port"]
74 if "use-tls" in config and isinstance(config["use-tls"], bool):
75     use_tls = config["use-tls"]
76 if "token-file" in config and isinstance(config["token-file"], string):
77     token_filename = config["token-file"]
78 if "ca-certificate" in config and isinstance(config["ca-certificate"], string):
79     ca_cert_filename = config["ca-certificate"]
80
81 if token_filename != "":
82     if verbose:
83         print(f"Reading authorization token {token_filename}")
84     token_file = open(token_filename, "r")
85     token = token_file.read()
86 else:
87     token = ""
88
89 print("Starting")
90 try:
91     asyncio.run(main())
92 except KeyboardInterrupt:
93     print("Exiting")
94
95 notify("STOPPING=1")
96 sys.exit(0)