OpenTherm în NodeRed
Acest tutorial este transpunerea practică a celor relatate în articolul "Economie de gaz cu OpenTherm".
Se presupune că am configurat modulul OpenTherm iar calea in Tasmota este: %topic%/%prefix%/ adica 'ot/...'.
Vom creea o logică de comandă pentru centrala OpenTherm după cum urmează:
Datele care ne interesează le preluăm din 'ot/tele/SENSOR' (mesaj JSON) cu un nod MQTT in.
Datele obținute sunt prelucrate în nodul funcție denumit 'work' astfel:
var B = msg.payload.OPENTHERM.BTMP.REQ;
var W = msg.payload.OPENTHERM.HWTMP.REQ;
var CH = msg.payload.OPENTHERM.SLAVE.CH;
var DHW = msg.payload.OPENTHERM.SLAVE.DHW;
var acm_low = temperatura(0); // temperatura ACM pentru reducere consum
var acm_high = temperatura(1); // temperatura ACM pentru baie
var ch_low = temperatura(2); // temperatura tur pentru mentinere
var ch_high = temperatura(3); // temperatura tur pentru incalzire
var incalzire = flow.get('incalzire') || false; // true daca avem necesar de incalzire
var iarna = flow.get('iarna') || false; // true daca incalzirea este activa
/////////////////////////////////////////////////////////////////////
if (DHW != 1 && W != acm_low)
return { topic: 'ot/cmnd/ot_twater', payload: acm_low };
if (DHW == 1 && W != acm_high)
return { topic: 'ot/cmnd/ot_twater', payload: acm_high };
/////////////////////////////////////////////////////////////////////
if (incalzire && B != ch_high)
return { topic: 'ot/cmnd/ot_tboiler', payload: ch_high };
if (!incalzire && B != ch_low)
return { topic: 'ot/cmnd/ot_tboiler', payload: ch_low };
/////////////////////////////////////////////////////////////////////
if (iarna && CH != 1)
return { topic: 'ot/cmnd/ot_ch', payload: 1 };
if (!iarna && CH == 1)
return { topic: 'cor/opentherm/cmnd/ot_ch', payload: 0 };
/////////////////////////////////////////////////////////////////////
return null;
function temperatura(tip) {
var afara = flow.get('afara'); // temperatura exterior
var pos = parseInt(afara);
var col = parseInt(tip);
if (pos < -20) pos = -20;
if (pos > 20) pos = 20;
pos += 20;
// coloana 1 = t acm low - uzual
// coloana 2 = t acm high - baie
// coloana 3 = t tur low - cand nu exista necesar de incalzire
// coloana 4 = t tur high - cand avem necesar de incalzire
corelare = [
[20,42,46,60], // -20ºC
[20,42,45,59], // -19
[20,42,45,59], // -18
[20,42,44,58], // -17
[20,42,44,58], // -16
[20,42,43,57], // -15
[20,42,43,57], // -14
[20,42,42,56], // -13
[20,42,42,56], // -12
[20,42,41,55], // -11
[20,42,41,55], // -10
[20,42,40,54], // -9
[20,42,40,54], // -8
[20,42,39,53], // -7
[20,42,39,53], // -6
[20,42,38,52], // -5
[20,42,38,52], // -4
[20,42,37,51], // -3
[20,42,37,51], // -2
[20,42,36,51], // -1
[20,42,36,40], // 0ºC
[20,42,35,39], // 1
[20,42,35,39], // 2
[20,42,34,38], // 3
[20,42,34,38], // 4
[20,42,33,37], // 5
[20,42,33,37], // 6
[20,42,32,36], // 7
[20,42,32,36], // 8
[20,42,31,35], // 9
[20,42,30,34], // 10
[20,42,29,33], // 11
[20,42,28,32], // 12
[20,42,27,31], // 13
[20,42,26,30], // 14
[20,42,25,29], // 15
[20,42,24,28], // 16
[20,42,23,28], // 17
[20,42,22,28], // 18
[20,42,21,28], // 19
[20,42,20,28] // 20ºC
];
return corelare[pos][col];
}
Nu rămâne decât să transmitem rezultatul prin MQTT cu un not MQTT out fără reținere:
Pe lângă cele de mai sus avem nevoie de temperatura exterioară, variabila 'iarna' și variabila 'incalzire'.
Să le luăm pe rând, mai întâi temperatura exterioară:
pe care o preluam de la un senzor de temperatura bluetooth - termohigrometrul LYWSD03MMC - cu un nod MQTT in configurat astfel
în nodul funcție nu facem altceva decât să salvăm în flow valoarea temperaturii exterioare
flow.set('afara', msg.payload.Temperature);
/*
senzorul are următorul tip de mesaj:
{
"Time": "2024-01-13T14:58:46",
"mac": "a4c138000000",
"Temperature": 3.2,
"Humidity": 64,
"DewPoint": -3.2,
"Battery": 67,
"RSSI": -90,
"TempUnit": "C"
}
*/
Variabila iarna
o preluăm cu un nod MQTT in
și o salvăm în flow cu un nod funcție
flow.set('iarna', msg.payload);
Variabila 'incalzire' o automatizăm cu un termostat.
Pentru această automatizare avem nevoie de
node-red-contrib-ramp-thermostat node-red-contrib-timeout
iar rezultatul final o să arate așa:
cu nodul MQTT in "t living" preluăm temperatura de la un senzor de temperatura bluetooth - termohigrometrul LYWSD03MMC
Nodul timeout numit siguranță îl configurăm astfel
Datele senzorului de temperatură le prelucrăm într-un nod funcție așa
var iarna = flow.get('iarna');
msg.topic = 'setCurrent';
msg.payload = msg.payload.Temperature;
if (!iarna)
msg.payload = 90;
return msg;
A doua intrare a nodului termostat este temperatura țintă pe care o preluăm cu un nod MQTT in
iar apoi cu un nod funcție îi modificăm topicul și transmitem mai departe mesajul
msg.topic = 'setTarget'; return msg;
Nodul ramp-termostat are nevoie de mai multă atenție. Deschidem nodul...
adăugăm un profil nou pe care îl numim living, cu 21ºC toată ziua (00:00 - 23:59)
apoi salvăm și nodul termostat va arăta așa:
Pe prima ieșire a nodului termostat avem necesarul de căldură pe care îl salvăm în flow cu un nod funcție:
if (msg.payload)
flow.set('incalzire',true);
else
flow.set('incalzire',false);
iar pe ieșirea 3 avem temperatura țintă curentă pe care o salvam cu un nod MQTT out în topicul 'setari/living'
În momentul acesta avem toate elementele gata și putem salva și activa automatizarea.