@@ -79,6 +79,13 @@ def __init__(self, device_data: dict, api_interface: "ThermiaAPI"):
7979
8080 self .__register_indexes = DEFAULT_REGISTER_INDEXES
8181
82+ # Precalculated data so it does not have to be updated
83+
84+ self .__operational_statuses = None
85+ self .__all_operational_statuses_map = None
86+ self .__visible_operational_statuses_map = None
87+ self .__running_operational_statuses = None
88+
8289 self .update_data ()
8390
8491 def update_data (self ):
@@ -106,6 +113,18 @@ def update_data(self):
106113
107114 self .__alarms = self .__api_interface .get_all_alarms (self .__device_id )
108115
116+ # Precalculate data (order is important)
117+ self .__operational_statuses = (
118+ self .__get_operational_statuses_from_operational_status ()
119+ )
120+ self .__all_operational_statuses_map = (
121+ self .__get_all_operational_statuses_from_operational_status ()
122+ )
123+ self .__visible_operational_statuses_map = (
124+ self .__get_all_visible_operational_statuses_from_operational_status ()
125+ )
126+ self .__running_operational_statuses = self .__get_running_operational_statuses ()
127+
109128 def get_register_indexes (self ):
110129 return self .__register_indexes
111130
@@ -318,7 +337,7 @@ def __set_historical_data_registers(self):
318337
319338 def __get_register_from_operational_status (
320339 self , register_name : str
321- ) -> Optional [dict ]:
340+ ) -> Optional [Dict ]:
322341 data = [
323342 d
324343 for d in self .__group_operational_status or []
@@ -403,23 +422,100 @@ def __get_operational_statuses_from_operational_status(self) -> Optional[Dict]:
403422 def __get_all_operational_statuses_from_operational_status (
404423 self ,
405424 ) -> Optional [ChainMap ]:
406- data = self .__get_operational_statuses_from_operational_status ()
425+ data = self .__operational_statuses
407426
408427 if data is None :
409- return None
428+ return ChainMap ()
410429
411430 operation_modes_map = map (
412431 lambda values : {
413- values .get ("value" ): values .get ("name" ).split (
414- self .__device_config ["operational_status_valueNamePrefix" ]
415- )[1 ],
432+ values .get ("value" ): {
433+ "name" : values .get ("name" ).split (
434+ self .__device_config ["operational_status_valueNamePrefix" ]
435+ )[1 ],
436+ "visible" : values .get ("visible" ),
437+ }
416438 },
417439 data ,
418440 )
419441
420442 operation_modes_list = list (operation_modes_map )
421443 return ChainMap (* operation_modes_list )
422444
445+ def __get_all_visible_operational_statuses_from_operational_status (
446+ self ,
447+ ) -> Optional [ChainMap ]:
448+ data = self .__all_operational_statuses_map
449+
450+ if data is None :
451+ return ChainMap ()
452+
453+ operation_modes_map = map (
454+ lambda item : {item [0 ]: item [1 ].get ("name" )}
455+ if item [1 ].get ("visible" )
456+ else {},
457+ data .items (),
458+ )
459+
460+ operation_modes_list = list (filter (lambda x : x != {}, operation_modes_map ))
461+ return ChainMap (* operation_modes_list )
462+
463+ def __get_running_operational_statuses (
464+ self ,
465+ ) -> List [str ]:
466+ if self .__device_config ["operational_status_register" ] is None :
467+ return []
468+
469+ data = self .__get_register_from_operational_status (
470+ self .__device_config ["operational_status_register" ]
471+ )
472+
473+ if data is None :
474+ return []
475+
476+ current_register_value = get_dict_value_or_none (data , "registerValue" )
477+
478+ data = self .__all_operational_statuses_map
479+
480+ if data is None :
481+ return []
482+
483+ data_items_list = list (data .items ())
484+
485+ current_operation_mode = [
486+ value .name
487+ for key , value in data_items_list
488+ if key == current_register_value
489+ ]
490+
491+ if len (current_operation_mode ) == 1 :
492+ return current_operation_mode
493+
494+ if (
495+ len (current_operation_mode ) != 1
496+ and current_register_value > 0
497+ and len (data_items_list ) > 1
498+ ):
499+ # Attempt to get multiple statuses by binary sum of the values
500+ data_items_list .sort (key = lambda x : x [0 ], reverse = True )
501+ list_of_current_operation_modes = []
502+
503+ if self .__device_config ["operational_status_minRegisterValue" ] is not None :
504+ current_register_value -= int (
505+ self .__device_config ["operational_status_minRegisterValue" ]
506+ )
507+
508+ for key , value in data_items_list :
509+ if key <= current_register_value :
510+ current_register_value -= key
511+ if value .get ("visible" ):
512+ list_of_current_operation_modes .append (value .get ("name" ))
513+
514+ if current_register_value == 0 :
515+ return list_of_current_operation_modes
516+
517+ return []
518+
423519 @property
424520 def name (self ):
425521 return get_dict_value_or_none (self .__info , "name" )
@@ -576,65 +672,17 @@ def cooling_supply_line_temperature(self):
576672 ###########################################################################
577673
578674 @property
579- def operational_status (self ) -> Optional [Union [str , List [str ]]]:
580- if self .__device_config ["operational_status_register" ] is None :
581- # Attempt to get the register from the status data
582- self .__get_operational_statuses_from_operational_status ()
583- if self .__device_config ["operational_status_register" ] is None :
584- return None
585-
586- data = self .__get_register_from_operational_status (
587- self .__device_config ["operational_status_register" ]
588- )
675+ def running_operational_statuses (self ) -> List [str ]:
676+ data = self .__running_operational_statuses
589677
590678 if data is None :
591- return None
592-
593- current_register_value = get_dict_value_or_none (data , "registerValue" )
594-
595- data = self .__get_all_operational_statuses_from_operational_status ()
596-
597- if data is None :
598- return None
599-
600- data_items_list = list (data .items ())
601-
602- current_operation_mode = [
603- name for value , name in data_items_list if value == current_register_value
604- ]
605-
606- if len (current_operation_mode ) == 0 :
607- return None
608-
609- if (
610- len (current_operation_mode ) != 1
611- and current_register_value > 0
612- and len (data_items_list ) > 1
613- ):
614- # Attempt to get multiple statuses by binary sum of the values
615- data_items_list .sort (key = lambda x : x [0 ], reverse = True )
616- list_of_current_operation_modes = []
617-
618- if self .__device_config ["operational_status_minRegisterValue" ] is not None :
619- current_register_value -= int (
620- self .__device_config ["operational_status_minRegisterValue" ]
621- )
622-
623- for value , name in data_items_list :
624- if value <= current_register_value :
625- current_register_value -= value
626- list_of_current_operation_modes .append (name )
627-
628- if current_register_value == 0 :
629- return list_of_current_operation_modes
630-
631- return None
679+ return []
632680
633- return current_operation_mode [ 0 ]
681+ return data
634682
635683 @property
636684 def available_operational_statuses (self ) -> Optional [List [str ]]:
637- data = self .__get_all_operational_statuses_from_operational_status ()
685+ data = self .__visible_operational_statuses_map
638686
639687 if data is None :
640688 return []
@@ -643,7 +691,7 @@ def available_operational_statuses(self) -> Optional[List[str]]:
643691
644692 @property
645693 def available_operational_statuses_map (self ) -> Optional [ChainMap ]:
646- return self .__get_all_operational_statuses_from_operational_status ()
694+ return self .__visible_operational_statuses_map
647695
648696 @property
649697 def operational_status_auxiliary_heater_3kw (self ):
@@ -677,39 +725,27 @@ def operational_status_auxiliary_heater_15kw(self):
677725
678726 @property
679727 def operational_status_compressor_status (self ):
680- return self .__get_value_by_key_and_register_name_from_operational_status (
681- "COMP_STATUS" , "COMP_VALUE_COMPR"
682- )
728+ return "COMPR" in self .running_operational_statuses
683729
684730 @property
685731 def operational_status_brine_pump_status (self ):
686- return self .__get_value_by_key_and_register_name_from_operational_status (
687- "COMP_STATUS" , "COMP_VALUE_BRINEPUMP"
688- )
732+ return "BRINEPUMP" in self .running_operational_statuses
689733
690734 @property
691735 def operational_status_radiator_pump_status (self ):
692- return self .__get_value_by_key_and_register_name_from_operational_status (
693- "COMP_STATUS" , "COMP_VALUE_RADIATORPUMP"
694- )
736+ return "RADIATORPUMP" in self .running_operational_statuses
695737
696738 @property
697739 def operational_status_cooling_status (self ):
698- return self .__get_value_by_key_and_register_name_from_operational_status (
699- "COMP_STATUS" , "COMP_VALUE_COOLING"
700- )
740+ return "COOLING" in self .running_operational_statuses
701741
702742 @property
703743 def operational_status_hot_water_status (self ):
704- return self .__get_value_by_key_and_register_name_from_operational_status (
705- "COMP_STATUS" , "COMP_VALUE_HOT_WATER"
706- )
744+ return "HOT_WATER" in self .running_operational_statuses
707745
708746 @property
709747 def operational_status_heating_status (self ):
710- return self .__get_value_by_key_and_register_name_from_operational_status (
711- "COMP_STATUS" , "COMP_VALUE_HEATING"
712- )
748+ return "HEATING" in self .running_operational_statuses
713749
714750 @property
715751 def operational_status_integral (self ):
@@ -790,11 +826,6 @@ def is_operation_mode_read_only(self):
790826 # Hot water data
791827 ###########################################################################
792828
793- # TODO: DEPRECATED, remove in next major release
794- @property
795- def is_hot_water_switch_available (self ):
796- return self .__group_hot_water is not None
797-
798829 @property
799830 def hot_water_switch_state (self ) -> Optional [int ]:
800831 return self .__group_hot_water ["hot_water_switch" ]
0 commit comments