fix: publish availability as JSON to fix EasyMQTT parse error
Plain string 'online'/'offline' caused SyntaxError in EasyMQTT which
wildcard-subscribes and JSON.parses all messages. Switch to
{"state":"online"} payload with availability_template in HA discovery.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+45
-21
@@ -3,6 +3,12 @@ const { getClient, getPrefix } = require('./client');
|
|||||||
const { allInputs, allOutputs } = require('../registry');
|
const { allInputs, allOutputs } = require('../registry');
|
||||||
const { getInputType } = require('../input-types');
|
const { getInputType } = require('../input-types');
|
||||||
|
|
||||||
|
// Availability payload is JSON so EasyMQTT (wildcard subscriber) can parse it.
|
||||||
|
// HA uses availability_template to extract the state field.
|
||||||
|
const AVAIL_ONLINE = JSON.stringify({ state: 'online' });
|
||||||
|
const AVAIL_OFFLINE = JSON.stringify({ state: 'offline' });
|
||||||
|
const AVAIL_TEMPLATE = '{{ value_json.state }}';
|
||||||
|
|
||||||
function publishAll() {
|
function publishAll() {
|
||||||
const client = getClient();
|
const client = getClient();
|
||||||
if (!client) return;
|
if (!client) return;
|
||||||
@@ -14,11 +20,14 @@ function publishAll() {
|
|||||||
const availTopic = `${prefix}/${inp.moduleSlug}/availability`;
|
const availTopic = `${prefix}/${inp.moduleSlug}/availability`;
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
name: inp.name || inp.metric,
|
name: inp.name || inp.metric,
|
||||||
unique_id: `myprimal_${inp.id}`,
|
unique_id: `myprimal_${inp.id}`,
|
||||||
state_topic: stateTopic,
|
state_topic: stateTopic,
|
||||||
value_template: '{{ value_json.value }}',
|
value_template: '{{ value_json.value }}',
|
||||||
availability_topic: availTopic,
|
availability_topic: availTopic,
|
||||||
|
availability_template: AVAIL_TEMPLATE,
|
||||||
|
payload_available: 'online',
|
||||||
|
payload_not_available: 'offline',
|
||||||
device: {
|
device: {
|
||||||
identifiers: [`myprimal_${inp.moduleId}`],
|
identifiers: [`myprimal_${inp.moduleId}`],
|
||||||
name: inp.moduleName,
|
name: inp.moduleName,
|
||||||
@@ -35,21 +44,24 @@ function publishAll() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const out of allOutputs()) {
|
for (const out of allOutputs()) {
|
||||||
const stateTopic = `${prefix}/${out.moduleSlug}/output/${out.index}/state`;
|
const stateTopic = `${prefix}/${out.moduleSlug}/output/${out.index}/state`;
|
||||||
const cmdTopic = `${prefix}/${out.moduleSlug}/output/${out.index}/set`;
|
const cmdTopic = `${prefix}/${out.moduleSlug}/output/${out.index}/set`;
|
||||||
const availTopic = `${prefix}/${out.moduleSlug}/availability`;
|
const availTopic = `${prefix}/${out.moduleSlug}/availability`;
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
name: out.name,
|
name: out.name,
|
||||||
unique_id: `myprimal_${out.moduleId}_${out.index}`,
|
unique_id: `myprimal_${out.moduleId}_${out.index}`,
|
||||||
state_topic: stateTopic,
|
state_topic: stateTopic,
|
||||||
command_topic: cmdTopic,
|
command_topic: cmdTopic,
|
||||||
payload_on: JSON.stringify({ action: 'run', duration: 30 }),
|
payload_on: JSON.stringify({ action: 'run', duration: 30 }),
|
||||||
payload_off: JSON.stringify({ action: 'stop' }),
|
payload_off: JSON.stringify({ action: 'stop' }),
|
||||||
value_template: '{{ value_json.value }}',
|
value_template: '{{ value_json.value }}',
|
||||||
state_on: '1',
|
state_on: '1',
|
||||||
state_off: '0',
|
state_off: '0',
|
||||||
availability_topic: availTopic,
|
availability_topic: availTopic,
|
||||||
|
availability_template: AVAIL_TEMPLATE,
|
||||||
|
payload_available: 'online',
|
||||||
|
payload_not_available: 'offline',
|
||||||
device: {
|
device: {
|
||||||
identifiers: [`myprimal_${out.moduleId}`],
|
identifiers: [`myprimal_${out.moduleId}`],
|
||||||
name: out.moduleName,
|
name: out.moduleName,
|
||||||
@@ -61,16 +73,28 @@ function publishAll() {
|
|||||||
client.publish(configTopic, JSON.stringify(payload), { retain: true });
|
client.publish(configTopic, JSON.stringify(payload), { retain: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Publish availability online for all modules
|
// Publish availability for all modules (JSON payload)
|
||||||
const seen = new Set();
|
const seen = new Set();
|
||||||
for (const inp of allInputs()) {
|
for (const inp of allInputs()) {
|
||||||
if (!seen.has(inp.moduleSlug)) {
|
if (!seen.has(inp.moduleSlug)) {
|
||||||
seen.add(inp.moduleSlug);
|
seen.add(inp.moduleSlug);
|
||||||
getClient().publish(`${prefix}/${inp.moduleSlug}/availability`, 'online', { retain: true });
|
client.publish(`${prefix}/${inp.moduleSlug}/availability`, AVAIL_ONLINE, { retain: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const out of allOutputs()) {
|
||||||
|
if (!seen.has(out.moduleSlug)) {
|
||||||
|
seen.add(out.moduleSlug);
|
||||||
|
client.publish(`${prefix}/${out.moduleSlug}/availability`, AVAIL_ONLINE, { retain: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('[discovery] HA autodiscovery published');
|
console.log('[discovery] HA autodiscovery published');
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { publishAll };
|
function publishOffline(moduleSlug) {
|
||||||
|
const client = getClient();
|
||||||
|
if (!client) return;
|
||||||
|
client.publish(`${getPrefix()}/${moduleSlug}/availability`, AVAIL_OFFLINE, { retain: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { publishAll, publishOffline };
|
||||||
|
|||||||
Reference in New Issue
Block a user