Skip to content

Scheduler

Direct Connect Bridge. Mirrors the Modbus Bridge page Scheduler section for section, so the two bridges can be compared page by page.

Back to the guide index

The Scheduler is the bridge's automation engine. Each schedule says when its window opens, whether conditions allow it to act, what to send, which gateway to send it to and when to stop. The bridge checks every schedule every 15 seconds (by default), per gateway, against the values the poller last read.

You find it on the Scheduler tab. It has three views: Schedules (the cards), Timeline and History.

A force command takes the battery out of its own mode

Force charge / discharge / standby writes a SunSpec power setpoint through the Modbus client (this bridge) to the Modbus TCP Server (aGate :502). That overrides the aGate's own mode until the bridge releases it. The aGate does not end a force by itself: the bridge's timer and the window's end do (see Exit and release).

Pages in this section

Page What it covers
Concepts The model (trigger → conditions → action → gateway → exit → outcome), the tick, by time / by event / by sensor. Start here.
Triggers Every trigger type, calendar restrictions, Next, what happens to a window that is missed.
Conditions Operators, Value vs Lookup, groups (ALL/ANY), scope, hold, Test, every sensor.
Actions Battery actions, mode, reserve, off-grid and circuits, HA-only schedules, Home Assistant actions and notifications.
Targets Bound and unbound schedules, the default gateway, gateway_scope all.
Exit and release How a window ends, End early when…, release, restore on exit.
Priorities and conflicts Which schedule gets a resource, If busy, manual control.
Outcomes and audit History, runs, retries, the dispatch record, Run now, Stop, Pause and Resume.
Restarts and the clock What a restart does, the site clock, daylight saving.
Dependencies and troubleshooting What each condition and action needs; fixes for "never fires", "always false", "does nothing".
Examples Worked recipes.

What these pages are based on

The scheduler pages describe the code of this release. Many behaviours have no automated test yet; the Scheduler test plan lists each one with its test status, the Scheduler parity page compares each with the Modbus Bridge, and the pages flag the known problems in warning boxes.

Your first schedule

This walkthrough discharges the battery on weekday evenings, but only if it has charge to spare, and stops at your minimum discharge SoC.

Force commands need the Modbus client (this bridge)

Force charge / discharge / standby goes through the Modbus client (this bridge) to the Modbus TCP Server (aGate :502). If the Modbus client (this bridge) is off, the action is listed as unavailable, with the reason. To try the Scheduler without it, use the Set operating mode action instead.

Add schedule: trigger, battery action, priority, If busy, gateway, entry conditions, hold and exit conditions

  1. On the Scheduler tab, press Add schedule.
  2. Name: Evening discharge.
  3. Trigger type: Weekly at time. Under Days, tick Mon to Fri (none ticked means every day). Set Fire at to 17:00 and Duration (min) to 180.
  4. Battery action: Force charge / discharge / standby. Set Direction to Force discharge, Power unit to % of inverter power, and Power to 50. Leave Target SoC empty.
  5. Leave Priority at 0, If busy at override and the gateway at Default gateway (the picker appears only with more than one gateway).
  6. Entry conditions (must hold to fire): press + row. Pick Battery SoC (%), operator >, value 40.
  7. End early when…: press + row. Pick Battery SoC (%), operator <=, press Lookup, and pick Const: min discharge SoC (%). Set that constant first under Settings → Automation → Automation Constants.
  8. Press Test under each block. Each row is marked pass, fail or no value against the live data.
  9. Untick Enabled while you try it, and press Create Entry. Tick it and Save Changes when you are happy.

What happens once it is enabled:

  • At 17:00 on a weekday the bridge checks the SoC. Above 40 %, it starts the force discharge, with the window's 180 minutes as its time limit. Otherwise it logs gated (once a day) and checks again every tick until 20:00, so it can still start later.
  • When the SoC falls to your minimum discharge SoC, the exit condition closes the window and the force is released. The schedule does not fire again until tomorrow's window.
  • At 20:00 the window closes and the bridge sends a release.

For a force action, use a trigger with Fire at and Duration

A force stops after the schedule's Duration (min) (#160). A Recurring windows schedule still has that value, although the form hides it, and a new schedule starts with 90. So a force in a three-hour recurring window stops after 90 minutes. Use Daily at time or Weekly at time for force actions.

