Skip to content

Latest commit

 

History

History
1451 lines (1099 loc) · 53.4 KB

help_td_restapi_cli.md

File metadata and controls

1451 lines (1099 loc) · 53.4 KB

OTBR REST API CLI — Command Reference

CLI wrapper for the OpenThread Border Router REST API.

Script Output style
otbr_restapi_cli.py Flattened (JSON:API envelopes unwrapped by default)

Run from the project root with:

PYTHONPATH=src python3 -m td_cli otbr-restapi [global-options] <command> ...

The wrapper forwards the same OTBR REST API global options to otbr_restapi_cli.py.

Compatibility note: otbr-restapi keeps its existing exit-code contract. In this codebase, rc 4 still means an HTTP/action failure, not a missing local input file.


Global Options

These options apply to every command and must be placed before the subcommand.

Option Default Description
--host HOST 127.0.0.1 OTBR REST API host
--port PORT 8081 OTBR REST API port
--base-url URL — Override host/port with a full base URL
--timeout SECS 10 HTTP request timeout in seconds
--accept MIME application/vnd.api+json Default Accept header; choices: application/vnd.api+json, application/json, text/plain
--raw off Return raw JSON:API envelopes instead of flattened output
--output FILE — Write JSON result to a file instead of stdout
--datadir DIR auto Data directory for file reads/writes (takes precedence over $TD_DATA_DIR; if omitted: $TD_DATA_DIR, then /data, then ./data)
--poll-interval FLOAT 2.0 Seconds between action status polls
--poll-timeout FLOAT derived Max wall-clock seconds to wait for an action. The default is task_timeout + max(5, 20% of task_timeout, 2 * poll_interval)
--no-progress off Suppress per-device [N/T] id → status (Xs) progress lines printed to stderr on fetch-all commands
--no-auto-output off Disable automatic output file naming; send JSON to stdout instead of <datadir>/td-otbr-restapi-<resource>-<command>.json
--lab off Allow currently experimental mutating commands (node state set, node dataset active set, actions enqueue add-thread-device, actions enqueue reset-network-diag-counter)
--debug, -d off Enable debug logging

Experimental command gate: The following commands are currently experimental and require --lab: node state set, node dataset active set, actions enqueue add-thread-device, actions enqueue reset-network-diag-counter.


Command Summary

Command Description
node get Get full OTBR node record from /api/node
node state get Get current Thread radio state
node state set Enable or disable Thread (experimental; requires --lab)
node dataset active get Get active Thread dataset (JSON or TLV hex)
node dataset active set Create or update active Thread dataset (experimental; requires --lab)
devices list List all known devices from /api/devices
devices get Get a single device by extAddress
devices fetch Trigger updateDeviceCollectionTask, wait, return device list
diagnostics list List all cached diagnostic records
diagnostics get Get a single diagnostic record by ID
diagnostics fetch Fetch diagnostics for one device (enqueue + wait + return result)
diagnostics fetch-all Fetch diagnostics for all (or given) devices
actions list List all actions
actions get Get a single action by ID
actions enqueue add-thread-device Enqueue addThreadDeviceTask (experimental; requires --lab)
actions enqueue get-network-diagnostic Enqueue getNetworkDiagnosticTask
actions enqueue reset-network-diag-counter Enqueue resetNetworkDiagCounterTask (experimental; requires --lab)
actions enqueue get-energy-scan Enqueue getEnergyScanTask
actions enqueue update-device-collection Enqueue updateDeviceCollectionTask
mesh-diagnostics children Fetch child table for a device (TLV 29)
mesh-diagnostics child-ipv6 Fetch child IPv6 addresses for a device (TLV 30)
mesh-diagnostics router-neighbors Fetch router neighbor table for a device (TLV 31)
mesh-diagnostics fetch Fetch caller-specified mesh-diagnostic TLVs for one device
mesh-diagnostics fetch-all Fetch mesh diagnostics for all (or given) devices
topology Full sweep: devices fetch → diagnostics fetch-all → mesh-diagnostics fetch-all

Commands

node

Read or mutate local OTBR node data.

node get

Get the OTBR node record from /api/node.

node get [--fields FIELDS]
Option Description
--fields Sparse-field selector (repeatable)

Examples:

# Print full node record
PYTHONPATH=src python3 -m td_cli otbr-restapi node get

# Select specific fields only
PYTHONPATH=src python3 -m td_cli otbr-restapi node get \
    --fields 'threadBorderRouter=extAddress,rloc16,role'

# Save to file
PYTHONPATH=src python3 -m td_cli otbr-restapi --output data/node.json node get

node state get

Get current Thread radio state.

node state get

Examples:

PYTHONPATH=src python3 -m td_cli otbr-restapi node state get

PYTHONPATH=src python3 -m td_cli otbr-restapi --host 192.168.1.10 node state get

node state set

Enable or disable Thread.

Warning: This command is currently experimental and requires --lab.

node state set --value {enable,disable}
Option Required Description
--value yes enable or disable

Examples:

PYTHONPATH=src python3 -m td_cli otbr-restapi --lab node state set --value enable

PYTHONPATH=src python3 -m td_cli otbr-restapi --lab node state set --value disable

node dataset active get

Get the active Thread dataset.

node dataset active get [--text]
Option Description
--text Request as text/plain TLV hex string instead of JSON

When output is written to a file, sensitive JSON fields such as networkKey and pskc are recursively replaced with [Redacted]. Because operational dataset TLV hex cannot be filtered field by field, --text file output is replaced entirely with [Redacted]. Output printed directly to the terminal is unchanged.

Examples:

# JSON
PYTHONPATH=src python3 -m td_cli otbr-restapi node dataset active get

# Raw TLV hex string
PYTHONPATH=src python3 -m td_cli otbr-restapi node dataset active get --text

node dataset active set

Create or update the active Thread dataset. Exactly one input source is required.

Warning: This command is currently experimental and requires --lab.

