View raw

FAPG DAQ system

Table of Contents

Overview

The goal of this project is to deploy a DAQ network at the /Ferme Aquaponique du Pays de Gex/ (FAPG). DAQ sensor nodes periodically send readings to a central DAQ hub. An external VPS obtains these readings, and presents them on a dashboard accessible via the web.

Architecture

  @startuml
  title FAPG DAQ - from reading to web dashboard

  actor "Farm user/browser" as Browser

  participant "EZO probe\npH / EC / DO / ORP" as Probe
  participant "Pi Zero 2W\nfapg-daq service" as Zero
  participant "Pi 5\nMosquitto MQTT broker" as Broker
  participant "VPS\nMQTT subscriber service" as VPSSubscriber
  database "Readings database\nSQLite / PostgreSQL" as DB
  participant "VPS\nLive dashboard app" as Dashboard

  == DAQ acquisition ==

  Zero -> Probe : Request UART reading
  Probe --> Zero : Return raw sensor value

  Zero -> Zero : Normalize reading

  == MQTT publication ==

  Zero -> Broker : MQTT PUBLISH\nfapg/daq/<probe>/<node>/reading\nvalid reading JSON payload
  Zero -> Broker : MQTT PUBLISH\nfapg/daq/<probe>/<node>/status\nnode/probe status JSON payload
  Broker -> Broker : MQTT PUBLISH\nfapg/daq/hub/<node>/status\nhub status JSON payload

  note right of Zero
    Example reading payload:
    {
      "schema": "fapg.daq.reading.v1",
      "node": "fapg-zero-ph-01",
      "probe": "ph",
      "value": 7.12,
      "unit": "pH",
      "timestamp": "2026-06-27T13:45:00Z"
    }

    Example status payload:
    {
      "schema": "fapg.daq.status.v1",
      "node": "fapg-zero-ph-01",
      "probe": "ph",
      "status": "probe_error",
      "timestamp": "2026-06-27T13:45:05Z",
      "error": "timeout waiting for EZO response"
    }
  end note

  VPSSubscriber -> Broker : MQTT SUBSCRIBE\nfapg/daq/#
  Broker --> VPSSubscriber : MQTT MESSAGE\nreading/status topic + JSON payload

  VPSSubscriber -> VPSSubscriber : Validate topic and payload\nparse probe, node, value/status, timestamp

  == Database storage ==

  VPSSubscriber -> DB : INSERT reading
  VPSSubscriber -> DB : INSERT node status
  DB --> VPSSubscriber : OK

  == Live dashboard presentation ==

  Browser -> Dashboard : Open HTTPS dashboard
  Dashboard -> DB : SELECT recent readings
  DB --> Dashboard : Return recent readings
  Dashboard --> Browser : Initial HTML + Chart.js data

  loop live updates
  	VPSSubscriber -> Dashboard : Notify new reading\nWebSocket / SSE / app event
  	Dashboard --> Browser : Push new reading\nWebSocket or Server-Sent Events
  	Browser -> Browser : Append point to Chart.js chart
  end

  @enduml

#+RESULTS: file:docs/architecture.png

Hosts

Raspberry Pi Zero 2W

These hosts collect DAQ readings, and publish them via MQTT on the LAN.

| Pi Zero | Probe | |---------+-------| | 01 | PH | | 02 | EC | | 03 | DO | | 04 | ORP |

Raspberry Pi 5

This host brokers MQTT messages sent on the LAN.

VPS

This host establishes a VPN connection with the Pi 5 host, subscribes to all MQTT topics, saves messages to a database, and exposes a realtime web dashboard available over the internet.

MQTT Topics

Valid probe measurements are published only on:

fapg/daq/<probe>/<node>/reading

Node/probe health is published separately on:

fapg/daq/<probe>/<node>/status

The DAQ hub publishes its own heartbeat status on:

fapg/daq/hub/<node>/status

Status payloads use schema fapg.daq.status.v1. A recent ok status means the node is reachable; for probe nodes it also means the node is publishing valid readings. A recent probe_error status means the node is reachable on the farm network, but the probe or USB serial path is not returning a valid reading. If the dashboard has no recent status for a node or the DAQ hub, it treats that system as unreachable.