Add persistent storage grpc API
[AGL/meta-agl-demo.git] / recipes-connectivity / kuksa-val / kuksa-can-provider / 0004-Enable-val2dbc-for-sensor-values.patch
1 From 937218a357ac1914fe410cf3ad31a67d54a63270 Mon Sep 17 00:00:00 2001
2 From: Scott Murray <scott.murray@konsulko.com>
3 Date: Mon, 17 Jun 2024 17:07:44 -0400
4 Subject: [PATCH 4/4] Enable val2dbc for sensor values
5
6 Rework to allow val2dbc mode to write out sensor values in
7 addition to actuator target values.
8
9 Upstream-Status: pending
10
11 Signed-off-by: Scott Murray <scott.murray@konsulko.com>
12 ---
13  dbcfeeder.py                            |  8 ++++++--
14  dbcfeederlib/databrokerclientwrapper.py | 18 ++++++++++++------
15  dbcfeederlib/dbc2vssmapper.py           | 21 ++++++++++-----------
16  dbcfeederlib/serverclientwrapper.py     |  2 +-
17  mapping/README.md                       |  2 --
18  5 files changed, 29 insertions(+), 22 deletions(-)
19
20 diff --git a/dbcfeeder.py b/dbcfeeder.py
21 index c252503..c1e20c4 100755
22 --- a/dbcfeeder.py
23 +++ b/dbcfeeder.py
24 @@ -289,19 +289,23 @@ class Feeder:
25              log.debug("Processing %d VSS Data Entry updates", len(updates))
26              dbc_signal_names: Set[str] = set()
27              for update in updates:
28 +                value = None
29                  if update.entry.value is not None:
30 -                    # This should never happen as we do not subscribe to current value
31                      log.warning(
32                          "Current value for %s is now: %s of type %s",
33                          update.entry.path, update.entry.value.value, type(update.entry.value.value)
34                      )
35 +                    value = update.entry.value.value
36  
37                  if update.entry.actuator_target is not None:
38                      log.debug(
39                          "Target value for %s is now: %s of type %s",
40                          update.entry.path, update.entry.actuator_target, type(update.entry.actuator_target.value)
41                      )
42 -                    affected_signals = self._mapper.handle_update(update.entry.path, update.entry.actuator_target.value)
43 +                    value = update.entry.actuator_target.value
44 +
45 +                if value != None:
46 +                    affected_signals = self._mapper.handle_update(update.entry.path, value)
47                      dbc_signal_names.update(affected_signals)
48  
49              messages_to_send: Set[Message] = set()
50 diff --git a/dbcfeederlib/databrokerclientwrapper.py b/dbcfeederlib/databrokerclientwrapper.py
51 index 716ee6d..db2b80a 100644
52 --- a/dbcfeederlib/databrokerclientwrapper.py
53 +++ b/dbcfeederlib/databrokerclientwrapper.py
54 @@ -199,14 +199,20 @@ class DatabrokerClientWrapper(clientwrapper.ClientWrapper):
55      def supports_subscription(self) -> bool:
56          return True
57  
58 -    async def subscribe(self, vss_names: List[str], callback):
59 +    async def subscribe(self, vss_entries: dict[str, str], callback):
60          """Create a subscription and invoke the callback when data received."""
61          entries: List[SubscribeEntry] = []
62 -        for name in vss_names:
63 -            # Always subscribe to target
64 -            subscribe_entry = SubscribeEntry(name, View.FIELDS, [Field.ACTUATOR_TARGET])
65 -            log.info("Subscribe entry: %s", subscribe_entry)
66 -            entries.append(subscribe_entry)
67 +        for name, signal_type in vss_entries.items():
68 +            if signal_type == "actuator":
69 +                subscribe_entry = SubscribeEntry(name, View.FIELDS, [Field.ACTUATOR_TARGET])
70 +                log.info("Subscribe entry: %s", subscribe_entry)
71 +                entries.append(subscribe_entry)
72 +            if signal_type == "sensor":
73 +                subscribe_entry = SubscribeEntry(name, View.FIELDS, [Field.VALUE])
74 +                log.info("Subscribe entry: %s", subscribe_entry)
75 +                entries.append(subscribe_entry)
76 +        if not entries:
77 +            return
78  
79          # If there is a path VSSClient will request a secure connection
80          if self._tls and self._root_ca_path:
81 diff --git a/dbcfeederlib/dbc2vssmapper.py b/dbcfeederlib/dbc2vssmapper.py
82 index 218f693..2be5e98 100644
83 --- a/dbcfeederlib/dbc2vssmapper.py
84 +++ b/dbcfeederlib/dbc2vssmapper.py
85 @@ -69,12 +69,13 @@ class VSSMapping:
86      parser: Parser = Parser()
87  
88      def __init__(self, vss_name: str, dbc_name: str, transform: dict, interval_ms: int,
89 -                 on_change: bool, datatype: str, description: str):
90 +                 on_change: bool, signal_type: str, datatype: str, description: str):
91          self.vss_name = vss_name
92          self.dbc_name = dbc_name
93          self.transform = transform
94          self.interval_ms = interval_ms
95          self.on_change = on_change
96 +        self.signal_type = signal_type
97          self.datatype = datatype
98          self.description = description
99          # For time comparison (interval_ms) we store last value used for comparison. Unit seconds.
100 @@ -347,7 +348,7 @@ class Mapper(DBCParser):
101          if can_signal_name not in self._dbc2vss_mapping:
102              self._dbc2vss_mapping[can_signal_name] = []
103          mapping_entry = VSSMapping(expanded_name, can_signal_name, transformation_definition, interval, on_change,
104 -                                   node["datatype"], node["description"])
105 +                                   node["type"], node["datatype"], node["description"])
106          self._dbc2vss_mapping[can_signal_name].append(mapping_entry)
107  
108          for msg_def in self.get_messages_for_signal(can_signal_name):
109 @@ -398,7 +399,7 @@ class Mapper(DBCParser):
110              log.warning("Ignoring \"interval_ms\" property of mapping definition for %s", expanded_name)
111  
112          mapping_entry = VSSMapping(expanded_name, can_signal_name, transform, interval, on_change,
113 -                                   node["datatype"], node["description"])
114 +                                   node["type"], node["datatype"], node["description"])
115          if can_signal_name not in self._vss2dbc_mapping:
116              self._vss2dbc_mapping[expanded_name] = []
117          self._vss2dbc_mapping[expanded_name].append(mapping_entry)
118 @@ -426,12 +427,7 @@ class Mapper(DBCParser):
119          if dbc2vss_def is not None:
120              self._analyze_dbc2vss(expanded_name, node, dbc2vss_def)
121          if "vss2dbc" in node:
122 -            if node["type"] == "actuator":
123 -                self._analyze_vss2dbc(expanded_name, node, node["vss2dbc"])
124 -            else:
125 -                # vss2dbc is handled by subscription to target value, so only makes sense for actuators
126 -                log.error("vss2dbc only allowed for actuators, VSS signal %s is not an actuator!", expanded_name)
127 -                sys.exit(-1)
128 +            self._analyze_vss2dbc(expanded_name, node, node["vss2dbc"])
129  
130      def _traverse_vss_node(self, name, node, prefix=""):
131          """
132 @@ -474,9 +470,12 @@ class Mapper(DBCParser):
133          """Get all CAN signal names for which a mapping to a VSS Data Entry exists."""
134          return self._dbc2vss_mapping.keys()
135  
136 -    def get_vss2dbc_entries(self) -> KeysView[str]:
137 +    def get_vss2dbc_entries(self) -> Dict[str, str]:
138          """Get all VSS Data Entry paths for which a mapping to a CAN signal name exists."""
139 -        return self._vss2dbc_mapping.keys()
140 +        entries: Dict[str, str] = {}
141 +        for name, mappings in self._vss2dbc_mapping.items():
142 +            entries[name] = mappings[0].signal_type
143 +        return entries
144  
145      def get_vss_names(self) -> Set[str]:
146          """Get all VSS names used in mappings, both vss2dbc and dbc2vss"""
147 diff --git a/dbcfeederlib/serverclientwrapper.py b/dbcfeederlib/serverclientwrapper.py
148 index fa43d28..86b2ceb 100644
149 --- a/dbcfeederlib/serverclientwrapper.py
150 +++ b/dbcfeederlib/serverclientwrapper.py
151 @@ -122,6 +122,6 @@ class ServerClientWrapper(clientwrapper.ClientWrapper):
152          log.info("Feature not implemented")
153          return False
154  
155 -    async def subscribe(self, vss_names: List[str], callback):
156 +    async def subscribe(self, vss_entries: dict[str, str], callback):
157          log.error("Feature not implemented")
158          return
159 diff --git a/mapping/README.md b/mapping/README.md
160 index 2155f28..ea6de07 100644
161 --- a/mapping/README.md
162 +++ b/mapping/README.md
163 @@ -44,8 +44,6 @@ This is built on the assumption that the DBC provider always send target values
164  Having separate configurations (`dbc2vss` and `vss2dbc`) is needed as wanted value and actual value never are sent
165  by the same DBC signal, they are not even part of the same CAN-frame.
166  
167 -*This means that `vss2dbc` only can be used for actuators, as only actuators have target values!*
168 -
169  ## Example mapping files
170  
171  Example mapping files for various VSS versions can be found in this folder.
172 -- 
173 2.44.0
174