fieldmesh

Farm stack foundation layer: spec v0#

Oct 7, 2026 · @anun333

Purpose and scope#

Layer zero is the data and device contract every farm app builds on: identity, time, records, observations, devices, messaging and commands. It ships no end-user features. Its job is to make sensor data trustworthy, farmer-owned and portable.

It is for small and mid-size diversified farms, DIY ag builders and researchers, and for developers building apps on their behalf.

In scope:

Out of scope (built on top): rules and alerts, irrigation logic, dashboards and UI, robots and guidance, ML.

Done means three different apps (an irrigation controller, a livestock water monitor and a research data logger) can each be built without changing layer zero.

Design principles#

Every rule below traces to a pain point farmers or field deployments report.

Principle What it means in layer zero Pain point it answers
Auditable Every reading, command and decision lands in an append-only log Silent failures, distrust of black boxes
Farmer-owned Local-first, full export in open formats, revocable sharing grants Fear of losing data ownership, vendor lock-in
Honest data Raw value, calibrated value and a quality flag on every reading; nothing silently cleaned Drift, stuck sensors, misleading recommendations
Works offline Store-and-forward delivery; nodes keep local schedules and limits Poor rural connectivity
Modular Every driver and adapter is optional; removing one breaks nothing Too many disconnected tools
Standards first farmOS conventions, OGC SensorThings, ISOBUS, Modbus, MQTT, LoRaWAN Interoperability, the top barrier after cost
Safety below software Hardwired interlocks and fail-safe power-off for anything that moves or pumps Liability, machinery and water risk
Reimplement, don't copy Build from published specs and documented models GPL entanglement

Identity#

Every entity gets a UUIDv7, generated offline with no coordination. UUIDv7 is time-sortable, so logs and records order naturally.

Open: whether a registry-assigned 16-bit point index should replace the channel index on very constrained links.

Time#

Every observation carries four time fields, so ordering survives outages and bad clocks.

Field Meaning
measured_at When the sensor took the reading (UTC)
received_at When the gateway received it (UTC)
seq The node's sequence number
clock_quality gps, network, rtc_unsynced, or none

Core data model#

Layer zero has two models joined by shared IDs: records follow farmOS conventions, sensing follows OGC SensorThings, and both write to one log.

A sensor asset and its Thing share one ID, as do a field or bed asset and the feature of interest it represents. Each observation belongs to a datastream, which ties one sensor, one observed property and one unit to its Thing.

Externally, records are served through a farmOS-compatible API and sensor data through a SensorThings-compatible API, so existing tools in both ecosystems work on day one.

Observation record#

An observation keeps the raw value, the calibrated value and a quality flag together, so nothing is ever silently cleaned.

Field Type Notes
id UUIDv7
datastream UUIDv7 Points to one sensor, one observed property, one unit
feature UUIDv7 The field, bed, tank or animal observed
measured_at, received_at, seq, clock_quality see Time
raw number or string Exactly as the node sent it
result number or string After calibration
calibration UUIDv7 The calibration record applied; null if none
quality enum good, suspect, stuck, stale, out_of_range

Devices, calibration and health#

Sensors are maintained assets with their own history, because drift and hardware failure are the most common reasons field data goes wrong.

Each device record holds:

Health checks run in the foundation and set each reading's quality flag:

Check Flags Example
Staleness stale No reading for 3× the expected interval
Flatline stuck Identical values for longer than physically plausible
Range out_of_range Soil moisture above saturation
Rate of change suspect A jump no real process could produce
Battery and signal trend device warning Voltage falling toward cutoff

Thresholds live on the datastream with sensible defaults, so apps can tune them without code. Every check result is logged, so a false alarm can be traced and the threshold fixed.

Pumps, wells and power sources are resource assets with declared capacities (flow, pressure, watts) that modules book time against, so two modules can never overdraw one well. Tasks for people are pending logs, following farmOS, rather than a separate entity.

One compact message format rides over any link; the gateway expands it into full observations.