node dataset active set (--json JSON | --json-file FILE | --text TEXT | --text-file FILE)
Option Description
--json JSON Inline JSON payload
--json-file FILE Path to a JSON file
--text TEXT Inline TLV hex string
--text-file FILE Path to a file containing the TLV hex string

Examples:

PYTHONPATH=src python3 -m td_cli otbr-restapi --lab \
    node dataset active set --json-file data/dataset.json

PYTHONPATH=src python3 -m td_cli otbr-restapi --lab \
    node dataset active set --text 0e080000000000010000000300000f...

devices

Read Thread devices from /api/devices.

devices list

List all known devices.

devices list [--fields FIELDS] [--with-meta]
Option Description
--fields Repeatable sparse-field selector, e.g. threadDevice=hostName,role
--with-meta Include collection meta alongside the flattened items

Examples:

PYTHONPATH=src python3 -m td_cli otbr-restapi devices list

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    devices list --fields 'threadDevice=hostName,role'

PYTHONPATH=src python3 -m td_cli otbr-restapi devices list --with-meta

devices get

Get a single device by its extAddress.

devices get --device-id DEVICE_ID [--fields FIELDS]
Option Required Description
--device-id yes Device extAddress (16-char hex)
--fields no Sparse-field selector

Examples:

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    devices get --device-id aabbccddeeff0011

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    devices get --device-id aabbccddeeff0011 \
    --fields 'threadDevice=extAddress,role'

devices fetch

Trigger updateDeviceCollectionTask, wait for completion, then return the populated device list. Combines enqueue + poll + list in one call.

devices fetch [--device-count N] [--task-timeout SECS] [--max-age SECS]
              [--max-retries N] [--whole-action-attempts N]
              [--structured-outcome]
Option Default Description
--device-count 255 Max devices to discover
--task-timeout 30 Server-side task timeout in seconds; the derived client deadline is 36 seconds with the default poll interval
--max-age 60 Max age of cached device entries in seconds
--max-retries 2 Max retries per device
--whole-action-attempts 1 Whole discovery attempts; repeats only after a known stopped/failed action, never after an ambiguous enqueue or client deadline
--structured-outcome off Include action, partial-result, freshness, attempt, and timing metadata instead of only the compatibility device array

deviceCount is a discovery target, not a cap applied to the returned collection. The default 255 lets OTBR exhaust discovery without requiring the caller to know the network size.

Examples:

PYTHONPATH=src python3 -m td_cli otbr-restapi devices fetch

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    --output data/devices.json \
    devices fetch --device-count 20 --task-timeout 60

diagnostics

Read Thread network diagnostics from /api/diagnostics.

diagnostics list

List all known diagnostic records.

diagnostics list [--fields FIELDS] [--with-meta]

Examples:

PYTHONPATH=src python3 -m td_cli otbr-restapi diagnostics list

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    diagnostics list --fields 'networkDiagnostics=extAddress,rloc16,macCounters'

diagnostics get

Get a single diagnostic record by ID.

diagnostics get --diagnostics-id ID
Option Required Description
--diagnostics-id yes Diagnostic record UUID

Examples:

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    diagnostics get --diagnostics-id a6a0b433-437e-45bf-9994-58e0d7b32399

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    --output data/diag-a6a0.json \
    diagnostics get --diagnostics-id a6a0b433-437e-45bf-9994-58e0d7b32399

diagnostics fetch

Enqueue getNetworkDiagnosticTask for one device, wait for completion, and return the diagnostic result. MAC counter enrichment is applied by default.

diagnostics fetch --device-id DEVICE_ID
                  [--types TLV ...]
                  [--preset {recommended,full,minimal,basic}]
                  [--task-timeout SECS]
                  [--child-task-timeout SECS]
                  [--child-poll-timeout FLOAT]
                  [--children-fetch-fast | --children-fetch-fast-no]
                  [--children-fetch-detail | --children-fetch-detail-no]
                  [--destination-type TYPE]
                  [--no-fallback]
                  [--fallback-preset {medium,minimal,basic}]
                  [--no-enrich-mac-counters]
Option Default Description
--device-id required Device extAddress (16-char hex)
--types recommended set Space-separated diagnostic TLV names
--preset — recommended, full, minimal, or basic; overrides --types
--task-timeout 15 Server-side task timeout in seconds; the default derived client deadline is 20 seconds
--destination-type extended Destination addressing mode: extended, mleid, or rloc
--no-fallback off Disable TLV fallback retry; skip the device immediately on failure
--fallback-preset minimal TLV preset to retry with when the primary request fails: medium, minimal, or basic
--no-enrich-mac-counters off Return raw macCounters values only; skip computed totals and ratios

Single-device fetch retries with the minimal TLV preset by default after a known terminal action failure. Pass --no-fallback to disable this. Timeouts, ambiguous enqueue outcomes, invalid responses, and transport failures are never retried as replacement actions.

Examples:

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    diagnostics fetch --device-id aabbccddeeff0011 --preset recommended

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    diagnostics fetch --device-id aabbccddeeff0011 \
    --types extAddress rloc16 macCounters mleCounters \
    --no-enrich-mac-counters

PYTHONPATH=src python3 -m td_cli otbr-restapi --no-auto-output \
    diagnostics fetch --device-id aabbccddeeff0011 --preset recommended --no-fallback

diagnostics fetch-all

Fetch diagnostics for all known devices (or a given list), one device at a time. The device list is automatically refreshed via updateDeviceCollectionTask before fetching (pass --no-update-devices to skip). MAC counter enrichment and per-device progress are on by default.

diagnostics fetch-all [--device-ids ID ...]
                      [--types TLV ...]
                      [--preset {recommended,full,minimal,basic}]
                      [--task-timeout SECS]
                      [--destination-type TYPE]
                      [--children-expand-by-rloc]
                      [--no-update-devices]
                      [--no-fallback]
                      [--fallback-preset {medium,minimal,basic}]
                      [--preserve-diagnostics]
                      [--items-only]
                      [--no-enrich-mac-counters]
