HerdTag

Source: docs/grazing.md

Cycle grazing

Move the herd through paddocks on a schedule. You draw each paddock once, then set the order and how long the herd stays in each. The server runs the moves.

How a move works

  1. Grazing. The tags enforce the current paddock. When its time is up, the move starts.
  2. Opening. The server sends a fence covering the current and next paddock (the "gate"). It waits until every tag confirms it.
  3. Moving. Cattle walk to the fresh grass on their own. The server waits until every tag has reported from at least 5 m inside the next paddock since the gate opened.
  4. Settling. It sends the next paddock's fence and waits for every tag to confirm. The old paddock's rest clock starts.

The code is in src/herdtag/server/rotation.py (engine, API, scheduler) and src/herdtag/server/fences.py (fence creation, assignment, sync tracking).

Safety rules

Farmer controls

On the map page, under Grazing rotation: draw paddocks, plan a rotation, then Start. While it runs you can:

API

Method Path Body / notes
GET /api/paddocks All paddocks (not archived)
POST /api/paddocks {name, points: [[lat, lon], ...], has_water, rest_days}
DELETE /api/paddocks/{id} Archive; 409 if a running rotation uses it
GET /api/rotations Status of every rotation
POST /api/rotations {name, steps: [{paddock_id, graze_hours}], dev_ids?, loop, allow_no_water, move_timeout_h}; returns warnings
GET /api/rotations/{id} Status: status, phase, step, steps, herd_size, unsynced, next_move_at, next_paddock, moved
POST /api/rotations/{id}/start Optional ?step=N
POST /api/rotations/{id}/pause, /resume, /move-now, /close-gate, /stop See farmer controls

The scheduler runs inside the server every 30 s. Set HERDTAG_NO_SCHEDULER=1 to turn it off (tests do).

Try it

uv run herdtag-server
uv run herdtag demo --rotation 0.05     # two paddocks, 3 minutes each, real time