diff --git a/packages/modules/vehicles/json/config.py b/packages/modules/vehicles/json/config.py index 29b75e2f61..8d31799d68 100644 --- a/packages/modules/vehicles/json/config.py +++ b/packages/modules/vehicles/json/config.py @@ -10,6 +10,7 @@ def __init__( soc_pattern: Optional[str] = None, range_pattern: Optional[str] = None, timestamp_pattern: Optional[str] = None, + odometer_pattern: Optional[str] = None, timeout: Optional[int] = None, calculate_soc: bool = False ): @@ -17,6 +18,7 @@ def __init__( self.soc_pattern = soc_pattern self.range_pattern = range_pattern self.timestamp_pattern = timestamp_pattern + self.odometer_pattern = odometer_pattern self.timeout = timeout self.calculate_soc = calculate_soc diff --git a/packages/modules/vehicles/json/soc.py b/packages/modules/vehicles/json/soc.py index 2b3ced8b43..9e69a8c5fe 100644 --- a/packages/modules/vehicles/json/soc.py +++ b/packages/modules/vehicles/json/soc.py @@ -61,7 +61,9 @@ def fetch_soc(config: JsonSocSetup, compiled_queries: Dict) -> CarState: compiled_queries["timestamp"], config.configuration.timestamp_pattern)) if compiled_queries["timestamp"] is not None else None) - return CarState(soc=soc, range=range, soc_timestamp=timestamp) + odometer = (float(parse_data(raw_data, compiled_queries["odometer"], config.configuration.odometer_pattern)) + if compiled_queries["odometer"] is not None else None) + return CarState(soc=soc, range=range, soc_timestamp=timestamp, odometer=odometer) def initialize_vehicle(vehicle_config: JsonSocSetup, compiled_queries: Dict) -> None: @@ -71,13 +73,16 @@ def initialize_vehicle(vehicle_config: JsonSocSetup, compiled_queries: Dict) -> compiled_queries["range"] = jq.compile(config.range_pattern) if config.range_pattern is not None else None compiled_queries["timestamp"] = (jq.compile(config.timestamp_pattern) if config.timestamp_pattern is not None else None) + compiled_queries["odometer"] = (jq.compile(config.odometer_pattern) + if config.odometer_pattern is not None else None) def create_vehicle(vehicle_config: JsonSocSetup, vehicle: int): compiled_queries = { 'soc': None, 'range': None, - 'timestamp': None + 'timestamp': None, + 'odometer': None } def initializer() -> None: @@ -97,14 +102,17 @@ def json_update(charge_point: int, soc_pattern: str, range_pattern: Optional[str] = None, timestamp_pattern: Optional[str] = None, + odometer_pattern: Optional[str] = None, calculate_soc: Optional[bool] = False): log.debug(f'json-soc: charge_point={charge_point} url="{url}" soc-pattern="{soc_pattern}" ' - f'range-pattern="{range_pattern}" timestamp-pattern="{timestamp_pattern}" calculate-soc={calculate_soc}') + f'range-pattern="{range_pattern}" timestamp-pattern="{timestamp_pattern}" ' + f'odometer-pattern="{odometer_pattern}" calculate-soc={calculate_soc}') store.get_car_value_store(charge_point).store.set( fetch_soc(JsonSocSetup(configuration=JsonSocConfiguration(url=url, soc_pattern=soc_pattern, range_pattern=range_pattern, timestamp_pattern=timestamp_pattern, + odometer_pattern=odometer_pattern, calculate_soc=calculate_soc)))) diff --git a/packages/modules/vehicles/json/test_json_soc.py b/packages/modules/vehicles/json/test_json_soc.py index a5d3611341..9cc0b2155d 100644 --- a/packages/modules/vehicles/json/test_json_soc.py +++ b/packages/modules/vehicles/json/test_json_soc.py @@ -31,9 +31,11 @@ def setUp(self): 'soc_pattern': '.energy[0].level', 'range_pattern': '.energy[0].autonomy', 'timestamp_pattern': '.energy[0].updated_at', + 'odometer_pattern': None, 'expected_soc': 69, 'expected_range': 214, - 'expected_timestamp': 1735984813 + 'expected_timestamp': 1735984813, + 'expected_odometer': None }, { 'sample_data': { @@ -46,9 +48,30 @@ def setUp(self): 'soc_pattern': '.response.value', 'range_pattern': None, 'timestamp_pattern': '.response.timestamp', + 'odometer_pattern': None, 'expected_soc': 20.2, 'expected_range': None, - 'expected_timestamp': 1736108141 + 'expected_timestamp': 1736108141, + 'expected_odometer': None + }, + { + 'sample_data': { + "response": { + "soc": "45.5", + "range": 300, + "timestamp": 1736108141, + "odometer": 12345.67 + } + }, + 'url': "http://example.com/soc3", + 'soc_pattern': '.response.soc', + 'range_pattern': '.response.range', + 'timestamp_pattern': '.response.timestamp', + 'odometer_pattern': '.response.odometer', + 'expected_soc': 45.5, + 'expected_range': 300, + 'expected_timestamp': 1736108141, + 'expected_odometer': 12345.67 } ] @@ -62,13 +85,15 @@ def test_fetch_soc(self, mock_get_http_session): compiled_queries = { 'soc': None, 'range': None, - 'timestamp': None + 'timestamp': None, + 'odometer': None } vehicle_config = JsonSocSetup(configuration=JsonSocConfiguration( url=case['url'], soc_pattern=case['soc_pattern'], range_pattern=case['range_pattern'], - timestamp_pattern=case['timestamp_pattern'] + timestamp_pattern=case['timestamp_pattern'], + odometer_pattern=case['odometer_pattern'] )) initialize_vehicle(vehicle_config, compiled_queries) car_state = fetch_soc(vehicle_config, compiled_queries) @@ -76,3 +101,4 @@ def test_fetch_soc(self, mock_get_http_session): self.assertEqual(car_state.soc, case['expected_soc']) self.assertEqual(car_state.range, case['expected_range']) self.assertEqual(car_state.soc_timestamp, case['expected_timestamp']) + self.assertEqual(car_state.odometer, case['expected_odometer']) diff --git a/packages/modules/vehicles/psacc/config.py b/packages/modules/vehicles/psacc/config.py index bb096546b6..3e15c7ee2e 100644 --- a/packages/modules/vehicles/psacc/config.py +++ b/packages/modules/vehicles/psacc/config.py @@ -13,6 +13,7 @@ def __init__(self, super().__init__(soc_pattern=prf + "level", range_pattern=prf + "autonomy", timestamp_pattern=prf + "updated_at", + odometer_pattern=".timed_odometer.mileage", timeout=10, calculate_soc=True)