Option Default Description
--device-ids all devices Space-separated extAddress IDs to query
--types recommended set Diagnostic TLV names
--preset — recommended, full, minimal, or basic; overrides --types
--task-timeout 15 Server-side task timeout for routers and non-children
--child-task-timeout 30 Server-side task timeout for all child passes and legacy child requests
--child-poll-timeout derived Independent client polling budget for child actions; must satisfy the derived timing minimum
--children-fetch-fast / --children-fetch-fast-no fast enabled Enable or disable MTD fast TLVs 0, 1, 2, 8
--children-fetch-detail / --children-fetch-detail-no detail disabled Enable or disable optional MTD detail TLVs 0, 1, 2, 8, 9
--destination-type extended Destination addressing mode: extended, mleid, or rloc
--children-expand-by-rloc off After the extended-address sweep, query children listed in selected parents' childTable by RLOC16; requires --destination-type extended
--no-update-devices off Skip updateDeviceCollectionTask; use the cached device list
--no-fallback off Disable additional diagnostic actions; known children retain their selected initial sets, with one attempt per enabled pass
--no-basic-fallback off Suppress only the final basic tier for routers and unknown-mode children; does not suppress MTD fast or its same-set retry
--fallback-preset off Use the legacy/custom policy with one explicit fallback preset after a known terminal failure
--preserve-diagnostics off Keep the existing diagnostics collection. By default a full sweep clears it once after checking for active diagnostic work
--items-only off Return only successful diagnostic items instead of the structured sweep outcome
--no-enrich-mac-counters off Return raw macCounters without computed totals and ratios

Note: --update-devices has been replaced by --no-update-devices. Device list refresh now runs by default; pass --no-update-devices to opt out.

The default result is a structured outcome containing items, deviceResults, partial, clearing state, counts, and timestamps. Results are automatically written to <datadir>/td-otbr-restapi-diagnostics-fetch-all.json unless --no-auto-output or --output is specified.

If unresolved mesh-local IIDs guard a partial sweep, the diagnostic outcome and its digest-bound .network.json companion are still updated. When no usable diagnostic items are returned, the previous diagnostic dataset, its network companion, and its checkpoint are retained unchanged. Outcome scope uses the normal observed/operator/unknown provenance rules; a guarded outcome does not make the retained data fresh or complete. A scope-write failure is reported as an error, and stale bindings remain invalid. Existing stale bindings are not repaired by cache-only Unified processing.

Every standalone sweep saves its full outcome, not only sweeps affected by the unresolved-IID guard. --items-only changes the returned primary payload to the compatibility array but does not discard outcome metadata. The outcome uses the primary filename with .outcome before its suffix, including custom output paths; --no-auto-output without an explicit output writes neither primary nor outcome.

By default, the roster's mode.fullThreadDevice and mode.device fields classify children. MTD fast requests exactly TLVs 0, 1, 2, 8; optional MTD detail and FTD medium each request exactly 0, 1, 2, 8, 9. mode.device is checked against fullThreadDevice when both are present. Missing, malformed, or conflicting evidence warns and uses the legacy child request progression. rxOnWhenIdle is not used to infer MTD versus FTD.

The two-pass model deliberately reduces coverage relative to the old 7-TLV child request: fast does not request macCounters, and neither pass requests threadStackVersion or mleCounters. Missing evidence stays absent in health evaluation. With both MTD passes enabled, fast runs first and detail is still requested after a fast success; up to four actions per MTD child are possible. Successful fast data is atomically checkpointed before detail begins. If detail fails, the fast data remains selected and the outcome is partial. Same-set retry recovery is reported separately from smaller-TLV fallback.

--types, a non-recommended --preset, or --fallback-preset selects the legacy/custom request policy. Explicit child pass controls cannot be combined with those options. --no-basic-fallback applies only to the final tier of router and unknown-mode legacy progression; --no-fallback disables retries but does not broaden known-child initial TLVs or disable the fast pass.

Child expansion by RLOC (--children-expand-by-rloc)

Off by default. When enabled, the normal extended-address sweep runs first and requests childTable from every selected non-child device, adding it to both the primary and fallback TLV lists only when missing (TLV 16 counts as present). Global presets are not changed. After the sweep, each child entry from this run's parent results is turned into a six-character RLOC destination: (parentRloc16 & 0xFC00) | childId, formatted as 00 plus the four hex digits. For example, parent 0x9400 with child IDs 53 and 14 gives 009435 and 00940e, and parent 0x3800 with child 42 gives 00382a.

  • Scope: expansion is one level deep and uses only the selected parents' current-run tables. It does not read cached data, does not run another discovery pass, and never expands a child's own childTable. Parents must report a router RLOC16 (low ten bits zero, router ID 0–62). Child IDs must be integers 1–511. Booleans, floats, and malformed strings are rejected.
  • Coverage: targets are deduplicated by child RLOC16. A target is skipped as covered when the base sweep already returned a valid extended address with that RLOC16. Duplicate entries with different parent identity or child mode are recorded as conflict and are not queried.
  • Policies: the child's childTable mode selects the existing mode-aware passes (MTD fast and optional detail, FTD medium) with child timing, retry, and disabled-pass rules. Missing or conflicting mode uses the legacy child progression (legacy-unknown-mode). --types, --preset, and --fallback-preset use the same legacy/custom request lists as extended-address children.
  • Identity checks: a response is published or checkpointed only if it has a usable extAddress, its rloc16 matches the target, and its extended address is not already in the results. A later pass must return the same extended address as the accepted pass. If a check fails, no further attempt is made for that target, and earlier validated evidence is kept.
  • Safety: an unresolved or indeterminate action (timeout, transport or HTTP error, ambiguous enqueue) in the base sweep or during expansion stops all later expansion actions; the remaining targets are recorded as not_attempted. Known terminal action failures and invalid responses are recorded for that target and expansion continues with the next one.
  • Outcome: the structured outcome gains a childrenExpansion object with enabled, partial, parentCount, targetCount, attemptedCount, completedCount, coveredCount, per-target results (destination, rloc16, parent identity, childId, mode, policy, status, and the validated extAddress when known), and parent/entry issues. Base deviceResults and counters keep their meaning. An incomplete expansion makes the overall outcome partial. Validated child items are appended to items. Progress and checkpoint labels use rloc:<destination>. If expansion is incomplete and no diagnostic items are usable, the previous dataset, network companion, and checkpoint are retained while the outcome is still written.
  • Compatibility and load: RLOC addressing depends on an OTBR REST build that resolves non-extended destinations correctly. It has been verified only against a user-built Docker image; older servers may return no result or a wrong device, which is reported as invalid_response. RLOC16 values can become stale if a child reattaches between the parent read and the child request. Each target adds up to one action per enabled pass plus retries, so mesh load and runtime grow with the number of children.

