@@ -21,17 +21,13 @@ class EnergyType(Enum):
2121 PRODUCTION_HOUR = auto ()
2222 CONSUMPTION_DAY = auto ()
2323 PRODUCTION_DAY = auto ()
24- CONSUMPTION_WEEK = auto ()
25- PRODUCTION_WEEK = auto ()
2624
2725
2826ENERGY_COUNTERS : Final = (
2927 EnergyType .CONSUMPTION_HOUR ,
3028 EnergyType .PRODUCTION_HOUR ,
3129 EnergyType .CONSUMPTION_DAY ,
3230 EnergyType .PRODUCTION_DAY ,
33- EnergyType .CONSUMPTION_WEEK ,
34- EnergyType .PRODUCTION_WEEK ,
3531)
3632ENERGY_HOUR_COUNTERS : Final = (
3733 EnergyType .CONSUMPTION_HOUR ,
@@ -41,20 +37,13 @@ class EnergyType(Enum):
4137 EnergyType .CONSUMPTION_DAY ,
4238 EnergyType .PRODUCTION_DAY ,
4339)
44- ENERGY_WEEK_COUNTERS : Final = (
45- EnergyType .CONSUMPTION_WEEK ,
46- EnergyType .PRODUCTION_WEEK ,
47- )
48-
4940ENERGY_CONSUMPTION_COUNTERS : Final = (
5041 EnergyType .CONSUMPTION_HOUR ,
5142 EnergyType .CONSUMPTION_DAY ,
52- EnergyType .CONSUMPTION_WEEK ,
5343)
5444ENERGY_PRODUCTION_COUNTERS : Final = (
5545 EnergyType .PRODUCTION_HOUR ,
5646 EnergyType .PRODUCTION_DAY ,
57- EnergyType .PRODUCTION_WEEK ,
5847)
5948
6049_LOGGER = logging .getLogger (__name__ )
@@ -105,11 +94,8 @@ def add_pulse_stats(
10594 self , pulses_consumed : int , pulses_produced : int , timestamp : datetime
10695 ) -> None :
10796 """Add pulse statistics."""
108- _LOGGER .debug (
109- "add_pulse_stats | consumed=%s, for %s" ,
110- str (pulses_consumed ),
111- self ._mac ,
112- )
97+ _LOGGER .debug ("add_pulse_stats for %s with timestamp=%s" , self ._mac , timestamp )
98+ _LOGGER .debug ("consumed=%s | produced=%s" , pulses_consumed , pulses_produced )
11399 self ._pulse_collection .update_pulse_counter (
114100 pulses_consumed , pulses_produced , timestamp
115101 )
@@ -160,9 +146,6 @@ def update(self) -> None:
160146 self ._energy_statistics .log_interval_consumption = (
161147 self ._pulse_collection .log_interval_consumption
162148 )
163- self ._energy_statistics .log_interval_production = (
164- self ._pulse_collection .log_interval_production
165- )
166149 (
167150 self ._energy_statistics .hour_consumption ,
168151 self ._energy_statistics .hour_consumption_reset ,
@@ -171,23 +154,18 @@ def update(self) -> None:
171154 self ._energy_statistics .day_consumption ,
172155 self ._energy_statistics .day_consumption_reset ,
173156 ) = self ._counters [EnergyType .CONSUMPTION_DAY ].update (self ._pulse_collection )
174- (
175- self ._energy_statistics .week_consumption ,
176- self ._energy_statistics .week_consumption_reset ,
177- ) = self ._counters [EnergyType .CONSUMPTION_WEEK ].update (self ._pulse_collection )
178-
179- (
180- self ._energy_statistics .hour_production ,
181- self ._energy_statistics .hour_production_reset ,
182- ) = self ._counters [EnergyType .PRODUCTION_HOUR ].update (self ._pulse_collection )
183- (
184- self ._energy_statistics .day_production ,
185- self ._energy_statistics .day_production_reset ,
186- ) = self ._counters [EnergyType .PRODUCTION_DAY ].update (self ._pulse_collection )
187- (
188- self ._energy_statistics .week_production ,
189- self ._energy_statistics .week_production_reset ,
190- ) = self ._counters [EnergyType .PRODUCTION_WEEK ].update (self ._pulse_collection )
157+ if self ._pulse_collection .production_logging :
158+ self ._energy_statistics .log_interval_production = (
159+ self ._pulse_collection .log_interval_production
160+ )
161+ (
162+ self ._energy_statistics .hour_production ,
163+ self ._energy_statistics .hour_production_reset ,
164+ ) = self ._counters [EnergyType .PRODUCTION_HOUR ].update (self ._pulse_collection )
165+ (
166+ self ._energy_statistics .day_production ,
167+ self ._energy_statistics .day_production_reset ,
168+ ) = self ._counters [EnergyType .PRODUCTION_DAY ].update (self ._pulse_collection )
191169
192170 @property
193171 def timestamp (self ) -> datetime | None :
@@ -211,14 +189,13 @@ def __init__(
211189 ) -> None :
212190 """Initialize energy counter based on energy id."""
213191 self ._mac = mac
192+ self ._midnight_reset_passed = False
214193 if energy_id not in ENERGY_COUNTERS :
215194 raise EnergyError (f"Invalid energy id '{ energy_id } ' for Energy counter" )
216195 self ._calibration : EnergyCalibration | None = None
217196 self ._duration = "hour"
218197 if energy_id in ENERGY_DAY_COUNTERS :
219198 self ._duration = "day"
220- elif energy_id in ENERGY_WEEK_COUNTERS :
221- self ._duration = "week"
222199 self ._energy_id : EnergyType = energy_id
223200 self ._is_consumption = True
224201 self ._direction = "consumption"
@@ -259,9 +236,16 @@ def energy(self) -> float | None:
259236 """Total energy (in kWh) since last reset."""
260237 if self ._pulses is None or self ._calibration is None :
261238 return None
239+
262240 if self ._pulses == 0 :
263241 return 0.0
264- pulses_per_s = self ._pulses / float (HOUR_IN_SECONDS )
242+
243+ # Handle both positive and negative pulses values
244+ negative = False
245+ if self ._pulses < 0 :
246+ negative = True
247+
248+ pulses_per_s = abs (self ._pulses ) / float (HOUR_IN_SECONDS )
265249 corrected_pulses = HOUR_IN_SECONDS * (
266250 (
267251 (
@@ -276,8 +260,9 @@ def energy(self) -> float | None:
276260 + self ._calibration .off_tot
277261 )
278262 calc_value = corrected_pulses / PULSES_PER_KW_SECOND / HOUR_IN_SECONDS
279- # Guard for minor negative miscalculations
280- calc_value = max (calc_value , 0.0 )
263+ if negative :
264+ calc_value = - calc_value
265+
281266 return calc_value
282267
283268 @property
@@ -297,16 +282,21 @@ def update(
297282 last_reset = datetime .now (tz = LOCAL_TIMEZONE )
298283 if self ._energy_id in ENERGY_HOUR_COUNTERS :
299284 last_reset = last_reset .replace (minute = 0 , second = 0 , microsecond = 0 )
300- elif self ._energy_id in ENERGY_DAY_COUNTERS :
301- last_reset = last_reset .replace (hour = 0 , minute = 0 , second = 0 , microsecond = 0 )
302- elif self ._energy_id in ENERGY_WEEK_COUNTERS :
303- last_reset = last_reset - timedelta (days = last_reset .weekday ())
304- last_reset = last_reset .replace (
305- hour = 0 ,
306- minute = 0 ,
307- second = 0 ,
308- microsecond = 0 ,
309- )
285+ if self ._energy_id in ENERGY_DAY_COUNTERS :
286+ # Postpone the last_reset time-changes at day-end until a device pulsecounter resets
287+ if last_reset .hour == 0 and (
288+ not pulse_collection .pulse_counter_reset
289+ and not self ._midnight_reset_passed
290+ ):
291+ last_reset = (last_reset - timedelta (days = 1 )).replace (
292+ hour = 0 , minute = 0 , second = 0 , microsecond = 0
293+ )
294+ else :
295+ if last_reset .hour == 0 and pulse_collection .pulse_counter_reset :
296+ self ._midnight_reset_passed = True
297+ if last_reset .hour == 1 and self ._midnight_reset_passed :
298+ self ._midnight_reset_passed = False
299+ last_reset = last_reset .replace (hour = 0 , minute = 0 , second = 0 , microsecond = 0 )
310300
311301 pulses , last_update = pulse_collection .collected_pulses (
312302 last_reset , self ._is_consumption
@@ -324,5 +314,6 @@ def update(
324314 self ._pulses = pulses
325315
326316 energy = self .energy
327- _LOGGER .debug ("energy=%s or last_update=%s" , energy , last_update )
317+ _LOGGER .debug ("energy=%s on last_update=%s" , energy , last_update )
328318 return (energy , last_reset )
319+
0 commit comments