🚚 WIA Delivery Robot Standard Ebook | Chapter 6 of 8


Chapter 6: Phase 4 Fleet Integration — Telemetry, Dispatch, Charging and OTA

A single delivery robot that follows the Phase 3 navigation protocol can complete a trip on its own. A business, however, does not run one robot; it runs a fleet across a campus, a building complex or a city district, and the value of the standard only shows when robots from different vendors can be observed, dispatched, charged and updated by one cloud platform. Phase 4 of WIA ROB-010 (Fleet Integration) describes that platform: the services it contains, the telemetry channel that feeds it, the way tasks are assigned and conflicts are resolved, the charging and maintenance workflows, and the security and recovery expectations around all of it.

This chapter reads Phase 4 as an engineer who has to build it. For each topic it states what the specification actually says, where the text is only a sketch, and what an implementation has to decide on its own. REST endpoint details (authentication, fleet listing, statistics and the error envelope) were covered in Chapter 4 and are not repeated here; fleet KPIs and conformance evidence are treated in Chapter 7. The running example uses the same robot as the rest of the book, 550e8400-e29b-41d4-a716-446655440000.

6.1 Reference architecture

Phase 4 §1.1 draws the fleet as a cloud platform with four services sitting on a shared message broker, and any number of robots connected underneath. The broker is named as “MQTT/Kafka”, which is a useful hint about roles rather than a product choice: MQTT is a lightweight publish/subscribe protocol suited to many small devices on unreliable links, while Kafka is a durable log suited to high-volume processing inside the data centre. A common pattern is to terminate robot connections on an MQTT broker and bridge the resulting stream into a log for the back-end consumers, but the standard does not require that split.

Cloud platform Fleet Manager registry · dispatch · health Route Optimizer multi-robot · re-route · charge plan Analytics Engine metrics · anomalies · wear Operator Dashboard live map · intervention Message broker (MQTT / Kafka) — topic fleet/robots/{robot_id}/state Robot 1 (vendor A) Robot 2 (vendor B) Robot N TLS 1.3 · QoS 1 · RobotState JSON
Figure 6-1. Phase 4 reference architecture, redrawn from §1.1. Service names are the standard's; the vendor labels are illustrative.

The division of responsibility in §2.1 is worth restating as interfaces, because each service consumes and produces different data:

ServiceResponsibilities in Phase 4 §2.1Main inputsMain outputs
Fleet ManagerRobot registration and lifecycle, task assignment and load balancing, health monitoring and alerting, configuration managementRobotState stream, new delivery tasks (Package + Route from Phase 1)Assignments, commands, configuration, alerts
Route OptimizerMulti-robot route planning, traffic prediction and avoidance, dynamic re-routing, charging schedule optimizationPlanned paths, map and zone data, station availabilityRoute objects, deconfliction decisions, charging plans
Analytics EngineReal-time dashboards, historical analysis, anomaly detection, predictive maintenanceTime-series telemetry, delivery outcomesMetrics, maintenance alerts, reports
Operator DashboardLive visualization, manual intervention, incident management, reportingCurrent fleet state, alertsOperator commands (via the Phase 2 API), incident records

Two properties of this architecture shape everything that follows. First, the robot is the authority on its own safety: the cloud assigns work and offers advice, but the emergency stop, obstacle response and failure-mode handling defined in Phase 3 run on board and must keep working when the cloud is gone (§8.1, “robots operate autonomously if cloud unreachable”). Second, the only data contract the architecture assumes between robot and cloud is the Phase 1 RobotState. Anything else a vendor sends — raw diagnostics, proprietary logs — is outside the standard and should not be something the Fleet Manager depends on for dispatch decisions.

6.2 The telemetry pipeline

6.2.1 Topic, QoS and payload

Phase 4 §2.2 fixes three things about robot telemetry: robots publish state updates every 1–5 seconds; the MQTT topic is fleet/robots/{robot_id}/state; and messages use QoS 1 with a JSON-encoded RobotState as payload. Everything else in the pipeline — broker product, stream processor, database — is left to the implementer. The flow from §2.2 is: robot → MQTT/HTTP → broker → stream processor → time-series database, with branches to the real-time dashboard, alerting and the analytics engine.