Examples:

# Opt-in child expansion by RLOC after the normal extended-address sweep
PYTHONPATH=src python3 -m td_cli otbr-restapi diagnostics fetch-all \
    --children-expand-by-rloc

# Detail-only MTD collection; FTD medium collection remains enabled
PYTHONPATH=src python3 -m td_cli otbr-restapi diagnostics fetch-all \
    --children-fetch-fast-no --children-fetch-detail

# Skip known MTD children while still collecting FTD medium diagnostics
PYTHONPATH=src python3 -m td_cli otbr-restapi diagnostics fetch-all \
    --children-fetch-fast-no --children-fetch-detail-no

Examples:

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    diagnostics fetch-all --preset recommended

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    diagnostics fetch-all --preset recommended --no-update-devices

PYTHONPATH=src python3 -m td_cli otbr-restapi --no-progress \
    diagnostics fetch-all \
    --device-ids aabbccddeeff0011 aabbccddeeff0022 \
    --no-enrich-mac-counters

PYTHONPATH=src python3 -m td_cli otbr-restapi --no-auto-output \
    diagnostics fetch-all --preset recommended

actions

Read or enqueue OTBR task actions.

actions list

List all actions.

actions list [--fields FIELDS] [--with-meta]
Option Description
--fields Sparse-field selector (repeatable)
--with-meta Include collection meta alongside the flattened items

Examples:

PYTHONPATH=src python3 -m td_cli otbr-restapi actions list

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    actions list --fields 'action=id,type,status'

actions get

Get a single action by ID (useful for polling status).

actions get --action-id ACTION_ID [--fields FIELDS]
Option Required Description
--action-id yes Action UUID
--fields no Sparse-field selector (repeatable)

Action status values: pending → active → completed / stopped / failed
(addThreadDeviceTask also uses undiscovered and attempted)

Examples:

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    actions get --action-id 9ecae480-07a0-4b72-869d-15858196144e

# Lightweight status-only poll
PYTHONPATH=src python3 -m td_cli otbr-restapi \
    actions get --action-id 9ecae480-07a0-4b72-869d-15858196144e \
    --fields 'action=id,status'

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    --output data/action-status.json \
    actions get --action-id 9ecae480-07a0-4b72-869d-15858196144e

actions enqueue add-thread-device

Enqueue addThreadDeviceTask to commission a new joiner device.

Warning: This command is currently experimental and requires --lab.

actions enqueue add-thread-device --pskd PSKD
    (--eui EUI | --discerner DISCERNER | --joiner-id JOINER_ID)
    [--timeout SECS]
Option Required Description
--pskd yes Pre-Shared Key for the Device
--eui one of three EUI-64 address
--discerner one of three Joiner discerner value
--joiner-id one of three Joiner ID
--timeout no Task timeout in seconds

Examples:

PYTHONPATH=src python3 -m td_cli otbr-restapi --lab \
    actions enqueue add-thread-device \
    --eui aabbccddeeff0022 \
    --pskd J01NME \
    --timeout 120

PYTHONPATH=src python3 -m td_cli otbr-restapi --lab \
    actions enqueue add-thread-device \
    --discerner 0xabc \
    --pskd S3CRET

actions enqueue get-network-diagnostic

Enqueue getNetworkDiagnosticTask for a destination address.

actions enqueue get-network-diagnostic --destination DEST
    [--types TLV ...]
    [--preset {recommended,full,minimal,basic}]
    [--timeout SECS]
    [--destination-type TYPE]
    [--wait]
Option Default Description
--destination required Destination address
--types recommended set TLV names or integers
--preset — recommended, full, minimal, or basic; overrides --types
--timeout — Server-side task timeout in seconds
--destination-type — extended, mleid, or rloc
--wait off Poll until completion and return the diagnostic result; exit code 4 on stopped/failed

Examples:

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    actions enqueue get-network-diagnostic \
    --destination aabbccddeeff0011 \
    --preset recommended

# Block until complete, return diagnostic result
PYTHONPATH=src python3 -m td_cli otbr-restapi \
    actions enqueue get-network-diagnostic \
    --destination aabbccddeeff0011 \
    --types extAddress rloc16 macCounters mleCounters \
    --timeout 120 \
    --wait

actions enqueue reset-network-diag-counter

Enqueue resetNetworkDiagCounterTask. Only macCounters (TLV 9) and mleCounters (TLV 34) are resettable; passing any other TLV name is rejected client-side before the request is sent.

Warning: This command is currently experimental and requires --lab.

actions enqueue reset-network-diag-counter --types TYPE ...
    [--destination DEST]
    [--timeout SECS]
    [--destination-type TYPE]
Option Required Description
--types yes Counter TLV names: macCounters and/or mleCounters
--destination no Target device address
--timeout no Server-side task timeout in seconds
--destination-type no extended, mleid, or rloc

Examples:

PYTHONPATH=src python3 -m td_cli otbr-restapi --lab \
    actions enqueue reset-network-diag-counter \
    --destination aabbccddeeff0011 \
    --types macCounters mleCounters

PYTHONPATH=src python3 -m td_cli otbr-restapi --lab \
    actions enqueue reset-network-diag-counter \
    --destination aabbccddeeff0011 \
    --types mleCounters \
    --timeout 60

