import 'dotenv/config' import mqtt from 'mqtt' import { v4 as uuidv4 } from 'uuid' const MQTT_URL = process.env.MQTT_URL if (!MQTT_URL) throw new Error('Missing MQTT_URL') const pattern = process.env.ACK_TOPIC_PATTERN || 'device/+/ack' const target = process.env.SIM_ACK_TARGET // e.g. userId or deviceId to fill the '+' const correlationId = process.env.SIM_CORRELATION_ID || uuidv4() const topic = (() => { const parts = pattern.split('/') const tParts = [] let used = false for (const p of parts) { if (p === '+') { tParts.push(target || 'test'); used = true } else tParts.push(p) } if (pattern.includes('+') && !used) throw new Error('Pattern contains + but could not fill it') return tParts.join('/') })() const payload = JSON.stringify({ correlation_id: correlationId, ok: true, t: Date.now() }) console.log('Publishing ACK', { topic, correlationId }) const client = mqtt.connect(MQTT_URL, { clientId: `ack-sim-${Math.random().toString(16).slice(2)}` }) client.on('connect', () => { client.publish(topic, payload, { qos: 1 }, (err) => { if (err) console.error('publish error', err) else console.log('ACK published') setTimeout(() => client.end(true, () => process.exit(err ? 1 : 0)), 200) }) }) client.on('error', (e) => { console.error('mqtt error', e); process.exit(2) })