@@ -843,6 +843,121 @@ def test_heating_block_is_still_covered(self):
843843 for number in (223 , 282 ):
844844 assert isinstance (parameters [number ], TimeOfDay ), number
845845
846+ def test_mixing_circuit_3_block_is_covered (self ):
847+ """788-848 is the Mk3 circuit, apart from the 162-667 run.
848+
849+ Same selector + WO/25/TG shape as the others (upstream `main` types
850+ it that way); two corpus units carry 34200 / 18000 (09:30 / 05:00)
851+ in 789, the rest hold 0.
852+ """
853+ from custom_components .luxtronik2 .lux_overrides import (
854+ TimeOfDay ,
855+ TimerProgram ,
856+ )
857+
858+ parameters = self ._applied ()
859+ selector = parameters [788 ]
860+ assert selector .name == "ID_Einst_SuMk3_akt2"
861+ assert isinstance (selector , TimerProgram )
862+ assert selector .from_heatpump (0 ) == "week"
863+ for number in (789 , 848 ):
864+ assert isinstance (parameters [number ], TimeOfDay ), number
865+ assert parameters [789 ].name == "ID_Einst_SuMk3Wo_zeit_0_0"
866+ assert parameters [789 ].from_heatpump (34200 ) == "09:30"
867+ assert parameters [848 ].name == "ID_Einst_SuMk3Tg_zeit_2_13"
868+ # The block is 788-848: 787 (ID_SU_FstdMK3) and 849
869+ # (ID_Ba_Hz_MK3_saved) are not schedule registers.
870+ assert not isinstance (parameters [787 ], TimeOfDay | TimerProgram )
871+ assert not isinstance (parameters [849 ], TimeOfDay | TimerProgram )
872+
873+
874+ class TestUpstreamCelsiusParameters :
875+ """Six limit temperatures upstream `main` types as Celsius (tenths).
876+
877+ All 30 corpus units store plausible tenths (84 at 650-700, 87 at
878+ 350-650, 91 at 350-450, 92 at -200/-220, 94 at 1150-1400, 96 at 500
879+ everywhere), which also matches the setting each one names.
880+ """
881+
882+ _EXPECTED = {
883+ 84 : ("ID_Sollwert_TLG_max" , 700 , 70.0 ),
884+ 87 : ("ID_Einst_TRBegr_akt" , 560 , 56.0 ),
885+ 91 : ("ID_Einst_TAmax_akt" , 350 , 35.0 ),
886+ 92 : ("ID_Einst_TAmin_akt" , - 200 , - 20.0 ),
887+ 94 : ("ID_Einst_THGmax_akt" , 1150 , 115.0 ),
888+ 96 : ("ID_Einst_TV2VDBW_akt" , 500 , 50.0 ),
889+ }
890+
891+ def test_are_celsius_in_tenths (self ):
892+ from luxtronik .datatypes import Celsius
893+ from luxtronik .parameters import Parameters
894+
895+ from custom_components .luxtronik2 .lux_overrides import (
896+ update_Luxtronik_Parameters ,
897+ )
898+
899+ update_Luxtronik_Parameters ()
900+ for number , (name , raw , value ) in self ._EXPECTED .items ():
901+ parameter = Parameters .parameters [number ]
902+ assert parameter .name == name , number
903+ assert isinstance (parameter , Celsius ), number
904+ assert parameter .from_heatpump (raw ) == value , number
905+
906+
907+ class TestUpstreamCounterParameters :
908+ """Operating-time counters and the heat-quantity date, typed as upstream
909+ `main` does. Nothing in the integration reads these registers (the
910+ sensors use the calculation mirrors 56-66); this only makes diagnostics
911+ dumps readable.
912+ """
913+
914+ _SECONDS = {
915+ 668 : "ID_Zaehler_BetrZeitWP" ,
916+ 669 : "ID_Zaehler_BetrZeitVD1" ,
917+ 670 : "ID_Zaehler_BetrZeitVD2" ,
918+ 671 : "ID_Zaehler_BetrZeitZWE1" ,
919+ 672 : "ID_Zaehler_BetrZeitZWE2" ,
920+ 673 : "ID_Zaehler_BetrZeitZWE3" ,
921+ 728 : "ID_Zaehler_BetrZeitHz" ,
922+ 729 : "ID_Zaehler_BetrZeitBW" ,
923+ 730 : "ID_Zaehler_BetrZeitKue" ,
924+ 859 : "ID_Zaehler_BetrZeitSW" ,
925+ }
926+
927+ def _applied (self ):
928+ from luxtronik .parameters import Parameters
929+
930+ from custom_components .luxtronik2 .lux_overrides import (
931+ update_Luxtronik_Parameters ,
932+ )
933+
934+ update_Luxtronik_Parameters ()
935+ return Parameters .parameters
936+
937+ def test_operating_time_counters_are_seconds (self ):
938+ from luxtronik .datatypes import Seconds
939+
940+ parameters = self ._applied ()
941+ for number , name in self ._SECONDS .items ():
942+ assert parameters [number ].name == name , number
943+ assert isinstance (parameters [number ], Seconds ), number
944+ # 60515833 s on one corpus unit, i.e. about 700 days of runtime.
945+ assert parameters [668 ].from_heatpump (60515833 ) == 60515833
946+
947+ def test_heat_quantity_date_is_a_timestamp (self ):
948+ from datetime import date , datetime
949+
950+ from luxtronik .datatypes import Timestamp
951+
952+ parameter = self ._applied ()[880 ]
953+ assert parameter .name == "ID_Waermemenge_Datum"
954+ assert isinstance (parameter , Timestamp )
955+ # Eight corpus units sit on the 2018-01-01 factory default
956+ # (01:00 UTC; the library renders it in the host's local zone).
957+ rendered = parameter .from_heatpump (1514768400 )
958+ assert isinstance (rendered , datetime )
959+ assert rendered .date () in (date (2017 , 12 , 31 ), date (2018 , 1 , 1 ))
960+
846961
847962class TestSmartGridMode :
848963 """P1030 is a four-option mode selector, so it needs a real datatype.
0 commit comments