actions enqueue get-energy-scan

Enqueue getEnergyScanTask. All scan parameters are optional; the server applies its own defaults when they are omitted.

actions enqueue get-energy-scan --destination DEST
    --channel-mask CHAN ...
    [--count N]
    [--period N]
    [--scan-duration N]
    [--timeout SECS]
    [--destination-type TYPE]
Option Required Description
--destination yes Target device address
--channel-mask yes One or more channel numbers
--count no Number of scans per channel (server default: 1)
--period no Time between scans in ms (server default: 32)
--scan-duration no Duration per channel scan in ms (server default: 0)
--timeout no Server-side task timeout in seconds
--destination-type no extended, mleid, or rloc

Examples:

# Minimal — server uses defaults for count, period, scan-duration
PYTHONPATH=src python3 -m td_cli otbr-restapi \
    actions enqueue get-energy-scan \
    --destination aabbccddeeff0011 \
    --channel-mask 11 15

# Explicit parameters
PYTHONPATH=src python3 -m td_cli otbr-restapi \
    actions enqueue get-energy-scan \
    --destination aabbccddeeff0011 \
    --channel-mask 11 15 \
    --count 3 --period 32 --scan-duration 50 \
    --timeout 60

# Full channel scan 11-26
PYTHONPATH=src python3 -m td_cli otbr-restapi \
    actions enqueue get-energy-scan \
    --destination aabbccddeeff0011 \
    --channel-mask 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 \
    --count 5 --period 32 --scan-duration 100 \
    --timeout 120

actions enqueue update-device-collection

Enqueue updateDeviceCollectionTask and return immediately with the action record. Use actions get to poll status, or use devices fetch for the combined enqueue-wait-list workflow.

actions enqueue update-device-collection
    [--device-count N]
    [--max-age SECS]
    [--max-retries N]
    [--timeout SECS]
Option Default Description
--device-count 255 Max devices to discover
--max-age 60 Max age of cached device entries in seconds
--max-retries 2 Max retries per device
--timeout 5 Server-side task timeout in seconds

Examples:

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    actions enqueue update-device-collection

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    actions enqueue update-device-collection \
    --device-count 20 --max-age 60 --max-retries 3 --timeout 90

# Capture action ID and poll manually
ACTION_ID=$(PYTHONPATH=src python3 -m td_cli otbr-restapi \
    actions enqueue update-device-collection | jq -r '.[0].id')
echo "Enqueued action: $ACTION_ID"

while true; do
    STATUS=$(PYTHONPATH=src python3 -m td_cli otbr-restapi \
        actions get --action-id "$ACTION_ID" | jq -r '.status')
    echo "status: $STATUS"
    [[ "$STATUS" == "completed" || "$STATUS" == "stopped" || "$STATUS" == "failed" ]] && break
    sleep 2
done

# Preferred: enqueue + wait + list in one shot
PYTHONPATH=src python3 -m td_cli otbr-restapi \
    devices fetch --device-count 20 --task-timeout 90

mesh-diagnostics

Fetch mesh-diagnostic TLVs via otMeshDiag. These require an additional round-trip on the server and have higher latency than standard diagnostic TLVs.

Router / leader devices only. The server omits children, childIpv6Addresses, and routerNeighbors for child devices (RLOC16 lower 10 bits non-zero). Use --routers-only on fetch-all or check roles first:

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    devices list --fields 'threadDevice=extAddress,role,hostName'

Common per-device options for children, child-ipv6, router-neighbors, and fetch:

Option Default Description
--device-id required Device extAddress (16-char hex)
--task-timeout 15 Server-side task timeout in seconds
--poll-timeout derived Client deadline derived from task timeout and poll interval; 20 seconds by default
--destination-type extended Destination addressing mode: extended, mleid, or rloc

mesh-diagnostics children

Fetch the child table for a device (TLV 29).

mesh-diagnostics children --device-id DEVICE_ID
    [--task-timeout SECS] [--poll-timeout FLOAT] [--destination-type TYPE]

Examples:

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    mesh-diagnostics children --device-id aabbccddeeff0011

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    --output data/children-aabb.json \
    mesh-diagnostics children --device-id aabbccddeeff0011

mesh-diagnostics child-ipv6

Fetch child IPv6 addresses for a device (TLV 30).

mesh-diagnostics child-ipv6 --device-id DEVICE_ID
    [--task-timeout SECS] [--poll-timeout FLOAT] [--destination-type TYPE]

Examples:

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    mesh-diagnostics child-ipv6 --device-id aabbccddeeff0011

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    mesh-diagnostics child-ipv6 --device-id aabbccddeeff0011 --task-timeout 600

mesh-diagnostics router-neighbors

Fetch router neighbor table for a device (TLV 31).

mesh-diagnostics router-neighbors --device-id DEVICE_ID
    [--task-timeout SECS] [--poll-timeout FLOAT] [--destination-type TYPE]

Examples:

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    mesh-diagnostics router-neighbors --device-id aabbccddeeff0011

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    --output data/router-nbrs-aabb.json \
    mesh-diagnostics router-neighbors --device-id aabbccddeeff0011

mesh-diagnostics fetch

Fetch a caller-specified subset of mesh-diagnostic TLVs for one device. Defaults to all three TLVs when --types is omitted.

mesh-diagnostics fetch --device-id DEVICE_ID
    [--types {children,childIpv6Addresses,routerNeighbors} ...]
    [--task-timeout SECS] [--poll-timeout FLOAT] [--destination-type TYPE]

Examples:

# All three TLVs
PYTHONPATH=src python3 -m td_cli otbr-restapi \
    mesh-diagnostics fetch --device-id aabbccddeeff0011

# Selected subset
PYTHONPATH=src python3 -m td_cli otbr-restapi \
    mesh-diagnostics fetch --device-id aabbccddeeff0011 \
    --types children childIpv6Addresses

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    mesh-diagnostics fetch --device-id aabbccddeeff0011 --types children

mesh-diagnostics fetch-all

