NEWS
full zigbee2tasmota integration
-
Re: [JSON](Zigbee und ein undefined)
Hi,
I recently bought a zigbee2tasmota device. I managed to set it up with the iobroker.sonoff adapter which allows me to read zigbee sensor values nicely.
But with the sonoff adapter I can not send control commands, for example to turn on a light or a socket.
To do that I understand that I have to send a mqtt command, but that is not possible with the sonoff adapter (afaik).
I can use another mqtt client, but then I don't have the feature of the sonoff adapter that splits up the mqtt json string into separate iobroker objectsHere's what I would like to achieve:
- receive tasmota mqtt messages and split them up into separate objects
- send an mqtt command to tasmota. Ideally by setting for example "myFancyMqtt.0.ZigbeeLight.power = true" will send the appropriate command to my zigbee2tasmota device that will turn on the ZigbeeLight.
Is there any out-of-the-box solution available as of 2023?
-
Maybe this script https://forum.iobroker.net/topic/48945/tasmota-steckdosen-per-mqtt-javascript-direkt-ansteuern/23 can help, but I don't want to modify a script every time I add a new zigbee device...
-
Ok, I finally had time to find a solution. Thanks to chatGPT
The zigbee2tasmota device is connected to a "regular" mqtt client in iobroker (not the sonoff adapter). When a zigbee message arrives it gets forwarded via mqtt to my iobroker as a json string.
My script parses that json and creates separate states for each of the key:value pairs in the json.For sending commands I automatically add an additional state "PowerSet" to devices that have a "Power" state. When I update the PowerSet state, a script creates a json string and writes it into the "mqtt.0.cmnd.ZigbeeGateway.ZbSend" state (see https://tasmota.github.io/docs/Zigbee/#sending-device-commands)
The advantage of this approach is that I have nothing to do on the iobroker side when I add new zigbee devices, they are handled automatically.
That's it Seems to work well so far. Here's the script in case anyone has a similar problem with zigbee2tasmota:
// ############## user config // where the mqtt messages arrive const zigbee2tasmotaSensorObjectId = 'mqtt.0.tele.ZigbeeGateway.SENSOR'; // where the states of the zigbee devices should appear const zbBaseFolder = '0_userdata.0.zigbee2tasmota'; // ZbSend state, see https://tasmota.github.io/docs/Zigbee/#sending-device-commands const zbsendObjId = 'mqtt.0.cmnd.ZigbeeGateway.ZbSend'; // ############## end user config const regexPowerSetStr = `${zbBaseFolder}\\..*PowerSet$`; const regexPowerSet = new RegExp(regexPowerSetStr); // receive on(zigbee2tasmotaSensorObjectId, (obj) => { const jsonString = obj.state.val; const jsonData = JSON.parse(jsonString); // log(`Received JSON string: ${jsonString}`); function createObjectsRecursively(parent, data) { for (const key in data) { const obj = data[key]; const stateName = `${parent}.${key}`; if (typeof obj === 'object') { createObjectsRecursively(stateName, obj); } else { let value = obj; // custom handling of special data types if (key.toLowerCase() == 'time') { value = new Date(obj); log("found time") } // Check if the state already exists. If it does, just update the value. // If it does not exist (-> new zigbee device), create the states. if (!existsState(stateName)) { // If the state does not exist, create it and set the value createState(stateName, value, { name: key, type: typeof value, role: "value", read: true, write: true }); log(`Created state ${stateName}`); // create additional state to set a new value that will be sent to the zigbee device. // If I use the normal "Power" state, I am afraid it will trigger the zbSend command // everytime it gets updated from the zigbee device itself. if (stateName.endsWith("Power")) { let powerSetStateName = stateName + "Set" createState(powerSetStateName, !!value, { name: key + "Set", type: "boolean", role: "value", read: true, write: true }); log(`Created state ${powerSetStateName}`); } // potentially add more custom handling for dimmer values, etc } else { setState(stateName, value); } // log(`set state ${parent}.${key} with value ${value}`); } } } createObjectsRecursively(zbBaseFolder, jsonData); }); // send power on/off on(regexPowerSet, (obj) => { const objId = obj.id; // probably regex is not needed and we can just take .Device or .Name // Define a regular expression to match the substring between "ZbReceived" and "PowerSet" const regex = /ZbReceived\.(.*?)\.PowerSet/; // Use the regular expression to extract the substring const match = objId.match(regex); if (match) { const zbname = match[1]; let newValue = obj.state.val; let zbsendstring = "\{\"Device\": \"" + zbname + "\"\,\"Send\"\:\{\"Power\"\: "+newValue+"\}}" log("zbsend: " + zbsendstring) setState(zbsendObjId, zbsendstring) } else { log(`The substring between "ZbReceived" and "PowerSet" not found in ${objId}`); } });
PS: sending zigbee commands is only supported for power on/off. I don't have any zigbee devices that have dimmer or hue values or anything else. I guess the script can be adapted to work with those kind of devices, too.