#!/usr/bin/env python3 import json import os import sys from datetime import datetime, timezone from pathlib import Path import paho.mqtt.client as mqtt def read_env(path=".env"): env = {} p = Path(path) if not p.exists(): return env for raw in p.read_text().splitlines(): line = raw.strip() if not line or line.startswith("#") or "=" not in line: continue k, v = line.split("=", 1) env[k.strip()] = v.strip().strip('"').strip("'") return env def utc_now(): return datetime.now(timezone.utc).isoformat(timespec="seconds").replace("+00:00", "Z") def build_payload(machine_id, mode): base = { "machine_id": machine_id, "ts": utc_now(), "source": "odoo_simulator", } if mode == "loaded": base.update({ "order_present": True, "order_coherent": True, "odoo_state": "ready", "workorder_id": 1000, "production_order": f"SIM-{machine_id}-OK", "product": "Orden simulada correcta", }) elif mode == "no_order": base.update({ "order_present": False, "order_coherent": False, "odoo_state": "none", "workorder_id": None, "production_order": None, "product": None, }) elif mode == "bad": base.update({ "order_present": True, "order_coherent": False, "odoo_state": "wrong_machine", "workorder_id": 9999, "production_order": f"SIM-{machine_id}-BAD", "product": "Orden simulada incoherente", "reason": "Orden asignada a otra máquina o estado no válido", }) elif mode == "fault": base.update({ "order_present": True, "order_coherent": True, "odoo_state": "ready", "workorder_id": 1001, "production_order": f"SIM-{machine_id}-FAULT", "product": "Orden simulada con fallo máquina", "force_machine_fault": True, }) else: raise SystemExit(f"Modo no reconocido: {mode}") return base def main(): if len(sys.argv) != 3: print("Uso:") print(" python publish_order_state.py CORT-00 loaded") print(" python publish_order_state.py CORT-00 no_order") print(" python publish_order_state.py CORT-00 bad") print(" python publish_order_state.py CORT-00 fault") raise SystemExit(1) machine_id = sys.argv[1] mode = sys.argv[2] env = read_env() mqtt_host = env.get("MQTT_HOST", "127.0.0.1") mqtt_port = int(env.get("MQTT_PORT", "1883")) mqtt_user = env.get("MQTT_USERNAME") or env.get("MQTT_USER") mqtt_password = env.get("MQTT_PASSWORD") tenant = env.get("TENANT", "ucepsa") site = env.get("SITE", "ucepsa_onpremise") vertical = env.get("VERTICAL", "edge_oee") topic = f"vertical/{tenant}/{site}/{vertical}/order_state/{machine_id}" payload = build_payload(machine_id, mode) client = mqtt.Client(client_id=f"order_state_sim_{machine_id}") if mqtt_user: client.username_pw_set(mqtt_user, mqtt_password) client.connect(mqtt_host, mqtt_port, 60) client.loop_start() info = client.publish(topic, json.dumps(payload, separators=(",", ":")), qos=0, retain=True) info.wait_for_publish(timeout=5) client.loop_stop() client.disconnect() print(f"Publicado en {topic}") print(json.dumps(payload, indent=2, ensure_ascii=False)) if __name__ == "__main__": main()