Inspiration
The Sperry Tech brief starts with a crew building a temporary access road in the Everglades in August. By noon the heat index is past 110°F, storms are building to the west, the ground is soaked from a week of rain, and somebody saw a gator next to the site yesterday, but that info only lives in one guy's texts. Every one of those hazards was knowable ahead of time. The problem is that it's spread across a weather app, an NWS page, a river gauge site and a group chat, and nobody turns it into a decision.
That got to us because it's such a fixable problem. The data is out there and most of it's free. What's missing is something that pulls it together and actually reaches the person standing in the mud, even when there's no cell signal out there.
What it does
allClear watches 14,700 real power plants from the EIA-860M list and tells a crew what can hurt them before it does.
- One risk picture per site: lightning, heat index, wind, flooding, wildfire, soil saturation and wildlife sightings, rolled into a 0-10 hazard index from a LightGBM model trained on historical weather tied to real incidents.
- Lightning stop-work: any strike within 10 miles puts the site in STOP WORK with a 30 minute all-clear countdown, and every new strike resets it. We also fit a track through recent strikes to warn a site before the storm reaches the 10 mile ring.
- Flood warnings for river sites after a night of heavy rain, plus a 6 PM briefing every evening with tomorrow's risks.
- Hard hat trackers: every worker wears a SenseCAP T1000-E on their hard hat. When a site goes to STOP WORK, every hard hat beeps. The worker presses the button to confirm they got it.
- Closed loop with the supervisor: the dashboard shows who confirmed and who didn't. If someone doesn't check in within 2 minutes, the supervisor gets flagged with their name and their position on the map, and that worker's hard hat keeps beeping until they respond.
- Crew reporting: snap a photo of a hazard, it gets pinned to the site map and saved, so the next crew on that site knows about it.
How we built it
Data. Lightning comes from NOAA's GOES-19 Geostationary Lightning Mapper, which drops a new file on a public AWS bucket every 20 seconds. Weather and forecasts come from Open-Meteo, plus NWS alerts, NWPS and USGS river gauges, NASA FIRMS fire detections, iNaturalist wildlife observations, FEMA flood zones and USDA soil data. For training labels we used NOAA Storm Events and OSHA Severe Injury Reports.
Alert engine. The engine is Python. The stop-work rule is a PostGIS-style distance check: 10 miles is 16,093 m. For the "lightning coming" warning we fit a least-squares line through the last 15 minutes of strikes near a site, which gives the storm's position $\mathbf{p}$ and velocity $\mathbf{v}$. Then we solve for when it hits the ring:
$$\lVert \mathbf{p} + \mathbf{v}t \rVert = R \;\;\Rightarrow\;\; \lVert\mathbf{v}\rVert^2 t^2 + 2(\mathbf{p}\cdot\mathbf{v})\,t + \lVert\mathbf{p}\rVert^2 - R^2 = 0$$
If the smallest positive $t$ is under 15 minutes, the site gets a heads-up. A storm that passes by outside the ring has no real root, so it never false-alarms.
Hardware. This was the part none of us had done before.
- SenseCAP T1000-E: a credit-card-sized LoRa tracker with GPS, a buzzer and a button. We run Meshtastic firmware on it, so the trackers form a mesh and don't need cell service.
- Heltec LoRa 32 V3: the base radio that connects the mesh to everything else.
- NVIDIA Jetson Orin Nano: an 8 GB edge computer that sits at the site. It runs the Mosquitto MQTT broker, the bridge that translates Meshtastic packets to MQTT, and the alert engine. When the engine decides a site is in STOP WORK, it publishes a message, the bridge sends it over LoRa, and the hard hat beeps. Button presses go the other way, so an ack shows up on the dashboard.
We also put real x/y/z positioning on the trackers. That lets us catch a worker standing too close to a machine, or something hanging overhead.
Storage. Supabase (Postgres + PostGIS) for live state, auth and realtime updates to the dashboard. The 16 years of history lives in Tiger Data: TimescaleDB hypertables for daily weather (7.6M rows), daily lightning (1.36M rows) and storm events (874K rows) across 1,300 sites, with compression and continuous aggregates for hourly per-site rollups. That's what the model trains on and what the history views read, and it keeps the live database small.
Frontend. Next.js with MapLibre for the supervisor dashboard and a crew view that works on a phone browser.
Challenges we ran into
Supabase's free tier. Our refresher pulls lightning every few minutes and rescores 14,700 plants, and that burned through the free plan's disk I/O budget. Once that happens, Supabase throttles everything. Simple reads took 30 to 140 seconds and inserts timed out. We slowed down the refresher and moved persistence onto the Jetson's SD card, so the site keeps its own data locally and Supabase only gets what the dashboard needs.
Lightning data lag. The 30 minute countdown is only as good as how fast we see the strike. In our first live run, the newest strike in the database was already about 20 minutes old. So we had to think hard about how fresh data gets from the satellite to the hard hat.
Hardware from scratch. None of us had flashed firmware, configured a LoRa mesh or wired up a buzzer before. The buzzer on the first tracker didn't beep on an incoming message, and we had to dig through Meshtastic's external notification settings to fix it. GPS altitude is also off by 10+ meters, which matters a lot when you're trying to tell if someone is up on a structure.
Small bugs that would've hurt in a demo. PostgREST caps a response at 1,000 rows, and we have 1,300 sites, so 300 sites were silently getting skipped until we added paging. During one live test, a laptop dropped off Wi-Fi mid-run, and the database's backup timer cleared the stop-work sites on schedule. Good to know the safety net actually works.
Accomplishments that we're proud of
We're CS majors. We build software. Going from never touching a LoRa radio to hard hats that beep when real lightning hits near a real power plant, in one weekend, is the thing we're most proud of.
Turning the trackers into hard hat beepers made the whole thing click. A dashboard alone tells a supervisor something. A beeping hard hat tells the person who's actually in danger, out where phones don't work.
We're also proud of the ack. Most alert systems send a message and assume it landed. Ours knows who confirmed, who didn't, and where to find anyone who didn't. And the x/y/z positioning goes past "is the crew on site" to "is this person too close to that machine."
The engine also ran live on real GOES-19 data and put Turkey Point into STOP WORK during an actual storm.
What we learned
- How LoRa mesh networking works, and how to bridge it to MQTT
- PostGIS distance queries, and why you always page your API reads
- Free tiers have limits you only find by hitting them
- How to split work across four people and a bunch of agents without stepping on each other: one shared schema, one contract file, and a message board everyone actually reads
What's next for allClear
- Fall and impact detection: add an accelerometer and a barometric pressure sensor to the hard hat. A sudden drop in altitude plus a spike in acceleration means someone fell off something, and a hard hit to the head means something struck them. Either one would send an SOS with their position automatically, no button press needed.
- Wind at the worker's height: use the tracker's altitude so the guy 30 m up a tower gets the wind alert and the guy on the ground doesn't.
- Faster lightning: read GLM straight off the satellite feed on the Jetson instead of waiting on a refresh loop.
- A real pilot with a utility crew, to find out what they actually want on their hard hat.
Built With
- heltec-lora32
- lightgbm
- lora
- maplibre
- meshtastic
- mosquitto
- mqtt
- nasa-firms
- next.js
- noaa-goes-19
- nvidia-jetson-orin-nano
- nws-api
- open-meteo
- postgis
- postgresql
- python
- react
- sensecap-t1000-e
- supabase
- tailwindcss
- tiger-data
- timescaledb
- typescript
Log in or sign up for Devpost to join the conversation.