Fetch mesh diagnostics for all known devices (or a given list), one device at a time. Device list is refreshed automatically before fetching (pass --no-update-devices to skip).

mesh-diagnostics fetch-all [--device-ids ID ...]
    [--types {children,childIpv6Addresses,routerNeighbors} ...]
    [--task-timeout SECS]
    [--poll-timeout FLOAT]
    [--destination-type TYPE]
    [--no-update-devices]
    [--routers-only]
    [--preserve-diagnostics]
    [--items-only]
Option Default Description
--device-ids all devices Space-separated extAddress IDs to query
--types all three children, childIpv6Addresses, routerNeighbors
--task-timeout 15 Server-side task timeout per device in seconds
--poll-timeout derived Client deadline derived from task timeout and poll interval; 20 seconds by default
--destination-type extended Destination addressing mode: extended, mleid, or rloc
--no-update-devices off Skip updateDeviceCollectionTask; use the cached device list
--routers-only off Filter to router devices only (RLOC16 lower 10 bits == 0); skips child devices that return empty mesh-diag records
--preserve-diagnostics off Keep the existing diagnostics collection instead of clearing once for this full sweep
--items-only off Return only successful diagnostic items; still save the full outcome companion when output is enabled

Note: --update-devices has been replaced by --no-update-devices. Device list refresh now runs by default.

Results are automatically written to <datadir>/td-otbr-restapi-mesh-diagnostics-fetch-all.json unless --no-auto-output or --output is specified.

Examples:

# Router devices only (recommended)
PYTHONPATH=src python3 -m td_cli otbr-restapi \
    mesh-diagnostics fetch-all --routers-only

# All devices, skip device refresh
PYTHONPATH=src python3 -m td_cli otbr-restapi \
    mesh-diagnostics fetch-all --no-update-devices

# Two specific devices, router-neighbors only
PYTHONPATH=src python3 -m td_cli otbr-restapi \
    mesh-diagnostics fetch-all \
    --device-ids aabbccddeeff0011 aabbccddeeff0022 \
    --types routerNeighbors

topology

Run the full topology sweep in a single command. Executes three steps in sequence and writes all output files automatically under --datadir:

Step Action Output file
1 devices fetch (updateDeviceCollectionTask) td-otbr-restapi-devices-fetch.json
2 diagnostics fetch-all --preset recommended td-otbr-restapi-diagnostics-fetch-all.json
3 mesh-diagnostics fetch-all --routers-only td-otbr-restapi-mesh-diagnostics-fetch-all.json
topology [--preset {recommended,full,minimal,basic}]
         [--child-task-timeout SECS]
         [--child-poll-timeout FLOAT]
         [--children-fetch-fast | --children-fetch-fast-no]
         [--children-fetch-detail | --children-fetch-detail-no]
         [--skip-devices]
         [--skip-diagnostics]
         [--skip-mesh-diagnostics]
         [--no-update-devices]
         [--no-enrich-mac-counters]
         [--no-fallback]
         [--fallback-preset {medium,minimal,basic}]
         [--preserve-diagnostics]
Option Default Description
--preset recommended TLV preset for the diagnostics step
--child-task-timeout 30 Server-side timeout for child diagnostic actions
--child-poll-timeout derived Independent client polling budget for child actions
--children-fetch-fast / --children-fetch-fast-no fast enabled Enable or disable the MTD fast pass
--children-fetch-detail / --children-fetch-detail-no detail disabled Enable or disable the optional MTD detail pass
--skip-devices off Skip Step 1 (device refresh); use the current device list for subsequent steps
--skip-diagnostics off Skip Step 2 (network diagnostics fetch-all)
--skip-mesh-diagnostics off Skip Step 3 (mesh diagnostics fetch-all)
--no-update-devices off When --skip-devices is set, also skip updateDeviceCollectionTask in Steps 2 and 3
--no-enrich-mac-counters off Disable MAC counter enrichment on the diagnostics result
--no-fallback off Disable additional actions while retaining known-child initial sets
--fallback-preset off Opt in to one terminal-failure retry for Step 2 with medium, minimal, or basic
--preserve-diagnostics off Keep existing diagnostics instead of the default one-time clear before Step 2

Progress for each step and each device is printed to stderr. Pass --no-progress (global flag) to suppress. Compatibility arrays remain in the three primary files. The diagnostic and mesh steps also write .outcome.json sidecars with partial/per-device metadata. Topology's diagnostics step uses the same mode-aware child policy and pass controls documented under diagnostics fetch-all; the mesh step remains independent.

Examples:

# Full sweep with defaults
PYTHONPATH=src python3 -m td_cli otbr-restapi topology

# Remote OTBR, custom data directory
PYTHONPATH=src python3 -m td_cli otbr-restapi \
    --host 192.168.1.10 --datadir /tmp/topology \
    topology

# Skip device refresh (already done)
PYTHONPATH=src python3 -m td_cli otbr-restapi topology --skip-devices

# Diagnostics step only
PYTHONPATH=src python3 -m td_cli otbr-restapi topology --skip-mesh-diagnostics

# Silent (no progress output)
PYTHONPATH=src python3 -m td_cli otbr-restapi --no-progress topology

Exit Codes

Code Constant Meaning
0 EXIT_SUCCESS Success
1 EXIT_UNEXPECTED Unexpected / unhandled error
2 EXIT_USAGE Usage / argument error (OTBRUsageError)
3 EXIT_CONNECTION Connection error (OTBRConnectionError)
4 EXIT_HTTP HTTP error, or action stopped/failed (OTBRHTTPError, OTBRActionError)
5 EXIT_INVALID_RESPONSE Invalid or unexpected API response (OTBRInvalidResponseError)

Auto-Output File Names

When --no-auto-output is not set and --output is not specified, fetch/list commands automatically write results to <datadir>/<filename>:

