fix: Simulateur MQTT 3/4 + OpenRemote master + Mapsettings
- MQTT OK: 3/4 (EMQX, Mosquitto, BunkerM) - OpenRemote: utilise realm master (token fonctionnel) - Realm smartcity recréé dans Keycloak - Assets IOTSensor créés dans master (30) et smartcity (30) - Mapsettings: layers iot-sensors + labels pour master et smartcity - INTERVAL=5s, réseau openremote_default ajouté - Dockerfile: --no-cache rebuild
This commit is contained in:
83
simulator.py
83
simulator.py
@@ -70,7 +70,7 @@ ENABLE_FROST = os.environ.get("ENABLE_FROST", "1") == "1"
|
||||
ENABLE_OPENREMOTE = os.environ.get("ENABLE_OPENREMOTE", "1") == "1"
|
||||
OR_ADMIN_USER = os.environ.get("OR_ADMIN_USER", "admin")
|
||||
OR_ADMIN_PASS = os.environ.get("OR_ADMIN_PASS", "Digitribe972")
|
||||
OR_REALM = os.environ.get("OR_REALM", "smartcity")
|
||||
OR_REALM = os.environ.get("OR_REALM", "master")
|
||||
OR_TOKEN_REALM = os.environ.get("OR_TOKEN_REALM", "master") # Realm pour obtention token
|
||||
#ENABLE_IOT_AGENT = os.environ.get("ENABLE_IOT_AGENT", "1") == "1"
|
||||
FROST_URL = os.environ.get("FROST_URL", "http://localhost:8090/FROST-Server/v1.1") # Exposer frost_http-web-1:8080 -> host:8086
|
||||
@@ -497,7 +497,8 @@ class MultiMQTT:
|
||||
ws: bool = False, use_v5: bool = False) -> mqtt.Client:
|
||||
cid = f"smartcity-sim-{name}-{os.getpid()}"
|
||||
protocol = mqtt.MQTTv5 if use_v5 else mqtt.MQTTv311
|
||||
c = mqtt.Client(client_id=cid, protocol=protocol)
|
||||
# Use Callback API v1 for compatibility with existing lambda callbacks
|
||||
c = mqtt.Client(client_id=cid, protocol=protocol, callback_api_version=mqtt.CallbackAPIVersion.VERSION1)
|
||||
if user:
|
||||
c.username_pw_set(user, pwd)
|
||||
if tls:
|
||||
@@ -536,11 +537,28 @@ class MultiMQTT:
|
||||
|
||||
def _setup(self):
|
||||
# Utiliser les variables d'environnement pour les brokers
|
||||
brokers = [
|
||||
("emqx", EMQX_HOST, EMQX_PORT, False, "", "", False),
|
||||
("mosquitto", MOSQUITTO_HOST, MOSQUITTO_PORT, False, "", "", False), # Same as emqx
|
||||
("bunkerm", BUNKERM_HOST, BUNKERM_PORT, False, "bunker", "bunker", False),
|
||||
]
|
||||
mqtt_version = os.environ.get("MQTT_PROTOCOL_VERSION", "311")
|
||||
use_v5 = (mqtt_version == "5")
|
||||
print(f"[MQTT] Version du protocole: {'v5.0' if use_v5 else 'v3.1.1'} (MQTT_PROTOCOL_VERSION={mqtt_version})")
|
||||
|
||||
# Check which brokers are enabled
|
||||
enable_emqx = os.environ.get("ENABLE_EMQX", "1") == "1"
|
||||
enable_mosquitto = os.environ.get("ENABLE_MOSQUITTO", "1") == "1"
|
||||
enable_bunkerm = os.environ.get("ENABLE_BUNKER", "1") == "1"
|
||||
|
||||
brokers = []
|
||||
if enable_emqx:
|
||||
brokers.append(("emqx", EMQX_HOST, EMQX_PORT, False, "", "", use_v5))
|
||||
if enable_mosquitto:
|
||||
brokers.append(("mosquitto", MOSQUITTO_HOST, MOSQUITTO_PORT, False, "", "", use_v5))
|
||||
if enable_bunkerm:
|
||||
brokers.append(("bunkerm", BUNKERM_HOST, BUNKERM_PORT, False, "bunker", "bunker", use_v5))
|
||||
|
||||
# OpenRemote MQTT broker (pour agents MQTT créés dans OpenRemote)
|
||||
if ENABLE_OPENREMOTE:
|
||||
brokers.append(("openremote", "openremote_manager_1", 1883, False, OR_ADMIN_USER, OR_ADMIN_PASS, use_v5))
|
||||
|
||||
print(f"[MQTT] 🔌 Connexion aux brokers (EMQX={enable_emqx}, Mosquitto={enable_mosquitto}, BunkerM={enable_bunkerm})...")
|
||||
print("[MQTT] 🔌 Connexion aux brokers...")
|
||||
for name, host, port, tls, user, pwd, use_v5 in brokers:
|
||||
c = self._mk_client(name, host, port, tls=tls, user=user, pwd=pwd, use_v5=use_v5)
|
||||
@@ -749,9 +767,9 @@ def _get_or_token() -> str:
|
||||
return _or_token_cache["token"]
|
||||
try:
|
||||
# Use password grant with admin user (full rights)
|
||||
token_url = f"http://localhost:8080/auth/realms/{OR_REALM}/protocol/openid-connect/token"
|
||||
token_url = f"http://openremote-keycloak-1:8080/auth/realms/{OR_TOKEN_REALM}/protocol/openid-connect/token"
|
||||
client_id = os.environ.get("OR_CLIENT_ID", "openremote")
|
||||
client_secret = os.environ.get("OR_CLIENT_SECRET", "QVTnyObwXdpQ0Vuc60kFSonidK49FiXb")
|
||||
client_secret = os.environ.get("OR_CLIENT_SECRET", "0oQjzTfiEELYmj5jFwT4iIuWUDtQDvVa")
|
||||
data = urllib.parse.urlencode({
|
||||
"grant_type": "password",
|
||||
"username": os.environ.get("OR_ADMIN_USER", "admin"),
|
||||
@@ -806,16 +824,38 @@ 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 (créés manuellement dans OR)
|
||||
# Mapping sid → asset ID (realm master)
|
||||
ASSET_MAP = {
|
||||
"traffic_000": "7b5c5670d1b84865ba3ac7", # Traffic Fort-de-France Centre
|
||||
"traffic_001": "557f6e993b994d3cb81017", # Traffic Fort-de-France North
|
||||
"traffic_002": "cb81dfd2d2dc4d25adc9c2", # Traffic Fort-de-France South
|
||||
"airquality_000": "a51c982a2d3e451898b978", # Air Quality Fort-de-France
|
||||
"parking_000": "b8f0df19e0af47b386ebb9", # Parking Fort-de-France Centre
|
||||
"noise_000": "9035103d1866454fb7e451", # Noise Fort-de-France Centre
|
||||
"weather_000": "b9de80905ac640f488ab27", # Weather Lamentin Airport
|
||||
"light_000": "ee7823a41e594851ba202f", # Light Fort-de-France
|
||||
"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",
|
||||
}
|
||||
asset_id = ASSET_MAP.get(sid)
|
||||
if not asset_id:
|
||||
@@ -1047,7 +1087,12 @@ def main():
|
||||
|
||||
for sid, sensor in SENSORS.items():
|
||||
stype = sensor["type"]
|
||||
topic = f"city/sensors/{stype}/{sid}"
|
||||
# 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]
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user