941abd98d5
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>
62 lines
1.6 KiB
JavaScript
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 };
|