A telemetry message for the running example looks like this. It is a valid Phase 1 document: all five required fields are present, version matches the SemVer pattern and mode uses the Phase 1 enum.

Topic:   fleet/robots/550e8400-e29b-41d4-a716-446655440000/state
QoS:     1
Payload:
{
  "robot_id": "550e8400-e29b-41d4-a716-446655440000",
  "timestamp": "2025-12-26T10:30:02.000Z",
  "version": "1.0.0",
  "position": {
    "latitude": 37.5665,
    "longitude": 126.9780,
    "accuracy": 0.4,
    "source": "fused"
  },
  "heading": 92.5,
  "speed": 1.2,
  "battery_level": 64,
  "mode": "autonomous"
}

Note that the robot_id appears twice, once in the topic and once in the body. Consumers should check that the two agree and reject the message if they do not; otherwise a misconfigured or compromised client can publish state that looks like it comes from another robot. The topic-level identifier is what the broker's access control can enforce (see 6.7), so it is the stronger of the two.

6.2.2 What QoS 1 means for consumers

MQTT QoS 1 is “at least once”: the broker keeps resending a message until the receiver acknowledges it, so a message can arrive more than once, for example after a reconnect in the middle of an acknowledgement. The standard chose QoS 1 over QoS 0 (at most once, may be lost) and QoS 2 (exactly once, more round trips). The consequence is a hard requirement for every consumer: processing must be idempotent. The natural key is the pair (robot_id, timestamp). A time-series store should upsert on that key instead of appending; an alerting rule that counts events should count distinct keys; and a “current state” cache should only replace its entry when the incoming timestamp is newer than the one it holds, because after a reconnect older buffered messages can arrive after newer ones.

The following Python sketch uses the paho-mqtt client (version 2 API) to show both sides. The publisher sends one RobotState per interval; the subscriber listens on the wildcard fleet/robots/+/state, cross-checks the identifier, drops duplicates and ignores stale updates for the live view.

import json, ssl, time
import paho.mqtt.client as mqtt

BROKER = "broker.example.net"          # illustrative host
ROBOT_ID = "550e8400-e29b-41d4-a716-446655440000"

# ---- robot side: publish RobotState every PUBLISH_S seconds ----
PUBLISH_S = 2                          # Phase 4 §2.2 allows 1–5 s

def run_publisher(read_state):
    c = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=ROBOT_ID,
                    clean_session=False)          # keep session across reconnects
    c.tls_set(certfile="robot.crt", keyfile="robot.key",
              cert_reqs=ssl.CERT_REQUIRED)
    c.connect(BROKER, 8883)
    c.loop_start()
    topic = f"fleet/robots/{ROBOT_ID}/state"
    while True:
        state = read_state()                      # dict that validates against Phase 1
        c.publish(topic, json.dumps(state), qos=1)
        time.sleep(PUBLISH_S)

# ---- cloud side: subscribe to all robots, dedupe, keep latest ----
seen = set()                                      # use a TTL cache in production
latest = {}                                       # robot_id -> last timestamp

def on_connect(client, userdata, flags, reason_code, properties):
    client.subscribe("fleet/robots/+/state", qos=1)

def on_message(client, userdata, msg):
    topic_id = msg.topic.split("/")[2]
    state = json.loads(msg.payload)
    if state.get("robot_id") != topic_id:
        return                                    # identifier mismatch: reject and log
    key = (topic_id, state["timestamp"])
    if key in seen:
        return                                    # QoS 1 duplicate
    seen.add(key)
    store_timeseries(state)                       # upsert on (robot_id, timestamp)
    if latest.get(topic_id, "") < state["timestamp"]:
        latest[topic_id] = state["timestamp"]     # safe only if all robots use
        update_live_view(state)                   # the same UTC "Z" format

