feat: Pulsar distribution service (Simulator → Pulsar → Brokers)

- Fix Pulsar: use binary client (port 6650) instead of non-existent REST /produce API
- Add pulsar-client to Dockerfile
- Create pulsar/distribution.py: consumes Pulsar and republishes to MQTT (EMQX/Mosquitto), NGSI-LD (Orion/Stellio), FROST
- Add docker-compose.distribution.yml for the distribution service
- Tested: Messages successfully distributed to EMQX and Orion-LD
- Update session resume
This commit is contained in:
Eric FELIXINE
2026-05-05 10:20:13 -04:00
parent 5ddde3e013
commit ad613beefb
11 changed files with 444 additions and 20 deletions

View File

@@ -817,27 +817,18 @@ def _init_pulsar() -> bool:
return False
def publish_pulsar(sid: str, sensor: dict, payload: dict) -> bool:
"""Publie un message sur Pulsar via l'API REST producer."""
"""Publie un message sur Pulsar via le client Python (port binaire 6650)."""
stype = sensor["type"]
topic = stype # air-quality, traffic, weather, parking, noise, light
topic = f"persistent://public/default/smartcity-{stype}"
try:
import urllib.request, base64
# Pulsar REST producer attend du base64
body = json.dumps(payload, ensure_ascii=False)
b64 = base64.b64encode(body.encode()).decode()
msg = {"messages": [{"payload": b64, "properties": {"sensor_id": sid, "source": "simulator"}}]}
url = f"{PULSAR_BASE}/admin/v2/persistent/public/default/{topic}/produce"
req = urllib.request.Request(
url,
data=json.dumps(msg).encode(),
headers={"Content-Type": "application/json"},
method="POST"
)
with urllib.request.urlopen(req, timeout=8) as resp:
return resp.status in (200, 204)
except urllib.error.HTTPError as e:
print(f" ⚠️ Pulsar → {e.code}")
return False
import pulsar
# Utiliser le client Pulsar binaire (socket 6650)
client = pulsar.Client(f"pulsar://{PULSAR_HOST}:6650")
producer = client.create_producer(topic)
body = json.dumps(payload, ensure_ascii=False).encode()
producer.send(body, properties={"sensor_id": sid, "source": "simulator"})
client.close()
return True
except Exception as e:
print(f" ⚠️ Pulsar → {e}")
return False