/* This script makes a LEDA LUC Ventilation control system / Unterdruck Controller IObroker compatible! * * A lot of introduction text.... * * ----- * * Warning: * It is a safety critical device that measures the temperature in your chimney as well as the * pressure difference between the room of your fireplace and the chimney. If there is more pressure * in your chimney than in your room, dangerous carbon monoxide as a combustion product is not sucked * into the chimney, but pushed into your room. You don't smell it - you don't notice it. * But taking a few breath of carbon monoxide kills you. * * Any ventilation system that is pushing used air out of the building can create a lower pressure * in your room than in your chimney. The LEDA LUC is designed to detect dangerous situations and it * turns off your ventilation system. * * ----- * * Unfortunately, it is another device that does measurements and processes in your home, but it does not * offer *any* option to read the measured values via *any* interface into a smarthome system. * Bloody hell! Similar to SYR with their (now discontinued) SAFE-T Connect leckage detector. * * * As with the SYR a little bit of debugging and one can identify a way to get the parameters into a * IObroker. It uses a CAN bus to communicate between the room device with the sensors and the control * unit in your switch board, where the relais is to turn off your ventilation system. The pinout * of the RJ12 6p6c cable is: 1=GND, 2=CAN-H, 3=CAN-L, 4=GND, 5=+12V, 6=+12V. (Note that in the * install instructions the pinout is listed inversed and CAN-H and CAN-L are named CAN-Tx and CAN-Rx) * * I use a Inno-maker usb2can adapter that is compatible with socketcan in linux. I have that connected * via USB to a Raspberry Pi 4 where IObroker is running. In the following I assume it has appeared in * your linux system as can0 in the network interfaces (type ifconfig in your bash console...) * * * Hook up GND, CAN-H and CAN-L to your usb2can adapter. Measure before to ensure you don't hook up the * +12V to your data lines. Might get a bit hot otherwise.... * Don't worry about flipping CAN-H and CAN-L. It does not break, but just will not result in valid * CAN bus packets. * * The baudrate for the LUC a bit odd, but so it be. Configure it in linux to 125kbaud via these system commands: * sudo ifconfig can0 down; sudo ip link set can0 type can bitrate 125000; sudo ifconfig can0 up; * * Now you should be able to see packets if you run a tcpdump via * sudo tcpdump -i can0 * (if not, check if your CAN-H and CAN-L are correct... ;-) ) * * The ioBroker.canbus adapter is used to get all CAN bus messages into the IObroker. * See: https://github.com/crycode-de/ioBroker.canbus and thank you for implementing that, Crycode! * * It reports unknown messages and should report a message with ID 28A. Add that to your known messages. * A object with the CAN message is created and the value of it is a string of the byte values in * the CAN message. It updates around 2-4x per second. * * There is only this one CAN message type which is further divided into 4 subtypes by the first data byte. The * message types 1, 9 and 85 (dec) are not further processed. The pressure sensor data and the * temperature are in message subtype 0, bytes 2, 3 and 4. These values are grabbed by this script, correctly * formated and pushed with the correct unit as new object to your IObroker. * * Voila! Your dumb LUBA LUC is integrated in your smart IOBroker! * * I have not further evaluated if any other byte/bit of the CAN messages contain a valuable information. Also I * did no further investigation if there are any bits set when a underpressure alarm sets off. * * I know myself and once I have that setup, I will forget about that. To ensure it is not forgotten, all my * work and findings here are published as beerware. Do whatever you like with it. Feel free to improve it! * I would love if you share any improvements with the world, too. I do hope my hack is helpful for you. * If it is and we met one day, feel free to buy me a beer. :-) * * Kachel 2025 * */ // Create states if they do not exist createState('javascript.0.LEDA_LUC.pressure', 0, {name: 'Pressure (Pa)', type: 'number', unit: 'Pa'}); createState('javascript.0.LEDA_LUC.temperature', 0, {name: 'Temperature (°C)', type: 'number', unit: '°C'}); on({id: 'canbus.0.28A.json', change: 'any'}, function (obj) { var arrStr = getState('canbus.0.28A.json').val; if (typeof arrStr !== 'string') return; // Parse the string to an array var arr; try { arr = JSON.parse(arrStr); } catch (e) { // Fallback for non-JSON array (e.g., [1,108,3,110,1,1,0,13]) try { arr = eval(arrStr); } catch (e2) { log('Could not parse array: ' + arrStr, 'error'); return; } } if (!Array.isArray(arr) || arr.length < 4) return; // Check message type if (arr[0] === 0) { // Pressure calculation (bytes 2 and 3: arr[1] and arr[2]) var raw = (arr[2] & 0x7F) << 8 | arr[1]; // Combine bytes (little endian) var sign = (arr[2] & 0x80) ? 1 : -1; // Highest bit of byte 3: 1=positive, 0=negative var pressure = sign * raw / 10; // Scaling factor 10 // Temperature calculation (byte 4: arr[3]) var temperature = arr[3]; //log('Pressure: ' + pressure + ' Pa'); //log('Temperature: ' + temperature + ' °C'); // Example: set to other states setState('javascript.0.LEDA_LUC.pressure', pressure, true); setState('javascript.0.LEDA_LUC.temperature', temperature, true); } });