pyisyox.runtime.program module

Runtime Program and ProgramFolder wrappers.

Programs and program-folders share the controller’s flat program list and the same /rest/programs/{id}/... command surface, but folders only support a subset of commands (typically run / stop / enable / disable). The runtime layer keeps them as separate types so consumers can branch on isinstance instead of a runtime is_folder flag.

State updates flow over the WebSocket: a <control>_1</control> frame with <action>0</action> carries an <eventInfo> body that updates the program’s status, last-run / last-finish times, and running state. The pyisyox.runtime.EventDispatcher owns the parse + apply path; this module just exposes the data shape the dispatcher mutates.

class ProgramCommand(*values)[source]

Bases: StrEnum

Verbs accepted by GET /rest/programs/{id}/{command}.

Members are the camelCase wire strings the eisy expects; consumers building HA-style snake-case service schemas can use the member names (ProgramCommand.RUN_THEN.name == "RUN_THEN") or pull the wire string via .value / direct comparison (StrEnum members compare equal to their underlying string).

Folders only support RUN, STOP, ENABLE, and DISABLEProgram-only verbs raise server-side on a folder target.

RUN

Run the program (or every program under a folder). For programs, evaluates the if-clause and runs the matching branch.

RUN_THEN

Run the program’s then clause directly.

RUN_ELSE

Run the program’s else clause directly.

RUN_IF

Re-evaluate the program’s if condition without running the matching clause’s actions.

STOP

Abort an executing program / folder.

ENABLE

Enable the program / folder for evaluation.

DISABLE

Disable the program / folder (status freezes).

ENABLE_RUN_AT_STARTUP

Mark the program as auto-run on controller boot.

DISABLE_RUN_AT_STARTUP

Clear the auto-run-on-boot flag.

class Program(record, client)[source]

Bases: _ProgramBase

User-facing handle for one program.

Parameters:
property enabled: bool | None

False when the program is disabled. None if the wire payload omitted the field (defensive — every captured program carries it).

property run_at_startup: bool | None

True if the program is set to run on controller boot.

property running: str | None

Raw runtime-state field as the controller reported it.

Two wire shapes: REST /api/programs emits a human label ("idle" / "running then" / "running else"); the WS event stream emits the cookbook <s> byte (two ASCII hex digits). Use run_state / eval_state for a firmware-agnostic typed view.

property run_state: ProgramRunState | None

Typed run-clause state — one of IDLE / THEN / ELSE.

None when the program errored (ProgramEvalState.NOT_LOADED) or the controller hasn’t reported a running field yet.

property eval_state: ProgramEvalState | None

Typed if-clause evaluation state — disambiguates the three “not really True/False” cases that status collapses. None from REST loads (which only carry the run label) and when the controller hasn’t reported a running field yet.

property last_run_time: datetime | None

Tz-aware datetime of the program’s last run start, or None if it has never run.

REST /api/programs emits the timestamp as ISO 8601 UTC ("2026-05-10T14:49:53.000Z"); we parse on read so the wrapper hands consumers a real datetime rather than the wire string. The raw form remains accessible via self._record.last_run_time for diagnostics / round-trip.

property last_finish_time: datetime | None

Tz-aware datetime of the program’s last run completion, or None.

property next_scheduled_run_time: datetime | None

Tz-aware datetime of the next scheduled run, or None for manual-only programs.

async run_then()[source]

Run the program’s then clause.

Wire: GET /rest/programs/{id}/runThen.

Return type:

None

async run_else()[source]

Run the program’s else clause.

Return type:

None

async run_if()[source]

Re-evaluate the program’s if condition (without running the matching clause’s actions).

Return type:

None

async enable_run_at_startup()[source]

Mark the program as auto-run on controller boot.

Return type:

None

async disable_run_at_startup()[source]

Clear the auto-run-on-boot flag.

Return type:

None

class ProgramFolder(record, client)[source]

Bases: _ProgramBase

Organisational container for programs.

Folders share the program command surface but only run / stop / enable / disable are documented to apply. The eisy aggregates child status into status server-side.

Parameters: