from http.server import HTTPServer, BaseHTTPRequestHandler
import json
from datetime import datetime, timezone
import uuid
devices = {} last_submissions = {}
def now_iso():
return datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
class MockBackendHandler(BaseHTTPRequestHandler):
def log_request_info(self, body=None):
print(f"\n{'='*60}")
print(f"[{datetime.now().isoformat()}] {self.command} {self.path}")
auth = self.headers.get("Authorization", "None")
print(f"Auth: {auth[:50]}..." if len(auth) > 50 else f"Auth: {auth}")
if body:
print(f"Body:\n{json.dumps(body, indent=2)}")
def send_json(self, status, data):
self.send_response(status)
self.send_header("Content-Type", "application/json")
self.end_headers()
self.wfile.write(json.dumps(data).encode())
def read_json(self):
length = int(self.headers.get("Content-Length", 0))
if length:
return json.loads(self.rfile.read(length))
return {}
def do_GET(self):
if self.path.startswith("/api/iot-devices/") and self.path.endswith("/last-data-submission"):
device_id = self.path.split("/")[3]
self.log_request_info()
ts = last_submissions.get(device_id)
print(f"-> Last submission for {device_id}: {ts}")
self.send_json(200, {
"timestamp": ts,
"createdAt": now_iso() if ts else None
})
else:
self.send_json(404, {"error": "Not found"})
def do_POST(self):
body = self.read_json()
self.log_request_info(body)
if self.path == "/api/iot-devices/data/submit":
data_entries = body.get("data", [])
total_points = 0
results = []
for entry in data_entries:
device_id = entry.get("iotDeviceId")
data_type = entry.get("dataType")
data_points = entry.get("data", [])
total_points += len(data_points)
print(f" -> Device {device_id[:8]}...: {len(data_points)} {data_type} points")
for dp in data_points:
ts = datetime.fromtimestamp(dp["timestamp"]).isoformat()
print(f" [{ts}] {dp['data']}")
results.append({
"id": str(uuid.uuid4()),
"timestamp": dp["timestamp"],
"dataType": data_type,
"data": dp["data"],
"createdAt": now_iso()
})
if data_points and device_id:
last_submissions[device_id] = max(dp["timestamp"] for dp in data_points)
print(f"-> Total: {total_points} data points received")
self.send_json(200, results)
elif self.path == "/api/iot-devices/exists":
hw_id = body.get("hardwareIdentifier", "")
exists = hw_id in devices
device_info = devices.get(hw_id, {})
print(f"-> Device {hw_id} exists: {exists}")
response = {"exists": exists}
if exists:
response.update({
"rememberDevice": True,
"id": device_info.get("id"),
"model": device_info.get("model"),
"trustLevel": "known",
"connectionType": device_info.get("connectionType"),
"supportedDataTypes": device_info.get("supportedDataTypes", [])
})
self.send_json(200, response)
elif self.path == "/api/iot-devices":
hw_id = body.get("hardwareIdentifier", "")
now = now_iso()
if hw_id not in devices:
device_id = str(uuid.uuid4())
devices[hw_id] = {
"id": device_id,
"createdAt": now,
"modifiedAt": now,
"revision": 1,
"hardwareIdentifier": hw_id,
"model": body.get("model", "generic"),
"trustLevel": "unknown",
"connectionType": body.get("connectionType", "unknown"),
"connectionMeta": body.get("connectionMeta", {}),
"connectionSecret": None,
"supportedDataTypes": body.get("supportedDataTypes", []),
"allowMultipleDeviceRelationships": False,
"devices": [],
"assignedUser": None,
"createdByDevice": None
}
print(f"-> Registered new device: {device_id}")
else:
print(f"-> Device already exists: {devices[hw_id]['id']}")
self.send_json(200, devices[hw_id])
else:
self.send_json(404, {"error": "Not found"})
if __name__ == "__main__":
port = 8080
server = HTTPServer(("0.0.0.0", port), MockBackendHandler)
print(f"Mock BCMS Backend running on http://0.0.0.0:{port}")
print("Endpoints:")
print(" POST /api/iot-devices/data/submit - Submit IoT data")
print(" POST /api/iot-devices/exists - Check device existence")
print(" POST /api/iot-devices - Register device")
print(" GET /api/iot-devices/{id}/last-data-submission")
print("\nWaiting for requests...")
server.serve_forever()