Hallo liebes IObroker Forum,
aus diversen Gründen habe ih neben meinem geliebten IOB auch noch eine HomeAssistant Installation laufen.
Mit dem folgenden Script ist es möglich IObroker states AUTOMATISCH via Autodiscovery im HomeAssistent sichtbar zu machen - ohne umtändlich in YAML files rumfuhrwerken zu müssen und ohne im IObrocker an jedem State das pub & sub zu aktivieren. .
Dazu setzt man einfach an einem State die Funktion "homeassistent_enabled":
Das Script scannt nach diesen Objekten und published sie via MQTT (ein Broker entweder in HA oder extern ist notwendig) an den HA:
Im JS-Adapter muss als zusätzliches Modul "mqtt" geladen werden:
Hier das script (Probleme siehe unten):
// Required libraries
const mqtt = require('mqtt');
// Configuration
const MQTT_BROKER_URL = 'mqtt://<IP>:<PORT>'; // Replace with your broker's address
const MQTT_USERNAME = '<username>'; // Replace with your MQTT username
const MQTT_PASSWORD = '<password>'; // Replace with your MQTT password
const DEBUG = true; // Set to true for debugging output
// MQTT client setup
const mqttClient = mqtt.connect(MQTT_BROKER_URL, {
username: MQTT_USERNAME,
password: MQTT_PASSWORD
});
mqttClient.on('connect', () => {
console.log('Connected to MQTT broker');
});
mqttClient.on('error', (err) => {
console.error('MQTT connection error:', err);
});
// Function to log debug information
function debugLog(message) {
if (DEBUG) {
console.log(message);
}
}
// Function to determine the type of a state
function determineStateType(stateObj) {
if (typeof stateObj.val === 'boolean') {
return 'switch';
} else if (typeof stateObj.val === 'number') {
return 'sensor';
} else if (typeof stateObj.val === 'string') {
return 'text';
} else {
return 'unknown';
}
}
// Function to publish MQTT discovery messages
function publishMQTTDiscovery(id, stateObj, deviceName) {
const baseTopic = `homeassistant`;
const deviceId = id.replace(/\./g, '_');
const stateType = determineStateType(stateObj);
let configTopic;
let configPayload;
switch (stateType) {
case 'switch':
configTopic = `${baseTopic}/switch/${deviceId}/config`;
configPayload = {
name: deviceName || id, // Use the provided deviceName or fallback to id
state_topic: `${baseTopic}/switch/${deviceId}/state`,
command_topic: `${baseTopic}/switch/${deviceId}/set`,
payload_on: true,
payload_off: false,
unique_id: deviceId,
device: {
identifiers: [deviceId],
name: deviceName || id, // Use deviceName for the device itself
},
};
break;
case 'sensor':
configTopic = `${baseTopic}/sensor/${deviceId}/config`;
configPayload = {
name: deviceName || id,
state_topic: `${baseTopic}/sensor/${deviceId}/state`,
unique_id: deviceId,
device: {
identifiers: [deviceId],
name: deviceName || id,
},
};
break;
case 'text':
configTopic = `${baseTopic}/text/${deviceId}/config`;
configPayload = {
name: deviceName || id,
state_topic: `${baseTopic}/text/${deviceId}/state`,
command_topic: `${baseTopic}/text/${deviceId}/set`,
unique_id: deviceId,
device: {
identifiers: [deviceId],
name: deviceName || id,
},
};
break;
default:
debugLog(`Unknown state type for ${id}`);
return;
}
mqttClient.publish(configTopic, JSON.stringify(configPayload), { retain: true });
// Publish initial state
const stateTopic = configPayload.state_topic;
mqttClient.publish(stateTopic, JSON.stringify(stateObj.val));
// Subscribe to command topic if applicable
if (configPayload.command_topic) {
mqttClient.subscribe(configPayload.command_topic);
mqttClient.on('message', (topic, message) => {
if (topic === configPayload.command_topic) {
try {
// Check if the message is JSON
let newValue;
if (message.toString().startsWith('{') || message.toString().startsWith('[')) {
newValue = JSON.parse(message.toString());
} else {
// Handle non-JSON payloads (e.g., "true", "false", "42")
newValue = message.toString().trim().toLowerCase();
if (newValue === 'true') newValue = true;
else if (newValue === 'false') newValue = false;
else if (!isNaN(newValue)) newValue = parseFloat(newValue);
}
setState(id, newValue); // Update ioBroker state
} catch (err) {
console.error(`Failed to process MQTT message on ${topic}:`, err);
}
}
});
}
debugLog(`Published MQTT discovery for ${id}: ${JSON.stringify(configPayload)}`);
}
function scanAndPublish() {
const homeAssistantDevices = getObject('enum.functions.homeassistent_enabled');
if (homeAssistantDevices) {
console.log('Devices with homeassistent_enabled function:');
homeAssistantDevices.common.members.forEach(deviceId => {
const deviceObj = getObject(deviceId); // Fetch the device object
const stateObj = getState(deviceId); // Fetch the state of the device
if (deviceObj && stateObj) {
console.log(`- ${deviceObj.common.name} (${deviceId})`);
// Pass the device name as an additional argument
publishMQTTDiscovery(deviceId, stateObj, deviceObj.common.name);
} else {
console.log(`Skipping device ${deviceId}: Unable to retrieve object or state.`);
}
});
} else {
console.log('No devices found with homeassistent_enabled function');
}
}
// Run the script periodically
schedule('*/1 * * * *', () => {
debugLog('Scanning for states with homeassistent_enabled...');
scanAndPublish();
});
Soweit so gut - ein Problemchen habe ich noch:
Wenn im HA einen der "switches" betätige schaltet es im IOB wie es soll, die Statusrückmeldung kommt aber entweder nicht im HA an oder bleibt nicht erhalten. Die Icons im HA werden also nicht blau (was für aktiviert steht). Hier ein Debug der herauskommt wenn ich im HA dem "sonoff_0_zwstecker_1_weihnachtsbaum_power" auf "true" schalte:
javascript.1 08:09:13.401 info Start JavaScript script.js.in_Entwicklung.MQTT2 (Javascript/js)
javascript.1 08:09:13.405 info script.js.in_Entwicklung.MQTT2: Scanning for states with homeassistent_enabled...
javascript.1 08:09:13.405 info script.js.in_Entwicklung.MQTT2: Devices with homeassistent_enabled function:
javascript.1 08:09:13.405 info script.js.in_Entwicklung.MQTT2: - Lüfter Elternbad.STATE (hm-rpc.0.LEQ0233457.13.STATE)
javascript.1 08:09:13.405 info script.js.in_Entwicklung.MQTT2: Published MQTT discovery for hm-rpc.0.LEQ0233457.13.STATE: {"name":"Lüfter Elternbad.STATE","state_topic":"homeassistant/switch/hm-rpc_0_LEQ0233457_13_STATE/state","command_topic":"homeassistant/switch/hm-rpc_0_LEQ0233457_13_STATE/set","payload_on":true,"payload_off":false,"unique_id":"hm-rpc_0_LEQ0233457_13_STATE","device":{"identifiers":["hm-rpc_0_LEQ0233457_13_STATE"],"name":"Lüfter Elternbad.STATE"}}
javascript.1 08:09:13.405 info script.js.in_Entwicklung.MQTT2: - Termostat Wohnzimmer:1.ACTUAL_TEMPERATURE (hm-rpc.2.000C9A49A7D845.1.ACTUAL_TEMPERATURE)
javascript.1 08:09:13.405 info script.js.in_Entwicklung.MQTT2: Published MQTT discovery for hm-rpc.2.000C9A49A7D845.1.ACTUAL_TEMPERATURE: {"name":"Termostat Wohnzimmer:1.ACTUAL_TEMPERATURE","state_topic":"homeassistant/sensor/hm-rpc_2_000C9A49A7D845_1_ACTUAL_TEMPERATURE/state","unique_id":"hm-rpc_2_000C9A49A7D845_1_ACTUAL_TEMPERATURE","device":{"identifiers":["hm-rpc_2_000C9A49A7D845_1_ACTUAL_TEMPERATURE"],"name":"Termostat Wohnzimmer:1.ACTUAL_TEMPERATURE"}}
javascript.1 08:09:13.406 info script.js.in_Entwicklung.MQTT2: - ZwStecker_1_Weihnachtsbaum POWER (sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER)
javascript.1 08:09:13.406 info script.js.in_Entwicklung.MQTT2: Published MQTT discovery for sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER: {"name":"ZwStecker_1_Weihnachtsbaum POWER","state_topic":"homeassistant/switch/sonoff_0_ZwStecker_1_Weihnachtsbaum_POWER/state","command_topic":"homeassistant/switch/sonoff_0_ZwStecker_1_Weihnachtsbaum_POWER/set","payload_on":true,"payload_off":false,"unique_id":"sonoff_0_ZwStecker_1_Weihnachtsbaum_POWER","device":{"identifiers":["sonoff_0_ZwStecker_1_Weihnachtsbaum_POWER"],"name":"ZwStecker_1_Weihnachtsbaum POWER"}}
javascript.1 08:09:13.406 info script.js.in_Entwicklung.MQTT2: - On/off state of the switch (zigbee.0.4c97a1fffe27ff06.state)
javascript.1 08:09:13.406 info script.js.in_Entwicklung.MQTT2: Published MQTT discovery for zigbee.0.4c97a1fffe27ff06.state: {"name":"On/off state of the switch","state_topic":"homeassistant/switch/zigbee_0_4c97a1fffe27ff06_state/state","command_topic":"homeassistant/switch/zigbee_0_4c97a1fffe27ff06_state/set","payload_on":true,"payload_off":false,"unique_id":"zigbee_0_4c97a1fffe27ff06_state","device":{"identifiers":["zigbee_0_4c97a1fffe27ff06_state"],"name":"On/off state of the switch"}}
javascript.1 08:09:13.407 info script.js.in_Entwicklung.MQTT2: registered 0 subscriptions, 0 schedules, 0 messages, 0 logs and 0 file subscriptions
javascript.1 08:09:13.408 info script.js.in_Entwicklung.MQTT2: Connected to MQTT broker
javascript.1 08:09:27.343 silly States user redis pmessage */sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER:{"val":true,"ack":false,"ts":1734419367340,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
sonoff.0 08:09:27.342 silly States user redis pmessage sonoff.0.*/sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER:{"val":true,"ack":false,"ts":1734419367340,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
sonoff.0 08:09:27.343 debug stateChange sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER: {"val":true,"ack":false,"ts":1734419367340,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
sonoff.0 08:09:27.343 debug onStateChange sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER: {"val":true,"ack":false,"ts":1734419367340,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
javascript.1 08:09:27.343 silly States user redis pmessage */sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER:{"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
javascript.1 08:09:27.343 silly States user redis pmessage */sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER:{"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
sonoff.0 08:09:27.343 silly States user redis pmessage sonoff.0.*/sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER:{"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
sonoff.0 08:09:27.343 debug stateChange sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER: {"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
sonoff.0 08:09:27.343 debug onStateChange sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER: {"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
sonoff.0 08:09:27.343 silly States user redis pmessage sonoff.0.*/sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER:{"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
sonoff.0 08:09:27.343 debug stateChange sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER: {"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
sonoff.0 08:09:27.344 debug onStateChange sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER: {"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
sonoff.0 08:09:27.384 silly States user redis pmessage sonoff.0.*/sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER:{"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
sonoff.0 08:09:27.384 debug stateChange sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER: {"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
javascript.1 08:09:27.384 silly States user redis pmessage */sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER:{"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
sonoff.0 08:09:27.384 debug onStateChange sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER: {"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
sonoff.0 08:09:27.384 silly States user redis pmessage sonoff.0.*/sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER:{"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
sonoff.0 08:09:27.384 debug stateChange sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER: {"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
sonoff.0 08:09:27.384 debug onStateChange sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER: {"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
javascript.1 08:09:27.384 silly States user redis pmessage */sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER:{"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
Hat dazu jemand eine Idee?
Und hat jemand weitere Ideen was man verbessern könnte?