fix(simulator): connexion MQTT OpenRemote sans auth, location dans payload REST, ASSET_MAP corrigé
- MQTT OpenRemote: connexion anonyme (pas de credentials) au broker Artemis - Payload REST: ajout attribut location (GeoJSONPoint) pour chaque capteur - ASSET_MAP: mise à jour avec les bons asset IDs (ceux avec agentLink + location) - Topics MQTT: index basé sur position du capteur (pas compteur global) - Désactivation PUT REST sur assets avec agentLink (403 Forbidden) - keepalive augmenté à 60s pour stabilité connexion Artemis
This commit is contained in:
108
simulator.py
108
simulator.py
@@ -509,7 +509,7 @@ class MultiMQTT:
|
||||
c.on_connect = lambda _c, _, __, rc: self._on_connect(name, rc)
|
||||
c.on_disconnect = lambda _c, _, __: self._on_disconnect(name)
|
||||
try:
|
||||
c.connect(host, port, keepalive=30)
|
||||
c.connect(host, port, keepalive=60, clean_start=True)
|
||||
c.loop_start()
|
||||
except Exception as e:
|
||||
print(f"[MQTT] ❌ {name} @ {host}:{port} → {e}")
|
||||
@@ -555,8 +555,9 @@ class MultiMQTT:
|
||||
brokers.append(("bunkerm", BUNKERM_HOST, BUNKERM_PORT, False, "bunker", "bunker", use_v5))
|
||||
|
||||
# OpenRemote MQTT broker (pour agents MQTT créés dans OpenRemote)
|
||||
# Le broker Artemis d'OR accepte les connexions anonymes (pas de credentials)
|
||||
if ENABLE_OPENREMOTE:
|
||||
brokers.append(("openremote", "openremote_manager_1", 1883, False, OR_ADMIN_USER, OR_ADMIN_PASS, use_v5))
|
||||
brokers.append(("openremote", "openremote_manager_1", 1883, False, "", "", use_v5))
|
||||
|
||||
print(f"[MQTT] 🔌 Connexion aux brokers (EMQX={enable_emqx}, Mosquitto={enable_mosquitto}, BunkerM={enable_bunkerm})...")
|
||||
print("[MQTT] 🔌 Connexion aux brokers...")
|
||||
@@ -564,7 +565,12 @@ class MultiMQTT:
|
||||
c = self._mk_client(name, host, port, tls=tls, user=user, pwd=pwd, use_v5=use_v5)
|
||||
self.clients[name] = c
|
||||
self.ok[name] = False
|
||||
time.sleep(3) # Attend les connexions
|
||||
# Attendre que tous les brokers soient connectés (Artemis peut être lent)
|
||||
for _ in range(20):
|
||||
time.sleep(1)
|
||||
if all(self.ok.values()):
|
||||
break
|
||||
print(f"[MQTT] État des connexions: {dict(self.ok)}")
|
||||
|
||||
def publish(self, topic: str, payload: str, sensor_type: str = "unknown") -> dict[str, bool]:
|
||||
results = {}
|
||||
@@ -837,38 +843,39 @@ def _or_put(asset_id: str, payload: dict) -> bool:
|
||||
|
||||
def publish_openremote(sid: str, sensor: dict, values: dict) -> bool:
|
||||
"""Met à jour les attributs d'un asset OpenRemote via REST."""
|
||||
# Mapping sid → asset ID (realm master)
|
||||
# Mapping sid → asset ID (realm master) — assets avec agentLink + location
|
||||
# Note: le compteur SENSORS est global (traffic=0-9, airquality=10-19, parking=20-29, noise=30-39, weather=40-49, light=50-59)
|
||||
ASSET_MAP = {
|
||||
"traffic_000": "a8043c3dba95d5aa8283ce",
|
||||
"traffic_001": "04d81c7396f131aa2985e8",
|
||||
"traffic_002": "ef6d0b07c9eebbc4caf0a6",
|
||||
"traffic_003": "cf7eb926b27fd029f7e352",
|
||||
"traffic_004": "da52c73cf4657ef6e108c9",
|
||||
"airquality_000": "4ea3e0c63624c751d7a658",
|
||||
"airquality_001": "4f83219bbee703b3e0a255",
|
||||
"airquality_002": "5335681981790e66cb97de",
|
||||
"airquality_003": "03c18679226329183b44b6",
|
||||
"airquality_004": "cb653676e1f5c8888263eb",
|
||||
"parking_000": "6231f03dfd384cf70a761e",
|
||||
"parking_001": "dafad430f5f2a9d692ad80",
|
||||
"parking_002": "a447074cc2be9781780bb4",
|
||||
"parking_003": "96020cc5aef95c5fda7bb4",
|
||||
"parking_004": "ae981dc9d155d1313b9acf",
|
||||
"noise_000": "0be31930e45d2eb5c12ccd",
|
||||
"noise_001": "1802e76e3432d5eda1deb7",
|
||||
"noise_002": "09c61402305f50282f7dd2",
|
||||
"noise_003": "fbf0f80417d49c8c91fe09",
|
||||
"noise_004": "93d09bfac36d2ed95fc858",
|
||||
"weather_000": "9942f881ab6df375d8d9fa",
|
||||
"weather_001": "5400fdf5c51a4fe4f5a89c",
|
||||
"weather_002": "7ee9441fc1295c6f700da3",
|
||||
"weather_003": "5f915a9a887c2dbd137775",
|
||||
"weather_004": "ec9cfb15533ddfe16c6388",
|
||||
"light_000": "1f4302946b1a4a1ded23f6",
|
||||
"light_001": "35e6ef027ed9a157ad8780",
|
||||
"light_002": "526538589aa981bdc77ce9",
|
||||
"light_003": "40bbe989be2ae5b2a98b30",
|
||||
"light_004": "fcad43e50a21d886c8f583",
|
||||
"traffic_000": "429858caca3341f56fbf65",
|
||||
"traffic_001": "301218322f5aaca9d6d168",
|
||||
"traffic_002": "bd35fe2a90133118b9b004",
|
||||
"traffic_003": "da59ec9301c4efd3fd55c4",
|
||||
"traffic_004": "834f4b7b9df848f5c5c2d8",
|
||||
"airquality_010": "0f922351a9894bc0144c94",
|
||||
"airquality_011": "4f83219bbee703b3e0a255",
|
||||
"airquality_012": "381cc31ab83dd66ed4be37",
|
||||
"airquality_013": "808b73c22ecd19589a33be",
|
||||
"airquality_014": "03c18679226329183b44b6",
|
||||
"parking_020": "0ee6689f5c0499643d48eb",
|
||||
"parking_021": "8fb6b2d0601d98b47a4172",
|
||||
"parking_022": "0c00bda9e5075d12d59694",
|
||||
"parking_023": "ae981dc9d155d1313b9acf",
|
||||
"parking_024": "96020cc5aef95c5fda7bb4",
|
||||
"noise_030": "0be31930e45d2eb5c12ccd",
|
||||
"noise_031": "1802e76e3432d5eda1deb7",
|
||||
"noise_032": "08edb6518750d50644afe3",
|
||||
"noise_033": "93d09bfac36d2ed95fc858",
|
||||
"noise_034": "7942726d84d2bd29de1e5d",
|
||||
"weather_040": "9942f881ab6df375d8d9fa",
|
||||
"weather_041": "5400fdf5c51a4fe4f5a89c",
|
||||
"weather_042": "1a3bf32aa5208892e68965",
|
||||
"weather_043": "d3725f922f96085f2df3f7",
|
||||
"weather_044": "13be192a8c23dd8fdceada",
|
||||
"light_050": "1f4302946b1a4a1ded23f6",
|
||||
"light_051": "35e6ef027ed9a157ad8780",
|
||||
"light_052": "526538589aa981bdc77ce9",
|
||||
"light_053": "d4a6ac7f34d64e581937c0",
|
||||
"light_054": "40bbe989be2ae5b2a98b30",
|
||||
}
|
||||
asset_id = ASSET_MAP.get(sid)
|
||||
if not asset_id:
|
||||
@@ -898,6 +905,16 @@ def publish_openremote(sid: str, sensor: dict, values: dict) -> bool:
|
||||
"timestamp": now,
|
||||
"unit": "µg/m³" if "ugm3" in field else ("°C" if "celsius" in field else ("%" if "percent" in field or "humidity" in field else ("dB" if "db" in field else ""))),
|
||||
}
|
||||
|
||||
# Ajouter la location du capteur (GeoJSON Point)
|
||||
lat = sensor.get("lat", 0)
|
||||
lon = sensor.get("lon", 0)
|
||||
attrs["location"] = {
|
||||
"type": "GeoJSONPoint",
|
||||
"value": {"type": "Point", "coordinates": [lat, lon]},
|
||||
"timestamp": now,
|
||||
}
|
||||
|
||||
payload = {
|
||||
"id": asset_id,
|
||||
"name": sensor["name"],
|
||||
@@ -1100,11 +1117,15 @@ def main():
|
||||
|
||||
for sid, sensor in SENSORS.items():
|
||||
stype = sensor["type"]
|
||||
# Utiliser un index 1-5 basé sur le compteur par type pour correspondre aux agents OpenRemote
|
||||
if not hasattr(mqtt_client, "type_counters"):
|
||||
mqtt_client.type_counters = {}
|
||||
mqtt_client.type_counters[stype] = mqtt_client.type_counters.get(stype, 0) + 1
|
||||
sensor_index = mqtt_client.type_counters[stype]
|
||||
# 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
|
||||
topic = f"smartcity/{stype}/{sensor_index}"
|
||||
|
||||
# --- Payload MQTT (ATTRIBUTES ONLY - pas de id/type/lat/lon !)
|
||||
@@ -1143,10 +1164,11 @@ def main():
|
||||
if isinstance(lo, (int, float)):
|
||||
or_values[field] = round(random.uniform(lo, hi), 1)
|
||||
|
||||
# --- OpenRemote REST ---
|
||||
if ENABLE_OPENREMOTE:
|
||||
ok_or = publish_openremote(sid, sensor, or_values)
|
||||
print(f" 🏠 OpenRemote: {'✅' if ok_or else '⚠️ skipped'}")
|
||||
# --- OpenRemote REST --- (DÉSACTIVÉ: les agents MQTT gèrent les mises à jour)
|
||||
# Le REST échoue en 403 sur les assets avec agentLink
|
||||
# if ENABLE_OPENREMOTE:
|
||||
# ok_or = publish_openremote(sid, sensor, or_values)
|
||||
# print(f" 🏠 OpenRemote: {'✅' if ok_or else '⚠️ skipped'}")
|
||||
|
||||
# # --- Orion-LD --- (DÉSACTIVÉ: tout passe par les IoT-Agents MQTT)
|
||||
# # if ENABLE_ORION:
|
||||
|
||||
Reference in New Issue
Block a user