Skip to content
Telemetry: MQTT, RFID, GPS, sensors

Telemetry: MQTT, RFID, GPS, sensors

Four connectors read physical telemetry: a sensor bus, a tag reader, a fleet tracker and a fixed probe gateway. Every protocol is implemented natively against its wire format. MQTT 3.1.1 packets, LLRP inventory rounds, Modbus-TCP register reads and NMEA 0183 sentences are written in FACE, with no third-party protocol library. All four emit one row type, SensorReading.

Plant equipment normally lives on private networks, so these connectors allow internal addresses by default. Set allow_internal_network=false on a connection to refuse them. The cloud instance-metadata address, multicast and the unspecified address are always refused. See Networking.

Common rules

  • An empty batch is not a success. A connector that connected and received nothing returns Success=false with <type> connector reached <what> and received no readings. A silent reader is reported as silent, never as “no excursions”.
  • Zero means “use the default” for every window and cap below. It never means “collect nothing”. Values above a maximum are reduced to the maximum.
  • Readings are sorted by observed time, then asset, then metric.
  • What Test does not establish. A successful probe does not establish that a sensor is publishing, that an antenna is attached or aimed, that a probe is calibrated, or that any readings exist.

MQTT (sensor bus)

Type spellingsmqtt, mqtts, iot, iothub, sensorbus, messagebus, iottelemetry (iot_telemetry)
Config messageMQTTConnectionConfig, or legacy IoTConnectionConfig with endpoint plus a comma-separated topics property
ProtocolMQTT 3.1.1 (protocol level 4): CONNECT, SUBSCRIBE, PUBLISH/PUBACK, PING, DISCONNECT
SettingMeaning
broker_urltcp://host:1883, tls://host:8883 (also ssl, mqtts), or a bare host:port. The default port is 1883, or 8883 with TLS.
topicsTopic filters. Required: an empty list is an error, and FACE never subscribes to # by default. A query can override the list with comma-separated filters.
qos0 or 1 (FACE subscribes at QoS 1). 2 is refused.
client_idThe default is a stable id derived from the connection id
usernameA setting. The password is a credential.
collect_secondsThe listening window: default 15 s, maximum 5 min
max_messagesDefault 500, maximum 20,000
protocol_version4 or 0. 5 and 3 are refused with an explanation.
use_tls, insecure_skip_verifyTLS, and an explicit opt-in to skip certificate verification
property asset_topic_segmentThe topic segment index that holds the asset id

Credentials: password (also mqtt_password, api_key, token); username may also come from the bundle.

  • Test dials the broker and completes CONNECT/CONNACK within 10 s, then disconnects. It does not subscribe.
  • Execute subscribes, listens for the window, and decodes each message:
    • JSON objects, arrays, numbers, booleans and numeric strings become readings.
    • When a JSON value names no metric, the metric comes from the topic’s last segment.
    • Non-JSON payloads are kept as rows with payload_kind and a short sample.
    • Topic, QoS and retained flags go into attributes.
  • WebSocket transport, MQTT 5, QoS 2 delivery and persistent sessions are not implemented. A legacy iot connection that declares a non-MQTT protocol (such as AMQP) is refused by name.
  • Explore returns supported=false. MQTT has no catalogue call.

RFID (LLRP and vendor REST)

Type spellingsrfid, epc, llrp, tagreader
Config messageRFIDConnectionConfig
SettingMeaning
protocolllrp (default, also llrps) or http (also https, rest)
endpointLLRP: host or host:5084. HTTP: the reader’s event API base URL.
reader_idCarried onto every reading. It defaults to the endpoint.
locationWhere the reader physically is. It is carried onto every reading.
antenna_portsAntennas to enable (1–65535). Empty means all.
collect_secondsThe inventory round: default 10 s, maximum 2 min
max_readsDefault 1,000, maximum 50,000
report_duplicatesReport every sighting instead of first/last seen per EPC
use_tlsTLS. It is also implied by https:// or llrps://.
property api_key_headerThe header for an API key (default X-API-Key)

Credentials for HTTP readers, tried in order:

  1. token → Authorization: Bearer
  2. api_key → the API-key header
  3. password with the username property → HTTP Basic
  • Test for LLRP connects and waits for the reader’s connection-attempt event. For HTTP, it makes one GET to the event API within 8 s.
  • Execute runs an inventory round and returns one reading per tag sighting. EPC, antenna, RSSI and read count go into attributes when the reader states them. HTTP event bodies are capped at 16 MiB, and an over-cap stream is refused rather than reported as a short round.
  • Explore returns supported=false.

GPS and telematics

Type spellingsgps, telematics, eld, nmea, tracker
Config messageGPSConnectionConfig
SettingMeaning
providersamsara, geotab, generic_rest (also generic, rest, http, https) or nmea (nmea0183). If it is empty and the endpoint is http(s)://, generic_rest is used.
endpointA REST base URL, or host:port for NMEA. Required.
asset_idsRestrict to these vehicles or assets. A query may narrow further, but only within this set.
lookback_minutesDefault 60, maximum 7 days
collect_secondsThe NMEA listening window: default 15 s, maximum 5 min
include_sensorsAlso request reefer and cargo sensor channels where the provider has them
property carrier / fleetCarried onto readings

