48
48
# "sensor.sigen_plant_accumulated_grid_import_energy",
49
49
# "sensor.sigen_plant_accumulated_pv_energy",
50
50
# "sigen_plant_accumulated_battery_charge_energy",
51
- "sigen_plant_accumulated_pv_energy"
51
+ "sensor.sigen_plant_accumulated_pv_energy" ,
52
+ # "sensor.sigen_plant_daily_pv_energy",
52
53
]
53
54
54
55
@@ -344,8 +345,12 @@ def calculate_plant_consumed_power(
344
345
# Sanity check
345
346
if consumed_power < 0 :
346
347
_LOGGER .warning (
347
- "[CS][Plant Consumed] Calculated power is negative: %s kW" ,
348
+ "[CS][Plant Consumed] Calculated power is negative: %s kW = %s + %s - %s - %s " ,
348
349
consumed_power ,
350
+ pv_power ,
351
+ grid_import ,
352
+ grid_export ,
353
+ battery_power
349
354
)
350
355
# Keep the negative value as it might be valid in some scenarios
351
356
@@ -487,6 +492,10 @@ def __init__(
487
492
source_entity_id : str = "" ,
488
493
pv_string_idx : Optional [int ] = None ,
489
494
) -> None :
495
+ # Initialize state variables
496
+ self ._state : Decimal | None = None
497
+ self ._last_valid_state : Decimal | None = None
498
+
490
499
"""Initialize the integration sensor."""
491
500
# Call SigenergyEntity's __init__ first
492
501
super ().__init__ (
@@ -512,10 +521,6 @@ def __init__(
512
521
self .log_this_entity = False
513
522
self ._last_coordinator_update = None
514
523
515
- # Initialize state variables
516
- self ._state : Decimal | None = None
517
- self ._last_valid_state : Decimal | None = None
518
-
519
524
# Time tracking variables
520
525
self ._max_sub_interval = (
521
526
None # disable time based integration
@@ -579,14 +584,27 @@ def _update_integral(self, area: Decimal) -> None:
579
584
self .entity_id , area , area_scaled
580
585
)
581
586
582
- self ._last_valid_state = self ._state
587
+ # Only update last_valid_state if we have a valid calculation
588
+ if self ._state is not None and isinstance (self ._state , Decimal ):
589
+ # We only want to save positive values
590
+ if self ._state >= Decimal ('0' ):
591
+ self ._last_valid_state = self ._state
592
+ if self .log_this_entity :
593
+ _LOGGER .debug (
594
+ "[%s] _update_integral - Updated _last_valid_state: %s (state_class: %s)" ,
595
+ self .entity_id ,
596
+ self ._last_valid_state ,
597
+ self .state_class
598
+ )
583
599
584
600
def _setup_midnight_reset (self ) -> None :
585
601
"""Schedule reset at midnight."""
586
602
now = dt_util .now ()
587
- midnight = (now + timedelta (days = 1 )).replace (
588
- hour = 0 , minute = 0 , second = 0 , microsecond = 0
589
- )
603
+ # Calculate last second of the current day (23:59:59)
604
+ midnight = now .replace (hour = 23 , minute = 59 , second = 59 , microsecond = 0 )
605
+ # If we're already past midnight, use tomorrow's date
606
+ if now .hour >= 23 and now .minute >= 59 and now .second >= 59 :
607
+ midnight = (now + timedelta (days = 1 )).replace (hour = 23 , minute = 59 , second = 59 , microsecond = 0 )
590
608
591
609
@callback
592
610
def _handle_midnight (current_time ):
@@ -636,7 +654,8 @@ async def async_added_to_hass(self) -> None:
636
654
init_value_dec = safe_decimal (init_value )
637
655
if init_value_dec is not None :
638
656
restore_value = init_value_dec
639
- _LOGGER .debug ("Saving initial value for %s: %s" , self .entity_id , restore_value )
657
+ if self .log_this_entity :
658
+ _LOGGER .info ("Saving initial value for %s: %s" , self .entity_id , restore_value )
640
659
restored_from_config = True # Mark that we restored from config
641
660
else :
642
661
_LOGGER .warning ("Could not convert init_value '%s' to Decimal for %s" , init_value , self .entity_id )
@@ -664,7 +683,21 @@ async def async_added_to_hass(self) -> None:
664
683
STATE_UNKNOWN ,
665
684
STATE_UNAVAILABLE ,
666
685
):
667
- restore_value = last_state .state
686
+ if self .unit_of_measurement == "MWh" :
687
+ restore_value = str (Decimal (last_state .state ) * 1000 )
688
+ else :
689
+ restore_value = str (Decimal (last_state .state ) * 1 )
690
+ if self .log_this_entity :
691
+ if self .unit_of_measurement == last_state .attributes ["unit_of_measurement" ]:
692
+ _LOGGER .debug ("Both are %s" , self .unit_of_measurement )
693
+ else :
694
+ _LOGGER .debug ("Self is %s and last is %s" , self .unit_of_measurement , last_state .attributes ["unit_of_measurement" ])
695
+
696
+ else :
697
+ _LOGGER .debug (
698
+ "No valid last state available for %s, using default value" ,
699
+ self .entity_id ,
700
+ )
668
701
669
702
if restore_value is not None : # Check if restore_value is not None before trying to use it
670
703
try :
@@ -677,8 +710,20 @@ async def async_added_to_hass(self) -> None:
677
710
self ._last_integration_time = dt_util .utcnow ()
678
711
else :
679
712
_LOGGER .warning ("Could not convert restore value '%s' to Decimal for %s" , restore_value , self .entity_id )
713
+ # Try to use last_valid_state if available as fallback
714
+ if self ._last_valid_state is not None :
715
+ self ._state = self ._last_valid_state
716
+ _LOGGER .debug ("Falling back to last valid state for %s: %s" , self .entity_id , self ._last_valid_state )
680
717
except (ValueError , TypeError , InvalidOperation ) as e :
681
718
_LOGGER .warning ("Could not restore state for %s from value '%s': %s" , self .entity_id , restore_value , e )
719
+ # Try to use last_valid_state if available as fallback
720
+ if self ._last_valid_state is not None :
721
+ self ._state = self ._last_valid_state
722
+ _LOGGER .debug ("Falling back to last valid state for %s: %s" , self .entity_id , self ._last_valid_state )
723
+ elif self ._last_valid_state is not None :
724
+ # If no restore value but we have a last valid state, use that
725
+ self ._state = self ._last_valid_state
726
+ _LOGGER .debug ("Using last valid state for %s: %s" , self .entity_id , self ._last_valid_state )
682
727
else :
683
728
_LOGGER .debug ("No restore value available for %s, state remains uninitialized." , self .entity_id )
684
729
@@ -778,6 +823,9 @@ def _integrate_on_state_change(
778
823
self , old_state : State | None , new_state : State | None
779
824
) -> None :
780
825
"""Perform integration based on state change."""
826
+ if self .log_this_entity :
827
+ _LOGGER .debug ("[_integrate_on_state_change] Starting for %s with old_state: %s, new_state: %s" ,
828
+ self .entity_id , old_state , new_state )
781
829
if new_state is None :
782
830
return
783
831
@@ -805,7 +853,7 @@ def _integrate_on_state_change(
805
853
)
806
854
807
855
# Update the integral
808
- self ._update_integral (area ) # Logging is now inside _update_integral
856
+ self ._update_integral (area )
809
857
810
858
# Write state
811
859
if self .log_this_entity :
0 commit comments