feat(cameras): UDOT IBI 511 traffic cameras -> cameras table #38

Merged
sirius merged 3 commits from osint-dashboard/t_5bfc52e8-osint-udot-ibi-511-cameras-cameras-table into master 2026-08-31 22:22:11 -04:00
Owner

Summary

Adds the Utah DOT traffic camera feed from the public IBI 511 platform (prod-ut.ibi511.com, no API key, discovery_source=udot) to the existing cameras table pipeline.

What

  • parse_udot_ibi_page — pure parser for one DataTables response: skips images[0].blocked/disabled and coord-less rows, parses WKT POINT(lng lat) from latLng.geography.wellKnownText, drops anything outside the Utah bbox (lat 36.9-42.1, lon -114.2--108.9).
  • scrape_udot_ibi — paginated fetcher: POSTs start/length form fields (server caps at 100 rows/page), walks pages via recordsTotal, capped at UDOT_IBI_MAX_PAGES (default 40) so a runaway total cannot fan out.
  • Stable identity = snapshot URL = https://prod-ut.ibi511.com/map/Cctv/{id}; stored once, frames are never scraped. Dedupe via url_hash. Identifying OSINT_USER_AGENT + X-Requested-With: XMLHttpRequest.
  • Wired into run_cycle alongside the existing sources.

Tests

Pure parser tests (no live IBI in CI): WKT lng/lat order, blocked/disabled skip, bbox drop, malformed payload, missing-WKT drop — in tests/test_live_layers.py.

Verified live: 2075 records, 100 rows/page, 21 pages; parser yields 100/100 in-bbox unblocked rows on page 1, clean dedupe across pages.

## Summary Adds the Utah DOT traffic camera feed from the public IBI 511 platform (prod-ut.ibi511.com, no API key, discovery_source=udot) to the existing `cameras` table pipeline. ## What - `parse_udot_ibi_page` — pure parser for one DataTables response: skips `images[0].blocked`/`disabled` and coord-less rows, parses WKT `POINT(lng lat)` from `latLng.geography.wellKnownText`, drops anything outside the Utah bbox (lat 36.9-42.1, lon -114.2--108.9). - `scrape_udot_ibi` — paginated fetcher: POSTs `start`/`length` form fields (server caps at 100 rows/page), walks pages via `recordsTotal`, capped at `UDOT_IBI_MAX_PAGES` (default 40) so a runaway total cannot fan out. - Stable identity = snapshot URL = `https://prod-ut.ibi511.com/map/Cctv/{id}`; stored once, frames are never scraped. Dedupe via `url_hash`. Identifying `OSINT_USER_AGENT` + `X-Requested-With: XMLHttpRequest`. - Wired into `run_cycle` alongside the existing sources. ## Tests Pure parser tests (no live IBI in CI): WKT lng/lat order, blocked/disabled skip, bbox drop, malformed payload, missing-WKT drop — in `tests/test_live_layers.py`. Verified live: 2075 records, 100 rows/page, 21 pages; parser yields 100/100 in-bbox unblocked rows on page 1, clean dedupe across pages.
sirius added 1 commit 2026-08-31 21:34:36 -04:00
Add parse_udot_ibi_page + scrape_udot_ibi for the UDOT IBI 511 traffic
camera feed (prod-ut.ibi511.com, no key). DataTables endpoint is POST
form-encoded and caps at 100 rows/page regardless of `length`; page walk
uses recordsTotal with a UDOT_IBI_MAX_PAGES (default 40) runaway cap.

Skip images[0].blocked/disabled, parse WKT POINT(lng lat) from
latLng.geography.wellKnownText, drop outside the Utah bbox
(lat 36.9-42.1, lon -114.2--108.9). discovery_source=udot, stable
source_url == snapshot_url == /map/Cctv/{id} (never scrape frames),
url_hash dedupe, OSINT_USER_AGENT + X-Requested-With header.

Unit tests: WKT lng/lat order, blocked/disabled skip, bbox drop,
malformed payload, missing WKT.
sirius added 1 commit 2026-08-31 22:11:04 -04:00
Keep both UDOT IBI 511 and already-merged MDOT MiDrive parsers
(disjoint camera sources on camera_scraper.py / tests).
sirius added 1 commit 2026-08-31 22:21:05 -04:00
Keep both UDOT IBI 511 (this PR) and ODOT TripCheck (merged #40)
plus existing MDOT parsers. Disjoint camera sources.
sirius merged commit f8dbfef6c2 into master 2026-08-31 22:22:11 -04:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: sirius/osint-dashboard#38
No description provided.