Credentials by provider:

ProviderCredentials
Samsaraapi_key, token or bearer_token
Geotabdatabase, username, password (or session_id)
Generic RESTbearer_token / token, or api_key, or username + password
NMEANone
  • Test:
    • Samsara: one GET /fleet/vehicles/stats?types=gps&limit=1
    • Geotab: a Get of one Device
    • Generic REST: one request
    • NMEA: a TCP connect
  • Execute returns position fixes as readings (latitude, longitude, geo_stated), with speed and heading in attributes. It also returns sensor channels where requested.
    • At most 5,000 readings and 20 pages. Truncation is stated in the message.
    • REST bodies are capped at 8 MiB.
    • NMEA reads RMC, GGA and VTG sentences, with lines capped at 8,192 bytes.
    • Units are taken from the provider (for example Geotab’s unit-of-measure ids) and never assumed.
  • Explore returns supported=false.

Sensor gateway (Modbus-TCP and HTTP)

Type spellingssensorgateway (sensor_gateway), sensor, modbus, temperature, infrared, thermal, probe
Config messageSensorGatewayConnectionConfig with one or more SensorChannel
SettingMeaning
transportmodbus_tcp (default) or http. mqtt is refused here: use an MQTT connection, which emits the same rows.
endpointModbus: host:502, or port 802 by default with use_tls. HTTP: a base URL.
unit_idThe Modbus unit (slave) id
channelsRequired. There is no safe default register.
collect_secondsThe sampling pass: default 15 s, maximum 5 min
poll_interval_secondsThe interval between polls: default 5 s. It is carried as sampling_interval_seconds.
use_tlsModbus/TCP Security, or HTTPS

Each SensorChannel states its own mapping:

FieldMeaning
asset_id, device_idWhat is measured, and by which device
metrictemperature, infrared, humidity, shock, door or battery. It is written verbatim to the reading.
addressModbus: the starting register. HTTP: the JSON path of the value.
register_typeholding (default), input, coil or discrete
data_typeint16 (default), uint16, int32, uint32 or float32. Word-swapped variants are accepted.
scale, offsetvalue = raw * scale + offset. A scale of 0 means 1.
unitWritten to the reading’s unit, for example C, F, %RH or g
threshold_min / _stated, threshold_max / _stated, threshold_sourceThe band the product spec states, and where it is stated. Leave these unset when nobody stated one.

HTTP credentials: token, api_key, or username + password.

  • Test connects and reads the first channel. For HTTP, it fetches the document and resolves the first channel’s path. A failure names the channel, register and unit. A Modbus exception response is reported as the device’s own refusal.
  • Execute polls every channel at the interval for the whole pass. The raw register and count go into attributes.
  • Explore returns supported=false. Modbus has no register map, so the channel list you configure is the schema.

The SensorReading row

Every telemetry connector, and the Flipper edge reader, returns rows with these columns, in this order:

ColumnMeaning
asset_idThe thing measured, for example REEFER-12
device_idThe thing measuring
reading_id, window_idThe reading id, and the monitoring run it belongs to
reference, carrierShipment or monitoring reference and carrier, only when the source states them
observed_atRFC 3339, UTC
observed_at_sourceWhose clock: device, gateway, or received (receipt time, used when the wire carries no timestamp)
metric, value, value_stated, unitThe measurement. value_stated=false marks a row with no numeric payload (a heartbeat, a door event, a tag sighting). Such rows are kept, because a gap in a feed is evidence too.
threshold_min, threshold_min_stated, threshold_max, threshold_max_stated, threshold_sourceThe band the source stated, and where
sampling_interval_secondsThe configured cadence. 0 means the source did not say.
max_excursion_minutes, max_excursion_minutes_statedThe excursion allowance stated by the spec
load_reference, load_value, load_value_statedThe load on the asset, where named
location, latitude, longitude, geo_statedWhere the reading was taken
source, transportThe connection type and the protocol actually spoken
qualityThe source’s own quality flag. FACE never computes it.
attributesEverything else the protocol knew, such as EPC and antenna, speed and heading, register and raw count, or topic

The *Stated fields

In the protocol format FACE uses, “the probe read 0 °C” and “the row has no reading” look the same, and in a cold chain they are opposite facts. So every connector sets a *_stated flag from whether the source carried the field, never from whether the value is non-zero:

  • A threshold is never assumed. FACE does not assume 2–8 °C because an asset is called REEFER. A band that no one stated stays unstated, and analysis reports that the threshold was not stated.
  • A unit that is absent stays absent. FACE never assumes Celsius.
  • A position without geo_stated is not a position.

Consumers must read a value only when its *_stated flag is true. See /docs/analysis/ for how these rows feed temperature-excursion and claims evidence.