To check it before the window opens, open the card's ⋮ menu and choose Test against live. It says Would fire or Would not fire, with the reason and each row's live value.

The entry list

The Schedules view: a schedule card with Explain, Edit, Turn on and the ⋮ menu

Each schedule is a card. It shows the name; the Fire at time and duration, the recurrence in words and the number of top-level conditions; Next: (see Triggers → Next fire); ● active while its window is open and it has fired; On or Off; the battery action (or No gateway action) and the number of HA actions; and the last result with its occurrence.

Control What it does
N active now Counts the cards showing ● active.
All / Enabled / Disabled Filters the cards. A note says how many are hidden.
Explain A plain-language summary of the schedule, at three levels: min, medium and full.
Edit Opens the form. If the schedule is ● active, saving asks first.
Turn on / Turn off Enables or disables the schedule.
Stop Shown while ● active. Releases the force this schedule started; the schedule stays enabled. See Run now and Stop.
⋮ → Test against live Evaluates the schedule against live values, without acting.
⋮ → Run now Runs the actions now, ignoring the window and the entry conditions. Asks first.
⋮ → Duplicate Opens a copy in the form, named "Copy of …", with Enabled unticked. It is saved as a new schedule.
⋮ → Delete Removes the schedule, after asking.

The list shows all schedules by default.

Duplicate opens an unsaved copy named "Copy of " with Enabled unticked; nothing is written until you press Create Entry.

Saving a schedule that is ● active asks "This schedule is running now — saving will apply the changes to the window in progress." The change is read by the next tick. A force that is already running is not re-sent: the schedule has fired this occurrence, so a changed power, direction or target SoC takes effect at the next window.