The string comparison of timestamps in the last lines only works because all timestamps are written in one fixed UTC format. Phase 1 allows any ISO 8601 date-time, including offsets such as +09:00; a robust consumer parses them into instants before comparing. This is a small example of a larger rule: normalize at the edge of the pipeline, once, rather than in every consumer.

6.2.3 Choosing the publish interval

The 1–5 second window is a trade-off between freshness and load. A shorter interval makes the dashboard smoother and lets the Fleet Manager notice a stuck robot sooner, but it multiplies broker traffic and storage by the number of robots. A practical approach is to vary the interval within the permitted window by state: publish at the fast end while mode is autonomous or while an error is active, and at the slow end while idle or charging. Events that matter immediately — an emergency stop, a failure-mode transition from Phase 3 — should not wait for the next tick; publish an extra state message at once. Phase 1 §6.3 also suggests Protocol Buffers and delta updates for high-frequency telemetry. If you adopt a binary encoding, keep the field names and semantics identical to the JSON schema so that the Phase 1 schema remains the single definition, and state the encoding in the deployment documentation because the MQTT topic alone does not reveal it.

6.2.4 Stream processing and storage

§2.2 lists what the stream processor does: compute aggregations such as average speed and battery, store history in a time-series database, feed the dashboard and drive anomaly alerts. Three practical decisions follow:

6.2.5 Clock synchronization

Idempotency keys, ordering and every latency figure in the book depend on clocks that agree. Annex E of Phase 4, which is explicitly non-normative, notes that NTPv4 against stratum-2 servers is sufficient for most deadlines in the phase and recommends PTP (IEEE 1588) for sites that need deterministic interlocks. NTPv4 is specified in IETF RFC 5905. In practice, synchronize the robot's clock before it starts publishing, record the synchronization status in the vendor diagnostics, and let the stream processor flag messages whose timestamp is far in the future relative to broker receive time — a symptom of a robot that booted without time sync.

6.3 Task assignment

6.3.1 Centralized minimum-cost assignment

Phase 4 §3.1 gives a centralized algorithm in pseudocode: for each new task, skip robots whose battery is below a threshold and robots already at capacity, compute a cost for each remaining robot as the sum of distance to pickup, estimated delivery time and impact on existing tasks, and assign the task to the cheapest robot. The algorithm is short and correct in spirit, but it leaves four decisions to the implementer.

  1. The battery threshold. The text does not give a number. A threshold that ignores the task itself is too weak: a robot at 40 % may be fine for a 500 m task and unable to finish a 4 km one. A better filter is “energy after this task, plus the energy to reach a charger, stays above the proactive-charging level”, which the standard places at 20–30 % (§4.2).
  2. Capacity. “max_capacity” is not defined in Phase 1. Package count is the obvious measure, but weight and volume (weight_kg, dimensions_cm) and temperature control (temperature_controlled) are more realistic constraints. Document the measure you use.
  3. Units. The cost adds a distance to a time. That only works after conversion to a common unit. Converting distance to travel time at a nominal speed gives a cost expressed entirely in seconds, which is also what the customer experiences.
  4. Impact on existing tasks. Inserting a new pickup into a robot's queue delays its current deliveries. Estimate the added delay and weight it, typically more heavily for urgent or express packages (the Phase 1 priority enum).
def assign(task, robots, v_nominal=1.5, reserve_pct=25, w_impact=1.0):
    """Return the robot_id with minimum cost, or None.
    Units: seconds. v_nominal (m/s) and reserve_pct are deployment parameters."""
    best, best_cost = None, float("inf")
    for r in robots:
        if r.telemetry_stale or r.mode in ("error", "manual"):
            continue
        if r.load + task.load > r.capacity:
            continue
        need_pct = energy_pct(r, task) + energy_pct_to_nearest_charger(r, task.dropoff)
        if r.battery_level - need_pct < reserve_pct:
            continue
        cost = (distance_m(r.position, task.pickup) / v_nominal
                + eta_delivery_s(task)
                + w_impact * added_delay_s(r, task))
        if cost < best_cost:
            best, best_cost = r.robot_id, cost
    return best

6.3.2 A worked example with three robots

