fix: telegraf containers names + openremote pg image + session snapshot 2026-05-25

- telegraf.conf: fix Mosquitto/BunkerM container names (hyphens not underscores)
- tegraf.conf: comment out BunkerM consumer (auth fails, simulator not sending)
- openremote/docker-compose.yml: switch PG image to timescaledb-ha:pg15 (fixes timescaledb_toolkit crash)
- Add session_resume + architecture snapshot 2026-05-25
- Update TODO.md with current status
This commit is contained in:
Eric FELIXINE
2026-05-25 14:13:39 -04:00
parent eb97f2a7dd
commit 6d1d9c8620
14 changed files with 2163 additions and 119 deletions

View File

@@ -1083,8 +1083,9 @@ def main():
print("║ Smart City Simulator — Martinique ║")
print("╚══════════════════════════════════════════════════╝")
print(f"[CFG] Capteurs: {len(SENSORS)} | Intervalle: {INTERVAL}s")
# print(f"[CFG] Orion-LD: {ENABLE_ORION} | Stellio: {ENABLE_STELLIO} | FROST: {ENABLE_FROST}")
print(f"[CFG] InfluxDB: {ENABLE_INFLUX} | Pulsar: {ENABLE_PULSAR} | Redpanda: {ENABLE_REDPANDA}")
print(f"[CFG] FROST: {ENABLE_FROST} | OpenRemote: {ENABLE_OPENREMOTE}")
print(f"[CFG] MQTT brokers: EMQX={os.getenv('ENABLE_EMQX','1')} Mosquitto={os.getenv('ENABLE_MOSQUITTO','1')}")
# --- Démarrer le serveur Prometheus ---
_start_metrics_server()
@@ -1094,16 +1095,17 @@ def main():
sensors_total.labels(sensor_type=stype).set(count)
up.set(1)
# Init connectivity checks
# Init connectivity checks (only if enabled)
if ENABLE_PULSAR:
_init_pulsar()
# Test immédiat
print(f" 🌪️ DEBUG: Test Pulsar direct...", flush=True)
test_payload = {"type": "test", "value": 123}
test_result = publish_pulsar("test_001", {"type": "air-quality"}, test_payload)
print(f" 🌪️ DEBUG: Test Pulsar result: {test_result}", flush=True)
try:
_init_pulsar()
except Exception as e:
print(f"[PULSAR] ⚠️ Init failed: {e}")
if ENABLE_REDPANDA:
_init_redpanda()
try:
_init_redpanda()
except Exception as e:
print(f"[REDPANDA] ⚠️ Init failed: {e}")
mqtt_client = MultiMQTT()
@@ -1124,19 +1126,13 @@ def main():
for sid, sensor in SENSORS.items():
stype = sensor["type"]
# Utiliser l'index du capteur dans FIXED_LOCATIONS (1-5) pour correspondre aux agents OpenRemote
# Le sid est formaté comme {stype}_{counter:03d} avec counter global
# On extrait l'index du capteur depuis le sid (derniers chiffres)
sensor_num = int(sid.split("_")[1])
# Calculer l'index 1-5 basé sur la position dans le type
# traffic: 0-9, airquality: 10-19, parking: 20-29, noise: 30-39, weather: 40-49, light: 50-59
type_offsets = {"traffic": 0, "airquality": 10, "parking": 20, "noise": 30, "weather": 40, "light": 50}
type_offset = type_offsets.get(stype, 0)
sensor_index = sensor_num - type_offset + 1 # 1-indexed
sensor_index = sensor_num - type_offset + 1
topic = f"smartcity/{stype}/{sensor_index}"
# --- Payload MQTT (ATTRIBUTES ONLY - pas de id/type/lat/lon !)
# # L'IoT Agent n'attend que les readings, pas le body complet
# --- Payload MQTT ---
ranges = SENSOR_RANGES.get(stype, {})
payload_mqtt = {
"timestamp": datetime.now(timezone.utc).isoformat(),
@@ -1158,77 +1154,19 @@ def main():
if ok_mqtt:
print(f" 📤 {topic}{','.join(ok_mqtt)}")
# # --- IoT-Agent (via EMQX) ---
# if ENABLE_IOT_AGENT:
# ok_iot = mqtt_client.publish_iot_agent(sid, payload_mqtt, sensor_type=stype)
# print(f" 🤖 IoT-Agent: {'✅' if ok_iot else '❌'}")
# Extraire les valeurs pour OpenRemote
or_values = {}
for field, val_range in ranges.items():
if isinstance(val_range, tuple) and len(val_range) == 2:
lo, hi = val_range
if isinstance(lo, (int, float)):
or_values[field] = round(random.uniform(lo, hi), 1)
# --- OpenRemote REST (round-robin: seulement quelques assets/itération) ---
# --- OpenRemote REST (round-robin) ---
if ENABLE_OPENREMOTE:
# Mettre à jour seulement ~5 assets par itération pour éviter timeups
# sensor_num % 12 == iteration % 12 → chaque asset est mis à jour toutes les ~60s
if sensor_num % 12 == iteration % 12:
or_values = {}
for field, val_range in ranges.items():
if isinstance(val_range, tuple) and len(val_range) == 2:
lo, hi = val_range
if isinstance(lo, (int, float)):
or_values[field] = round(random.uniform(lo, hi), 1)
ok_or = publish_openremote(sid, sensor, or_values)
print(f" 🏠 OpenRemote: {'' if ok_or else '⚠️ skipped'}")
# else: skip OR update this iteration (asset updated in previous cycle)
# # --- Orion-LD --- (DÉSACTIVÉ: tout passe par les IoT-Agents MQTT)
# # if ENABLE_ORION:
# # ok_or = publish_orion(sid, sensor)
# # print(f" 🌐 Orion-LD: {'✅' if ok_or else '⚠️ skipped'}")
# # --- Stellio --- (DÉSACTIVÉ: tout passe par les IoT-Agents MQTT)
# # if ENABLE_STELLIO:
# # ok_st = publish_stellio(sid, sensor)
# # print(f" 🏢 Stellio: {'✅' if ok_st else '❌'}")
# --- FROST ---
if ENABLE_FROST:
ranges2 = SENSOR_RANGES.get(stype, {})
for field, val_range in ranges2.items():
if isinstance(val_range, tuple) and len(val_range) == 2:
lo, hi = val_range
if isinstance(lo, (int, float)):
val = round(random.uniform(lo, hi), 1)
ok_fr = publish_frost(sid, sensor, field, val)
print(f" 📊 FROST: {'' if ok_fr else ''}")
# --- InfluxDB ---
if ENABLE_INFLUX:
influx_vals = {}
for field, val_range in ranges.items():
if isinstance(val_range, tuple) and len(val_range) == 2:
lo, hi = val_range
if isinstance(lo, (int, float)):
influx_vals[field] = round(random.uniform(lo, hi), 1)
ok_influx = publish_influx(sid, sensor, influx_vals)
print(f" 📈 InfluxDB: {'' if ok_influx else ''}")
# --- Pulsar (HTTP REST) ---
if ENABLE_PULSAR:
print(f" 🌪️ DEBUG: calling publish_pulsar for {sid}, payload_mqtt exists: {bool(locals().get('payload_mqtt'))}", flush=True)
ok_pulsar = publish_pulsar(sid, sensor, payload_mqtt)
print(f" 🌪️ Pulsar: {'' if ok_pulsar else ''}")
# --- Redpanda (Kafka REST Proxy) ---
if ENABLE_REDPANDA:
ok_redpanda = publish_redpanda(sid, sensor, payload_mqtt)
print(f" 🐟 Redpanda: {'' if ok_redpanda else ''}")
# --- BunkerM HTTP ---
if os.getenv("BUNKERM_HTTP", "0") == "1":
ok_bunkerm = publish_bunkerm(sid, sensor, payload_mqtt)
print(f" 📦 BunkerM: {'' if ok_bunkerm else ''}")
print(f"[SIM] ✅ {len(SENSORS)} capteurs | MQTT OK: {sum(mqtt_client.ok.values())}/{len(mqtt_client.clients)} | OR: {ENABLE_OPENREMOTE}")
print(f"[SIM] ✅ {len(SENSORS)} capteurs | MQTT OK: {sum(mqtt_client.ok.values())}/{len(mqtt_client.clients)}")
try:
time.sleep(INTERVAL)