尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
☁️ SkyWindow: Should I let the sky in? Try it: https://mahitp.github.io/phs-hackathon/ (showcase mode: the live sky over Princeton High School and a simulated room sensor, no Raspberry Pi needed). It's published from main by .github/workflows/pages.yml on every push. On June 7, 2023, wildfire smoke from Canada turned Princeton's sky orange. That day, opening a window was the worst thing you could do. On most other days, opening a window is the best thing you can do for a stuffy room.查看完整 README ↗
hackPHS 2026 · Theme: "Into the Skies" · Built by Mahit's Team
Try it: https://mahitp.github.io/phs-hackathon/ (showcase mode: the live sky over Princeton High School and a simulated room sensor, no Raspberry Pi needed). It's published from main by .github/workflows/pages.yml on every push.
On June 7, 2023, wildfire smoke from Canada turned Princeton's sky orange. That day, opening a window was the worst thing you could do. On most other days, opening a window is the best thing you can do for a stuffy room.
SkyWindow is a small device that sits on your windowsill. It watches the sky above you and the air in your room, then gives you one clear answer:
| LCD | Verdict | When |
|---|---|---|
| 🟢 | OPEN THE WINDOW | The sky is cleaner than your room (clean outdoor air, or moderate outdoor air and a stale room) |
| 🟡 | EITHER WAY | Inside and outside are about the same (moderate outdoor air, room not stale) |
| 🔴 | KEEP IT SHUT | Smoke, haze, ozone or particles in the sky (AQI > 100, PM2.5 > 35, or heavy haze) |
| 🟣 | VENTILATE NOW | Your room just spiked (cleaners, markers, cooking, sanitizer) |
Press Read it aloud and it reads the verdict to the classroom: "SkyWindow update: the sky is hazy with pollution, so please keep the windows shut…"
T = exp(−AOD / sin(sun elevation)). That's about 88% on a clear day with the sun high, and about 5–30% under the 2023 smoke depending on the sun angle.SKYWINDOW_AUTO_ANNOUNCE=1 the device announces every time the verdict changes.ml/train.py) on it. The dashboard shows what it thinks is happening in the room. Accuracy is cross-validated by labeling session, so it isn't inflated by near-identical back-to-back samples. The model and labeled data stay on the device (ml/model.joblib, data/skywindow.db); run python ml/train.py on the Pi after labeling.Verdict thresholds have hysteresis (for example, KEEP IT SHUT starts above AQI 100 and only ends below 95), so readings that hover around a boundary don't make the LCD or the announcements flip back and forth.
Honesty note: the Grove Air Quality v1.3 is a VOC gas sensor with relative output. We never call its reading AQI. It becomes a 0–100 "stale index" measured against the room's own clean-air baseline. The outdoor AQI comes from real atmospheric data.
web/ has two pages: a 3D story that explains the project (index.html, the home page) and the live dashboard (app.html).
The story is a scroll-driven 3D film in one continuous flight, from 824 km up to a classroom windowsill. It is built with three.js, GSAP and Lenis (all bundled, so it works offline):
Scroll snaps to each hero pose. Sound is generated in the browser and follows the real wind. Rendering uses a post-processing chain chosen per device: ambient occlusion, god rays, depth of field, bloom, filmic tone mapping, anti-aliasing and film grain. scripts/fetch_story_assets.sh re-downloads and compresses the imagery, star catalogue and classroom models. The story adapts to the device (lighter effects on phones and slower GPUs), respects reduced-motion settings, and becomes a plain text article if WebGL isn't available. scripts/bake_story_data.py re-creates the map and smoke data files.
The live dashboard (app.html, reached through the dive from the story):
Map controls: every map view has the same small control in the corner: recenter, satellite/map and NASA fires. 3. Forecast — "When can PHS open its windows?" An hour-by-hour strip for the next 24 hours: weather icon, temperature, AQI, rain chance and a window verdict per hour (open, either, shut for bad air, shut for rain). It also highlights the best daytime window to air out and shows sunrise, sunset, max UV, clouds and ozone. On the device it also charts the last hour of the room vs the sky from the Pi's history. Hourly rules: shut if the forecast AQI is over 100, PM2.5 is over 35 or there's heavy haze; shut if rain is 60%+ likely; open if AQI is 50 or less and it's dry. 4. Earth (global context): city dots on the 3D globe in EPA colors, a breakdown of how many of 43 cities are Good, Moderate, Unhealthy and so on, the median AQI, and region jumps, with each city's name and AQI next to its dot. Tap anywhere for a side-by-side comparison with PHS (AQI, PM2.5, haze, weather, temperature, humidity, wind, local time). Earth never shows the classroom sensor or a windows verdict. Those belong to PHS Campus, and clicks more than 25 km from PHS on the campus map are sent to Earth.
The June 7, 2023 smoke day and how SkyWindow works are told by the story, so the dashboard keeps to these four views.
Real alerts:
Fires (NASA FIRMS): the Pi downloads the public VIIRS active-fire file every hour and keeps detections within 300 km of PHS, dropping low-confidence points. It works out which ones are upwind from the live wind direction. These detections include small crop and brush burns and some industrial heat sources, so the site reports their size (fire radiative power) and only warns when the upwind fire power is significant.
The site runs in one of two modes:
http://<pi-ip>:8000 (story) or http://<pi-ip>:8000/app.html (dashboard). Both the story and the dashboard read the Pi's /api/now, so the Pi's verdict, room reading, forecast and fires show everywhere. The status chip says which source is live: DEVICE LIVE (Raspberry Pi sensors), DEVICE · SENSOR OFFLINE (Pi running but the Grove HAT/sensor isn't answering, so the verdict uses outside air only), DEVICE · BACKUP FEED (the backup backend on port 8001) or DEVICE · DEV MODE (laptop with mock sensors). The page must be opened from the server's own address: a copy of web/ served by anything else can't reach the Pi and runs in showcase mode.web/ from any static host, or run python -m http.server -d web. The page fetches the sky straight from Open-Meteo and simulates the room sensor, so judges can try it on their own phones.Pi backend — server/, device/ (port 8000) | Backup backend — simulator/ (port 8001) | |
|---|---|---|
| Indoor air | The Pi's Grove sensors only | Scenario-driven classroom (simulator/scenarios.py) |
| If a sensor fails | Shows SENSOR OFFLINE and decides on outside air only. It never substitutes made-up numbers, and it reconnects automatically | n/a |
| Outside air, weather, NASA fires | Real | The same real data, unless the chosen scenario overrides it |
| LCD / GPIO | Real | Never touched |
| Database | data/skywindow.db (real readings only) | data/sim.db |
| Scenario controls | None | Operator page at /sim |
| Dashboard label for the room reading | RASPBERRY PI / LIVE (or SENSOR OFFLINE) | BACKUP FEED |
simulator/ (a test enforces this). The backup runs as its own process and wraps its own copy of the server code, so nothing it does can reach the Pi backend's readings, verdict or database.SKYWINDOW_MOCK=1 is set explicitly. scripts/dev.py sets it for laptop development, and the dashboard then says DEV MODE.http://<pi>:8001/sim, not part of the dashboard):
Grove sensors ──► device/hw.py ─┐
├─► server/app.py (FastAPI, 1 Hz loop) ──► device/lcd.py (verdict + color)
Open-Meteo ────► server/sky.py ─┤ │ └─► web/ dashboard (phone, any browser)
2023 replay ───► server/replay.py┘ ├─► server/decide.py (verdict engine)
├─► server/clarity.py (sun position, clear-sky, Beer-Lambert)
├─► server/report.py (Gemini classroom announcement)
├─► server/voice.py (ElevenLabs TTS)
└─► server/store.py (SQLite history + labels) ──► ml/train.py
On the Raspberry Pi:
git clone <this repo> ~/skywindow && cd ~/skywindow
bash scripts/setup_pi.sh # enables I2C, installs deps + grove.py, starts the service on boot
nano .env # optional: GEMINI_API_KEY, ELEVENLABS_API_KEY
sudo systemctl restart skywindow
Then open http://<pi-ip>:8000/app.html (the dashboard) or http://<pi-ip>:8000 (the story page) on any phone on the same network. The site's libraries, fonts and Earth textures are bundled in web/vendor/, so it renders even when the phone has no internet (for example on a Pi hotspot); only the live sky data needs a connection.
Hardware checks:
python device/hw.py # live sensor values
python device/lcd.py --test # cycles the 4 verdict colours
On a laptop (no hardware, simulated sensors):
python -m venv .venv
.venv/bin/pip install -r requirements.txt # macOS / Linux (Windows: .venv\Scripts\pip)
.venv/bin/python scripts/dev.py # http://localhost:8000 - use the "Mock" buttons under Setup
Tests: .venv/bin/pip install -r requirements-dev.txt && .venv/bin/python -m pytest
| Method | Path | What it does |
|---|---|---|
| GET | /api/now | Full live state: verdict, indoor, sky, clarity, replay |
| GET | /api/history?minutes=60 | Logged readings |
| POST | /api/report {"speak": true} | Generate the spoken announcement (+ ElevenLabs audio). Repeat requests within 15 s reuse it |
| POST | /api/replay {"on": true} | Start or stop the Smoke Day replay |
| POST | /api/calibrate {"what": "air"|"light"} | Set the clean-air baseline, or calibrate the light sensor to the sky |
| POST | /api/label {"label": "chemical"} | Record a labeled sample for the classifier |
If SKYWINDOW_TOKEN is set in .env, every POST needs an X-SkyWindow-Token header. Open the dashboard once as http://<pi-ip>:8000/app.html?token=<token> and the phone remembers it. Reads stay open.
Sky data: Open-Meteo (CC BY 4.0), CAMS air-quality and ERA5 reanalysis. The dashboard's 3D Earth is adapted from TerraShift's EarthGlobe (MIT License, Copyright (c) 2026 TerraShift), with NASA Blue Marble imagery from the three.js example textures. Story imagery: NASA Earth Observatory (Blue Marble Next Generation, Black Marble 2016, Blue Marble clouds, GEBCO/BMNG topography) and NASA/Goddard Scientific Visualization Studio (Deep Star Maps 2020). Star catalogue: HYG database v4.1 (CC BY-SA 4.0). Satellite model: NASA 3D Resources. Classroom models, textures and lighting: Poly Haven (CC0). Map data: © OpenStreetMap contributors (ODbL). Built in 24 hours at hackPHS 2026.
simulator/room.pysetup_pi.sh installs both services. On a laptop, run python scripts/dev.py (8000) and python scripts/sim.py (8001).