Изменил скрипт вот так, чтобы было меньше дублированных оповещений.
Теперь вообще не работает.
/* бойлер */
var BoilerName = "BoilerTermostat/Name";
var BoilerONOFF = "BoilerTermostat/ON_OFF";
var BoilerScheduleMode = "BoilerTermostat/ScheduleMode";
var BoilerTemperature = "wb-mai6_51/IN 1 P Temperature";
var BoilerSetpoint = "BoilerTermostat/Setpoint";
var BoilerHysteresis = "BoilerTermostat/Hysteresis";
var BoilerPressure = 4; // пока не поставил датчик давления на бойлер
var BoilerMinPressure = 2;
var BoilerMaxPressure = 5;
var BoilerMainRelayState = "wb-mio-gpio_70:2/IN9"; // если подаётся ток с клеммы S термореле бойлера на реле WB
var BoilerWBRelayState = "wb-mio-gpio_70:4/K1";
var BoilerABBRelayState = "wb-mio-gpio_70:2/IN11";
var BoilerVirtualPumpRelayState = true; // виртуальный насос чисто потому что в функции heatingRules нужен такой аргумент для унификации с котлом
var BoilerCirculationTimeout = 10000; // 10 секунд
var BoilerCirculationRelay = "wb-mr6cu_76/K4";
var BoilerCirculationButtons = ["wb-mr6c_120/Input 4 Double Press Counter", "wb-mr6c_126/Input 5 Double Press Counter"];
var BoilerCirculationNames = ["на первом этаже", "на втором этаже"];
/* котёл */
var KotelName = "KotelTermostat/Name";
var KotelONOFF = "KotelTermostat/ON_OFF";
var KotelScheduleMode = "KotelTermostat/ScheduleMode";
var KotelTemperature = "wb-mai6_51/IN 1 N Temperature";
var KotelSetpoint = "KotelTermostat/Setpoint";
var KotelHysteresis = "KotelTermostat/Hysteresis";
var KotelPressure = "wb-mai6_51/IN 5 P Value";
var KotelMinPressure = 1;
var KotelMaxPressure = 2;
var KotelMainRelayState = "wb-mio-gpio_70:2/IN1"; // если подаётся ток с предельного термореле котла на реле WB
var KotelWBRelayState = "wb-mio-gpio_70:4/K2";
var KotelABBRelayState = "wb-mio-gpio_70:2/IN12";
var KotelPumpRelayState = "wb-mr6cu_76/K2";
defineVirtualDevice("KotelTermostat", {
title: "Термостат котла",
cells: {
Name: {
title: "Название",
type: "text",
value: "Котёл",
},
ON_OFF: { // активация термостата 0-выкл 1-включен
title: "Выключатель",
type: "switch",
value: false,
},
ScheduleMode: { // режим 0-ручной 1-по расписанию с 23 вечера до 7 утра
title: "Работа по расписанию",
type: "switch",
value: false,
},
Temperature: {
title: "Температура",
type: "value",
value: "",
units: "deg C",
precision: 2,
},
Setpoint: { // уставка
title: "Уставка",
type: "range",
value: 70,
min: 40,
max: 90,
readonly: false,
},
Hysteresis: {
title: "Гистерезис",
type: "range",
value: 10,
min: 5,
max: 20,
readonly: false,
},
Pressure: {
title: "Давление",
type: "value",
value: "",
units: "bar",
precision: 2,
},
MainRelayState: { // состояние термореле в котле 0-ожидание (ВЫКЛ) 1-нагрев (ВКЛ)
title: "Термореле в котле",
type: "text",
value: false,
},
WBRelayState: { // состояние реле 0-ожидание (ВЫКЛ) 1-нагрев (ВКЛ)
title: "Реле WB",
type: "text",
value: false,
},
ABBRelayState: { // состояние реле 0-ожидание (ВЫКЛ) 1-нагрев (ВКЛ)
title: "Реле ABB",
type: "text",
value: false,
},
PumpRelayState: { // состояние реле 0-ожидание (ВЫКЛ) 1-циркуляция (ВКЛ)
title: "Циркуляционный насос",
type: "text",
value: false,
},
Lock: { // блокировка в визуализации 0-снята 1-заблокирована
title: "Блокировка изменений",
type: "switch",
value: false,
},
}
});
defineVirtualDevice("BoilerTermostat", {
title: "Термостат бойлера",
cells: {
Name: {
title: "Название",
type: "text",
value: "Бойлер",
},
ON_OFF: { // активация термостата 0-выкл 1-включен
title: "Выключатель",
type: "switch",
value: false,
},
ScheduleMode: { // режим 0-ручной 1-по расписанию с 23 вечера до 7 утра
title: "Работа по расписанию",
type: "switch",
value: false,
},
Temperature: {
title: "Температура",
type: "value",
value: "",
units: "deg C",
precision: 2,
},
Setpoint: { // уставка
title: "Уставка",
type: "range",
value: 50,
min: 20,
max: 70,
readonly: false,
},
Hysteresis: {
title: "Гистерезис",
type: "range",
value: 10,
min: 5,
max: 20,
readonly: false,
},
MainRelayState: { // состояние термореле в бойлере 0-ожидание (ВЫКЛ) 1-нагрев (ВКЛ)
title: "Термореле в бойлере",
type: "text",
value: false,
},
WBRelayState: { // состояние реле 0-ожидание (ВЫКЛ) 1-нагрев (ВКЛ)
title: "Реле WB",
type: "text",
value: false,
},
ABBRelayState: { // состояние реле 0-ожидание (ВЫКЛ) 1-нагрев (ВКЛ)
title: "Реле ABB",
type: "text",
value: false,
},
Lock: { // блокировка в визуализации 0-снята 1-заблокирована
title: "Блокировка изменений",
type: "switch",
value: false,
},
}
});
/* ПРАВИЛА УПРАВЛЕНИЯ КОТЛОМ */
// запись давления в ячейку виртуального устройства
defineRule("KotelPressureRule", {
whenChanged: KotelPressure,
then: function (newValue, devName, cellName) {
dev['KotelTermostat/Pressure'] = newValue;
log.info( 'KotelTermostat/Pressure = ' + newValue );
}
});
// запись температуры в ячейку виртуального устройства
defineRule("KotelTemperatureRule", {
whenChanged: KotelTemperature,
then: function (newValue, devName, cellName) {
dev['KotelTermostat/Temperature'] = newValue;
log.info( 'KotelTermostat/Temperature = ' + newValue );
}
});
// запись состояния главного термореле бойлера в ячейку виртуального устройства
defineRule("KotelMainRelayStateRule", {
whenChanged: KotelMainRelayState,
then: function (newValue, devName, cellName) {
if (newValue == true) { dev['KotelTermostat/MainRelayState'] = "включено"; }
if (newValue == false) { dev['KotelTermostat/MainRelayState'] = "выключено"; }
log.info( 'KotelTermostat/MainRelayState = ' + newValue );
}
});
// запись состояния реле WB в ячейку виртуального устройства
defineRule("KotelWBRelayStateRule", {
whenChanged: KotelWBRelayState,
then: function (newValue, devName, cellName) {
if (newValue == true) { dev['KotelTermostat/WBRelayState'] = "включено"; }
if (newValue == false) { dev['KotelTermostat/WBRelayState'] = "выключено"; }
log.info( 'KotelTermostat/WBRelayState = ' + newValue );
}
});
// запись состояния реле ABB в ячейку виртуального устройства
defineRule("KotelABBRelayStateRule", {
whenChanged: KotelABBRelayState,
then: function (newValue, devName, cellName) {
if (newValue == true) { dev['KotelTermostat/ABBRelayState'] = "включено"; }
if (newValue == false) { dev['KotelTermostat/ABBRelayState'] = "выключено"; }
log.info( 'KotelTermostat/ABBRelayState = ' + newValue );
}
});
// запись состояния реле насоса в ячейку виртуального устройства
defineRule("KotelPumpRelayStateRule", {
whenChanged: KotelPumpRelayState,
then: function (newValue, devName, cellName) {
if (newValue == true) { dev['KotelTermostat/PumpRelayState'] = "включено"; }
if (newValue == false) { dev['KotelTermostat/PumpRelayState'] = "выключено"; }
log.info( 'KotelTermostat/PumpRelayState = ' + newValue );
}
});
/* КОНЕЦ ПРАВИЛ УПРАВЛЕНИЯ КОТЛОМ */
/* ПРАВИЛА УПРАВЛЕНИЯ БОЙЛЕРОМ */
// запись температуры в ячейку виртуального устройства
defineRule("BoilerTemperatureRule", {
whenChanged: BoilerTemperature,
then: function (newValue, devName, cellName) {
dev['BoilerTermostat/Temperature'] = newValue;
log.info( 'BoilerTermostat/Temperature = ' + newValue );
}
});
// запись состояния главного термореле бойлера в ячейку виртуального устройства
defineRule("BoilerMainRelayStateRule", {
whenChanged: BoilerMainRelayState,
then: function (newValue, devName, cellName) {
if (newValue == true) { dev['BoilerTermostat/MainRelayState'] = "включено"; }
if (newValue == false) { dev['BoilerTermostat/MainRelayState'] = "выключено"; }
log.info( 'BoilerTermostat/MainRelayState = ' + newValue );
}
});
// запись состояния реле WB в ячейку виртуального устройства
defineRule("BoilerWBRelayStateRule", {
whenChanged: BoilerWBRelayState,
then: function (newValue, devName, cellName) {
if (newValue == true) { dev['BoilerTermostat/WBRelayState'] = "включено"; }
if (newValue == false) { dev['BoilerTermostat/WBRelayState'] = "выключено"; }
log.info( 'BoilerTermostat/WBRelayState = ' + newValue );
}
});
// запись состояния реле ABB в ячейку виртуального устройства
defineRule("BoilerABBRelayStateRule", {
whenChanged: BoilerABBRelayState,
then: function (newValue, devName, cellName) {
if (newValue == true) { dev['BoilerTermostat/ABBRelayState'] = "включено"; }
if (newValue == false) { dev['BoilerTermostat/ABBRelayState'] = "выключено"; }
log.info( 'BoilerTermostat/ABBRelayState = ' + newValue );
}
});
// запустить насос циркуляции ГВС при двойном нажатии выключателя в ванной или в сортире
defineRule("BoilerCirculationControlRule", {
whenChanged: BoilerCirculationButtons,
then: function (newValue, devName, cellName) {
var index = BoilerCirculationButtons.indexOf(devName + '/' + cellName);
if (newValue) {
dev['BoilerCirculationRelay']=true;
setTimeout(function (){
dev['BoilerCirculationRelay']=false;
}, BoilerCirculationTimeout);
SendTelegramMsg('В Южном кто-то пошёл мыться ' + BoilerCirculationNames[index]);
}
}
});
/* КОНЕЦ ПРАВИЛ УПРАВЛЕНИЯ БОЙЛЕРОМ */
/*
Режим работы котла
1) Проверка давления.
Нормальный режим 1,8...2,2 бар.
Если стало 1,5 или 2,5, то высылаем смс в телегу.
Если стало 1 или 3, то останавливаем котёл.
2) Проверка температуры
3) Проверка времени
Котёл включается с 23-00 по 07-00 при температуре датчика менее 70 градусов и отключается при 90.
Режим работы бойлера
Насос бойлера работает всё время при условии:
1) Температура в ТА больше температуры бойлера
2) Температура включения насоса 50, выключение при 60.
Режим работы полов
1) Проверка давления.
Нормальный режим 1,8...2,2 бар.
Если стало 1,5 или 2,5, то высылаем смс в телегу.
Если стало 1 или 3, то выключаем насос.
2) Насос включается в 5 утра и выключается в 7 вечера.
*/
function heatingRules(name, temperature, setpoint, hysteresis, pressure, MinPressure, MaxPressure, MainRelayState, WBRelayState, ABBRelayState, PumpRelayState) {
SendTelegramMsg('Время ' + time.getHours() + '. heatingRules started в Южном');
log.info('Время ' + time.getHours() + '. heatingRules started в Южном');
if (pressure <= MinPressure) {
dev[WBRelayState] = false;
dev[PumpRelayState] = false;
log.info('В Южном критически низкое давление в ' + name + ' ' + pressure + ' бар. ' + name + ' отключен.');
SendTelegramMsg('В Южном критически низкое давление в ' + name + ' ' + pressure + ' бар. ' + name + ' отключен.');
}
else if (pressure >= MaxPressure) {
dev[WBRelayState] = false;
dev[PumpRelayState] = false;
log.info('В Южном очень высокое давление в ' + name + ' ' + pressure + ' бар. ' + name + ' отключен.');
SendTelegramMsg('В Южном очень высокое давление в ' + name + ' ' + pressure + ' бар. ' + name + ' отключен.');
}
/* =================== тут работаем ============================= */
else if (pressure > MinPressure && pressure < MaxPressure) { // pressure > MinPressure И pressure < MaxPressure
if ( dev[temperature] <= (dev[setpoint] - dev[hysteresis]) ) { // если температура датчика меньше, чем (уставка минус гистерезис)
// доп проверка ЕСЛИ реле на момент проверки было выключено, то включаем его и шлём уведомление
// а ЕСЛИ реле на момент проверки было уже включено, то ничего не делаем
if ( dev[WBRelayState] == false ) {
dev[WBRelayState] = true;
dev[PumpRelayState] = true;
log.info(dev[name] + ' в Южном. Температура ' + name + ' ' + dev[temperature] + ' <= ' + dev[setpoint] + '-' + dev[hysteresis] +
'. Положение реле WB ' + dev[WBRelayState] + '. Начался нагрев.');
SendTelegramMsg(dev[name] + ' в Южном. Температура ' + name + ' ' + dev[temperature] + ' <= ' + dev[setpoint] + '-' + dev[hysteresis] +
'. Положение реле WB ' + dev[WBRelayState] + '. Начался нагрев.');
}
}
else if ( dev[temperature] > (dev[setpoint] - dev[hysteresis]) && dev[temperature] < dev[setpoint] ) {
// тут ничего не делаем (либо идёт нагрев либо остывание)
dev[PumpRelayState] = true;
}
else if ( dev[temperature] = dev[setpoint] ) { // если температура датчика достигла уставки выключить нагрев
// доп проверка ЕСЛИ реле на момент проверки было включено, то выключаем его и шлём уведомление
// а ЕСЛИ реле на момент проверки было уже выключено, то ничего не делаем
if ( dev[WBRelayState] == true ) {
dev[WBRelayState] = false;
dev[PumpRelayState] = true;
SendTelegramMsg(dev[name] + ' в Южном. Температура ' + name + ' ' + dev[temperature] + ' = ' + dev[setpoint] + ' (настройка термостата). Нагрев остановлен.');
log.info(dev[name] + ' в Южном. Температура ' + name + ' ' + dev[temperature] + ' = ' + dev[setpoint] + ' (настройка термостата). Нагрев остановлен.');
}
}
else if ( dev[temperature] > dev[setpoint] ) { // если температура датчика больше уставки выключить нагрев
dev[WBRelayState] = false;
dev[PumpRelayState] = true;
SendTelegramMsg(dev[name] + ' в Южном. Температура ' + name + ' ' + dev[temperature] + ' > ' + dev[setpoint] + ' (настройка термостата).');
log.info(dev[name] + ' в Южном. Температура ' + name + ' ' + dev[temperature] + ' > ' + dev[setpoint] + ' (настройка термостата).');
}
else { // на всякий случай во всех других ситуациях вырубаем ТЭН
if ( dev[WBRelayState] == true ) {
dev[WBRelayState] = false;
SendTelegramMsg('Последний else по температуре сработал. Надо проверить почему. Температура ' + name + ' ' + dev[temperature] + ' . Нагрев остановлен.');
log.info('Последний else по температуре сработал. Надо проверить почему. Температура ' + name + ' ' + dev[temperature] + ' . Нагрев остановлен.');
}
}
}
/* =================== конец работы ============================= */
else { // на всякий случай во всех других ситуациях вырубаем ТЭН, например WBRelayState undefined
if ( dev[WBRelayState] == true ) {
dev[WBRelayState] = false;
SendTelegramMsg('Последний else по давлению сработал. Надо проверить почему. Температура ' + name + ' ' + dev[temperature] + ' . Нагрев остановлен.');
log.info('Последний else по давлению сработал. Надо проверить почему. Температура ' + name + ' ' + dev[temperature] + ' . Нагрев остановлен.');
}
}
}
function TermostatController(name, onoff, scheduleMode, temperature, setpoint, hysteresis, pressure, MinPressure, MaxPressure, MainRelayState, WBRelayState, ABBRelayState, PumpRelayState) {
defineRule( {
whenChanged: [onoff, scheduleMode, setpoint, hysteresis, temperature, pressure],
then: function (newValue, devName, cellName) {
time = new Date(); //Текущее время
if (dev[onoff]) { // если термостат включён
log.info( 'Термостат включён');
if (dev[scheduleMode]) { // если термостат работает по расписанию
// тут ТЭН нельзя включать вручную
// то есть в виджете выключатель реле "wb-mio-gpio_70:4/K1"
// должен быть спрятан или виден, но заблокирован для нажатия
log.info('scheduleMode ON - нагрев по расписанию ночью');
if (time.getHours() < 7 || time.getHours() == 23) { // время меньше 7 часов ИЛИ равно 23 часам, то есть с 23 ночи до 7 утра
log.info('Началось ночное время нагрева по расписанию');
heatingRules(name, temperature, setpoint, hysteresis, pressure, MinPressure, MaxPressure, MainRelayState, WBRelayState, ABBRelayState, PumpRelayState);
}
else { // с 7 утра до 23 ночи
if ( dev[WBRelayState] == true ) {
dev[WBRelayState] = false;
SendTelegramMsg( 'Время ' + time.getHours() + '. heatingRules stopped в Южном. Ночь закончилась.');
log.info( 'Время ' + time.getHours() + '. heatingRules stopped в Южном. Ночь закончилась.');
}
}
}
else { // scheduleMode == false, то есть термостат работает вручную по кнопке
// тут ТЭН надо включать вручную
// то есть в виджете выключатель реле "wb-mio-gpio_70:4/K1"
// должен быть виден и активен для нажатия
log.info( 'scheduleMode OFF - ручной режим');
heatingRules(name, temperature, setpoint, hysteresis, pressure, MinPressure, MaxPressure, MainRelayState, WBRelayState, ABBRelayState, PumpRelayState);
}
}
else { // если термостат выключён, то нагрев не работает
if ( dev[WBRelayState] == true ) {
dev[WBRelayState] = false;
SendTelegramMsg( dev[name] + ' в Южном. Температура ' + name + ' ' + dev[temperature] + '. Нагрев остановлен. Термостат выключён.');
log.info( dev[name] + ' в Южном. Температура ' + name + ' ' + dev[temperature] + '. Нагрев остановлен. Термостат выключён.');
}
}
}
});
}
defineRule("cron minute timer", { // задание, которое выполняется каждую минуту
when: cron("00 * * * * *"),
then: function () {
TermostatController(BoilerName, BoilerONOFF, BoilerScheduleMode, BoilerTemperature, BoilerSetpoint, BoilerHysteresis, BoilerPressure, BoilerMinPressure, BoilerMaxPressure, BoilerMainRelayState, BoilerWBRelayState, BoilerABBRelayState, BoilerVirtualPumpRelayState);
TermostatController(KotelName, KotelONOFF, KotelScheduleMode, KotelTemperature, KotelSetpoint, KotelHysteresis, KotelPressure, KotelMinPressure, KotelMaxPressure, KotelMainRelayState, KotelWBRelayState, KotelABBRelayState, KotelPumpRelayState);
}
});
выдаёт вот такие ошибки
Oct 02 10:08:55 wirenboard-AM363YRR wb-mqtt-db[26775]: WARNING: [conventions] converting empty value to boolean "false"
Oct 02 10:08:55 wirenboard-AM363YRR wb-mqtt-db[26775]: WARNING: [conventions] converting empty value to boolean "false"
Oct 02 10:08:55 wirenboard-AM363YRR wb-mqtt-db[26775]: WARNING: [conventions] converting empty value to boolean "false"
Oct 02 10:08:55 wirenboard-AM363YRR wb-mqtt-db[26775]: WARNING: [conventions] converting empty value to boolean "false"
Oct 02 10:08:55 wirenboard-AM363YRR wb-mqtt-db[26775]: WARNING: [conventions] converting empty value to boolean "false"
Oct 02 10:08:55 wirenboard-AM363YRR wb-mqtt-db[26775]: WARNING: [conventions] converting empty value to boolean "false"
Oct 02 10:08:56 wirenboard-AM363YRR wb-rules[16332]: INFO: reloading file: /etc/wb-rules/heating.js
Oct 02 10:09:00 wirenboard-AM363YRR wb-rules[16332]: ERROR: [rule error] ECMAScript error: Error: invalid whenChanged spec
transformWhenChangedItem /usr/share/wb-rules-system/scripts/lib.js:209 preventsyield
map native strict preventsyield
anon /usr/share/wb-rules-system/scripts/lib.js:230 preventsyield
forEach native strict preventsyield
anon /usr/share/wb-rules-system/scripts/lib.js:243
TermostatController /etc/wb-rules/heating.js:480
anon /etc/wb-rules/heating.js:493 preventsyield
call native strict preventsyield
anon /usr/share/wb-rules-system/scripts/lib.js:240 preventsyield