Command Auto-output filename
devices list td-otbr-restapi-devices-list.json
devices fetch td-otbr-restapi-devices-fetch.json
diagnostics list td-otbr-restapi-diagnostics-list.json
diagnostics fetch td-otbr-restapi-diagnostics-fetch.json
diagnostics fetch-all td-otbr-restapi-diagnostics-fetch-all.json
actions list td-otbr-restapi-actions-list.json
mesh-diagnostics fetch td-otbr-restapi-mesh-diagnostics-fetch.json
mesh-diagnostics fetch-all td-otbr-restapi-mesh-diagnostics-fetch-all.json
topology (step 1 — devices) td-otbr-restapi-devices-fetch.json
topology (step 2 — diagnostics) td-otbr-restapi-diagnostics-fetch-all.json
topology (step 3 — mesh-diagnostics) td-otbr-restapi-mesh-diagnostics-fetch-all.json

Topology also writes td-otbr-restapi-diagnostics-fetch-all.outcome.json and td-otbr-restapi-mesh-diagnostics-fetch-all.outcome.json. These sidecars distinguish complete and partial sweeps without changing the array shape consumed by existing dashboard code.

Commands with an automatic or explicit output path may atomically update a sibling .partial.json checkpoint while collection is running. The web server exposes checkpoint metadata to the dashboard for progressive rendering. A checkpoint is transient and does not replace the mandatory final output.

Action POST requests are single-attempt because the OTBR action API has no idempotency key. A lost POST response is reported as indeterminate_enqueue; the client does not blindly create a replacement action. Idempotent reads may use bounded transport retries.

Note: The topology command always writes its three files regardless of --no-auto-output because all output is file-based (the command returns nothing to stdout).


--fields Sparse Field Reference

The --fields option restricts which attributes are returned. The server filters at the source, so only the requested attributes are transmitted.

Syntax: --fields 'TYPE=field1,field2' or --fields TYPE (all fields of that type).
Repeatable: pass --fields multiple times to select fields from more than one type.

The TYPE matches the JSON:API resource type value for the collection being queried.


threadDevice / threadBorderRouter — Devices fields

Used with devices list, devices get, devices fetch, node get.

Field Type Description
extAddress string (hex) 64-bit IEEE 802.15.4 extended address — device ID
mlEidIid string (hex) Mesh-Local EID Interface Identifier
omrIpv6Address string (IPv6) Off-Mesh-Routable IPv6 address
hostName string mDNS hostname (.local)
role string Thread role: leader, router, child, sleepy-child
mode object Device mode flags
mode.deviceTypeFTD bool true = Full Thread Device
mode.rxOnWhenIdle bool true = receiver always on
mode.fullNetworkData bool true = subscribes to full network data
created ISO 8601 Timestamp when the device entry was created
updated ISO 8601 Timestamp when the device entry was last updated

Additional fields present only on threadBorderRouter items:

Field Type Description
rloc16 string (hex) 16-bit RLOC address
routerId number Router ID (upper 6 bits of RLOC16)
rlocAddress string (IPv6) Full RLOC IPv6 address
routerCount number Number of active routers in the network
networkName string Thread network name
extPanId string (hex) Extended PAN ID
leaderData object Leader data
leaderData.partitionId number Partition ID
leaderData.weighting number Leader weighting
leaderData.dataVersion number Network data version
leaderData.stableDataVersion number Stable network data version
leaderData.leaderRouterId number Current leader's router ID
baId string (hex) Border Agent ID
baState string Border Agent state

Examples:

devices list --fields 'threadDevice=hostName,role,mode'
devices list --fields threadDevice
node get --fields 'threadBorderRouter=extAddress,rloc16,baId'

networkDiagnostics — Diagnostics fields

Used with diagnostics list, diagnostics get, diagnostics fetch, diagnostics fetch-all.

Field TLV Description
extAddress 0 64-bit extended MAC address
rloc16 1 16-bit RLOC (hex string, e.g. 0x1400)
routerId 1 Router ID (derived from RLOC16; routers only)
mode 2 Device mode flags (deviceTypeFTD, rxOnWhenIdle, fullNetworkData)
timeout 3 Max polling period for SEDs (seconds)
connectivity 4 Connectivity info (parentPriority, linkQuality1/2/3, leaderCost, idSequence, activeRouters, sedBufferSize, sedDatagramCount)
route 5 Route64 info: idSequence, routeData[] (each with routeId, linkQualityIn, linkQualityOut, routeCost)
leaderData 6 Leader data object
networkData 7 Network data (hex string)
ipv6Addresses 8 List of IPv6 addresses
macCounters 9 MAC packet counters (raw: ifInUnknownProtos, ifInErrors, ifOutErrors, ifInUcastPkts, ifInBroadcastPkts, ifInDiscards, ifOutUcastPkts, ifOutBroadcastPkts, ifOutDiscards; enriched: ifintotalpkts, ifouttotalpkts, iftotalpkts, iftotalerrors, iftotaldiscards, plus per-direction error/discard totals)
batteryLevel 14 Battery level (0–100)
supplyVoltage 15 Supply voltage (mV)
childTable 16 Array of child entries (childId, timeout, linkQuality, mode)
channelPages 17 Supported channel pages (hex string)
maxChildTimeout 19 Max child timeout (seconds)
eui64 23 EUI-64 address
version 24 Thread version number
vendorName 25 Vendor name string
vendorModel 26 Vendor model string
vendorSwVersion 27 Vendor software version string
threadStackVersion 28 Thread stack version string
children 29 Mesh-diag child table (routers only) — requires otMeshDiag
childIpv6Addresses 30 Mesh-diag child IPv6 addresses (routers only) — requires otMeshDiag
routerNeighbors 31 Mesh-diag router neighbor table (routers only) — requires otMeshDiag
mleCounters 34 MLE counters (radioDisabledCount, detachedRoleCount, childRoleCount, routerRoleCount, leaderRoleCount, attachAttemptsCount, partIdChangesCount, betterPartIdAttachAttemptsCount, newParentCount, plus time counters)
isBorderRouter ext true if device is a border router
isLeader ext true if device is the current leader
isPrimaryBBR ext true if device is the primary Backbone Border Router
hostsService ext true if device hosts a Thread service
brCounters ext Border routing packet counters

