Skip to content

Commit

Permalink
Make master a slave
Browse files Browse the repository at this point in the history
  • Loading branch information
rgc99 committed Nov 26, 2023
1 parent 87c1ebd commit 67ba23e
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 50 deletions.
71 changes: 27 additions & 44 deletions custom_components/irrigation_unlimited/irrigation_unlimited.py
Original file line number Diff line number Diff line change
Expand Up @@ -1105,6 +1105,15 @@ def __init__(
self._remaining_time: timedelta = self._end_time - self._start_time
self._percent_complete: int = 0
self._status = self._get_status(stime)
self.master_ref: weakref.ReferenceType["IURun"] = None

@property
def master_obj(self) -> "IURun":
"""Return the associated master run"""
# pylint: disable=not-callable
if self.master_ref is not None and self.master_ref() is not None:
return self.master_ref()
return None

@property
def expired(self) -> bool:
Expand Down Expand Up @@ -1450,6 +1459,9 @@ def pop_run(self, index) -> "IURun":
self._next_run = None
if run == self._next_run:
self._next_run = None
if (obj := run.master_obj) is not None:
run.zone.controller.runs.remove_run(obj)
run.master_ref = None
return run

def remove_run(self, run: IURun) -> "IURun":
Expand Down Expand Up @@ -2171,30 +2183,12 @@ def clear_runs(self) -> bool:
# pylint: disable=arguments-differ
return super().clear_runs(True)

def find_run(
self,
start_time: datetime,
zone_run: IURun,
) -> IURun:
"""Find the specified run in the queue"""
for run in self:
if (
start_time == run.start_time
and zone_run.zone == run.zone
and run.schedule is not None
and zone_run.schedule is not None
and run.schedule == zone_run.schedule
):
return run
return None

def add_zone(
self,
stime: datetime,
zone_run: IURun,
preamble: timedelta,
postamble: timedelta,
no_find: bool,
) -> IURun:
"""Add a new master run to the queue"""
start_time = zone_run.start_time
Expand All @@ -2204,20 +2198,15 @@ def add_zone(
duration += preamble
if postamble is not None:
duration += postamble
if not no_find:
run = self.find_run(start_time, zone_run)
else:
run = None
if run is None:
run = self.add(
stime,
start_time,
duration,
zone_run.zone,
zone_run.schedule,
zone_run.sequence_run,
zone_run,
)
run = self.add(
stime,
start_time,
duration,
zone_run.zone,
zone_run.schedule,
zone_run.sequence_run,
zone_run,
)
return run

def rebuild_schedule(
Expand All @@ -2226,19 +2215,17 @@ def rebuild_schedule(
zones: list[IUZone],
preamble: timedelta,
postamble: timedelta,
clear_all: bool,
) -> IURQStatus:
"""Create a superset of all the zones."""
# pylint: disable=too-many-arguments

status = IURQStatus(0)
if clear_all:
self.clear_all()
else:
self.clear_runs()
for zone in zones:
for run in zone.runs:
if not run.expired:
self.add_zone(stime, run, preamble, postamble, clear_all)
if run.master_obj is None:
run.master_ref = weakref.ref(
self.add_zone(stime, run, preamble, postamble)
)
status |= IURQStatus.EXTENDED | IURQStatus.REDUCED
return status

Expand Down Expand Up @@ -3913,9 +3900,8 @@ def muster(self, stime: datetime, force: bool) -> IURQStatus:
| IURQStatus.CANCELED
| IURQStatus.CHANGED
):
clear_all = zone_status.has_any(IURQStatus.CLEARED | IURQStatus.CANCELED)
status |= self._run_queue.rebuild_schedule(
stime, self._zones, self._preamble, self._postamble, clear_all
stime, self._zones, self._preamble, self._postamble
)
status |= self._run_queue.update_queue()

Expand Down Expand Up @@ -4171,7 +4157,6 @@ def s2b(test: bool, service: str) -> bool:
sequence.runs.clear_runs()
sequences_changed = True
if sequences_changed:
self._run_queue.clear_runs()
self.request_update(True)
result = True
return result
Expand Down Expand Up @@ -4205,7 +4190,6 @@ def service_suspend(self, data: MappingProxyType, stime: datetime) -> bool:
sequence.runs.clear_runs()
sequences_changed = True
if sequences_changed:
self._run_queue.clear_runs()
self.request_update(True)
result = True
return result
Expand Down Expand Up @@ -4236,7 +4220,6 @@ def service_adjust_time(self, data: MappingProxyType, stime: datetime) -> bool:
sequence.runs.clear_runs()
sequences_changed = True
if sequences_changed:
self._run_queue.clear_runs()
self.request_update(True)
result = True
return result
Expand Down
38 changes: 32 additions & 6 deletions tests/iu_test_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,14 @@ def check_summary(self, config_file: str = None) -> None:
def check_labyrinth(self) -> None:
"""Check the run integrity between controller, zone and sequence runs"""

def print_run(run: IURun) -> None:
schedule = run.schedule.name if run.schedule else "manual"
print(
f"zone: {run.zone.id1}, "
f"start: {fmt_local(run.start_time)}, "
f"schedule: {schedule}"
)

def check_controller(controller: IUController) -> None:
lst = list(controller.runs)
controller_runs: set[IURun] = set(lst)
Expand Down Expand Up @@ -365,14 +373,32 @@ def check_controller(controller: IUController) -> None:
sqr.symmetric_difference(sequence_runs),
key=lambda run: run.start_time,
):
schedule = run.schedule.name if run.schedule else "manual"
print(
f"zone: {run.zone.id1}, "
f"start: {fmt_local(run.start_time)}, "
f"schedule: {schedule}"
)
print_run(run)
assert False, "Zone and sequence runs not identical"

referred = set(
run.master_obj for run in zone_runs if run.master_obj is not None
)
if controller_runs != referred:
for run in sorted(
referred.symmetric_difference(controller_runs),
key=lambda run: run.start_time,
):
print_run(run)
assert False, "Controller and referred zones runs not identical"

referrer = set(run for run in zone_runs if run.master_obj is not None)
if zone_runs != referrer:
for run in sorted(
referrer.symmetric_difference(zone_runs),
key=lambda run: run.start_time,
):
print_run(run)

assert len(zone_runs) == len(
controller_runs
), f"Controller ({len(controller_runs)}) and zones ({len(zone_runs)}) not identical"

for controller in self._coordinator.controllers:
check_controller(controller)

Expand Down

0 comments on commit 67ba23e

Please sign in to comment.