Ein vollständiger Space-API Server nach dem SpaceAPI Standard für Hackerspaces und Makerspaces. Dieses Projekt stellt den Status und die Sensordaten eines Spaces über eine standardisierte REST-API bereit.
Derzeit in Einsatz beim Odenwilusenz in Beringen, Schweiz.
- Features
- Installation & Setup
- API Endpoints
- Keep-Alive System
- Verwendungsbeispiele
- Für deinen Space konfigurieren
- Manual Override Interface
- Sensoren
Dieses Projekt stellt eine REST-API nach dem SpaceAPI Standard bereit, mit der der Zustand und die Sensordaten eines Hackerspaces oder Makerspaces abgefragt werden können.
✅ SpaceAPI Standard konform - Kompatibel mit allen SpaceAPI-kompatiblen Anwendungen
✅ Einfache Konfiguration - Alle statischen Daten in api.json
✅ Dynamische Sensordaten - Echtzeit-Aktualisierung von Temperatur, Luftfeuchtigkeit, Stromverbrauch, etc.
✅ API-Key Authentisierung - Schreibzugriffe erfordern API-Key Header
✅ State Management - Einfaches An/Aus-Schalten des Spaces mit Nachricht
✅ Keep-Alive System - Automatisches Schließen des Spaces nach 30 Sekunden ohne Signal
✅ Manual Override Interface - Passwort-geschützte HTML Seite zur manuellen Bearbeitung
- Hackerspaces können ihren aktuellen Status veröffentlichen
- Integrationen mit Websites und Chatbots
- Monitoring und Visualisierung von Space-Daten
- Integration mit anderen Spaces durch SpaceAPI-Verzeichnisse
- Python 3.7 oder höher
- pip (Python Package Manager)
-
Repository klonen oder herunterladen:
git clone <repository-url> cd Space-API
-
Abhängigkeiten installieren:
pip install -r requirements.txt
-
Erforderliche Umgebungsvariablen setzen:
# Linux/Mac - in ~/.bashrc oder ~/.zshrc export FLASK_SECRET_KEY="eine-lange-zufallszeichenkette-mindestens-32-zeichen" export SPACE_API_PASSWORD="dein-sicheres-admin-passwort" export SPACE_API_ADMIN_KEY="dein-eindeutiger-api-key-fuer-aenderungen" # Windows (PowerShell) $env:FLASK_SECRET_KEY="eine-lange-zufallszeichenkette-mindestens-32-zeichen" $env:SPACE_API_PASSWORD="dein-sicheres-admin-passwort" $env:SPACE_API_ADMIN_KEY="dein-eindeutiger-api-key-fuer-aenderungen"
-
Server starten:
python main.py
-
Server ist aktiv: Der Server läuft jetzt auf
http://localhost:8000
Die api.json enthält alle statischen Informationen über deinen Space nach dem SpaceAPI Standard. Diese Datei wird nicht verändert vom Script und sollte angepasst werden, um deinen Space zu beschreiben.
{
"api_compatibility": ["14", "15"], // SpaceAPI Versionen
"space": "Odenwilusenz", // Name des Spaces
"logo": "https://...", // Logo URL
"url": "https://...", // Website des Spaces
"location": {
"address": "Hardmorgenweg 21, ...", // Physische Adresse
"lon": 8.57171860, // Longitude
"lat": 47.69790250, // Latitude
"timezone": "Europe/Zurich", // Zeitzone
"country_code": "CH", // Ländercode
"hint": "Immer am Mittwoch ab 19:00..." // Öffnungszeiten/Hinweis
},
"contact": {
"email": "mail@example.ch", // Kontakt-E-Mail
"issue_mail": "spaceapi@example.ch" // Problem-Reports
},
"sensors": { // Alle Sensoren die dein Space anbietet
}
}Im main.py werden die folgenden Werte dynamisch aktualisiert:
state.open-trueoderfalse(ob der Space offen ist)state.message- Text-Nachricht (z.B. "Space offen!", "Temporär geschlossen")state.lastchange- Zeitstempel der letzten Änderung (wird automatisch aktualisiert)
Temperatur:
sensors.temperature[0].value- Temperatur Innensensors.temperature[1].value- Temperatur Außen
Luftfeuchtigkeit:
sensors.humidity[0].value- Luftfeuchtigkeit Innensensors.humidity[1].value- Luftfeuchtigkeit Außen
Stromverbrauch:
sensors.power_consumption[0].value- Gesamtstromverbrauch in Watt
Netzwerk:
sensors.network_connections[0].value- Anzahl aktiver Verbindungensensors.network_traffic[0].properties.bits_per_second.value- Download Trafficsensors.network_traffic[1].properties.bits_per_second.value- Upload Traffic
python main.pyAusgabe:
============================================================
Odenwilusenz Space-API Server
============================================================
Starting auf http://localhost:8000
Wichtige Endpoints:
- Hauptendpoint (SpaceAPI Standard): GET http://localhost:8000/api.json
- Admin State: GET/POST http://localhost:8000/admin/state
- Alle Sensoren: GET http://localhost:8000/admin/all_sensors
- Hilfe: GET http://localhost:8000/help
============================================================
Mit curl oder einem REST-Client (z.B. Postman, Insomnia):
# Komplette API abrufen (SpaceAPI Standard)
curl http://localhost:8000/api.json
# State auslesen
curl http://localhost:8000/api/get/state/open
# Wert ändern (mit API-Key Header)
curl -X POST http://localhost:8000/api/post/state/open \
-H "X-API-Key: dein-api-key-fuer-schreibzugriffe" \
-H "Content-Type: application/json" \
-d '{"value": true}'Gibt die komplette api.json mit allen aktuellen Sensordaten und State nach SpaceAPI Standard zurück.
Beispiel Response:
{
"api_compatibility": ["14", "15"],
"space": "Odenwilusenz",
"state": {
"open": false,
"message": "Space ist geschlossen",
"lastchange": 1704067200
},
"sensors": { ... },
...
}Liest beliebige Werte aus der API aus. Keine Authentisierung erforderlich.
Beispiele:
# State auslesen
GET /api/get/state/open
Response: {"value": true}
# Temperatur auslesen
GET /api/get/sensors/temperature/0/value
Response: {"value": 22.5}Ändert Werte in der API. Erforderlich: X-API-Key Header
Request Header:
X-API-Key: dein-api-key-fuer-schreibzugriffe
Content-Type: application/json
Request Body:
{
"value": <beliebiger-wert>
}Beispiele:
# Space öffnen
curl -X POST http://localhost:8000/api/post/state/open \
-H "X-API-Key: dein-api-key" \
-H "Content-Type: application/json" \
-d '{"value": true}'
# Nachricht setzen
curl -X POST http://localhost:8000/api/post/state/message \
-H "X-API-Key: dein-api-key" \
-H "Content-Type: application/json" \
-d '{"value": "Space ist offen!"}'
# Temperatur aktualisieren
curl -X POST http://localhost:8000/api/post/sensors/temperature/0/value \
-H "X-API-Key: dein-api-key" \
-H "Content-Type: application/json" \
-d '{"value": 23.5}'Response (erfolgreich):
{
"success": true,
"path": "state/open",
"new_value": true,
"message": "Wert erfolgreich aktualisiert"
}Response (Fehler - fehlender API-Key):
{
"error": "Unauthorized - X-API-Key Header erforderlich"
}Zeigt ein passwort-geschütztes HTML-Interface zum manuellen Bearbeiten der api.json.
Verwendung:
- Browser zu
http://localhost:8000/manual-overridenavigieren - Mit SPACE_API_PASSWORD anmelden
- JSON editieren und speichern
Login für Manual Override Session.
Request:
{
"password": "dein-admin-passwort"
}Response (erfolgreich):
{
"success": true,
"csrf_token": "..."
}Speichert die editierte JSON (mit CSRF-Schutz).
Request Header:
X-CSRF-Token: <csrf-token-von-login>
Content-Type: application/json
Request Body: Die komplette api.json mit Änderungen
Zeigt "Kein Command".
Zeigt "Kein Command".
JavaScript/HTML:
fetch('http://localhost:8000/api.json')
.then(response => response.json())
.then(data => {
const statusDiv = document.getElementById('space-status');
if (data.state.open) {
statusDiv.innerHTML = `<h2 style="color: green;">✓ Space ist offen!</h2>`;
} else {
statusDiv.innerHTML = `<h2 style="color: red;">✗ Space ist geschlossen</h2>
<p>${data.state.message}</p>`;
}
});Python Script:
import requests
import json
# Space öffnen
response = requests.post(
'http://localhost:8000/admin/state',
json={
'open': True,
'message': 'Space geöffnet durch Bot!'
}
)
print(response.json())
# Temperatur aktualisieren
response = requests.post(
'http://localhost:8000/admin/sensors/temperature/indoor',
json={'value': 22.5}
)
print(response.json())Python Script:
import requests
# Komplette API abrufen
response = requests.get('http://localhost:8000/api.json')
data = response.json()
print(f"Space: {data['space']}")
print(f"Status: {'Offen' if data['state']['open'] else 'Geschlossen'}")
print(f"Nachricht: {data['state']['message']}")
print(f"\nSensoren:")
print(f" Innentemp: {data['sensors']['temperature'][0]['value']}°C")
print(f" Luftfeuchtigkeit: {data['sensors']['humidity'][0]['value']}%")
print(f" Stromverbrauch: {data['sensors']['power_consumption'][0]['value']}W")Bearbeite die api.json und passe folgende Werte an:
{
"space": "Dein Space Name",
"logo": "https://example.com/logo.png",
"url": "https://example.com",
"location": {
"address": "Deine Adresse",
"lon": 8.5, // Deine Longitude
"lat": 47.5, // Deine Latitude
"timezone": "Europe/Zurich", // Deine Zeitzone
"country_code": "CH", // Ländercode
"hint": "Öffnungszeiten..."
},
"contact": {
"email": "dein-email@example.com",
"issue_mail": "probleme@example.com"
}
}Wenn dein Space andere Sensoren hat, bearbeite die sensors Section in der api.json:
- Entferne nicht benötigte Sensoren
- Füge neue Sensoren hinzu
- Passe Namen, Beschreibungen und Einheiten an
Wenn neue Sensoren hinzugefügt werden, müssen auch neue POST/GET Endpoints in main.py hinzugefügt werden:
@app.route('/admin/sensors/my_custom_sensor', methods=['GET', 'POST'])
def manage_custom_sensor():
"""Mein Custom Sensor"""
if request.method == 'GET':
return jsonify({
'value': sensor_data['my_sensor'],
'unit': 'MY_UNIT'
}), 200
elif request.method == 'POST':
try:
data = request.get_json()
if 'value' in data:
sensor_data['my_sensor'] = float(data['value'])
return jsonify({
'success': True,
'new_value': sensor_data['my_sensor']
}), 200
except Exception as e:
return jsonify({'error': str(e)}), 400-
Authentifizierung hinzufügen - Der aktuelle Admin-Endpoints haben keine Authentifizierung. Für Produktivbetrieb sollte eine API-Key oder OAuth2 hinzugefügt werden.
-
HTTPS verwenden - In Produktion sollte HTTPS über einen Reverse-Proxy (z.B. Nginx) verwendet werden.
-
Port ändern - Standard ist
localhost:8000, für externe Zugriffe auf einen anderen Port mappen. -
CORS konfigurieren - Bei Bedarf können CORS-Header konfiguriert werden.
Beispiel für Authentifizierung:
from functools import wraps
def require_api_key(f):
@wraps(f)
def decorated(*args, **kwargs):
api_key = request.headers.get('X-API-Key')
if api_key != 'dein-geheimschluessel':
return jsonify({'error': 'Unauthorized'}), 401
return f(*args, **kwargs)
return decorated
@app.route('/admin/state', methods=['POST'])
@require_api_key
def manage_state():
# ... Code hier- SpaceAPI Dokumentation: https://spaceapi.io/
- SpaceAPI Directory: https://directory.spaceapi.io/
- Flask Dokumentation: https://flask.palletsprojects.com/
Entwickelt für Odenwilusenz (https://odenwilusenz.ch)
Fragen oder Probleme? Kontaktiere: spaceapi@justsomeone.ch