128 lines
4.7 KiB
Markdown
128 lines
4.7 KiB
Markdown
# StaySense (MVP NRW)
|
|
|
|
StaySense bewertet fuer die Nacht (22:00-06:00) die voraussichtliche Ruhe eines Spots in NRW (Pilot: Kreis Mettmann).
|
|
|
|
## MVP Status
|
|
|
|
Implementiert:
|
|
- Night Safety Score (0-100) mit Ampel (`green`, `yellow`, `red`)
|
|
- Begruendung mit Top-Faktoren (OSM-Typ, Distanz-POIs, Zeitlogik, Events, Community)
|
|
- API: `GET /spot/score`, `POST /spot/signal`
|
|
- Kartenwahl via OpenStreetMap (Leaflet), inkl. Klickauswahl und Ortssuche
|
|
- API: `GET /geocode/search` (Nominatim-Proxy), `GET /map/tile/{z}/{x}/{y}.png` (OSM-Tile-Proxy)
|
|
- PWA-Basis (Manifest, Service Worker, iOS-Standalone-Meta, Offline-Shell)
|
|
- Admin-Bereich (Setup/Login, geschuetzt per User/Passwort + Session-Token)
|
|
- Admin-API fuer Uebersicht und Event-Verwaltung (`/admin/*`)
|
|
- Anti-Spam ohne Account: lokaler Token + serverseitiger HMAC-Hash
|
|
- Quick Decision UI mit Signal-Buttons
|
|
- Offline-First im Frontend: Score-Cache + Signal-Queue
|
|
- Echter OSM-Import via Overpass (POIs, Landuse-Zonen, Highway-Typen)
|
|
- OpenData-Connectoren (CSV/JSON aus URL oder Datei)
|
|
- Automatischer Import-Job-Runner (`once` oder `daemon`)
|
|
|
|
Nicht im MVP:
|
|
- Accounts/Login
|
|
- Chat/Kommentare
|
|
- Stellplatz-Portal
|
|
- Routenplanung
|
|
|
|
## Start
|
|
|
|
1. Datenbank initialisieren:
|
|
- `cd StaySense/backend`
|
|
- `python3 -c "from db import init_db; init_db()"`
|
|
2. OSM importieren (Pilot-BBox Mettmann):
|
|
- `python3 import_osm_overpass.py`
|
|
3. OpenData-Connectoren aus Konfig ausfuehren:
|
|
- `python3 run_import_jobs.py --config ../docs/open_data_sources.json --prune-legacy`
|
|
4. Optional: periodische Imports (alle 6h) inkl. OSM:
|
|
- `python3 run_import_jobs.py --config ../docs/open_data_sources.json --with-osm --prune-legacy --daemon --interval-seconds 21600`
|
|
5. API starten:
|
|
- `python3 server.py`
|
|
6. Frontend starten (zweites Terminal):
|
|
- `cd ../src`
|
|
- `python3 -m http.server 8080`
|
|
7. App oeffnen:
|
|
- `http://localhost:8080`
|
|
8. PWA-Test:
|
|
- iOS Safari: Seite aufrufen -> Teilen -> "Zum Home-Bildschirm"
|
|
- Danach aus Home-Screen starten (Standalone-Modus)
|
|
|
|
## OpenData Connector Config
|
|
|
|
Datei: `docs/open_data_sources.json`
|
|
|
|
- `enabled`: Quelle aktivieren/deaktivieren
|
|
- `format`: `csv` oder `json`
|
|
- `url` oder `file`: Quelle
|
|
- `field_map`: Mapping auf StaySense-Felder
|
|
- `event_type_map`: optionale Typ-Normalisierung
|
|
- `json_path`: Pfad auf Array bei JSON-Feeds
|
|
- Validierung aktiv:
|
|
- Koordinaten muessen in DE-Bounds liegen
|
|
- `start_datetime < end_datetime`
|
|
- Event-Typ muss auf `market|waste|event|construction` normalisiert werden
|
|
|
|
Live-Beispiel fuer echte NRW-OpenData-Quellen:
|
|
- Datei: `docs/open_data_sources_nrw_live.json`
|
|
- Enthalten:
|
|
- Koeln Verkehrsbeeintraechtigungen (ArcGIS JSON)
|
|
- Koeln Baustellen Notfall (WFS GeoJSON)
|
|
- Import:
|
|
- `cd StaySense/backend`
|
|
- `python3 run_import_jobs.py --config ../docs/open_data_sources_nrw_live.json --prune-legacy`
|
|
|
|
## Tests
|
|
|
|
- Backend Unit-Tests:
|
|
- `cd StaySense/backend`
|
|
- `python3 -m unittest discover -s tests -p \"test_*.py\"`
|
|
|
|
## API Beispiele
|
|
|
|
Score holen:
|
|
- `curl "http://127.0.0.1:8787/spot/score?lat=51.25&lon=6.97&at=2026-02-15T20:00:00Z"`
|
|
|
|
Signal senden:
|
|
- `curl -X POST "http://127.0.0.1:8787/spot/signal" -H "Content-Type: application/json" -d '{"spot_id":"<ID>","signal_type":"noise","device_token":"<uuid-v4>","timestamp":"2026-02-15T20:15:00Z"}'`
|
|
|
|
Ortssuche:
|
|
- `curl "http://127.0.0.1:8787/geocode/search?q=Mettmann%20Bahnhof"`
|
|
|
|
Tile-Proxy:
|
|
- `curl -I "http://127.0.0.1:8787/map/tile/12/2149/1387.png"`
|
|
|
|
Admin-Setup (nur beim ersten Start):
|
|
- `curl -X POST "http://127.0.0.1:8787/admin/bootstrap" -H "Content-Type: application/json" -d '{"username":"admin","password":"<starkes-passwort>"}'`
|
|
|
|
## DSGVO-Hinweise im MVP
|
|
|
|
- Kein Login
|
|
- Keine IP-Speicherung in der Anwendung
|
|
- Kein Device Fingerprinting
|
|
- Missbrauchsschutz nur ueber `hashed_device = HMAC_SHA256(device_token, server_salt)`
|
|
|
|
## Attribution (Rechtliches)
|
|
|
|
Unter `Attribution` muessen die verwendeten Datenquellen und Lizenzen klar genannt werden:
|
|
- OpenStreetMap-Mitwirkende + ODbL-Hinweis
|
|
- Geocoding-Dienst (Nominatim) als Quelle
|
|
- Jede OpenData-Quelle mit Lizenzhinweis (z. B. Datenlizenz Deutschland Zero/By)
|
|
|
|
In der App ist dafuer die Seite `quellen.html` vorgesehen.
|
|
|
|
## Produktion
|
|
|
|
- `STAYSENSE_SERVER_SALT` zwingend als geheimes Env setzen
|
|
- HTTPS-only bereitstellen
|
|
- OpenStreetMap-/Open-Data-Attribution in App verpflichtend sichtbar halten
|
|
|
|
## Doku Uebersicht
|
|
|
|
- Architektur / Umsetzung: `docs/IMPLEMENTATION_PLAN.md`
|
|
- Server-Deployment (Linux + Nginx + systemd): `docs/DEPLOYMENT.md`
|
|
- CloudPanel-Setup (Hetzner): `docs/CLOUDPANEL_SETUP.md`
|
|
- Betrieb / Runbook: `docs/OPERATIONS.md`
|
|
- GitHub Publish Ablauf: `docs/GITHUB_PUBLISH.md`
|
|
- Connector-Konfiguration: `docs/open_data_sources.json`
|
|
- Event-Template: `docs/open_data_events_template.csv`
|