No description
| .github/workflows | ||
| backend | ||
| deploy | ||
| docs | ||
| scripts | ||
| src | ||
| .gitignore | ||
| README.md | ||
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 (
onceoderdaemon)
Nicht im MVP:
- Accounts/Login
- Chat/Kommentare
- Stellplatz-Portal
- Routenplanung
Start
- Datenbank initialisieren:
cd StaySense/backendpython3 -c "from db import init_db; init_db()"
- OSM importieren (Pilot-BBox Mettmann):
python3 import_osm_overpass.py
- OpenData-Connectoren aus Konfig ausfuehren:
python3 run_import_jobs.py --config ../docs/open_data_sources.json --prune-legacy
- 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
- API starten:
python3 server.py
- Frontend starten (zweites Terminal):
cd ../srcpython3 -m http.server 8080
- App oeffnen:
http://localhost:8080
- 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/deaktivierenformat:csvoderjsonurloderfile: Quellefield_map: Mapping auf StaySense-Felderevent_type_map: optionale Typ-Normalisierungjson_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|constructionnormalisiert 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/backendpython3 run_import_jobs.py --config ../docs/open_data_sources_nrw_live.json --prune-legacy
Tests
- Backend Unit-Tests:
cd StaySense/backendpython3 -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_SALTzwingend 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