1- from typing import List
21import logging
32import jq
43
4+ from typing import List , Optional , Union , Any , Dict
5+ from datetime import datetime
6+
57from helpermodules .cli import run_using_positional_cli_args
68from modules .common import req
79from modules .common import store
1012from modules .common .component_state import CarState
1113from modules .common .configurable_vehicle import ConfigurableVehicle
1214from modules .vehicles .json .config import JsonSocSetup , JsonSocConfiguration
13- from typing import Any , Dict
14- from datetime import datetime
1515
1616
1717log = logging .getLogger (__name__ )
1818
1919
20- def extract_to_epoch (input_string : str ) -> float :
20+ def extract_to_epoch (input_string : Union [ str , int , float ] ) -> float :
2121 # If already an integer, return it
2222 if isinstance (input_string , int ) or isinstance (input_string , float ):
2323 return int (input_string )
@@ -27,70 +27,89 @@ def extract_to_epoch(input_string: str) -> float:
2727 dt = datetime .fromisoformat (input_string )
2828 return int (dt .timestamp ())
2929 except ValueError :
30- log .exception (f" Kein ISO 8601 formatiertes Datum in ' { input_string } ' gefunden." )
30+ log .exception (f' Kein ISO 8601 formatiertes Datum in " { input_string } " gefunden.' )
3131 return None
3232
3333
34- def parse_data (data : Dict [str , Any ], pattern : str ) -> any :
35- log .debug (f"parse_data: data='{ data } ' pattern='{ pattern } '" )
34+ def parse_data (data : Dict [str , Any ], compiled_query : Any , pattern : str = None ) -> any :
35+ if compiled_query is None :
36+ raise ValueError ("Kein Pattern zum extrahieren der Daten definiert. Bitte die Konfiguration aktualisieren!" )
3637
37- if pattern == "" :
38- raise ValueError ("Kein Pattern zum extrahieren der Daten definiert. Bitte in der Konfiguration aktualisieren." )
39-
40- result = jq .compile (pattern ).input (data ).first ()
38+ result = compiled_query .input (data ).first ()
4139 if result is None :
42- raise ValueError (f" Pattern { pattern } hat keine Ergebnisse in ' { data } ' geliefert." )
40+ raise ValueError (f' Pattern " { pattern } " hat keine Ergebnisse in " { data } " geliefert!' )
4341
44- log .debug (f" result=' { result } '" )
42+ log .debug (f' result=" { result } "' )
4543 return result
4644
4745
48- def fetch_soc (config : JsonSocSetup ) -> CarState :
46+ def fetch_soc (config : JsonSocSetup , compiled_queries : Dict ) -> CarState :
4947 url = config .configuration .url
50- soc_pattern = config .configuration .soc_pattern
51- range_pattern = config .configuration .range_pattern
52- timestamp_pattern = config .configuration .timestamp_pattern
5348 timeout = config .configuration .timeout if isinstance (config .configuration .timeout , int ) else None
5449
5550 if url is None or url == "" :
5651 raise ValueError ("Keine URL zum Abrufen der Daten definiert. Bitte in der Konfiguration aktualisieren." )
52+ if compiled_queries ["soc" ] is None :
53+ raise ValueError ("Kein Pattern zum Extrahieren des SOC definiert. Bitte in der Konfiguration aktualisieren." )
5754
5855 raw_data : Dict [str , Any ] = req .get_http_session ().get (url , timeout = timeout ).json ()
5956
60- soc = float (parse_data (raw_data , soc_pattern ))
61-
62- if range_pattern is None or range_pattern == "" :
63- log .debug ("Kein Pattern für Range angegeben, setze Range auf None." )
64- range = None
65- else :
66- range = int (parse_data (raw_data , range_pattern ))
57+ soc = float (parse_data (raw_data , compiled_queries ["soc" ], config .configuration .soc_pattern ))
58+ range = (int (parse_data (raw_data , compiled_queries ["range" ], config .configuration .range_pattern ))
59+ if compiled_queries ["range" ] is not None else None )
60+ timestamp = (extract_to_epoch (parse_data (raw_data ,
61+ compiled_queries ["timestamp" ],
62+ config .configuration .timestamp_pattern ))
63+ if compiled_queries ["timestamp" ] is not None else None )
64+ return CarState (soc = soc , range = range , soc_timestamp = timestamp )
6765
68- if timestamp_pattern is None or timestamp_pattern == "" :
69- log .debug ("Kein Pattern für Timestamp angegeben, setze Timestamp auf None." )
70- timestamp = None
71- else :
72- log .debug (f"timestamp_pattern='{ timestamp_pattern } '" )
73- timestamp = parse_data (raw_data , timestamp_pattern )
74- timestamp = extract_to_epoch (timestamp )
7566
76- return CarState (soc = soc , range = range , soc_timestamp = timestamp )
67+ def initialize_vehicle (vehicle_config : JsonSocSetup , compiled_queries : Dict ) -> None :
68+ config = vehicle_config .configuration
69+ log .debug (f'Initialisiere Fahrzeug mit Konfiguration: { config } ' )
70+ compiled_queries ["soc" ] = jq .compile (config .soc_pattern ) if config .soc_pattern is not None else None
71+ compiled_queries ["range" ] = jq .compile (config .range_pattern ) if config .range_pattern is not None else None
72+ compiled_queries ["timestamp" ] = (jq .compile (config .timestamp_pattern )
73+ if config .timestamp_pattern is not None else None )
7774
7875
7976def create_vehicle (vehicle_config : JsonSocSetup , vehicle : int ):
80- def updater (vehicle_update_data : VehicleUpdateData ) -> CarState :
81- return fetch_soc (vehicle_config )
82- return ConfigurableVehicle (vehicle_config = vehicle_config , component_updater = updater , vehicle = vehicle ,
83- calc_while_charging = vehicle_config .configuration .calculate_soc )
77+ compiled_queries = {
78+ 'soc' : None ,
79+ 'range' : None ,
80+ 'timestamp' : None
81+ }
8482
83+ def initializer () -> None :
84+ return initialize_vehicle (vehicle_config , compiled_queries )
8585
86- def http_update (soc_url : str , range_url : str , charge_point : int ):
87- log .debug ("http_soc: soc_url=" + soc_url + "range_url=" + range_url + "charge_point=" + str (charge_point ))
86+ def updater (vehicle_update_data : VehicleUpdateData ) -> CarState :
87+ return fetch_soc (vehicle_config , compiled_queries )
88+ return ConfigurableVehicle (vehicle_config = vehicle_config ,
89+ component_updater = updater ,
90+ vehicle = vehicle ,
91+ calc_while_charging = vehicle_config .configuration .calculate_soc ,
92+ initializer = initializer )
93+
94+
95+ def json_update (charge_point : int ,
96+ url : str ,
97+ soc_pattern : str ,
98+ range_pattern : Optional [str ] = None ,
99+ timestamp_pattern : Optional [str ] = None ,
100+ calculate_soc : Optional [bool ] = False ):
101+ log .debug (f'json-soc: charge_point={ charge_point } url="{ url } " soc-pattern="{ soc_pattern } " '
102+ f'range-pattern="{ range_pattern } " timestamp-pattern="{ timestamp_pattern } " calculate-soc={ calculate_soc } ' )
88103 store .get_car_value_store (charge_point ).store .set (
89- fetch_soc (JsonSocSetup (configuration = JsonSocConfiguration (soc_url , range_url ))))
104+ fetch_soc (JsonSocSetup (configuration = JsonSocConfiguration (url = url ,
105+ soc_pattern = soc_pattern ,
106+ range_pattern = range_pattern ,
107+ timestamp_pattern = timestamp_pattern ,
108+ calculate_soc = calculate_soc ))))
90109
91110
92111def main (argv : List [str ]):
93- run_using_positional_cli_args (http_update , argv )
112+ run_using_positional_cli_args (json_update , argv )
94113
95114
96115device_descriptor = DeviceDescriptor (configuration_factory = JsonSocSetup )
0 commit comments