Consider one new task and three robots. All numbers below are illustrative: a nominal speed of 1.5 m/s, a delivery leg of 720 s after pickup for every robot, and a reserve of 25 %.

RobotBatteryDistance to pickupQueued workFilterCost (s)
R164 %900 m2 deliveries; inserting the pickup delays them by 240 spasses600 + 720 + 240 = 1,560
R291 %1,400 mnonepasses933 + 720 + 0 = 1,653
R331 %300 mnonefails: task plus return to charger needs about 9 %, leaving 22 % < 25 %—

R1 wins by about 90 seconds. The margin is small, and it depends entirely on how much the 240 s delay to R1's existing customers is worth. If those two deliveries are marked urgent and the operator sets w_impact to 1.5, R1's cost becomes 1,680 s and R2 wins. This sensitivity is the real content of the algorithm: the formula is simple, but the weights encode business policy, and they should be configuration, recorded with every assignment decision so that an operator can later explain why a particular robot was chosen. R3 is also instructive. It is the closest robot and would win on distance alone; the energy filter prevents a dispatch that would strand it below the charging reserve.

6.3.3 The auction protocol

The alternative in §3.1 is a distributed auction: the manager broadcasts the task, each robot computes a bid equal to its own cost to complete it, robots submit bids, the manager awards the task to the lowest bidder, and the winner confirms. The auction moves the cost calculation onto the robot, where the most current information lives — its exact queue, its own energy model, the local obstacles it has just seen. It also lets vendors keep their energy models private: they publish a number, not the model behind it.

The five steps are not a complete protocol. An implementation must add at least the following, and the choices should be documented because they are not in the standard:

Phase 4 does not name topics for auction messages. If you run the auction over MQTT, a layout such as fleet/tasks/{task_id}/offer, .../bid and .../award works; treat it as a deployment convention, not as part of WIA ROB-010.

AspectCentralized minimum costAuction
Where cost is computedCloud, from telemetryEach robot, from local state
Freshness of inputsAs old as the last telemetry message (1–5 s)Current at bid time
Decision latencyOne computationAt least one broadcast plus the bid deadline
Behaviour with poor connectivityWorks from last known stateRobots that cannot hear the offer simply do not bid
Vendor model privacyCloud needs an energy model per vendorVendors publish only the bid
Explaining a decisionStraightforward: all inputs are logged centrallyRequires logging every bid received

Many fleets end up with a hybrid: the manager filters and ranks centrally, then asks the top two or three candidates to confirm with a fresh cost before awarding. Either way, the assignment should be written back into the Phase 1 data — the package status moves from pending to assigned, and the robot's route reflects the new plan — so that every consumer sees one version of the truth.

6.4 Multi-robot deconfliction

Phase 3 already teaches each robot to avoid obstacles it can sense, including other robots, through local planning (Chapter 5). Fleet-level deconfliction deals with the conflicts a single robot cannot see coming: two robots about to enter the same one-way corridor from opposite ends, or three robots converging on one elevator. §3.2 gives two mechanisms.

6.4.1 Coordination zones and tokens

A coordination zone is a restricted area — a narrow doorway, a lift, a ramp — that only one robot may occupy at a time. Access is token based: a robot requests the zone's token, waits if another robot holds it, enters when granted and releases on exit. This is a distributed mutual-exclusion problem, and the standard's three sentences need three safeguards to be safe in the field:

Elevators deserve a note of their own. Phase 1's navigation_constraints.elevator_allowed tells the planner whether a route may use one, but Phase 4 says nothing about how a robot calls the car or tells the building which floor it wants. That integration is building-specific today; treat the lift as a coordination zone with a long lease and handle the building interface outside the standard.

6.4.2 Shared paths and conflict detection

The second mechanism is dynamic deconfliction: robots share planned paths with the fleet manager, the manager looks for paths that intersect within a time window, assigns priorities by urgency and battery, and the lower-priority robot yields by stopping or re-routing. A workable conflict check treats each planned path as a sequence of timed points and flags a conflict when two robots are predicted to be closer than a separation distance at overlapping times:

