#!/usr/bin/env python3 """ Simulate an infrastructure node publishing environmental data to MQTT. Use this to test the ingestion pipeline and dashboard without real hardware. """ import json import random import time import argparse from datetime import datetime, timezone import paho.mqtt.client as mqtt NODE_IDS = ["!a1b2c3d4", "!b2c3d4e5", "!c3d4e5f6"] NODE_COORDS = { "!a1b2c3d4": (49.82, 18.26), # Ostrava-ish "!b2c3d4e5": (49.75, 18.20), # Nearby "!c3d4e5f6": (49.78, 18.35), # Nearby } def make_payload(node_id: str): now = datetime.now(timezone.utc).isoformat() lat, lon = NODE_COORDS.get(node_id, (50.0, 14.0)) return { "type": "enviro_reading", "node_id": node_id, "received_at": now, "hop_count": random.randint(1, 3), "lat": lat, "lon": lon, "payload": { "time": now, "node_id": node_id, "temperature_c": round(random.uniform(15.0, 25.0), 2), "humidity_percent": round(random.uniform(40.0, 80.0), 2), "pressure_pa": round(random.uniform(100800.0, 102000.0), 2), "wind_speed_ms": round(random.uniform(0.0, 12.0), 1), "wind_direction": random.randint(0, 359), "pm25_ugm3": round(random.uniform(5.0, 35.0), 1), "pm10_ugm3": round(random.uniform(10.0, 50.0), 1), "gas_resistance_kohm": round(random.uniform(50.0, 200.0), 1), "battery_voltage": round(random.uniform(3.2, 4.2), 2), "solar_voltage": round(random.uniform(4.5, 6.0), 2), }, } def main(): parser = argparse.ArgumentParser(description="Simulate KosmoConnect bridge node") parser.add_argument("--host", default="localhost", help="MQTT broker host") parser.add_argument("--port", type=int, default=1883, help="MQTT broker port") parser.add_argument("--topic", default="kosmo/ingest/enviro", help="MQTT topic") parser.add_argument("--interval", type=int, default=10, help="Seconds between messages") parser.add_argument("--count", type=int, default=0, help="Number of messages to send (0=forever)") args = parser.parse_args() client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2) client.connect(args.host, args.port, 60) client.loop_start() print(f"Connected to {args.host}:{args.port}. Publishing to {args.topic} every {args.interval}s") sent = 0 try: while args.count == 0 or sent < args.count: node_id = random.choice(NODE_IDS) payload = make_payload(node_id) client.publish(args.topic, json.dumps(payload)) print(f"[{sent+1}] Published for {node_id}") sent += 1 time.sleep(args.interval) except KeyboardInterrupt: print("\nStopped by user.") finally: client.loop_stop() client.disconnect() if __name__ == "__main__": main()