factcircuit
FactCircuit는 불변 출처와 단계별 검증, 제한된 검색, 재현 가능한 평가를 제공하는 감사 가능한 주장·증거 검증 루프입니다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Cloudgebaseerd dashboard voor actuele en historische weergegevens van een Alecto WS5500 weerstation. Fase 1 legde de technische fundering (database, infrastructuur, basislayout). Fase 2 voegde de volledige data-ingestie toe (ontvangen, opslaan, parsen, normaliseren, diagnosticeren).README 전문 보기 ↗
Cloudgebaseerd dashboard voor actuele en historische weergegevens van een Alecto WS5500 weerstation. Fase 1 legde de technische fundering (database, infrastructuur, basislayout). Fase 2 voegde de volledige data-ingestie toe (ontvangen, opslaan, parsen, normaliseren, diagnosticeren). Fase 3 (dit document) bouwt daarbovenop het live dashboard, historie en de weerstatistieken: automatische achtergrond-ingestie via een cronjob, dag/maand/jaar-samenvattingen, downsamplede grafieken, regen-, wind- en recordspagina's, en een gepagineerde historieverkenner — allemaal op basis van echte, genormaliseerde stationdata. Zie Buiten scope voor wat bewust nog niet gebouwd is.
Geen Raspberry Pi, NAS of thuisserver nodig: de architectuur is volledig cloud-based (GitHub → Vercel/Next.js → TiDB Cloud).
docs/ARCHITECTURE.md §4 voor
de afweging tegenover Prisma)Volledige architectuurkeuzes, tabelontwerp, indexering en
schaalbaarheidsoverwegingen staan in
docs/ARCHITECTURE.md.
GitHub
|
v
Next.js / Vercel
|
v
TiDB Cloud
Zie docs/ARCHITECTURE.md voor het volledige
diagram inclusief de toekomstige koppeling met de WS5500.
Vereist: Node.js 20+ en npm.
git clone https://github.com/<jouw-gebruikersnaam>/weerstation-ws5500.git
cd weerstation-ws5500
npm install
Kopieer .env.example naar .env.local en vul de waarden in:
Copy-Item .env.example .env.local
| Variabele | Verplicht | Omschrijving |
|---|---|---|
DATABASE_URL | Ja | TiDB Cloud connection string. Zie TiDB Cloud setup. |
NEXT_PUBLIC_STATION_NAME | Nee (default Alecto WS5500) | Naam die in de UI getoond wordt. |
NEXT_PUBLIC_TIMEZONE | Nee (default Europe/Amsterdam) | Tijdzone voor presentatie en kalenderaggregaties. |
NEXT_PUBLIC_DEMO_MODE | Nee (default false) | Toont een "Demo-gegevens"-label als er (nog) geen echte stationdata is. |
WEATHER_INGEST_SECRET | Ja, voor ingestie | Geheime waarde in het pad van /api/weather/ingest/<secret> en /api/weather/providers/ecowitt-cloud/<secret>. Zie docs/WS5500_SETUP.md. |
SITE_AUTH_USERNAME | Ja | Gebruikersnaam voor de site-brede login op /login (Fase 7). Beveiligt de hele site: dashboard, alle pagina's, /admin/stations, /station/diagnostics. |
SITE_AUTH_PASSWORD | Ja | Wachtwoord bij SITE_AUTH_USERNAME (minimaal 8 tekens). Kies een sterk, uniek wachtwoord. |
SITE_AUTH_SESSION_SECRET | Ja | Ondertekent de sessiecookie na het inloggen — een lange, willekeurige string (minimaal 32 tekens, bv. openssl rand -hex 32), géén wachtwoord dat je onthoudt. Wijzigen logt iedereen in één keer uit. |
ECOWITT_APPLICATION_KEY / ECOWITT_API_KEY / ECOWITT_DEVICE_MAC | Nee, alleen voor de Ecowitt Cloud-fallbackroute | Zie docs/WS5500_SETUP.md §5. |
Alle variabelen worden bij gebruik gevalideerd met Zod
(src/lib/env.ts). Server-only variabelen (zoals DATABASE_URL) komen
nooit in de browserbundle terecht; alleen NEXT_PUBLIC_*-variabelen zijn
client-veilig.
Zet nooit echte geheimen in git. .env.local staat in .gitignore.
Sinds Fase 7 vereist de HELE site (dashboard, alle pagina's,
/admin/stations, /station/diagnostics) inloggen op /login met de
gebruikersnaam/het wachtwoord uit SITE_AUTH_USERNAME/SITE_AUTH_PASSWORD
(zie de variabelentabel hierboven). Eén gedeeld account voor de hele site —
geen aparte accounts per pagina.
/api/weather/ingest/<WEATHER_INGEST_SECRET>) en de
externe cronjob-pinger (/api/weather/providers/ecowitt-cloud/ <WEATHER_INGEST_SECRET>) — zie Automatische ingestie.
Die blijven beveiligd met hun eigen geheime sleutel in het pad, zoals
voorheen. /api/health (publieke uptime-check, geen gevoelige data)
blijft ook zonder login bereikbaar.SITE_AUTH_USERNAME/
SITE_AUTH_PASSWORD/SITE_AUTH_SESSION_SECRET weigert de site bewust
duidelijk te starten, in plaats van per ongeluk onbeveiligd te draaien.SITE_AUTH_SESSION_SECRET wijzigen maakt alle bestaande sessies in één
keer ongeldig (iedereen moet opnieuw inloggen) — handig als een sessie
ooit onbedoeld gedeeld is.De vroegere losse ?key=<STATION_DIAGNOSTICS_SECRET>/
?key=<STATION_ADMIN_SECRET>-sleutels voor respectievelijk
/station/diagnostics en /admin/stations bestaan niet meer — die
variabelen kunnen uit .env.local en de Vercel-projectinstellingen
verwijderd worden.
Volledige stap-voor-stapinstructies (account, cluster, gebruiker, SSL,
DATABASE_URL samenstellen, lokaal en in Vercel instellen) staan in
docs/TIDB_SETUP.md.
Migraties zijn gewone SQL-bestanden in db/migrations/, gegenereerd met
Drizzle Kit vanuit src/lib/db/schema.ts.
# Migratie(s) genereren vanuit het schema (na een schemawijziging)
npm run db:generate
# Migraties uitvoeren tegen de database in DATABASE_URL
npm run db:migrate
# Optioneel: schema direct pushen zonder migratiebestand (alleen handig
# tijdens snelle lokale iteratie — gebruik db:generate + db:migrate als
# vaste procedure, ook in productie)
npm run db:push
# Optioneel: Drizzle Studio openen om de database visueel te bekijken
npm run db:studio
# Maakt (of werkt bij) het demo-station "Mijn Alecto WS5500"
npm run db:seed
# Genereert ~24 uur fictieve weermetingen (herkenbaar aan source =
# "demo_generator"), zodat dashboard/station iets te tonen hebben
npm run demo
# Verwijdert alle door npm run demo gegenereerde data weer
npm run demo:clear
Zet NEXT_PUBLIC_DEMO_MODE=true zodat de UI duidelijk "Demo-gegevens"
toont zolang er geen echte stationdata binnenkomt.
npm run dev
Open http://localhost:3000. De statuspagina
(/) en het dashboard (/dashboard) tonen live de databasestatus en
(indien aanwezig) de laatste meting (elke ~60 seconden automatisch
ververst).
Twee routes leveren data aan, via één gedeelde parser/normalisatielaag:
POST/GET /api/weather/ingest/<WEATHER_INGEST_SECRET>.
Waarschijnlijk niet bruikbaar zonder tussenstap: de WS5500's
"Customized"-uploadmodus ondersteunt in de praktijk geen TLS, en Vercel
accepteert alleen HTTPS. Zie de analyse in
docs/WS5500_INGESTION.md.GET /api/weather/providers/ecowitt-cloud/<WEATHER_INGEST_SECRET>
haalt de actuele meting op bij Ecowitt.net (waar het station wél
rechtstreeks naartoe kan uploaden) en verwerkt die via dezelfde
pijplijn. Vereist een externe periodieke trigger (bv. cron-job.org) —
Vercel Functions draaien niet vanzelf periodiek.Volledige koppelinstructies (PASSKEY opzoeken, environment variables,
stationconfiguratie, Ecowitt-account): docs/WS5500_SETUP.md.
Architectuur, beveiliging, deduplicatie en ontwerpkeuzes:
docs/WS5500_INGESTION.md. Veldreferentie en
hoe een nieuw/onbekend veld toe te voegen:
docs/ECOWITT_FIELDS.md.
Diagnose en beheer (sinds Fase 7 achter de site-brede login, zie Inloggen hieronder):
/station/diagnostics — overzicht van binnengekomen pakketten,
verwerkingsstatus, onbekende velden en Ecowitt Cloud-status; klik een
pakket open voor het volledige (redacted) ruwe payload en de afgeleide
meting.GET /api/weather/current — actuele, genormaliseerde meting (geen
cache).GET /api/weather/station/status — stationconfiguratie (zonder het
echte PASSKEY prijs te geven) en pakketstatistieken.Scripts:
# Stuurt een testpayload naar het ingestie-endpoint (lokaal of live)
npm run weather:test-payload -- --fixture=full-payload
# Verwerkt eerder ontvangen ruwe pakketten opnieuw met de huidige parser
npm run weather:reprocess -- 42
# Toont welke velden de parser recent niet herkende
npm run weather:unknown-fields
Een externe cronjob (cron-job.org, elke 5 minuten) roept
/api/weather/providers/ecowitt-cloud/<secret> automatisch aan — geen
handmatige actie meer nodig. Volledige onderbouwing en instelinstructies:
docs/AUTOMATIC_INGESTION.md. De cronjob-
status ("Actief"/"Vertraagd"/"Offline") is zichtbaar op /station.
Na elke geslaagde meting worden de dag/maand/jaar-samenvattingen
(daily_weather_summary/monthly_weather_summary/yearly_weather_summary)
automatisch bijgewerkt. Volledige uitleg van alle rekenlogica (downsampling,
regen-tellerlogica, windroos, records, trends, lokale-kalenderdag-grenzen
met zomer-/wintertijd): docs/DATA_AGGREGATION.md.
# Herbereken dag/maand/jaar-samenvattingen (standaard: alleen vandaag)
npm run weather:recompute-summaries
# Herbereken een specifieke periode
npm run weather:recompute-summaries -- --from 2026-08-01 --to 2026-08-31
# Herbereken alles sinds de eerste meting (bv. na een reparatiescript)
npm run weather:recompute-summaries -- --all
| Pagina | Inhoud |
|---|---|
/dashboard | Live metingen (auto-ververst) + 24-uursgrafiek (temperatuur/gevoelstemperatuur/dauwpunt). |
/grafieken | Categorie- en periodeselector, tijdreeksgrafieken via /api/weather/history (server-side downsampling). |
/regen | Neerslag per uur/dag/maand, met correcte tellerdelta-berekening (nooit dubbel tellen). |
/wind | Interactieve windroos (16 richtingen) + gemiddelde snelheid/hoogste windstoot. |
/records | Hoogste/laagste waarden per periode (vandaag/maand/jaar/all-time), SQL-side berekend. |
/historie | Gepagineerde, filterbare lijst van individuele metingen. |
/station | Stationgegevens + cronjob-/ingestiestatus + dekkingspercentage. |
/station/diagnostics | Technische diagnose (ruwe pakketten, parserstatus). |
Sinds Fase 5 kan de applicatie meerdere Ecowitt-compatibele weerstations tegelijk bedienen (bv. "Achtertuin" naast "Vakantiehuis") — elk met zijn EIGEN dashboard, historie, grafieken, records, regen-/windoverzicht, exports en datakwaliteit; nooit vermengd met een ander station. Elk station heeft zijn eigen tijdzone (lokale-kalendergrenzen), en niet elk station hoeft dezelfde sensoren te hebben (een ontbrekende sensor toont "Niet beschikbaar", nooit een verzonnen waarde).
Fase 5.1 legde het fundament — databasemodel, tijdzone- en capability-laag,
de Ecowitt-koppeling voor meerdere apparaten via één cron-aanroep, en een
?station=-queryparameter op alle pagina's/API's. Fase 5.2 (huidige stand)
bouwt daar de zichtbare UI bovenop:
?station= reist mee bij het doorklikken./station/beheer (tabblad Beheer van Stations; het oude
/admin/stations stuurt hierheen door) — beheerscherm (achter de site-brede login, zie
Inloggen): stations toevoegen (met "verbinding testen" —
welke sensoren het apparaat daadwerkelijk meldt, vóór opslaan), bewerken,
als default instellen, activeren/deactiveren.Zonder ?station=-parameter, of met precies één station, blijft alles
werken zoals vóór Fase 5: het bestaande WS5500-station is en blijft het
default-station. Fase 5.3 (volledig testmatrix, productie-uitrol,
eindrapport) volgt nog. Volledige uitleg:
docs/MULTI_STATION.md.
npm run typecheck # TypeScript, strict mode
npm run lint # ESLint
npm run test # Vitest (eenheidsconversies, environment-validatie, parser, ingestiepijplijn, aggregatielogica)
npm run format:check # Prettier (controleren zonder te wijzigen)
npm run typecheck genereert eerst automatisch Next.js' route-types
(next typegen) en voert daarna tsc --noEmit uit.
Databasetests vereisen geen live TiDB-verbinding: de databaselaag is zo
gebouwd dat modules importeren nooit verbinding maakt (zie
docs/ARCHITECTURE.md §6). De ingestiepijplijn
wordt getest via een gemockte @/lib/db/queries-laag
(tests/weather-ingest-pipeline.test.ts); parser, tijdstip-, hash- en
redactielogica zijn pure-functietests (tests/weather-*.test.ts) — samen
met tests/env.test.ts/tests/units.test.ts meer dan 100 tests, waaronder
een expliciete test die bewijst dat een payload met deels foute velden
nooit tot volledig dataverlies leidt.
npm run build
npm run start
De build slaagt ook zonder geldige DATABASE_URL (handig voor CI en
voor een eerste deploy vóórdat TiDB is ingericht) — de databaseverbinding
wordt pas bij een echt binnenkomend request opgezet, nooit tijdens de
build zelf.
Volledige stap-voor-stapinstructies (GitHub-repository, project
importeren, environment variables, deployment, /api/health controleren,
custom domain) staan in docs/VERCEL_SETUP.md.
Bewust (nog) niet gebouwd, zoals afgebakend voor Fase 3:
Het datamodel (weather_observations, de summary-tabellen) en de
service-laag (src/lib/db/queries.ts, src/lib/weather/*) zijn zo
opgezet dat dit later zonder herontwerp toegevoegd kan worden.
Fase 3 gereed: live dashboard, historie en weerstatistieken werken met echte Alecto WS5500-data.