@@ -624,6 +624,8 @@ async def write_time_windows_if_changed(self, inverter_sn):
624624 current_cid = SOLIS_CID_DISCHARGE_CURRENT [slot - 1 ]
625625 max_discharge_current_amps = min (self .cached_infos .get (inverter_sn , {}).get (current_cid , {}).get ('sysCommand' , {}).get ('max' , max_discharge_current_amps ), max_discharge_current_amps )
626626
627+ # Prep: extract active currents from slot 1 and zero out times for disabled slots
628+ # so that the two-pass write below has clean data to compare against.
627629 for slot in slots_to_check :
628630 slot_data = time_windows .get (slot )
629631 if not slot_data :
@@ -634,80 +636,123 @@ async def write_time_windows_if_changed(self, inverter_sn):
634636 charge_current = slot_data .get ("charge_current" , charge_current )
635637 discharge_current = slot_data .get ("discharge_current" , discharge_current )
636638
637- # Check and write charge enable if changed
638- if "charge_enable" in slot_data :
639+ # When a slot is disabled, zero out its times so the inverter shows a clean 00:00-00:00
640+ if not slot_data .get ("charge_enable" , 0 ):
641+ slot_data ["charge_start_time" ] = "00:00"
642+ slot_data ["charge_end_time" ] = "00:00"
643+ if not slot_data .get ("discharge_enable" , 0 ):
644+ slot_data ["discharge_start_time" ] = "00:00"
645+ slot_data ["discharge_end_time" ] = "00:00"
646+
647+ # Pass 1: Clear all disabled slots first.
648+ # This prevents stale times on the inverter from blocking active-slot writes due to overlap conflicts.
649+ for slot in slots_to_check :
650+ slot_data = time_windows .get (slot )
651+ if not slot_data :
652+ continue
653+
654+ if not slot_data .get ("charge_enable" , 0 ):
639655 enable_cid = SOLIS_CID_CHARGE_ENABLE_BASE + (slot - 1 )
640- new_enable_str = str (int (slot_data ['charge_enable' ]))
641656 cached_enable = self .cached_values .get (inverter_sn , {}).get (enable_cid )
642- if cached_enable != new_enable_str :
643- result = await self .read_and_write_cid (inverter_sn , enable_cid , new_enable_str , field_description = f"charge slot { slot } enable" )
657+ if cached_enable != "0" :
658+ result = await self .read_and_write_cid (inverter_sn , enable_cid , "0" , field_description = f"charge slot { slot } enable" )
644659 success &= result
645-
646- # Check and write charge time if changed
647- if "charge_start_time" in slot_data and "charge_end_time" in slot_data :
648660 time_cid = SOLIS_CID_CHARGE_TIME [slot - 1 ]
649- new_time_str = f"{ slot_data ['charge_start_time' ]} -{ slot_data ['charge_end_time' ]} "
650661 cached_time = self .cached_values .get (inverter_sn , {}).get (time_cid )
651- if cached_time != new_time_str :
652- result = await self .read_and_write_cid (inverter_sn , time_cid , new_time_str , field_description = f"charge slot { slot } time" )
653- success &= result
654-
655- # Check and write charge SOC if changed
656- if "charge_soc" in slot_data :
657- soc_cid = SOLIS_CID_CHARGE_SOC_BASE + (slot - 1 )
658- new_soc_str = str (int (slot_data ['charge_soc' ]))
659- cached_soc = self .cached_values .get (inverter_sn , {}).get (soc_cid )
660- if cached_soc != new_soc_str :
661- result = await self .read_and_write_cid (inverter_sn , soc_cid , new_soc_str , field_description = f"charge slot { slot } SOC" )
662+ if cached_time != "00:00-00:00" :
663+ result = await self .read_and_write_cid (inverter_sn , time_cid , "00:00-00:00" , field_description = f"charge slot { slot } time" )
662664 success &= result
663665
664- # Check and write charge current if changed
665- if "charge_current" in slot_data :
666- current_cid = SOLIS_CID_CHARGE_CURRENT [slot - 1 ]
667- new_current = float (slot_data ['charge_current' ])
668- new_current = min (new_current , max_charge_current_amps )
669- cached_current = float (self .cached_values .get (inverter_sn , {}).get (current_cid , max_charge_current_amps ))
670- if round (cached_current , 1 ) != round (new_current , 1 ):
671- result = await self .read_and_write_cid (inverter_sn , current_cid , new_current , field_description = f"charge slot { slot } current" )
672- success &= result
673-
674- # Check and write discharge enable if changed
675- if "discharge_enable" in slot_data :
666+ if not slot_data .get ("discharge_enable" , 0 ):
676667 enable_cid = SOLIS_CID_DISCHARGE_ENABLE_BASE + (slot - 1 )
677- new_enable_str = str (int (slot_data ['discharge_enable' ]))
678668 cached_enable = self .cached_values .get (inverter_sn , {}).get (enable_cid )
679- if cached_enable != new_enable_str :
680- result = await self .read_and_write_cid (inverter_sn , enable_cid , new_enable_str , field_description = f"discharge slot { slot } enable" )
669+ if cached_enable != "0" :
670+ result = await self .read_and_write_cid (inverter_sn , enable_cid , "0" , field_description = f"discharge slot { slot } enable" )
681671 success &= result
682-
683- # Check and write discharge time if changed
684- if "discharge_start_time" in slot_data and "discharge_end_time" in slot_data :
685672 time_cid = SOLIS_CID_DISCHARGE_TIME [slot - 1 ]
686- new_time_str = f"{ slot_data ['discharge_start_time' ]} -{ slot_data ['discharge_end_time' ]} "
687673 cached_time = self .cached_values .get (inverter_sn , {}).get (time_cid )
688- if cached_time != new_time_str :
689- result = await self .read_and_write_cid (inverter_sn , time_cid , new_time_str , field_description = f"discharge slot { slot } time" )
674+ if cached_time != "00:00-00:00" :
675+ result = await self .read_and_write_cid (inverter_sn , time_cid , "00:00-00:00" , field_description = f"discharge slot { slot } time" )
690676 success &= result
691677
692- # Check and write discharge SOC if changed
693- if "discharge_soc" in slot_data :
694- soc_cid = SOLIS_CID_DISCHARGE_SOC [slot - 1 ]
695- new_soc_str = str (int (slot_data ['discharge_soc' ]))
696- cached_soc = self .cached_values .get (inverter_sn , {}).get (soc_cid )
697- if cached_soc != new_soc_str :
698- result = await self .read_and_write_cid (inverter_sn , soc_cid , new_soc_str , field_description = f"discharge slot { slot } SOC" )
678+ # Pass 2: Write active slot settings (enable, time, SOC, current).
679+ # By this point all disabled slots should have been cleared on the inverter,
680+ # so there is no risk of a time-overlap rejection from the API.
681+ for slot in slots_to_check :
682+ slot_data = time_windows .get (slot )
683+ if not slot_data :
684+ continue
685+
686+ if slot_data .get ("charge_enable" , 0 ):
687+ # Check and write charge enable if changed
688+ enable_cid = SOLIS_CID_CHARGE_ENABLE_BASE + (slot - 1 )
689+ cached_enable = self .cached_values .get (inverter_sn , {}).get (enable_cid )
690+ if cached_enable != "1" :
691+ result = await self .read_and_write_cid (inverter_sn , enable_cid , "1" , field_description = f"charge slot { slot } enable" )
699692 success &= result
700693
701- # Check and write discharge current if changed
702- if "discharge_current" in slot_data :
703- current_cid = SOLIS_CID_DISCHARGE_CURRENT [slot - 1 ]
704- new_current = float (slot_data ['discharge_current' ])
705- new_current = min (new_current , max_discharge_current_amps )
706- cached_current = float (self .cached_values .get (inverter_sn , {}).get (current_cid , max_discharge_current_amps ))
707- if round (cached_current , 1 ) != round (new_current , 1 ):
708- result = await self .read_and_write_cid (inverter_sn , current_cid , new_current , field_description = f"discharge slot { slot } current" )
694+ # Check and write charge time if changed
695+ if "charge_start_time" in slot_data and "charge_end_time" in slot_data :
696+ time_cid = SOLIS_CID_CHARGE_TIME [slot - 1 ]
697+ new_time_str = f"{ slot_data ['charge_start_time' ]} -{ slot_data ['charge_end_time' ]} "
698+ cached_time = self .cached_values .get (inverter_sn , {}).get (time_cid )
699+ if cached_time != new_time_str :
700+ result = await self .read_and_write_cid (inverter_sn , time_cid , new_time_str , field_description = f"charge slot { slot } time" )
701+ success &= result
702+
703+ # Check and write charge SOC if changed
704+ if "charge_soc" in slot_data :
705+ soc_cid = SOLIS_CID_CHARGE_SOC_BASE + (slot - 1 )
706+ new_soc_str = str (int (slot_data ['charge_soc' ]))
707+ cached_soc = self .cached_values .get (inverter_sn , {}).get (soc_cid )
708+ if cached_soc != new_soc_str :
709+ result = await self .read_and_write_cid (inverter_sn , soc_cid , new_soc_str , field_description = f"charge slot { slot } SOC" )
710+ success &= result
711+
712+ # Check and write charge current if changed
713+ if "charge_current" in slot_data :
714+ current_cid = SOLIS_CID_CHARGE_CURRENT [slot - 1 ]
715+ new_current = min (float (slot_data ['charge_current' ]), max_charge_current_amps )
716+ cached_current = float (self .cached_values .get (inverter_sn , {}).get (current_cid , max_charge_current_amps ))
717+ if round (cached_current , 1 ) != round (new_current , 1 ):
718+ result = await self .read_and_write_cid (inverter_sn , current_cid , new_current , field_description = f"charge slot { slot } current" )
719+ success &= result
720+
721+ if slot_data .get ("discharge_enable" , 0 ):
722+ # Check and write discharge enable if changed
723+ enable_cid = SOLIS_CID_DISCHARGE_ENABLE_BASE + (slot - 1 )
724+ cached_enable = self .cached_values .get (inverter_sn , {}).get (enable_cid )
725+ if cached_enable != "1" :
726+ result = await self .read_and_write_cid (inverter_sn , enable_cid , "1" , field_description = f"discharge slot { slot } enable" )
709727 success &= result
710728
729+ # Check and write discharge time if changed
730+ if "discharge_start_time" in slot_data and "discharge_end_time" in slot_data :
731+ time_cid = SOLIS_CID_DISCHARGE_TIME [slot - 1 ]
732+ new_time_str = f"{ slot_data ['discharge_start_time' ]} -{ slot_data ['discharge_end_time' ]} "
733+ cached_time = self .cached_values .get (inverter_sn , {}).get (time_cid )
734+ if cached_time != new_time_str :
735+ result = await self .read_and_write_cid (inverter_sn , time_cid , new_time_str , field_description = f"discharge slot { slot } time" )
736+ success &= result
737+
738+ # Check and write discharge SOC if changed
739+ if "discharge_soc" in slot_data :
740+ soc_cid = SOLIS_CID_DISCHARGE_SOC [slot - 1 ]
741+ new_soc_str = str (int (slot_data ['discharge_soc' ]))
742+ cached_soc = self .cached_values .get (inverter_sn , {}).get (soc_cid )
743+ if cached_soc != new_soc_str :
744+ result = await self .read_and_write_cid (inverter_sn , soc_cid , new_soc_str , field_description = f"discharge slot { slot } SOC" )
745+ success &= result
746+
747+ # Check and write discharge current if changed
748+ if "discharge_current" in slot_data :
749+ current_cid = SOLIS_CID_DISCHARGE_CURRENT [slot - 1 ]
750+ new_current = min (float (slot_data ['discharge_current' ]), max_discharge_current_amps )
751+ cached_current = float (self .cached_values .get (inverter_sn , {}).get (current_cid , max_discharge_current_amps ))
752+ if round (cached_current , 1 ) != round (new_current , 1 ):
753+ result = await self .read_and_write_cid (inverter_sn , current_cid , new_current , field_description = f"discharge slot { slot } current" )
754+ success &= result
755+
711756 # Decide if Solar charges the batter or exports
712757 if charge_current == 0 :
713758 self .log (f"Solis API: Charge current is 0A for { inverter_sn } , setting storage mode to 'Feed-in priority'" )
0 commit comments