How Manifest Settings Drive Busroot¶
The Schema Reference says what each field is. This page says what it does — how each part of the configuration shapes what Busroot records, calculates and shows. It is worth reading before changing configuration on a live account, because several settings have effects that are not obvious from their names.
Time and calendar¶
A plant's timezone, dayStartHour and weekStartDay anchor every time-based
calculation for its stations:
- Every date range resolves in the plant's timezone. "Today", a named day, a week, a month, a quarter, a year — all are interpreted where the plant is, not where the server or the viewer is.
dayStartHourmoves the day boundary. A factory whose day starts at 06:00 means "Tuesday" runs from 06:00 Tuesday to 06:00 Wednesday, in every report and dashboard. "Today" and "Yesterday" respect the same offset.weekStartDaymoves the week boundary, and with it the boundaries of quarters and years, which are built from weeks. Weekly and longer views for a plant that starts its week on Sunday genuinely start on Sunday.
Change these on an established plant with care: the boundaries of historical reporting periods move with them.
Shift patterns and OEE¶
Shifts decide when time counts. Production counts only need a running schedule (below), but utilisation, OEE and the station's live running/stopped state additionally require the time to fall inside a shift:
- Outside shift hours a station reads out of shift and accrues no productive time, however much it is producing. Counts still record; the percentages don't move.
- A station resolves its shift pattern from its own
shiftPatternCode, or its group's if it doesn't set one. A station with no resolvable pattern is never in shift — it will show production counts and permanently zero utilisation. This is the most common surprise when commissioning a new station: if the numbers are all zero except the count, check the shift pattern first. - This is why a 24/7 shift pattern is the practical choice while commissioning — a test at any hour still produces figures. Realistic patterns can come later.
Station codes are permanent¶
A station's code is the key that ties everything recorded — production, downtime,
utilisation, energy — to the station. Two consequences:
- Renaming a code orphans the station's history. The data recorded under the old code
is not deleted, but nothing will ever read it back. Treat a code change as
decommissioning one station and creating another; change
namefor display instead. - Incoming device messages must use the station code exactly as it is spelled in the
manifest. Signals are stored under the code as published on the MQTT topic, so a
device publishing to
station1does not land data on a station whose code isSTATION1.
Archived stations keep their history, and creating a new station with an archived station's code (case-insensitively) is rejected — so the historical data can never be silently claimed by a new station.
Station behaviour settings¶
These settings decide how raw device signals become "running", "down" and performance figures:
- Running is decided by
productiveStatusMode. With the defaultproductive_signal, the station is productive while the device sends productive signals, each one holding the state forproductiveHoldOnTime(so a machine that signals once per cycle stays "running" between cycles — set the hold-on to comfortably exceed the gap between signals). Withelectrical_usageorline_speedthe station is running while the measured value is above the corresponding stopped-threshold. Production counts alone never make a station productive — a device that publishes only counts shows output and 0% utilisation until it also publishes a productive signal, or the mode is switched. - Down is decided by
downtimeDetectionMode. In the commonutilisationmode, a stop becomes a recorded downtime once it lasts longer thanutilisationDowntimeThreshold(default 1 hour — usually worth lowering). Inproductionmode the threshold derives from the SKU's cycle time anddowntimeDurationThresholdMultiplier.offrecords no downtimes at all. - Speed signals pass through
speedScaleandspeedOffsetbefore display, so a sensor whose raw value doesn't match the real speed can be calibrated in configuration rather than in the device.speedToProductionRatioadditionally converts speed into production counts for continuous processes that have no discrete unit signal. - Performance targets come from the running SKU's rate (
cycleTime,unitsPerMinuteorunitsPerHour) when it has one, falling back to the station's own rate fields.lineSpeedTargetswitches the performance comparison to speed-vs-target. - Costs use the SKU's
valueper unit where set, with the station'sidleCostPerMinutecovering losses that can't be attributed to a SKU.electricalPowerNominalKwfeeds the energy views' expected-usage comparisons.
Configuration vs runtime state¶
A handful of station fields — statusCode, statusCodeUpdatedAt,
currentOperatorInitials, alertMessage, alertExpiresAt — are state Busroot
writes, not configuration you author. They appear in the schema so the document is
complete, but the live values are maintained by the platform as devices report and
operators sign in and out. Setting them in a manifest achieves nothing lasting.
SKUs¶
- A schedule may only name a SKU that already exists. Creating a schedule with an
unknown SKU code is rejected — nothing creates the SKU for you. Add the SKU first,
either in the admin UI or in a version-controlled manifest; keeping a permanent test SKU
(e.g.
CALIBRATION) in the list is normal practice. valuedrives money. Lost-production cost and the cost of rejected (bad-quality) units are bothunits × value.- Rates drive targets. The SKU's
cycleTime/unitsPerMinute/unitsPerHourset the ideal counts the performance and OEE figures compare against while a schedule for the SKU runs, and project schedule durations on the Gantt. stationCodes/stationGroupCodesrestrict scheduling — when set, only the named stations (or stations in the named groups) can be scheduled with the SKU.allowUseInQuickSchedulecontrols whether operators can pick the SKU when starting an ad-hoc schedule from the tablet.
Reasons and the include/exclude cascade¶
A reason's type list decides where it is offered: downtime reasons when categorising
stoppages, non-production reasons when scheduling planned non-production time, quality
reasons when recording rejected units.
Which reasons a particular station offers is decided by the
includeReasonCodes/excludeReasonCodes lists, evaluated level by level — account, then
plant, then station group, then station:
- No include list anywhere → every reason is available.
- Any include list → the available set starts from the include lists: each level's includes are added (a lower level can re-add something a parent excluded).
- Each level's excludes are then subtracted at that level, after its includes.
The same cascade, with the same semantics, controls which Tasks apply to a station via
includeTaskCodes/excludeTaskCodes.
requireNotes on a reason works differently — it inherits down the reason tree, not
the station hierarchy: a child reason that doesn't set it takes the nearest ancestor
reason's setting, and false explicitly opts out. When it resolves on, operators must
enter a note before the reason can be confirmed against a downtime.
Tasks¶
- A
frequencyofschedulemeans the Task must be completed once per production schedule — it appears when a schedule starts and is missed if the schedule ends without it. - A
frequencyofcronmeans the Task is due at every cron fire, evaluated in the plant's timezone; the fire is the deadline.availableBeforeDeadlineMinutescontrols how long before the deadline the Task appears on the tablet, so a weekly check due Friday 17:00 can be made available only from Friday morning. - Which stations a Task applies to follows the include/exclude cascade above; a SKU's
taskCodesadd SKU-specific Tasks whenever a schedule for that SKU runs. - Task lists are purely visual grouping — membership changes nothing about when or where a Task is due.
- Task completion history records every instance as completed, missed or pending, so the audit trail exists whether or not operators tick things off.
Energy totals¶
By default a plant's or group's energy (kWh, cost, CO2) is the sum over its member
stations. totalEnergyStationCodes replaces that: when set, the level's energy is the
designated stations' energy instead — the physical meter's reading rather than the sum
of sub-meters.
The designated stations are usually meter-only stations
(enableMeterOnly), which exist to carry a physical meter's electrical signals and are
hidden from production views. Group designations apply first, then the plant's own — so a
plant total can legitimately differ from the sum of the group rows on screen, because it
is a different physical measurement. Energy CSV exports include the meter stations as rows
so the totals can always be reconciled.
Feature flags in practice¶
The flag table lists what each flag does; the cascade is what makes them practical at scale. Two worked examples:
- Enable manual downtime for one plant only. Leave
enableManualDowntimeunset (off) at the account, set"on"on the plant. Every group and station in that plant inherits on; the rest of the account stays off. - Enable a feature everywhere except one station. Set
"on"at the account, and"off"on the one station. The station's own value is the nearest defined one, so it wins over the account's.
Remember the default: a flag nothing sets is off. When a feature seems missing on a new account, check whether its flag was ever turned on at any level.