Schema Reference
Field-by-field references for the definitions behind
Settings → My Master Data. Pick a schema below.
Each schema ships a built-in set (provided by inMotion, read-only — also called Global master data) alongside your account's own entries; an account entry replaces a built-in one when they share the same key. Field names follow each format's own convention — hyphenated for Activity Types and Standard Data Types, camelCase for Device Configs — so copy them exactly as shown here.
Each schema ships a built-in set (provided by inMotion, read-only — also called Global master data) alongside your account's own entries; an account entry replaces a built-in one when they share the same key. Field names follow each format's own convention — hyphenated for Activity Types and Standard Data Types, camelCase for Device Configs — so copy them exactly as shown here.
An Activity Type is the kind of thing an activity records — Tractor, Car,
Weather site — and it sets that activity's default accuracy, speed band, navigation
model, icon and units. Your account's entries live under Settings → My Master Data
→ Activity Types (a per-entry editor, no draft/publish step); this reference is
for hand-editing or reviewing one rather than just using that editor.
Activity Type entry
| Field | Required | Type | Notes |
|---|---|---|---|
key |
Required | string | Hierarchical identifier, domain/category/type — e.g.
agriculture/machinery/tractor, transport/vehicle/car,
site/weather, other/unknown. Lower-cased on import and
used as the entry's identity: re-importing the same key updates that
entry in place. Profile activity-regex patterns
and a Device Config's
profile.compatibleActivityTypes
list both match against these keys. |
name |
Required | string | Display name. |
highest-accuracy |
Required | enum | best, high, medium, low. The best
position-fix accuracy this activity is expected to warrant. Case-insensitive; an
unrecognised value fails the import. |
nominal-speed |
Required | enum | very-fast, fast, medium, slow,
very-slow, fixed. Typical travel-speed band;
fixed is a stationary installation (e.g. a weather site).
Case-insensitive; an unrecognised value fails the import. |
navigation-nature |
Required | enum | fitness, automotive, general,
other. The broad movement model track processing should assume.
Case-insensitive; an unrecognised value fails the import. |
icon |
Required | string | Icon name, resolved by each client (web app, inMotion Track)
against its own icon mapping — not validated on import. Two tiers of valid names:
Curated names (below) — guaranteed to look intentional (not a generic fallback) on every client, since each one has a specific icon chosen for it on each platform. Any icon name from Google's Material Symbols library (e.g. icon: kayaking)
— not curated, so it renders using that icon directly rather than a
hand-picked substitute, but works without a code change on either client.
An unrecognised name (neither a curated name nor a real Material Symbols name) falls back to a generic question icon on every client.
Curated names: Farm equipment (a dedicated icon font, since neither client's general-purpose icon set covers this domain): atv, bailer, chaser,
cultivator, harvester, loader, planter,
spreader, sprayer, tractor.
Vehicles & transport: bus, car, crane,
ems, ferry, glider, helicopter,
motorcycle, off-road, plane, sailboat,
ship, train, truck.
Human-powered / fitness: bicycle, golf,
hiking, mountain-bike, run, skating,
skiing, walk, wheelchair.
Other: camera, meh, question,
user, weather. |
colour |
Optional | string | Colour name for the activity's map / UI accent — e.g. brown,
blue, grey. Free-form lowercase (quoted in YAML). |
profile |
Required | string (profile code) | Single-letter inMotion profile code — e.g.
A (Agriculture), T (Transportation), W
(Weather). See the Profiles tab. |
allowed-adapters |
Optional | list of strings | Legacy — still stored, no longer consulted. Old regex patterns matched
against a mobile adapter code to gate which sensors an activity could use; replaced
by a Device Config's
profile.compatibleActivityTypes
list. Default empty. |
preferred-unit-system |
Optional | enum | si (default), imperial, aviation,
marine. The unit system this activity's data is shown in unless the
viewer overrides it. An unrecognised value falls back to si. |
deprecated |
Optional | boolean | Default false. Hides the type from new-activity pickers without
touching existing activities. Set this instead of deleting the entry —
see Scope & import. |
Fields not listed here are ignored when the entry is loaded.
Example
activity-types: - key: agriculture/machinery/tractor name: Tractor highest-accuracy: best nominal-speed: slow navigation-nature: automotive allowed-adapters: - l:[o|m|b]:.* icon: tractor colour: 'brown' profile: A - key: transport/aircraft/commercial name: Commercial Aircraft highest-accuracy: medium nominal-speed: very-fast navigation-nature: general icon: plane colour: 'cyan' preferred-unit-system: aviation profile: V - key: transport/water/kayak name: Kayak highest-accuracy: best nominal-speed: slow navigation-nature: general icon: kayaking # a raw Material Symbols name, not curated - see the icon field's notes above colour: 'cyan' profile: B
Scope & import
- Built-in vs your account. The built-in catalogue is read-only. On a plan
that includes
custom-activity-type, your account can add its own entries under Settings → My Master Data → Activity Types using the same fields above. An entry whosekeymatches a built-in one overrides it for your account; a newkeyis added alongside. Custom entries can be named in a Device Config'sprofile.compatibleActivityTypesand are delivered to your account's apps. - Create-or-update, keyed by
key. Loading entries adds new keys and updates changed ones. It never deletes: an entry removed from the source stays in the database — retire a type withdeprecated: trueinstead. (Deleting a custom entry in the editor does remove that row.) - For inMotion operators. The built-in
catalogue loads from
conf/master-data/activity-types.yml(bundled) or theapp-data/master-data/activity-types.ymldeploy override, as one list under a top-levelactivity-types:key; the block is skipped if that key is absent. A deliberate clear-and-reload is the only path that wipes the table. - The API master-data endpoint exposes these read-only as
activityTypes, with the enum fields rendered as short codes rather than the names above.
A Standard Data Type pins down the shared meaning, units and display behaviour of
one kind of value — air temperature, speed, load — so readings from different
sensors line up. Your account's entries live in the My Standard Types tab of
Settings; this reference is
for hand-editing or reviewing one rather than just using that editor. Two entry kinds
follow: Data Type and the smaller Data Variant Type it can point at.
Data Type entry
| Field | Required | Type | Notes |
|---|---|---|---|
key |
Required | string | Entry identity within your account. Replaces a built-in entry of the same key. |
name |
Required | string | May embed a ${variant} placeholder token. |
kind |
Required | enum | One of BYTE, CHAR, SHORT, INTEGER,
LONG, BOOLEAN, FLOAT, DOUBLE,
NUMERIC, DATETIME, TIME, STRING,
TEXT. Matching is case-insensitive - YAML in practice uses lowercase
(e.g. "numeric"). |
base-units |
Required | string | Free-form - not restricted to an enum (observed examples: m/s,
degC, hPa, ug/m^3). Paired with
attributes.display-units to convert to a display unit, e.g. base
m/s → display km/h. |
profiles |
Optional | list of enum (profile code) | e.g. ["A"], ["A", "T"] - single-letter codes from the
Profiles tab. If omitted, the data type applies to all
profiles. |
description |
Optional | string | Longer-form explanation shown alongside name. In practice only set on
entries whose name is abbreviated (e.g. name: "Min. Air
Temperature" → description: "Minimum Air Temperature") -
most entries omit it and rely on name alone. |
variant-type |
Optional | string (key ref) | External reference — must match a Data Variant Type key (built-in
or account scope). A dangling reference is flagged. |
modulo |
Optional | boolean | Despite the name, this is a boolean flag rather than a modulus number - e.g.
physical/heading sets modulo: true to mark that its
valid-range ([0, 360]) wraps rather than clamps. |
valid-range |
Optional | tuple [lower, upper] |
Must be exactly 2 numbers if present. |
synonyms |
Optional | list of strings | Legacy/alternate field-name aliases for migration and lookup, e.g.
["windSpeed"], ["lat"]. |
deprecated |
Optional | boolean | Soft-deprecation flag - hides/flags the entry without deleting it. |
attributes |
Optional | object | See Data Type attributes below. Unlike the top-level Device Config document, this object isn't restricted to a known key set - unrecognised keys are accepted and passed through. |
Data Type attributes (nested object, all fields optional)
Structurally validated - the client checks type, shape, and enum membership.
| Field | Type |
|---|---|
display-units | {si, imperial}, each a display-scale string, e.g. si: "0.1 km/h". |
display-units-unicode | {si, imperial}, unicode display of the unit symbol, e.g. si: '°C'. |
payload-encoding | {si, imperial}, each integer 0–15 - number of encoded bytes/precision slots for the wire payload. |
display-order | enum: lowest, low, medium, high, highest - relative priority for ordering the data type in a UI list. |
display-plot-style | {colour: enum c0–c7, fill: boolean} - plot line colour slot and whether the area under the line is filled. |
display-stats-style | enum: min-only, min-max, avg-only, min-avg-max, max-only. |
display-allowed | list, values restricted to live, tracker, plot, hist, map, qc, dashboard - the UI surfaces the data type is displayed on. |
display-axis-range | {lower, upper} (numeric, required), step (numeric, optional) - e.g. {lower: 0, upper: 360, step: 30} sizes axis tick/gridline spacing. |
spike-filter | {delta, max-repeats} (numeric) - a jump of more than delta between consecutive readings is treated as a spike and suppressed for up to max-repeats occurrences. |
Free-form - accepted and passed through, but not structurally validated client-side.
| Field | Observed usage |
|---|---|
display-axis-labels | Map of numeric axis value → short label string, for compass-style axes, e.g. {0: "N", 90: "E", 180: "S", 270: "W"}. |
editing-allowed | Boolean, present on almost every entry. Whether the value is user-editable in the app (true for planned/target/manual-entry values) vs. read-only/derived (false). |
relative-to | String - reference datum for a vertical measurement, e.g. "MSL" (mean sea level) on altitude/depth types. |
positive | String, "up" or "down" - direction of increasing value relative to relative-to. |
angle-convention | String, e.g. "degrees_north" - which compass convention the angle is measured against. |
vector-components | List of related data type keys forming a vector pair, e.g. ["sensed/wind-speed", "sensed/wind-direction"]. |
related-data-types | List of related data type keys shown together in the UI (e.g. a value and its planned/applied counterpart, or a min/max pair). |
Data Variant Type entry
| Field | Required | Type | Notes |
|---|---|---|---|
key |
Required | string | Entry identity. Referenced by a Data Type's variant-type. |
name |
Required | string | Display name of the variant group, e.g. "Spreading Material". |
description |
Optional | string | Longer-form explanation of the variant group; most entries omit it in favour of name. |
deprecated |
Optional | boolean | Soft-deprecation flag, same semantics as the Data Type field. |
values |
Required | non-empty list of {key, name} |
Internal nested structure: the variant's selectable option set, e.g.
{key: "lime", name: "Lime"}. |
Cross-entry rules
- A Data Type's
variant-typenames the Data Variant Type it draws its options from (many Data Types can share one). - A Data Variant Type can't be deleted while any Data Type still points at it.
- An account entry with the same
keyas a built-in entry replaces it for that account; a differentkeyis added alongside. - A Data Type
keymay embed a${variant}token, tying it to the referenced variant type's set of keys.
Example
key: "sensed/particulate-matter/10" name: "10um Particulate Matter" kind: "double" base-units: "ug/m^3" profiles: ["E", "W"] attributes: display-allowed: ["dashboard", "hist", "live", "map", "plot"] display-order: "high" display-plot-style: colour: "c1" fill: "false" display-stats-style: "min-avg-max" display-units: imperial: "ug/m^3" si: "ug/m^3" editing-allowed: "true"
A Device Config describes how one sensor or piece of machinery reports data —
the activity types it suits, its settings, and the values it produces. Your account's
entries live in the My Device Configs tab of
Settings; this reference
is for hand-editing or reviewing one rather than just using that editor. One entry is one
profile, optionally plus a transport block: gatt for Bluetooth
(BLE) devices, or mqtt for devices that publish over MQTT.
Top-level document
| Field | Required | Type | Notes |
|---|---|---|---|
label |
Required | string | Display name. |
type |
Required | string | Device kind. 'ble' triggers the gatt requirement below;
'mqtt' triggers the mqtt requirement;
'internal' means using a module already bundled with the target environment
(usually the mobile app); 'none' otherwise. |
schemaVersion |
Required | integer | Always 2 - the current document format. |
version |
Optional | string | Display-only in the YAML body - not the authoritative version. See Versioning. |
profile |
Required | object | See profile object below. |
variables |
Optional | object | Standard Data Type registry that transport-block fields bind to; see
variables object below. Required in practice
whenever gatt/mqtt fields reference variables by name. |
gatt |
Conditional | object | Required only if type == 'ble'; see gatt
object below. Omitted entirely for non-BLE types. |
mqtt |
Conditional | object | Required only if type == 'mqtt'; see mqtt
object below. Omitted entirely for non-MQTT types. |
Any key outside this set is flagged as unknown.
profile object
| Field | Required | Type | Notes |
|---|---|---|---|
name |
Required | string | The name of the profile - sole identity of the entry within its scope. |
compatibleActivityTypes |
Optional | list | Activity types the profile can be applied to. If missing or empty, it applies to all activity types. |
profiles |
Optional | list | inMotion profile codes (see the Profiles tab), restricting which domain(s) of interest the device applies to. |
symbol |
Optional | string | External reference into the mobile app's icon set. A curated set of aliases still works
for backward compatibility (e.g. keyboardSensor, heartSensor,
bluetoothSensor), but any icon name from Google's
Material Symbols library also works directly - e.g.
symbol: thermostat. An unrecognised name falls back to a generic Unknown
icon.
symbol: thermostat |
managedAdapter |
Optional | string | Identifier of the adapter implementation that drives this device, e.g.
ble-generic for the shared generic-BLE adapter, or a device-specific id
such as mock-avery-indicator-ble. |
deviceDiscovery |
Optional | object | {adapterType, settings: {name, address}}. Configures how the device is
found/paired; adapterType selects the discovery strategy (e.g.
usc-serial), and settings.name/settings.address
map discovered-device fields to setting keys. |
settings |
Optional | object | User-configurable settings for the device, keyed by setting name. Each entry:
{name, type, default?, required?, isEnumerable?, enums?}, where
enums is a list of {id, title}. |
data |
Optional | object | The data fields this device produces, keyed by field name. Each entry:
{name, units, type, required?, format?}. |
platforms |
Optional | list | Client platforms the profile is available on: ios-handheld,
ios-tablet, android-handheld, android-tablet. |
type |
Optional | enum | Broad device-behavior category: fitness (BLE fitness-machine style, e.g.
heart rate/cycling), geo-vector (location/navigation), manual
(user-entered readings, e.g. rate/area spraying), serial (raw serial
passthrough). |
variables object
A map of
name → entry. The Standard Data Type registry a transport block's fields
bind to: gatt/mqtt fields carry only decode mechanics and reference a
variable by name, and that name resolves here to a Standard Data Type and units. One registry shape,
used identically by both transports - an mqtt block is "a gatt block for a
different transport". A referenced-but-undeclared variable name is flagged; an unused entry is not.
| Field | Required | Type | Notes |
|---|---|---|---|
standardDataType |
Required | string (key ref) | External reference - must resolve to a Standard Data Type in the catalog (built-in or
account scope): its key, one of that entry's declared synonyms,
or a $variant-suffixed ref matching a ${variant} template key.
A reference that resolves to none of those is flagged. |
units |
Required | string | Free-form unit string; checked for consistency against the referenced Standard Data
Type's base-units. |
dataType |
Optional | enum | numeric, time, text. Default numeric. |
validRange |
Optional | tuple [lower, upper] |
Exactly 2 numbers. Narrows the Standard Data Type's own valid-range for
ingest clamping. |
description |
Optional | string | Free-form. |
gatt object (present only if top-level type == 'ble')
| Field | Required | Type |
|---|---|---|
service | Required | UUID string |
characteristics | Required | non-empty list, see characteristics[] entry below |
characteristics[] entry
| Field | Required | Type | Notes |
|---|---|---|---|
uuid |
Required | string | |
mode |
Required | enum | read, write, notify |
encode |
Conditional | — | Required iff mode == 'write'. |
decode |
Conditional | — | Required iff mode is read or notify. |
fields |
Optional | list | Not independently validated client-side; byte-level field decoding lives within
decode/encode. Field names may reference
variables entries. |
mqtt object (present only if top-level type == 'mqtt')
| Field | Required | Type | Notes |
|---|---|---|---|
topic |
Required | string | Relative topic pattern - no account/deployment segments (those are prepended by the
deployment at registration). Named captures {name}; MQTT +
matches one segment (captured only when written {name}); #
disallowed. e.g. "+/state", "{room}/{metric}/state". |
qos |
Optional | enum | 0, 1, 2. Default 1. |
decode |
Required | enum or plugin name | json, linear, flagged, or a registered plugin name.
json uses source as a JSONPath-lite selector;
linear/flagged reuse the same byte-codec field specs as
gatt. |
semantics |
Optional | enum | state keeps just the latest value; event adds successive
readings up. Default state. |
flush |
Optional | object | {type, latest_period?, statistics_period?}. type default
window (only window supported currently); periods are duration
strings, e.g. 2s, 60s. |
fields |
Required | non-empty list | See fields[] entry below. |
fields[] entry
| Field | Required | Type | Notes |
|---|---|---|---|
variable |
Required | string (key ref) | Must match a variables entry, or a
reserved name: latitude, longitude, altitude,
timeUtc. |
source |
Required | string | Selector into the decoded payload. "$" = the whole payload is the scalar
value; "$.a.b" / "$.arr[0]" = JSONPath-lite (for
decode: json); a byte-field name (for linear/flagged). |
when_metric |
Optional | string or ordered list | Match against the topic's captured token(s). Omit = the rule always applies. Used for one-metric-per-topic devices; unused when a single payload carries all fields. |
scale |
Optional | number | value * scale + offset, applied before the validRange check.
Default 1.0. |
offset |
Optional | number | Default 0.0. |
aggregate |
Optional | enum | How readings in a flush window are combined: mean, minimum,
maximum, last, circular_mean, none.
Defaults to the Standard Data Type's recommended statistic; a deployment/station
config may override it. |
Example
label: Area Spraying type: internal schemaVersion: 2 version: 1.0.0 profile: name: area-spraying compatibleActivityTypes: - agriculture/machinery/sprayer - agriculture/machinery/spreader type: manual profiles: - A symbol: keyboardSensor variantSetting: material settings: initialTankVolume: name: Initial Tank Volume (l) type: number
This is an
internal config, so no gatt block is present.Example (type: 'mqtt')
label: Backyard Weather (ESPHome) type: mqtt schemaVersion: 2 profile: name: Backyard Weather profiles: - W managedAdapter: mqtt-generic variables: airTemperature: standardDataType: sensed/air-temperature units: degC validRange: [-40, 60] windDirection: standardDataType: sensed/wind-direction units: degrees_true rainAccumulation: standardDataType: sensed/rain-accumulation units: mm mqtt: topic: "esphome/backyard/+/state" qos: 1 decode: json semantics: state flush: type: window latest_period: 2s statistics_period: 60s fields: - variable: airTemperature when_metric: temperature source: "$" aggregate: mean - variable: windDirection when_metric: wind_dir source: "$" aggregate: circular_mean - variable: rainAccumulation when_metric: rain source: "$.mm" aggregate: last
Each device publishes one metric per topic (the
+ segment, matched by
when_metric); rainAccumulation arrives as {"mm": …} so its
source is "$.mm". This config is a class - a deployment registered
against an account supplies the location and prepends the {account}/{deployment} topic
segments.Beyond the fields
Detail you only need when publishing configs or versioning them — skip on a first read.
Versioning (per name, account scope only)
- At most one draft version per name, plus any number of published versions kept as history.
- A version is either Draft or Published; a separate Withdrawn flag hides a published version from consumers without deleting it.
- The
semanticVersionyou publish must be strictly higher than the name's current published version (server-enforced), and the editor requiresmajor.minor.patchform. - Deleting a name removes all its versions at once - you can't delete a single version.
- The built-in scope keeps no history: one entry per name, read-only.
Cross-entry rules
- An account entry with the same
nameas a built-in entry replaces it for that account (same as Standard Data Types). - A config's
variables/gatt/mqtt/profilecan reference an account-scoped Standard Data Type, so a config can't be shared straight to another account. There's no public-catalog tier — sharing is manual YAML export/import. - Deployment binding (
type: 'mqtt') — an MQTT config is a class. You bind it to an account by registering a deployment (one unit, one location), which creates the backing Site activity from thevariablesblock and issues the publish credential. Thetopicis relative; the deployment prepends the{account}/{deployment}routing segments. BLE differs — there the mobile app instantiates the device directly.
Profiles are inMotion's domains of interest. Their
single-letter codes appear in an Activity Type's
profile, a Standard Data
Type's profiles list, and a Device Config's profile.profiles list
— in each case naming which domain(s) the entry belongs to.
Profile codes
| Code | Name |
|---|---|
A | Agriculture |
V | Aviation |
B | Boating |
C | Construction |
E | Environmental |
H | Health |
M | Mining |
S | Surveying |
T | Transportation |
W | Weather |
O | Other |
U | Unknown |
Some activity-type keys map to a profile automatically (e.g. anything under
agriculture/ suggests A); the mapping is a starting point you can
override.