Turn on / Turn off sends only part of the schedule; since 0.5.2 the bridge merges it into the stored schedule, so nothing else changes (#157).

A PUT without enabled turns the schedule on

The form and the toggle always send enabled. An API call that does not, for example one that only renames a disabled schedule, turns it back on: enabled defaults to true in the request model. Issue #168.

Templates, export and import

The built-in Templates

  • Templates opens a list of presets. Use loads one into the form unticked, for review; nothing is saved until you press Create Entry. There is no prompt to enable it afterwards. Presets marked Modbus use a force action and need the Modbus client (this bridge).

  • The presets: Self-Consumption all day, Time-of-Use in the evening, Emergency Backup (storm), Turn a circuit off overnight, Low battery alert (notify only), Peak window — notify start & end, Time-of-Use at peak (only if charged), and four force presets: Peak shaving, Battery Bonus export (evening), Solar sponge (charge midday) and Off-peak charge (overnight), each with an SoC condition and a target SoC.

  • Export ▾ downloads every schedule, as This bridge (franklinwh-local-schedules) or Modbus bridge (franklinwh-automations). Through the API, GET /api/schedules/export?ids=<id>,<id> exports some.

  • Import takes a file. The bridge first validates it (a dry run) and shows, per entry, errors (a missing name, a Fire at that is not HH:MM, an unknown action) and warnings (a gateway or notify device that does not exist here). Import valid creates the valid entries disabled. An entry whose gateway does not exist here is pointed at the default gateway. Both bundle types are read; a Modbus bridge bundle is mapped field by field.

Not in this bridge: a per-entry Export in the card menu.

Visual timeline

The Timeline view shows today, 00:00 to 24:00:

  • a band along the top coloured by the operating mode the gateway actually ran;
  • the battery SoC as a line;
  • dashed markers where a schedule fired, exited, was gated or had an error;
  • a line at the current time.

Below it, Planned windows lists each enabled schedule's windows for today as a bar ((+1d) when a window wraps past midnight). Every N minutes, Custom cron and Always schedules are not drawn, nor are schedules the calendar excludes today.

A One-off schedule appears only on its date.

The Timeline is not per gateway, and uses the container's clock

The planned windows list every enabled schedule whatever its gateway, the markers come from every gateway's History, and "today" and "now" are the bridge container's clock, not the site's (#161).

Activity Log

Every decision the scheduler makes is written to History, newest first: created, fired, gated, waiting, deferred, exit, error, missed and more. The status list and filter chips are on Outcomes and audit. Times are in the bridge host's zone.

Using schedules from Home Assistant (Direct Connect only)

Everything the Scheduler tab does is also a REST call. Home Assistant can make those calls with rest_command, so automations and scripts can read, create, update, delete and run schedules. Home Assistant entities for run, pause and state over MQTT are planned (#128).

The address. From Home Assistant, the add-on is reachable on its internal hostname. The add-on's Info page shows it (for example 4a12892f-franklinwh-local-bridge). Use http://<that hostname>:8101. A Docker install uses its own host and port.

The bridge's HTTP API has no login, and writes are not gated (writes_enabled always returns true). Anything that can reach it can do all of the below. Keep it on a trusted network.

# configuration.yaml
rest_command:
  fwh_schedule_create:          # body: a full schedule (see "The fields" below)
    url: "http://<hostname>:8101/api/schedules"
    method: POST
    content_type: "application/json"
    payload: "{{ schedule | tojson }}"
  fwh_schedule_update:          # merges what you send (#157); always send name and enabled (#168)
    url: "http://<hostname>:8101/api/schedules/{{ id }}"
    method: PUT
    content_type: "application/json"
    payload: "{{ schedule | tojson }}"
  fwh_schedule_delete:
    url: "http://<hostname>:8101/api/schedules/{{ id }}"
    method: DELETE
  fwh_schedule_run:             # runs its actions NOW, ignoring the window and conditions
    url: "http://<hostname>:8101/api/schedules/{{ id }}/run"
    method: POST
  fwh_schedule_stop:            # releases this schedule's battery dispatch; stays enabled
    url: "http://<hostname>:8101/api/schedules/{{ id }}/stop"
    method: POST

Update merges. PUT changes only the fields you send (since 0.5.2, #157), but always send name (required) and enabled: without enabled the schedule is switched on (#168).

Reading. A rest sensor on GET /api/schedules lists every schedule with enabled, next_fire and active_now (container clock, #161). GET /api/schedules/runs and GET /api/schedules/log give what ran and why.

Pause vs disable: they are different.

You want Call
Release a battery dispatch this schedule started, and leave the rule enabled stop
Stop the rule from firing at all until further notice PUT with "name" and "enabled": false
Hold the current run and resume it later pause / resume exist, but do not work as intended; see the warning

Pause and Resume do not hold a run

POST /api/schedules/{id}/pause only finds a run that has not yet succeeded (pending or failed). For a force that is running it answers "no run is open for this schedule" and does nothing. For a failed run it marks it paused, but the next tick retries it anyway: the tick does not check for paused. Use stop or disable the schedule. Issue

200; see Outcomes and audit.

Run means real actions. run does what the schedule does: a mode change, a smart circuit, off-grid, or a battery force. Test a new rule with POST /api/schedules/{id}/test first: it evaluates the conditions and says what would happen, without acting.

The fields are those of the Scheduler tab's form. A minimal rule that switches to Self-Consumption at midnight:

{"name": "Self-Consumption all day", "enabled": true,
 "fire_at": "00:00", "duration_min": 0,
 "action": {"kind": "set_mode", "mode": "self"}}

For anything more involved, build it in the Scheduler tab and export it (GET /api/schedules/export): each entry is the exact JSON the API accepts.

Where the old sections went

The Scheduler used to be two pages. Their sections now live here:

Old section New place
Concepts Concepts
How a schedule is evaluated Concepts → The tick
Your first schedule above
The schedule list The entry list
Timeline Visual timeline
History Outcomes → Activity Log results
1. Trigger Triggers
Calendar restrictions Triggers → Summary
How fast can a schedule react Concepts → The tick
Which clock Restarts and the clock → The clock
2. Conditions Conditions
Operators Conditions → Operators
Value or Lookup Conditions → Value and Lookup
ALL / ANY, and nesting Conditions → Groups and items
The rule that matters most Conditions → Rules for every condition
What you can gate on Conditions → Every sensor in the picker
Gating on Home Assistant Conditions → Home Assistant entities
3. Hold, and conflict resolution Conditions → Hold for, Priorities and conflicts
4. Actions Actions
The force action in detail Actions → Force Charge and Force Discharge
Home Assistant actions Actions → Home Assistant actions
5. Exit Exit and release
6. Working with schedules Templates, export and import, Conditions → Test Verification
Run now, Stop, Pause and Resume Outcomes → Run now and Stop
When a run fails, is missed, or the bridge restarts Outcomes → Retries, Restarts and the clock
Not available in this bridge the Not in this bridge notes on each page, and Scheduler parity
7. Using schedules from Home Assistant above
Multi-gateway behaviour Targets