2626
2727
2828class Analyser_Merge_Charging_station_FR (Analyser_Merge_Point ):
29-
29+ # constant to limit bad formatting in open data (in kW)
30+ MAX_POWER_KW = 401
3031 WIKIDATA_MAP = {
3132 "ionity" : "Q42717773" ,
3233 "bouygues" : "Q3046208" ,
@@ -38,6 +39,95 @@ class Analyser_Merge_Charging_station_FR(Analyser_Merge_Point):
3839 "Izivia" : "Q86671322" ,
3940 }
4041
42+ @staticmethod
43+ def keepMaxValueIfEnum (str_val ):
44+
45+ # if the value contains a semicolon, we split it and keep only the highest value
46+ if ";" in str_val :
47+ boom = str_val .split (";" )
48+ max_val = 0
49+ for p in boom :
50+ p_clean = p .lower ().replace ("kw" , "" ).strip ()
51+ try :
52+ p_val = int (float (p_clean ))
53+ if (
54+ p_val <= Analyser_Merge_Charging_station_FR .MAX_POWER_KW
55+ and p_val > max_val
56+ ):
57+ max_val = p_val
58+ except ValueError :
59+ # exclude values we can not convert to number
60+ pass
61+
62+ if max_val > 0 :
63+ str_val = str (max_val )
64+ else :
65+ # case without delimiter, handle unit
66+ if "kw" in str_val .lower ():
67+ p_clean = str_val .lower ().replace ("kw" , "" ).strip ()
68+ try :
69+ p_val = int (float (p_clean ))
70+ if p_val <= Analyser_Merge_Charging_station_FR .MAX_POWER_KW :
71+ str_val = str (p_val )
72+ except ValueError :
73+ pass
74+ return str_val
75+
76+ def _normalize_number (self , v : float ) -> str :
77+ """Formats in float by removing unwanted zeros."""
78+ try :
79+ iv = int (v )
80+ if abs (v - iv ) < 1e-9 :
81+ return str (iv )
82+ return f"{ v :.6f} " .rstrip ("0" ).rstrip ("." )
83+ except Exception :
84+ return str (v )
85+
86+ def getPuissanceNominaleInKw (self , raw ):
87+ """Computes nominal power in kW from a possible enumeration of values."""
88+ if raw is None :
89+ return None
90+
91+ s = str (raw ).strip ()
92+ if s == "" :
93+ return None
94+
95+ max_kw = getattr (self , "MAX_POWER_KW" , 500 )
96+
97+ # enumeration case: we only want the max value and format it.
98+ if ";" in s :
99+ max_str = self .keepMaxValueIfEnum (s )
100+ if not max_str :
101+ return None
102+ try :
103+ v = float (
104+ str (max_str ).replace ("," , "." ).lower ().replace ("kw" , "" ).strip ()
105+ )
106+ except Exception :
107+ return None
108+ return f"{ self ._normalize_number (v )} kW"
109+
110+ # case of only one value
111+ s_norm = s .lower ().replace ("," , "." )
112+ try :
113+ if s_norm .endswith ("kw" ):
114+ v = float (s_norm [:- 2 ].strip ())
115+ return f"{ self ._normalize_number (v )} kW"
116+
117+ if s_norm .endswith ("w" ):
118+ v_w = float (s_norm [:- 1 ].strip ())
119+ v = v_w / 1000.0
120+ return f"{ self ._normalize_number (v )} kW"
121+
122+ # case without unit
123+ v = float (s_norm )
124+ if v > max_kw :
125+ # On suppose des watts => conversion en kW
126+ v = v / 1000.0
127+ return f"{ self ._normalize_number (v )} kW"
128+ except Exception :
129+ return None
130+
41131 def __init__ (self , config , logger = None ):
42132 Analyser_Merge_Point .__init__ (self , config , logger )
43133 doc = dict (
@@ -85,6 +175,9 @@ def __init__(self, config, logger=None):
85175 "ref:EU:EVSE" : "id_station_itinerance"
86176 },
87177 mapping2 = {
178+ "charging_station:output" : lambda fields : self .getPuissanceNominaleInKw (
179+ fields ["puissance_nominale" ]
180+ ),
88181 "operator:phone" : "telephone_operateur" ,
89182 "operator:email" : "contact_operateur" ,
90183 "start_date" : "date_mise_en_service" ,
0 commit comments