Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ TEMPORAL_MODEL_THRESHOLD=0.45
# auto-sets a dev token; set the same value here to require auth on other targets.
TEMPORAL_API_TOKEN=

# only usefull to download some real sequences from real/distant Pyronear alert API
DISTANT_API_URL=''
# Prod admin creds, only needed by `make fetch-alerts` (scripts/replay_alerts.py)
DISTANT_API_URL=https://alertapi.pyronear.org/
DISTANT_ALERT_API_LOGIN=''
DISTANT_ALERT_API_PASSWORD=''
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,4 @@ containers/notebooks/app/.Trash-0

data/alert_samples/
data/triangulated_sequences/
data/replay_alerts/
30 changes: 30 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ help:
@echo " ps Show compose status"
@echo " logs Follow logs"
@echo " test Run pytest"
@echo " test-replay Unit tests of the replay scripts (no stack needed)"
@echo " fetch-alerts Download prod alerts: make fetch-alerts ALERTS=54194"
@echo " publish-alerts Upload fetched alerts to the replay-alerts GitHub release"
@echo " list-alerts List the alerts available in the release"
@echo " update-cameras Set last image and ping of the alert cameras: make update-cameras [ALERTS=49767]"
@echo " replay-alerts Replay alerts locally: make replay-alerts ALERTS=\"49767 54194\" [MODE=live] [START=...]"

# -------------------------------------------------------------------
# Init
Expand Down Expand Up @@ -104,3 +110,27 @@ logs:

test:
pytest -s tests/*

test-replay:
uv run --with-requirements tests/requirements.txt pytest -q tests/test_replay_alerts.py

# -------------------------------------------------------------------
# Real alert replays (see scripts/replay_alerts.py)
# -------------------------------------------------------------------

MODE ?= demo

fetch-alerts:
uv run scripts/replay_alerts.py fetch $(ALERTS)

publish-alerts:
uv run scripts/replay_alerts.py publish $(ALERTS)

list-alerts:
uv run scripts/replay_alerts.py list

replay-alerts:
uv run scripts/replay_alerts.py replay $(ALERTS) --mode $(MODE) $(if $(START),--start $(START))

update-cameras:
uv run scripts/update_cameras.py $(ALERTS)
74 changes: 68 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ make build
make run
```

* Send an alert by opening [http://0.0.0.0:8889/notebooks/notebooks/send_real_alerts.ipynb](http://0.0.0.0:8889/notebooks/notebooks/send_real_alerts.ipynb)
* Replay a real alert with `make replay-alerts ALERTS=<id>` (see [Replay real alerts](#replay-real-alerts))
* Observe the alert on the frontend at [http://localhost:8080/](http://localhost:8080/)
* Use credentials from `data/csv/API_DATA_DEV/users.csv`
* Or check directly on the API at [http://0.0.0.0:5050/docs](http://0.0.0.0:5050/docs) with the same creds
Expand Down Expand Up @@ -117,13 +117,75 @@ docker logs engine

Create a directory `data/images` before starting the environment and put your images inside.

### Send custom alerts
### Replay real alerts

Use Jupyter notebooks (e.g., `notebooks/send_real_alerts.ipynb`).
When running notebooks **inside Docker**, set:
`scripts/replay_alerts.py` replays real production alerts (all their sequences and
images) on the local stack. Alerts are stored as `alert_<id>.zip` in the
[`replay-alerts`](https://github.com/pyronear/pyro-envdev/releases/tag/replay-alerts)
GitHub release. Needs [uv](https://docs.astral.sh/uv/) (dependencies are installed on the fly).

```bash
make list-alerts # alerts available in the release
make replay-alerts ALERTS="49767 54194" # demo mode (default)
make replay-alerts ALERTS=49767 START=2026-09-28T18:53 # demo, first sequence at a local time
make replay-alerts ALERTS=49767 MODE=live # live mode
```

Log in to the frontend as `test77` / `test` to see them.

Published alerts (`make list-alerts` for the up-to-date list):

| Alert | Prod date | Cameras | Detections |
|---|---|---|---|
| 49767 | 2026-07-10 | croix-augas-01, nemours-01, nemours-02 | 267 |
| 54194 | 2026-09-24 | moret-sur-loing-01, croix-augas-02, nemours-01, nemours-02, videlles-01 | 488 |

* **demo**: copies the prod alert as is: images and crops go to the organization
bucket, alert, sequences and detections are written straight into the DB, with prod
azimuths, cones and location. Times are shifted as a block so the latest sequence
starts 1 hour ago, or the first one at `START`. Nothing is recomputed, so replays
never mix and it takes seconds. Each replay gets its own copy of the images.
Sequences are left unlabeled so the alert shows as live. Tied to the pyro-api DB
schema.
* **live**: posts one frame per camera every 30 s (`--interval`) through the API,
dated now, so validation and triangulation run locally. Replays within 2 hours of
each other get triangulated together when their cones cross: use a fresh stack
(`make stop && make run`) per alert.
* Cameras are matched by name and set up as in prod (position, elevation, poses);
local poses that do not exist in prod (seeded or left by older replays) are
deactivated. Each sequence is attached to the local copy of its prod pose. Missing
cameras are created in organization 2 (`--org-id`), so the alerts show up for the
`test77` user.

To make the alert cameras look alive, `make update-cameras` sets up each camera of the
published alerts (or `ALERTS="..."`) as in prod, sets its last image to its most
recent image in those alerts and sends a heartbeat, as a real camera would. The ping goes stale like a real one: run it again
before a demo.

To test the replay:

```bash
make test-replay # unit tests (bboxes, frames, time shift), no stack needed
make run # then, end to end on the local stack:
make replay-alerts ALERTS="49767 54194"
make update-cameras
```

Log in at [http://localhost:8080](http://localhost:8080) as `test77` / `test`: both alerts
are listed as live, each at its prod location, with images and crops, and their
cameras have a recent image. `make stop && make run` starts again from an empty DB.

Add new alerts (needs prod admin creds `DISTANT_*` in `.env`, and `gh` for publishing):

```bash
make fetch-alerts ALERTS="54095" # writes data/replay_alerts/alert_54095.zip
make publish-alerts ALERTS="54095" # uploads it to the release
```

A zip holds `alert.json` (alert, sequences, detections, cameras), the detection
images and their crops. `publish` creates the release if needed and overwrites an existing zip.
`replay` uses the local zip when present, so publishing is only needed to share.

```python
API_URL = "http://api:5050"

### Update the last image for a camera

Expand Down

This file was deleted.

Loading
Loading