def conflicts(path_a, path_b, sep_m=2.0, window_s=30, dt=1.0):
    """path(t) -> (x, y) in a local metric frame; returns first conflict time or None."""
    t = 0.0
    while t <= window_s:
        ax, ay = path_a(t)
        bx, by = path_b(t)
        if (ax - bx) ** 2 + (ay - by) ** 2 < sep_m ** 2:
            return t
        t += dt
    return None

def who_yields(a, b):
    # Higher delivery priority wins, then lower battery (it can least afford a detour),
    # then a deterministic tie-break so that every node reaches the same answer.
    rank = {"urgent": 2, "express": 1, "normal": 0}
    ka = (rank[a.priority], -a.battery_level, a.robot_id)
    kb = (rank[b.priority], -b.battery_level, b.robot_id)
    return b if ka > kb else a

The separation distance, prediction window and time step are parameters, not values from the standard. The prediction window is bounded by how far ahead a path is trustworthy: in dense pedestrian areas the local planner will deviate from the global path often, so predictions beyond a few tens of seconds add false alarms rather than safety. Two further details matter. Compute distances in a local metric frame, not by subtracting latitudes and longitudes (Chapter 2 covers the conversion). And make the tie-break deterministic, because deconfliction decisions may be computed on more than one node and must agree.

Yielding should be expressed as a normal command to the robot, not as a new kind of safety stop. The yielding robot decelerates, waits or re-plans through its ordinary Phase 3 behaviour (the WAITING state in the behaviour state machine), while its own obstacle detection stays fully in charge of what happens in the next metre.

6.5 Charging integration

6.5.1 The station protocol

Phase 4 §4.1 describes charging in four stages. The table adds, for each stage, what the robot should report in its Phase 1 state and what can go wrong.

StageWhat happens (§4.1)RobotState reportedTypical failure to handle
1. NavigationTravel to the station's coordinates; fine positioning with visual markers (AprilTags)mode: autonomous, route to a waypoint of type charging_stationMarker not visible (occlusion, glare); approach blocked
2. DockingAlign using camera feedback, make contact with the charging pads, verify that charging started from voltage/current sensorsmode: charging only after current is confirmedContact made but no current: retry alignment a bounded number of times, then report an error
3. ChargingMonitor battery level and rate, estimate time to full, update the fleet managermode: charging, rising battery_levelCharge rate far below expected: possible pad wear or battery fault; raise a maintenance alert
4. CompletionDetect full charge, undock, return to service, report availabilitymode: idle until assignedUndocking obstructed; station slot not released

Two refinements are worth making to the text. First, the standard says full charge is detected by a “voltage plateau”. For lithium-ion packs charged with the usual constant-current / constant-voltage method, voltage reaches the set point early in the constant-voltage phase and it is the current that then tapers; the reliable end-of-charge signal is the battery management system's own status rather than the robot's voltage reading. Second, do not report charging merely because the robot is parked on the dock. The Fleet Manager uses that mode to plan availability, and a robot that is docked but not receiving current is a fault, not a charging robot.

6.5.2 Station reservation

The standard defines three station operations — list stations with status, check a station's availability, reserve a slot — whose HTTP form is listed in Chapter 4. At the fleet level the important question is the semantics of a reservation. The text does not say how long a reservation lasts or what happens if the robot never arrives. A sensible policy is a reservation that expires at the robot's estimated arrival time plus a grace period, is extended when fresh telemetry shows the robot still approaching, and is released immediately when the robot's plan changes. Without expiry, a single robot that breaks down on the way to a station quietly removes that slot from the fleet.

6.5.3 Charging strategies

Strategy (§4.2)TriggerBenefitImplementation note
ProactiveBattery at 20–30 %Avoids emergency low-battery situations; the fleet manager reserves slots in advanceShould be well above the Phase 3 failure-mode threshold of 15 %, which is the emergency case
OpportunisticIdle periodsPartial top-ups keep robots available without long charge sessionsOnly worthwhile when a station is close; count the trip energy
Dynamic schedulingFleet-wide planKeeps enough robots available at peak demand; can shift charging to off-peak electricity tariffsNeeds a demand forecast; see the analytics techniques in §6.2 of the phase