Examples:

diagnostics list --fields 'networkDiagnostics=extAddress,rloc16'
diagnostics list --fields 'networkDiagnostics=extAddress,macCounters,mleCounters'
diagnostics list --fields 'networkDiagnostics=extAddress,vendorName,vendorModel,vendorSwVersion,threadStackVersion'

action — Actions fields

Used with actions list, actions get.

Field Description
id UUID assigned by the server
type Task type: addThreadDeviceTask, getNetworkDiagnosticTask, resetNetworkDiagCounterTask, getEnergyScanTask, updateDeviceCollectionTask
status pending → active → completed / stopped / failed (addThreadDeviceTask also: undiscovered, attempted)
created ISO 8601 creation timestamp
destination Target device address
destinationType extended, mleid, or rloc
types Requested TLV names (diagnostic and reset tasks)
timeout Countdown timeout in seconds
eui Joiner EUI-64 (addThreadDeviceTask)
pskd Pre-Shared Key for the Device (addThreadDeviceTask)
maxAge Max cache age in seconds (updateDeviceCollectionTask)
maxRetries Max retries per device (updateDeviceCollectionTask)
deviceCount Target device count (updateDeviceCollectionTask)
channelMask Channel list (getEnergyScanTask)
count Scan count (getEnergyScanTask)
period Scan period in ms (getEnergyScanTask)
scanDuration Scan duration in ms (getEnergyScanTask)

Examples:

actions list --fields 'action=id,status,type'
actions get --action-id <UUID> --fields 'action=id,status,destination'

Worked Examples

1. Discover devices — one-shot fetch

PYTHONPATH=src python3 -m td_cli otbr-restapi devices fetch

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    --output data/devices.json \
    devices fetch

2. Discover devices — manual enqueue → poll → list

# Enqueue and capture the action ID
ACTION_ID=$(PYTHONPATH=src python3 -m td_cli otbr-restapi \
    actions enqueue update-device-collection | jq -r '.[0].id')
echo "Enqueued: $ACTION_ID"

# Poll until terminal status
while true; do
    STATUS=$(PYTHONPATH=src python3 -m td_cli otbr-restapi \
        actions get --action-id "$ACTION_ID" | jq -r '.status')
    echo "status: $STATUS"
    [[ "$STATUS" == "completed" || "$STATUS" == "stopped" || "$STATUS" == "failed" ]] && break
    sleep 2
done

# List the refreshed devices
PYTHONPATH=src python3 -m td_cli otbr-restapi devices list

3. Fetch diagnostics for a single device

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    diagnostics fetch --device-id aabbccddeeff0011 --preset recommended

4. Fetch diagnostics for all devices

# Refresh device list and fetch (auto-saved to file)
PYTHONPATH=src python3 -m td_cli otbr-restapi \
    diagnostics fetch-all --preset recommended

# Skip device refresh when the list was just updated
PYTHONPATH=src python3 -m td_cli otbr-restapi \
    diagnostics fetch-all --preset recommended --no-update-devices

# Explicit output path
PYTHONPATH=src python3 -m td_cli otbr-restapi \
    --output data/all-diagnostics.json \
    diagnostics fetch-all --preset recommended

5. Enqueue a diagnostic task and wait inline

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    actions enqueue get-network-diagnostic \
    --destination aabbccddeeff0011 \
    --preset recommended \
    --wait

6. Get node status and dataset

PYTHONPATH=src python3 -m td_cli otbr-restapi node get
PYTHONPATH=src python3 -m td_cli otbr-restapi node state get
PYTHONPATH=src python3 -m td_cli otbr-restapi node dataset active get
PYTHONPATH=src python3 -m td_cli otbr-restapi node dataset active get --text

7. Mesh diagnostics for a device

# All three TLVs for one device
PYTHONPATH=src python3 -m td_cli otbr-restapi \
    mesh-diagnostics fetch --device-id aabbccddeeff0011

# Child table only
PYTHONPATH=src python3 -m td_cli otbr-restapi \
    mesh-diagnostics children --device-id aabbccddeeff0011

# All mesh diagnostics for all router devices (recommended)
PYTHONPATH=src python3 -m td_cli otbr-restapi \
    mesh-diagnostics fetch-all --routers-only

8. Commission a new joiner device

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    actions enqueue add-thread-device \
    --pskd J01NME \
    --eui aabbccddeeff0022 \
    --timeout 120

9. Reset diagnostic counters

PYTHONPATH=src python3 -m td_cli otbr-restapi --lab \
    actions enqueue reset-network-diag-counter \
    --destination aabbccddeeff0011 \
    --types macCounters mleCounters

10. Sparse field selection

# Device hostname and role
PYTHONPATH=src python3 -m td_cli otbr-restapi \
    devices list --fields 'threadDevice=hostName,role'

# Action id and status only (lightweight polling view)
PYTHONPATH=src python3 -m td_cli otbr-restapi \
    actions list --fields 'action=id,status,type'

# Single action with sparse fields
PYTHONPATH=src python3 -m td_cli otbr-restapi \
    actions get --action-id 9ecae480-07a0-4b72-869d-15858196144e \
    --fields 'action=id,status'

11. Target a non-default OTBR host

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    --host 192.168.1.100 --port 8081 \
    devices list

PYTHONPATH=src python3 -m td_cli otbr-restapi \
    --base-url http://192.168.1.100:8081 \
    devices list

12. Raw envelope output

PYTHONPATH=src python3 -m td_cli otbr-restapi --raw devices list

13. Full topology sweep

# Default sweep — all three steps, auto-save all files
PYTHONPATH=src python3 -m td_cli otbr-restapi topology

# Skip mesh diagnostics (faster)
PYTHONPATH=src python3 -m td_cli otbr-restapi topology --skip-mesh-diagnostics

# Remote OTBR, custom data directory
PYTHONPATH=src python3 -m td_cli otbr-restapi \
    --host 192.168.1.10 --datadir /tmp/scan \
    topology