1616logger = logging .getLogger (__name__ )
1717
1818# Singleton pattern to ensure only one instance of CommonLogic exists
19+
20+
1921class CommonLogic :
2022 """ General logic for battery control that is not specific to control strategies. """
2123
2224 _instance = None # Singleton instance
2325 charge_rate_multiplier : float
2426 always_allow_discharge_limit : float
2527 max_capacity : float # Maximum capacity of the battery in Wh
26- min_charge_energy : float = 100 # Minimum amount of energy before charging from grid in Wh
28+ # Minimum amount of energy before charging from grid in Wh
29+ min_charge_energy : float = 100
2730
2831 @classmethod
2932 def get_instance (cls , charge_rate_multiplier = 1.1 ,
@@ -34,9 +37,9 @@ def get_instance(cls, charge_rate_multiplier=1.1,
3437 if cls ._instance is None :
3538 cls ._instance = cls .__new__ (cls )
3639 cls ._instance .initialize (charge_rate_multiplier ,
37- always_allow_discharge_limit ,
38- max_capacity ,
39- min_charge_energy )
40+ always_allow_discharge_limit ,
41+ max_capacity ,
42+ min_charge_energy )
4043 return cls ._instance
4144
4245 def __init__ (self , * args , ** kwargs ):
@@ -47,25 +50,41 @@ def __init__(self, *args, **kwargs):
4750 self .initialize (* args , ** kwargs )
4851
4952 def initialize (self , charge_rate_multiplier = 1.1 ,
50- always_allow_discharge_limit = 0.9 ,
51- max_capacity = 10000 ,
52- min_charge_energy = 100 ):
53+ always_allow_discharge_limit = 0.9 ,
54+ max_capacity = 10000 ,
55+ min_charge_energy = 100 ):
5356 """ Private initialization method. """
54- self .charge_rate_multiplier = charge_rate_multiplier
55- self .always_allow_discharge_limit = always_allow_discharge_limit
56- self .max_capacity = max_capacity
57- self .min_charge_energy = min_charge_energy
57+ self .charge_rate_multiplier = float (charge_rate_multiplier )
58+ self .always_allow_discharge_limit = self ._to_float (
59+ always_allow_discharge_limit )
60+ self .max_capacity = float (max_capacity )
61+ self .min_charge_energy = float (min_charge_energy )
5862
5963 def set_charge_rate_multiplier (self , multiplier : float ):
6064 """ Set the charge rate multiplier. """
6165 logger .debug ('Setting charge rate multiplier to %s' , multiplier )
6266 self .charge_rate_multiplier = multiplier
6367
68+ @staticmethod
69+ def _to_float (value ) -> float :
70+ """ Convert a value to float, handling European comma decimal notation.
71+ Args:
72+ value: The value to convert. Can be a float, int, or string
73+ (including European notation like '0,9').
74+ Returns:
75+ float: The converted value.
76+ Raises:
77+ ValueError: If the value cannot be converted to float.
78+ """
79+ if isinstance (value , str ):
80+ return float (value .replace (',' , '.' ))
81+ return float (value )
82+
6483 def set_always_allow_discharge_limit (self , limit : float ):
6584 """ Set the always allowed discharge limit. """
6685 logger .debug (
6786 'Setting always allowed discharge limit to %s' , limit )
68- self .always_allow_discharge_limit = limit
87+ self .always_allow_discharge_limit = self . _to_float ( limit )
6988
7089 def get_always_allow_discharge_limit (self ) -> float :
7190 """ Get the always allowed discharge limit. """
@@ -92,11 +111,11 @@ def is_discharge_always_allowed_capacity(self, capacity: float) -> bool:
92111
93112 if capacity >= self .max_capacity * self .always_allow_discharge_limit :
94113 logger .debug (
95- 'Discharge is \' always allowed\' for current capacity: %.0f Wh' , round (capacity ,0 ))
114+ 'Discharge is \' always allowed\' for current capacity: %.0f Wh' , round (capacity , 0 ))
96115 return True
97116
98117 logger .debug (
99- 'Discharge is NOT \' always allowed\' for current capacity: %.0f Wh' , round (capacity ,0 ))
118+ 'Discharge is NOT \' always allowed\' for current capacity: %.0f Wh' , round (capacity , 0 ))
100119 return False
101120
102121 def is_charging_above_minimum (self , needed_energy : float ) -> bool :
0 commit comments