1111from multiplus2 import MultiPlus2
1212from timer import Timer
1313from trace import Trace
14- from us2000 import US2000
14+ from bms_us2000 import US2000
1515from utils import *
1616from web import AppWeb
1717
18+ from bms_dummy import BMS_DUMMY
19+
1820"""
1921ESS Application
2022"""
@@ -29,11 +31,15 @@ def __init__(self):
2931 self .trace = Trace ()
3032 self .config = config
3133 self .meterhub = ApiRequest (config ['meterhub_address' ], timeout = 0.5 , lifetime = 10 , log_name = 'meterhub' )
32- self .bms = US2000 (port = config ['pylontech_bms_port' ],
33- pack_number = config ['us2000_pack_number' ],
34- baudrate = config ['us2000_baudrate' ],
35- lifetime = 30 ,
36- log_name = 'bms' )
34+
35+ if 'bms_us2000' in config :
36+ self .bms = US2000 (** self .config ['bms_us2000' ]) # pass config to BMS class
37+ # elif 'bms_seplos' in config:
38+ # self.bms = SEPLOS(**self.config['bms_seplos']) # pass config to BMS class
39+ else :
40+ self .log .exception ("undefined BMS" )
41+ self .bms = None
42+
3743 self .multiplus = MultiPlus2 (config ['victron_mk3_port' ])
3844 self .blackbox = Blackbox (size = config ['blackbox_size' ],
3945 path = config ['log_path' ],
@@ -52,16 +58,13 @@ def __init__(self):
5258 self .home_all_p = 0
5359 self .car_p = 0
5460 self .pv_p = 0
55- self .soc = None
56- self .soc_low = None # lowest SOC
57- self .soc_high = None # highest SOC
58- self .ubat = None
5961
6062 self .charge_start_timer = Timer ()
6163 self .feed_start_timer = Timer ()
6264 self .feed_throttle_timer = Timer ()
6365 self .state_timer = Timer ()
6466
67+
6568 def get_setting (self , name ):
6669 """
6770 Give a setting depending on the option used or default
@@ -85,12 +88,13 @@ def start(self):
8588 # === meterhub =================================================== ~ 15ms
8689
8790 self .meterhub .read (
88- post = {'bat_info' : self .get_info_text (), 'bat_soc' : dictget ( self .bms .data , ' soc' ) })
91+ post = {'bat_info' : self .get_info_text (), 'bat_soc' : self .bms .soc })
8992 self .log .debug ("meterhub {}" .format (self .meterhub .data ))
9093
9194 # === bms =================================================== ~ 0ms (Thread)
9295
93- self .log .debug ("bms {}" .format (self .bms .data ))
96+ self .bms .update ()
97+ self .log .debug ("bms {}" .format (self .bms .get_state ()))
9498
9599 # ================================================================
96100
@@ -137,38 +141,23 @@ def update_in(self):
137141 else :
138142 self .home_p = None
139143
140- self .soc = dictget (self .bms .data , 'soc' )
141-
142- try :
143- self .soc_low = min (self .bms .data ['soc_pack' ])
144- self .soc_high = max (self .bms .data ['soc_pack' ])
145- except :
146- self .soc_low = None
147- self .soc_high = None
148144
149- self .ubat = dictget (self .bms .data , 'u' )
150145
151146 def fsm_switch (self ):
152147 """
153148 Auto state change by events
154149 """
155- if dictget ( self .bms .data , 'u' , 0 ) > self .config ['udc_max' ]:
156- self .log .error ("error max voltage at bms {}" .format (self .bms .data ))
150+ if self .bms .voltage and self . bms . voltage > self .config ['udc_max' ]:
151+ self .log .error ("error max voltage at bms {}" .format (self .bms .get_state () ))
157152 self .set_fsm_state ('error' )
158- # elif dictget(self.multiplus.data, 'bat_u', 0) > self.config['udc_max']:
159- # self.log.error("error max voltage at multiplus {}".format(self.multiplus.data))
160- # self.set_fsm_state('error')
161- elif dictget (self .bms .data , 't' , 0 ) > self .config ['t_max' ]:
162- self .log .error ("error max bms temperature {}" .format (self .bms .data ))
153+ elif self .bms .temperature and self .bms .temperature > self .config ['t_max' ]:
154+ self .log .error ("error max bms temperature {}" .format (self .bms .get_state ()))
163155 self .set_fsm_state ('error' )
164156 elif not self .is_meterhub_ready ():
165157 self .log .error ("meterhub error {}" .format (self .meterhub .data ))
166158 self .set_fsm_state ('error' )
167- elif not self .is_bms_ready ():
168- self .log .error ("bms not ready {}" .format (self .bms .data ))
169- self .set_fsm_state ('error' )
170- elif self .is_bms_error ():
171- self .log .error ("bms error {}" .format (self .bms .data ))
159+ elif self .bms .error :
160+ self .log .error ("bms error {}" .format (self .bms .get_state ()))
172161 self .set_fsm_state ('error' )
173162 elif not self .is_multiplus_ready ():
174163 self .log .error ("multiplus error {}" .format (self .multiplus .data ))
@@ -192,7 +181,7 @@ def is_charge_start(self):
192181 except :
193182 p = 0
194183
195- if p < self .get_setting ('charge_min_power' ) or self .soc_high > (
184+ if p < self .get_setting ('charge_min_power' ) or self .bms . soc_high is None or self . bms . soc_high > (
196185 self .get_setting ('charge_end_soc' ) - self .get_setting ('charge_hysteresis_soc' )):
197186 self .charge_start_timer .stop ()
198187 else :
@@ -215,7 +204,7 @@ def is_feed_start(self):
215204 except :
216205 p = 0
217206
218- if p < self .get_setting ('feed_min_power' ) or self .soc_low < (
207+ if p < self .get_setting ('feed_min_power' ) or self .bms . soc_low is None or self . bms . soc_low < (
219208 self .get_setting ('feed_end_soc' ) + self .get_setting ('feed_hysteresis_soc' )):
220209 self .feed_start_timer .stop ()
221210 else :
@@ -226,12 +215,6 @@ def is_feed_start(self):
226215 return True
227216 return False
228217
229- def is_bms_error (self ):
230- return True if self .bms .data ['error' ] else False
231-
232- def is_bms_ready (self ):
233- return self .bms .data ['ready' ]
234-
235218 def is_meterhub_ready (self ):
236219 return True if self .meterhub .data and 'error' not in self .meterhub .data else False
237220
@@ -247,16 +230,14 @@ def fsm_init(self, entry):
247230 self .set_p = 0
248231 self .state_timer .start (10 )
249232
250- if self .is_meterhub_ready () and self .is_bms_ready () and self .is_multiplus_ready ():
233+ if self .is_meterhub_ready () and not self .bms . error and self .is_multiplus_ready ():
251234 self .fsm_switch ()
252235
253236 if self .state_timer .is_expired ():
254237 if not self .is_meterhub_ready ():
255238 self .log .error ("meterhub error {}" .format (self .meterhub .data ))
256- if not self .is_bms_ready ():
257- self .log .error ("bms not ready {}" .format (self .bms .data ))
258- if self .is_bms_error ():
259- self .log .error ("bms error {}" .format (self .bms .data ))
239+ if self .bms .error ():
240+ self .log .error ("bms error {}" .format (self .bms .get_state ()))
260241 if not self .is_multiplus_ready ():
261242 self .log .error ("multiplus error={}" .format (self .multiplus .data ))
262243 self .set_fsm_state ('error' )
@@ -323,10 +304,10 @@ def fsm_auto_charge(self, entry):
323304 # ToDo Filter schnell runter, langsam hoch
324305
325306 charge_set_p = limit (p , 0 , self .get_setting ('charge_max_power' )) # limit to 0..max
326- if self .soc_high >= self .get_setting ('charge_end_soc' ): # end by SOC
307+ if self .bms . soc_high and self . bms . soc_high >= self .get_setting ('charge_end_soc' ): # end by SOC
327308 self .log .info ("charge end by soc (config.charge_end_soc)" )
328309 self .set_fsm_state ('auto_idle' )
329- elif self .ubat >= self .get_setting ('charge_end_voltage' ): # end by UDC
310+ elif self .bms . voltage and self . bms . voltage >= self .get_setting ('charge_end_voltage' ): # end by UDC
330311 self .log .info ("charge end by voltage (config.charge_end_voltage)" )
331312 self .set_fsm_state ('auto_idle' )
332313 else :
@@ -356,12 +337,11 @@ def fsm_auto_feed(self, entry):
356337 try :
357338 p = self .home_p - self .pv_p - self .get_setting ('feed_reserve_power' )
358339
359- if self .soc_low <= 25 :
340+ if self .bms . soc_low and self . bms . soc_low <= 25 :
360341 max_p = self .get_setting ('feed_soc25_max_power' )
361342 else :
362343 max_p = self .get_setting ('feed_max_power' )
363344
364-
365345 feed_set_p = limit (p , 0 , max_p ) # limit to 0..max
366346
367347 # ------ throttle --------------
@@ -387,10 +367,10 @@ def fsm_auto_feed(self, entry):
387367 feed_set_p = limit (p , 0 , self .get_setting ('feed_throttle_power' ))
388368 # --------------------------------------------------------------------------------
389369
390- if self .soc_low <= self .get_setting ('feed_end_soc' ): # end by SOC
370+ if self .bms . soc_low and self . bms . soc_low <= self .get_setting ('feed_end_soc' ): # end by SOC
391371 self .log .info ("feed end by soc (config.feed_end_soc)" )
392372 self .set_fsm_state ('auto_idle' )
393- elif self .ubat <= self .get_setting ('feed_end_voltage' ): # end by UDC
373+ elif self .bms . voltage and self . bms . voltage <= self .get_setting ('feed_end_voltage' ): # end by UDC
394374 self .log .info ("feed end by voltage (config.feed_end_voltage)" )
395375 self .set_fsm_state ('auto_idle' )
396376 else :
@@ -457,11 +437,11 @@ def get_state(self, bms_detail=False):
457437 'info' : self .get_info_text ()
458438 },
459439 'meterhub' : self .meterhub .data ,
460- 'bms' : self .bms .data ,
440+ 'bms' : self .bms .get_state () ,
461441 'multiplus' : self .multiplus .data ,
462442 }
463443 if bms_detail :
464- d ['bms_detail' ] = self .bms .data_detail
444+ d ['bms_detail' ] = self .bms .get_detail ()
465445 return d
466446
467447 def get_info_text (self ):
0 commit comments