Skip to content

Commit a540809

Browse files
authored
Add subscribe-performance test app (#126)
1 parent 00838f8 commit a540809

File tree

7 files changed

+492
-0
lines changed

7 files changed

+492
-0
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"manifestVersion": "v1",
3+
"name": "performance-subscribe",
4+
"interfaces": [
5+
{
6+
"type": "vehicle-signal-interface",
7+
"config": {
8+
"src": "https://github.com/COVESA/vehicle_signal_specification/releases/download/v4.1/vss_rel_4.1.json",
9+
"datapoints": {
10+
"required": [
11+
]
12+
}
13+
}
14+
}
15+
]
16+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
## Usage
2+
3+
1) Create a .json file named: "subscription_signals.json"
4+
2) Place it in the same folder as the binary
5+
3) Exeucute the binary e.g. "./sampleapp"
6+
4) Check the console output for the timestamps: "<Timestamp> - <Signal_Name> - <Value>"
7+
8+
## .json format
9+
10+
The following format is mandatory for the input file:
11+
12+
```
13+
{
14+
"signals": [
15+
{
16+
"path": "Vehicle.LowVoltageBattery.CurrentVoltage"
17+
},
18+
{
19+
"path": "Vehicle.LowVoltageBattery.CurrentCurrent"
20+
},
21+
{
22+
"path": "Vehicle.Speed"
23+
},
24+
...
25+
]
26+
}
27+
```
28+
29+
Signals which are not available will be printed in the console as a warning.
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# Copyright (c) 2022-2024 Contributors to the Eclipse Foundation
2+
#
3+
# This program and the accompanying materials are made available under the
4+
# terms of the Apache License, Version 2.0 which is available at
5+
# https://www.apache.org/licenses/LICENSE-2.0.
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
#
13+
# SPDX-License-Identifier: Apache-2.0
14+
15+
import asyncio
16+
import json
17+
import logging
18+
import signal
19+
from datetime import datetime
20+
21+
from sdv_model import Vehicle, vehicle # type: ignore
22+
23+
from velocitas_sdk.model import DataPoint
24+
from velocitas_sdk.util.log import ( # type: ignore
25+
get_opentelemetry_log_factory,
26+
get_opentelemetry_log_format,
27+
)
28+
from velocitas_sdk.vdb.reply import DataPointReply
29+
from velocitas_sdk.vehicle_app import VehicleApp
30+
31+
# Configure the VehicleApp logger with the necessary log config and level.
32+
logging.setLogRecordFactory(get_opentelemetry_log_factory())
33+
logging.basicConfig(format=get_opentelemetry_log_format())
34+
logging.getLogger().setLevel("DEBUG")
35+
logger = logging.getLogger(__name__)
36+
37+
# The file path may need to be updated based on the location of the file.
38+
SIGNALS_JSON = "subscription_signals.json"
39+
40+
41+
class PerformanceTestApp(VehicleApp):
42+
"""
43+
A sample vehicle app that subscribes to a list of signals (from a file) and prints
44+
the values + timestamps of the signals.
45+
"""
46+
47+
def __init__(self, vehicle_client: Vehicle):
48+
super().__init__()
49+
self.Vehicle = vehicle_client
50+
51+
async def on_start(self):
52+
signals_paths = self.read_signals_paths()
53+
for signal_str in signals_paths:
54+
await self.subscribe(signal_str)
55+
56+
def read_signals_paths(self) -> list[str]:
57+
test_signals_json = self.read_json(SIGNALS_JSON)
58+
signals_json = test_signals_json["signals"]
59+
60+
signal_paths: list[str] = []
61+
for signal_json in signals_json:
62+
signal_path = signal_json["path"]
63+
signal_paths.append(signal_path)
64+
65+
return signal_paths
66+
67+
def read_json(self, file_path: str) -> dict:
68+
with open(file_path, "r") as file:
69+
return json.load(file)
70+
71+
async def subscribe(self, signal_str: str):
72+
try:
73+
node: DataPoint = self.Vehicle.getNode(signal_str) # type: ignore
74+
await node.subscribe(self.on_node_change)
75+
except AttributeError:
76+
print(f"Signal {signal_str} not found in the vehicle model.")
77+
78+
async def on_node_change(self, data: DataPointReply):
79+
current_timestamp = datetime.now()
80+
81+
datapoint_str = data.reply.fields.popitem()[
82+
0
83+
] # The key of the first field is the datapoint path
84+
node = self.Vehicle.getNode(datapoint_str)
85+
data_point = data.get(node) # type: ignore
86+
data_point_value = data_point.value
87+
88+
print(f"{current_timestamp.time()} - {node.name} - {data_point_value}")
89+
90+
91+
async def main():
92+
"""Main function"""
93+
logger.info("Starting the subscribe-performance test app")
94+
vehicle_app = PerformanceTestApp(vehicle)
95+
await vehicle_app.run()
96+
97+
98+
LOOP = asyncio.get_event_loop()
99+
LOOP.add_signal_handler(signal.SIGTERM, LOOP.stop)
100+
LOOP.run_until_complete(main())
101+
LOOP.close()

0 commit comments

Comments
 (0)