The three strategies interact with task assignment. The energy filter in 6.3 and the proactive threshold should use the same reserve value, otherwise the dispatcher will keep assigning work to robots that the charging planner is trying to send home. Keep both in one configuration and log the value with every decision.

6.6 Maintenance and over-the-air updates

6.6.1 Predictive maintenance

§5.1 lists the wear indicators to monitor: battery charge cycles and capacity degradation; motor runtime and current-draw anomalies; wheel odometry and, where fitted, tyre pressure; and sensor calibration drift and data-quality degradation. Most of these are not in the Phase 1 RobotState, which carries operating state rather than component health. A fleet therefore needs a second, lower-rate diagnostic channel, and the vendor has to map its internal counters onto the indicators the analytics engine expects. The standard's alert format is the common output:

{
  "alert_id": "maint-2025-12-26-001",
  "robot_id": "550e8400-e29b-41d4-a716-446655440000",
  "severity": "warning",
  "component": "battery",
  "issue": "Capacity degraded to 75% of original",
  "recommendation": "Schedule battery replacement within 30 days",
  "timestamp": "2025-12-26T10:30:00Z"
}

This example comes from §5.1, and its values are illustrative. The standard does not publish a schema for the alert, so the allowed values of severity and component are not fixed. If you exchange alerts between systems, define an enum for each (for example info/warning/critical, and one entry per monitored component), version that schema the way Phase 1 versions its own, and link the alert to the telemetry window that triggered it so that a technician can see the evidence.

6.6.2 The OTA process

§5.2 describes updates to firmware, software and maps as a staged rollout: prepare the package, deploy it to a subset of the fleet (a canary), monitor, roll out to everyone if successful, roll back affected robots if not. The safety rules are that packages are cryptographically signed, the signature is verified before installation, the previous version is kept for rollback, and a robot is never updated while navigating.

“Never while navigating” has to become a concrete gate on the robot, evaluated by the robot itself, because the cloud's view of the robot can be seconds old. A reasonable gate combines Phase 1 fields with the charging reserve:

def may_install_update(state, has_cargo, pkg):
    return (
        state["mode"] in ("idle", "charging")       # not autonomous or manual
        and not has_cargo                           # no customer package on board
        and state["battery_level"] >= 50            # example floor; set per platform
        and verify_signature(pkg)                   # before anything is written
        and pkg.target_version != current_version()
    )

Beyond the gate, three practices make rollback real rather than aspirational. Install to an inactive slot (an A/B layout) and switch only after the new image has booted and passed a self-test, so that a failed update leaves the old version untouched. Report the installed software version in your diagnostics channel, so that analytics can compare canary and control groups. And define the canary's success criteria before the rollout — for example the emergency-stop rate, failure-mode events and task success over a fixed number of trips — instead of deciding afterwards whether the numbers “look fine”.

The standard requires signing but does not name a format. Established options include The Update Framework (TUF), which protects against compromised repositories and rollback attacks, and its automotive adaptation Uptane. Chapter 7 discusses Sigstore, which WIA uses for signing conformance evidence; the same tooling can sign update manifests, but that is an implementation choice.

6.7 Security, privacy and resilience

6.7.1 Data security

§7.1 requires TLS 1.3 for all cloud communication (TLS 1.3 is IETF RFC 8446), AES-256 for data at rest, role-based access control for the operator dashboard and audit logging of all API calls and operator actions. For the telemetry channel, three additions turn these requirements into a defensible design:

6.7.2 Privacy

Delivery robots film public space. §7.2 requires blurring faces before video is uploaded to the cloud, collecting only necessary data, retention policies that auto-delete old telemetry (the standard gives 90 days as an example) and compliance with GDPR, CCPA and local privacy law. Two points need care in implementation.

