Using the inMotion Data Logger
The Data Logger runs a station of sensors unattended on a small always-on machine – a
Raspberry Pi, an industrial gateway, or similar – and forwards their readings to
inMotion as a Site activity. It is a companion to
inMotion Track (the phone app)
for fixed installations where no phone is present.
Overview
A Python application for logging a station of sensors and publishing their readings to
inMotion. A single YAML file declares the station: its location,
its sensors, how readings are aggregated, and where they are published. Support for new
hardware is added as a plugin, without modifying the core package.
- Runs unattended – installed on a Pi or gateway and left running as a service.
- BLE and MQTT sensors – the mqtt-generic plugin subscribes to a broker and drives a Device Config of type: mqtt; ble-generic drives a type: ble one.
- Edge aggregation – means, extremes, and circular means are computed on the gateway over a rolling window before anything is sent.
- Creates its own Site activity – the logger finds or creates a Site activity by name and writes records to it.
When to Use It
Use the Data Logger when:
- The site's connectivity is unreliable, or absent for hours at a time.
- Several sensors at one location – say a weather station over MQTT, a soil probe over BLE, a tipping-bucket on a GPIO – should be aggregated and uploaded as one coherent Site activity.
- You want a permanent local copy of every reading, independent of the cloud.
- Aggregation should happen at the edge rather than in the platform.
Describing a Station
One config file describes the station:
- station – the name (this names the Site activity in inMotion), plus latitude, longitude, and altitude.
- sensors – a list of plugin instances. Each mqtt-generic or ble-generic entry points at a Device Config file and the broker or device to read.
- collector – latest_period (snapshot cadence) and statistics_period (the aggregation window).
- statistics – the reduction applied to each variable over the window (mean, minimum, maximum, last, circular_mean).
- publish – where readings go: console for development, inmotion to forward to the platform, plus the durability options below.
station: name: "Backyard Weather - Unit 1" # names the Site activity latitude: 51.5 longitude: -0.1 altitude: 12.0 sensors: - type: mqtt-generic params: device_config: device_configs/backyard-weather.yml broker: mqtt://localhost:1883 topic_prefix: inmotion/backyard/unit-1 username: ${MQTT_USERNAME} password: ${MQTT_PASSWORD} statistics: airTemp: mean humidity: mean windSpeed: maximum windDir: circular_mean collector: latest_period: 30 seconds statistics_period: 5 minutes publish: reading_journal: # pre-aggregate durability db_path: data-logger-readings.sqlite3 retain: 30 minutes inmotion: # store-and-forward to the platform base_url: ${INMOTION_BASE_URL} dev_key: ${INMOTION_DEV_KEY} dev_secret: ${INMOTION_DEV_SECRET} api_key: ${INMOTION_API_KEY} account: ${INMOTION_ACCOUNT} queue_db_path: data-logger-queue.sqlite3 retry_interval: 30 seconds history: # optional permanent local log db_path: data-logger-history.sqlite3
The logger finds an existing Site activity by station.name or creates
one. The name identifies the activity; changing it creates a second activity, so choose it once.
Reliable Publishing and Offline Durability
Two independent buffers cover different failure points, and the edge path uses both:
- reading_journal – pre-aggregate. Individual readings are journaled as they arrive, so a crash or power cut partway through a window doesn't lose the samples already in it. retain bounds how far back it keeps them.
- queue_db_path – post-aggregate. Each computed window is written to an on-disk queue and retried in order every retry_interval until inMotion acknowledges it. A multi-hour outage, or the process restarting during one, loses nothing.
Authentication on the Gateway
Forwarding to inMotion needs two credentials on the gateway, both created in
Settings:
Protect dev_secret. It is the one long-lived secret that lets requests be signed as your account. If the gateway is lost or compromised, revoke that Developer key in Settings.
See Data Platform for the full authentication model (Developer keys vs API keys, HMAC signing) and the Python SDK.
- A Developer key (key + secret) with HMAC signing enabled – the SDK signs every request with it so inMotion can verify the body wasn't altered.
- An API key (account key + api key) with at least Contributor access to the account the data belongs to.
Protect dev_secret. It is the one long-lived secret that lets requests be signed as your account. If the gateway is lost or compromised, revoke that Developer key in Settings.
See Data Platform for the full authentication model (Developer keys vs API keys, HMAC signing) and the Python SDK.
Setup
- Set up the gateway. Install the Data Logger with uv. For MQTT sensors, start a broker – the Data Logger includes a docker-compose.yml that starts a hardened Mosquitto alongside the logger (no anonymous access, a password file, localhost-published ports, a TLS template). Give each device its own broker account.
- Point the sensors at it. Configure the weather station (or other device) to publish to the local broker, using the same topic layout and payload it would use against the cloud.
- Write the station config. station.name / lat / lon / altitude, one mqtt-generic or ble-generic sensor per device pointing at its Device Config, then collector windows and per-variable statistics.
- Validate offline. Run data-logger validate --device-config <file> --broker mqtt://localhost:1883 --topic-prefix <prefix> --duration 2m with the device publishing. It reports decode results, range violations, and each aggregation window as it fires – no credentials, nothing sent. Fix the config here; data-logger reset clears local state to start clean.
- Enable forwarding. Add the publish.inmotion block (with queue_db_path and retry_interval) and publish.reading_journal; add publish.history for a permanent local log.
- Run in production. data-logger --config station.yaml. Confirm the Site activity appears in Studio, then disconnect the gateway's network for a few minutes and confirm the queue drains and backfills when it returns.
- Run as a service. Run it as a service (systemd) so it restarts on boot and on crash, keep the gateway clock synced with NTP (record timestamps come from the gateway), and watch queue depth as a health signal.
Next Steps
- Device Config schema reference – the full grammar for type: ble and type: mqtt configs.
- Data Platform – the data model, authentication, the Python SDK, and publishing directly to the MQTT broker without a logger.
- Using inMotion Studio – viewing the Site activity the logger creates.