A reading's path:

  1. The node samples, applies nothing, and packs a compact binary message: short node ID, channel index, seq, age or timestamp, raw value.
  2. The node buffers it locally until the link confirms delivery (store-and-forward).
  3. A link driver carries it: Meshtastic, LoRaWAN via ChirpStack, wifi, cellular or wired.
  4. The gateway resolves IDs through the registry, computes times, applies calibration and health checks, and drops duplicates by node ID plus seq.
  5. The full observation is written to the append-only log and the time-series store, then published on the bus (MQTT for edge devices; bridged to ROS 2 for robots and machinery).

Rules:

Modules watch for new observations and events through a stable subscription API; nothing above layer zero polls.

Command contract#

Commands state a desired outcome, carry their own safety bounds, and are safe to send twice, so a lost or repeated message can never leave a pump or valve in a bad state.

Every command carries:

A command can also carry a dry_run flag. The node validates it, checks its limits and acknowledges, but does not act, so simulation and backtesting run through the real code path.

The node answers with an acknowledgement: accepted, rejected (with reason), or completed. No acknowledgement within the link's timeout means the command is treated as not delivered.

Node-side limits are configured on the node, not sent with each command: maximum runtime, minimum off-time, interlocks with other outputs, and the safe state on power loss or link loss. The server cannot override them.

Concepts follow SensorThings Part 2 (Tasking) where they fit, rather than inventing new ones. Hardwired interlocks for machinery and high-energy loads sit below all of this and are outside software's reach.

Storage, ownership and sharing#

The farm's own machine holds the authoritative copy; the cloud is optional and never required to operate.

Automated actions are logged as decision events: the observations used as inputs, the rule or model and its version, the output, and the trust level it ran under. Any action can be traced back to why it happened.

Security#

Secure by default, because no farm will harden its network later.

Modules are permissioned like users. Each declares what it may read, write and command, scoped per point; the farmer grants it at install and the foundation enforces it, which is what makes third-party modules safe to run.

Driver SDK and conformance tests#

Anyone can add hardware without touching the core, and a passing conformance suite is what makes a driver or implementation official.

Two driver kinds, one plugin interface each:

A driver declares its points, units, sample interval and safe states; the foundation handles everything else. Python is the first SDK language, with Rust for the edge daemon.

The conformance suite includes:

Reliability claims require at least one full growing season of field data, not a few weeks in the lab.

Interoperability adapters#

Adapters let farmers bring in what they already have and let existing tools read layer zero on day one.

Adapter Direction When Purpose
CSV and spreadsheets In and out v0 Bring in existing records; nothing re-entered by hand
farmOS API In and out v0 Use farmOS v4 as the records backend at first; existing farmOS clients keep working
SensorThings API Out v0 Standard sensor-data endpoint for GIS and research tools
Local weather stations In v0 Ecowitt local API, WeatherFlow broadcast, Davis AirLink
ISOBUS task data (ISOXML) In and out Later Prescriptions and as-applied data from machinery

Open: target SensorThings 2.0 once published in 2026, or ship on 1.1 and migrate.

Layers above#

Everything above layer zero is optional and depends only on the layers below it.

Layer What lives there Must get right
1. Core services Rules and alerts, scheduler for sequences and regimens, notifications, query and analytics Rules backtested on past seasons before going live; resource conflicts resolved; alerts escalate and need acknowledgement
2. Domain modules Irrigation, greenhouse climate, livestock, storage and cold chain, field operations, robotics, inputs and inventory, harvest and traceability, compliance reports Built only on layers 0 and 1; each one removable
3. Decision support Agronomic models, forecasting and ML, cost per field or crop, simulation Models versioned and calibrated per site; confidence shown; suspect and stuck readings excluded
4. Apps and interfaces Phone field app, desktop planning, SMS and voice, a plain-language assistant Offline, glove- and sunlight-friendly, bilingual; the assistant cites readings and never commands without approval
5. Ecosystem Module registry, multi-farm and co-op use, research sharing, buyer and certification exports Signed modules with declared permissions; sharing only by consent

Rules for building upward:

Versioning and governance#

The spec is published separately from the code, so others can build on it or write their own implementation.

Open questions#