API Reference
Moisture Live

Moisture Live API

GET /api/rfid/u300/moisture/live

Returns the current fluid level classification for every AZN3120-AFR sensor tag in antenna range. Called by the useLiveFluidLevels React hook every ~3 seconds.

GET /api/rfid/u300/moisture/live
Authorization: Bearer <token>
x-selected-location: 42

Response:

{
  "ok": true,
  "locationId": 42,
  "skipTidReads": true,
  "tagFamily": "AZN3120-AFR",
  "items": [
    {
      "epc": "E28011702000021A12345678",
      "isMagnus": true,
      "tidPending": false,
      "scValue": 412,
      "level": "3/4",
      "readCount": 5,
      "error": null
    },
    {
      "epc": "E28011702000021A87654321",
      "isMagnus": true,
      "tidPending": false,
      "scValue": null,
      "level": null,
      "readCount": 1,
      "error": "no match for target EPC"
    }
  ]
}

Response item fields

FieldTypeDescription
epcstringTag EPC (uppercase hex)
isMagnusbooleantrue if tag is identified as a sensor tag
tidPendingbooleantrue if TID read is in progress (only when skipTidReads: false)
scValuenumber | nullRaw SC sensor value (0–511). Null if read failed
levelstring | nullClassified level: "Full", "3/4", "1/2", "1/4", "Empty". Null if insufficient reads
readCountnumberNumber of stable readings in history window
errorstring | nullRelay error message if SC read failed

Classification logic

  1. Items with isMagnus: false and tidPending: false are inventory-only tags — no level data
  2. Items with isMagnus: true but level: null have insufficient history (readCount < minReads)
  3. Items with tidPending: true show a "Reading…" badge in the UI until resolved
  4. Once readCount >= minReads and readings are stable, level is set

Frontend hook

import { useLiveFluidLevels } from '@/hooks/useLiveFluidLevels'
 
const { levels, pendingEpcs } = useLiveFluidLevels(epcs)
 
// levels: Map<string, ClassifyResult>  — EPC → level result
// pendingEpcs: Set<string>             — EPCs with TID read in progress

The hook polls /api/rfid/u300/moisture/live every 3 seconds, maintains per-EPC rolling history in a useRef Map, and prunes history for tags that have left antenna range.

Error handling

  • If the relay is unreachable, the endpoint returns { ok: true, items: [] } — the UI simply shows no badges rather than an error
  • "no match for target EPC" means the tag moved out of range between the inventory scan and the bank read — will retry on the next poll
  • SC reads are batched in a single relay round trip using /banks/read/batch