Files
myprimal/src/mqtt/client.js
T
arnaudne 941abd98d5 feat: initial myprimal MQTT bridge service
Dynamic MySolem/MyIndygo IoT bridge with MQTT, Home Assistant
autodiscovery, and Homebridge EasyMQTT compatibility.

- Device discovery via MySolem API on startup (all modules/inputs/outputs)
- Configurable poll engine (fast/normal/slow buckets, per-input overrides)
- MQTT retained state publishing + HA autodiscovery payloads
- Unified manual command routing (linesControl vs sendManualModuleCommand)
- Runtime config via MQTT $config/set, persisted to config.json
- Expression override system (API-provided > hardcoded > passthrough)
- Minimal REST API: /health, /state, /control, /rediscover
- Docker deployment (Dockerfile + docker-compose.yml)
- 38 unit tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 01:05:24 +02:00

62 lines
1.6 KiB
JavaScript

'use strict';
const mqtt = require('mqtt');
const PREFIX = process.env.MQTT_TOPIC_PREFIX || 'myprimal';
let client = null;
function connect() {
return new Promise((resolve, reject) => {
const url = process.env.MQTT_URL || 'mqtt://localhost:1883';
const opts = {
clientId: `myprimal_${Math.random().toString(16).slice(2, 8)}`,
clean: true,
reconnectPeriod: 5000,
};
if (process.env.MQTT_USERNAME) opts.username = process.env.MQTT_USERNAME;
if (process.env.MQTT_PASSWORD) opts.password = process.env.MQTT_PASSWORD;
client = mqtt.connect(url, opts);
client.once('connect', () => {
console.log(`[mqtt] Connected to ${url}`);
resolve(client);
});
client.once('error', err => {
console.error('[mqtt] Connection error:', err.message);
reject(err);
});
client.on('error', err => console.error('[mqtt] Error:', err.message));
client.on('reconnect', () => console.log('[mqtt] Reconnecting…'));
});
}
function publish(topic, payload, opts = {}) {
if (!client) return;
const msg = typeof payload === 'string' ? payload : JSON.stringify(payload);
client.publish(`${PREFIX}/${topic}`, msg, { retain: true, ...opts });
}
function subscribe(topic, handler) {
if (!client) return;
const full = `${PREFIX}/${topic}`;
client.subscribe(full);
client.on('message', (t, buf) => {
if (t !== full) return;
try {
handler(JSON.parse(buf.toString()));
} catch {
handler(buf.toString());
}
});
}
function getPrefix() { return PREFIX; }
function getClient() { return client; }
module.exports = { connect, publish, subscribe, getPrefix, getClient };