The first is where blurring happens. “Before uploading” means on the robot, which requires on-board compute for face detection and a policy for what happens when detection fails: uploading an unblurred frame by default defeats the rule. Phase 1 already recommends sending detections and image URLs rather than raw frames; for most fleet functions the detection list is all the cloud needs.

The second is that retention has two clocks. Routine telemetry can be deleted on a short schedule such as the 90-day example. Audit logs, incident records and conformance evidence serve a different purpose and usually need to be kept longer. Phase 4 Annex E states that a seven-year window satisfies ISO/IEC 17065 audit expectations in most jurisdictions; that note is non-normative and gives no source, so do not rely on it. Set each retention period from the legal and contractual requirements that actually apply to your deployment, and keep personal data out of the long-retention store wherever possible.

6.7.3 Resilience and recovery

§8.1 lists four fault-tolerance measures: multi-region deployment, real-time database replication, graceful degradation in which robots operate autonomously if the cloud is unreachable, and durable storage for in-flight messages. §8.2 gives a six-step recovery procedure: detection, failover, data synchronization, robot reconnection, validation and post-mortem.

The robot side of that procedure is where fleets most often fail in practice. When the cloud disappears, the Phase 3 communication-loss rule applies: after 60 seconds without cloud contact the robot continues its current task and logs locally. It should not accept a new task it cannot report on, and it must not depend on the cloud for any safety function. When the endpoint changes during failover, every robot will try to reconnect at once; exponential back-off with random jitter spreads that load so the new region is not knocked over by its own fleet. With persistent MQTT sessions (a fixed client ID and a non-clean session), the broker can hold QoS 1 messages addressed to a robot while it is away — provided the broker's own storage is replicated, which is what “message queue durability” in §8.1 asks for.

EventRobot behaviourCloud behaviour
Link lost, under 60 sContinue normally, buffer telemetryMark robot stale after several missed intervals; do not reassign yet
Link lost, 60 s or morePhase 3 rule: continue current task, log locally; accept no new workHold the robot's tasks; alert operators if a delivery deadline is at risk
Region failoverReconnect to new endpoint with back-off and jitterPromote replica, verify data consistency, accept reconnections
ReconnectionUpload buffered state labelled as backfillDeduplicate, rebuild live view from the newest timestamps, validate fleet state before resuming dispatch

Annex E also recommends a monthly error-budget summary covering p95 latency, error rate and violation hours. Recovery events are the main input to that report; Chapter 7 shows how it fits into the conformance evidence, together with the Phase 4 KPI targets.

6.8 Implementation checklist

The items below are the decisions this chapter has shown Phase 4 leaves open. Recording an answer to each in the deployment documentation is what turns the phase from a description into an integration that another vendor's robot can join.

#DecisionWhere the standard stops
1Broker product, TLS configuration, per-robot credentials and topic ACLsNames MQTT/Kafka and TLS 1.3 only
2Publish interval policy within 1–5 s, and event-driven extra messagesGives the window, not the policy
3Deduplication key and handling of out-of-order and backfilled messagesImplied by QoS 1, not stated
4Assignment weights, battery reserve, capacity measure, unitsPseudocode without values
5Auction deadlines, confirmation timeout, tie-break, message topicsFive steps, no timing
6Coordination-zone leases, waiting positions, acquisition orderToken idea only
7Station reservation expiry and end-of-charge signalOperations named, semantics open
8Maintenance alert schema and enumsOne example, no schema
9OTA signing format, install gate, A/B layout, canary criteriaRequires signing and rollback only
10Retention periods for telemetry and for audit evidence, set separately90-day example; Annex E note is non-normative

With these answers in place, the fleet has a complete loop: robots publish Phase 1 state over the Phase 4 channel, the cloud assigns and deconflicts work, charging and updates happen without interrupting deliveries, and the whole system degrades safely when the network does. Chapter 7 turns to proving it — the test vectors, evidence package and field metrics by which a deployment claims a WIA ROB-010 conformance tier.


← Chapter 5: Phase 3 Navigation Protocol — Planning, Traffic Rules and Emergency Response | Back to Index | Chapter 7: Testing, Conformance and Certification — Surface, Verified, Anchored →