Добрый день.
Использую следующую конфигурацию: контроллер WB-7.4 c GSM модемом и модуль реле WB-MR6CU. Контроллер выполняет управление уличным освещением по расписанию, записанному в wb-rules. Также добавлен функционал перезагрузки модема в случае пропадания пинга с хостом в сети. Все отрабатывает хорошо. Но, если я включу вручную контактор, поведение короткого запрограммировано в скрипте, при проверке доступности хоста контактор возвращается в позицию, которая прописана в правиле, т.е. хост пингуется каждые 5 сек, вот, в течение 5 сек, если время дневное и я включу пускатель, он отключится. Как сделать так, чтобы сработка контакторов производилась только в то время, которое указано в скрипте и состояние контакторов не менялось при пинге.
Скрипты прилагаю:
street_lights_schedule.js
(function() {
Schedules.registerSchedule({ // замыкание к1
"name" : "streetlightsk1",
"autoUpdate" : "1m",
"intervals" : [
//декабрь
[ [12, 1, 15, 18], [12, 2, 8, 57] ],
[ [12, 2, 15, 17], [12, 3, 8, 59] ],
[ [12, 3, 15, 15], [12, 4, 9, 1] ],
[ [12, 4, 15, 14], [12, 5, 9, 3] ],
[ [12, 5, 15, 13], [12, 6, 9, 5] ],
[ [12, 6, 15, 12], [12, 7, 9, 7] ],
[ [12, 7, 15, 11], [12, 8, 9, 9] ],
[ [12, 8, 15, 10], [12, 9, 9, 11] ],
[ [12, 9, 15, 9], [12, 10, 9, 12] ],
[ [12, 10, 15, 9], [12, 11, 9, 14] ],
[ [12, 11, 15, 8], [12, 12, 9, 15] ],
[ [12, 12, 15, 7], [12, 13, 9, 17] ],
[ [12, 13, 15, 7], [12, 14, 9, 18] ],
[ [12, 14, 15, 6], [12, 15, 9, 19] ],
[ [12, 15, 15, 6], [12, 16, 9, 20] ],
[ [12, 16, 15, 6], [12, 17, 9, 21] ],
[ [12, 17, 15, 6], [12, 18, 9, 22] ],
[ [12, 18, 15, 6], [12, 19, 9, 23] ],
[ [12, 19, 15, 6], [12, 20, 9, 24] ],
[ [12, 20, 15, 7], [12, 21, 9, 24] ],
[ [12, 21, 15, 7], [12, 22, 9, 25] ],
[ [12, 22, 15, 8], [12, 23, 9, 25] ],
[ [12, 23, 15, 8], [12, 24, 9, 26] ],
[ [12, 24, 15, 9], [12, 25, 9, 26] ],
[ [12, 25, 15, 10], [12, 26, 9, 25] ],
[ [12, 26, 15, 11], [12, 27, 9, 25] ],
[ [12, 27, 15, 12], [12, 28, 9, 25] ],
[ [12, 28, 15, 13], [12, 29, 9, 25] ],
[ [12, 29, 15, 15], [12, 30, 9, 24] ],
[ [12, 30, 15, 16], [12, 31, 9, 23] ],
[ [12, 31, 15, 17], [1, 1, 9, 23] ],
]
});
Schedules.registerSchedule({ // замыкание к2
"name" : "streetlightsk2",
"autoUpdate" : "1m",
"intervals" : [
//декабрь
[ [12, 1, 15, 18], [12, 2, 0, 0] ],
[ [12, 2, 15, 17], [12, 3, 0, 0] ],
[ [12, 3, 15, 15], [12, 4, 0, 0] ],
[ [12, 4, 15, 14], [12, 5, 0, 0] ],
[ [12, 5, 15, 13], [12, 6, 0, 0] ],
[ [12, 6, 15, 12], [12, 7, 0, 0] ],
[ [12, 7, 15, 11], [12, 8, 0, 0] ],
[ [12, 8, 15, 10], [12, 9, 0, 0] ],
[ [12, 9, 15, 9], [12, 10, 0, 0] ],
[ [12, 10, 15, 9], [12, 11, 0, 0] ],
[ [12, 11, 15, 8], [12, 12, 0, 0] ],
[ [12, 12, 15, 7], [12, 13, 0, 0] ],
[ [12, 13, 15, 7], [12, 14, 0, 0] ],
[ [12, 14, 15, 6], [12, 15, 0, 0] ],
[ [12, 15, 15, 6], [12, 16, 0, 0] ],
[ [12, 16, 15, 6], [12, 17, 0, 0] ],
[ [12, 17, 15, 6], [12, 18, 0, 0] ],
[ [12, 18, 15, 6], [12, 19, 0, 0] ],
[ [12, 19, 15, 6], [12, 20, 0, 0] ],
[ [12, 20, 15, 7], [12, 21, 0, 0] ],
[ [12, 21, 15, 7], [12, 22, 0, 0] ],
[ [12, 22, 15, 8], [12, 23, 0, 0] ],
[ [12, 23, 15, 8], [12, 24, 0, 0] ],
[ [12, 24, 15, 9], [12, 25, 0, 0] ],
[ [12, 25, 15, 10], [12, 26, 0, 0] ],
[ [12, 26, 15, 11], [12, 27, 0, 0] ],
[ [12, 27, 15, 12], [12, 28, 0, 0] ],
[ [12, 28, 15, 13], [12, 29, 0, 0] ],
[ [12, 29, 15, 15], [12, 30, 0, 0] ],
[ [12, 30, 15, 16], [12, 31, 0, 0] ],
[ [12, 31, 15, 17], [1, 1, 0, 0] ],
]
});
Schedules.initSchedules();
// Управление пускателем К1
defineRule("streetlightsk1OnOff", {
when: function() {
return dev._schedules.streetlightsk1 || true;
},
then: function (newValue, devName, cellName) {
log("streetlightsk1OnOff newValue={}, devName={}, cellName={}", newValue, devName, cellName);
var on = dev._schedules.streetlightsk1;
dev["wb-mr6cu_23/K1"] = on;
}
});
// Управление пускателем К2
defineRule("streetlightsk2OnOff", {
when: function() {
return dev._schedules.streetlightsk2 || true;
},
then: function (newValue, devName, cellName) {
log("streetlightsk2OnOff newValue={}, devName={}, cellName={}", newValue, devName, cellName);
var on = dev._schedules.streetlightsk2;
dev["wb-mr6cu_23/K2"] = on;
}
});
})()
modem_watchdog.js
//ChangeME! Определим пингуемый адрес
var addrString = "ya.ru"
//ChangeME! Время между пингами, мс
var timeBeetveenPing=5000
//ChangeME! Максимальное количество пропущенных пингов
var pingFaultCountMAX = 3
//ChangeME! Время отключенного состояния, мс
var timeForDisable=300000
//Сделаем таймер, который будет работать каждые "timeBeetveenPing"
startTicker("pingTimer", timeBeetveenPing);
var pingFaultCount = 0;
defineRule("rule_pingTimer",{
when: function () { return timers.pingTimer.firing; },
then: function () {
//Отправим 1 пинг на адрес. Оценим результат
runShellCommand("/bin/ping -c1 "+addrString,
{
captureOutput: true, //Захватывать stdout
captureErrorOutput: true, //Захватывать stderr (если нужно)
exitCallback: function (exitCode, capturedOutput, capturedErrorOutput) //Функция, в которую попадает вывод
{
log("exitCode:",exitCode); //Результат выполнения
log("cmd output: " + capturedOutput); //строка полностью
//log("cmd Erroroutput: " + capturedErrorOutput);
if (exitCode) {pingFaultCount=pingFaultCount+1} //инкрементим счетчик
else {pingFaultCount=0}
if (pingFaultCount >= pingFaultCountMAX) {
log.info("Device", addrString, "not answered for", pingFaultCount, "ping. Modem reset executed");
timers.pingTimer.stop(); //отключисм таймер
runShellCommand("systemctl restart wb-gsm",
{
captureOutput: true,
//capturedErrorOutput: true,
exitCallback: function (exitCode, capturedOutput, capturedErrorOutput) {
if (exitCode) {
log.error("Modem restart failed");
//log.warning(WBT);
log.info(capturedErrorOutput);
} else {
log.info("Modem restarted");
log.info(capturedOutput);
}
}
});
pingFaultCount=0;
// setTimeout("alert('Modem watchdog is sleaping...')", 30000);
log.info("Start tiker");
setTimeout(function () {
startTicker("pingTimer", timeBeetveenPing); //запустим таймер
}, timeForDisable);
}
}
})
}
});
lib_schedules.js
global.__proto__.Schedules = {};
(function(Schedules) { // замыкание
function todayAt(now, month, day, hours, minutes) {
var date = new Date(now);
// i.e. "today, at HH:MM". All dates are in UTC!
date.setMonth(month-1);
date.setDate(day);
date.setHours(hours);
date.setMinutes(minutes);
return date;
}
function checkScheduleInterval(now, start_time, end_time) {
var start_date = todayAt(now, start_time[0], start_time[1], start_time[2], start_time[3]);
var end_date = todayAt(now, end_time[0], end_time[1], end_time[2], end_time[3]);
log("checkScheduleInterval {} {} {}".format(now, start_date, end_date));
if (end_date >= start_date) {
if ((now >= start_date) && (now < end_date)) {
return true;
}
} else {
// end date is less than start date,
// assuming they belong to a different days (e.g. today and tomorrow)
// option 1: what if it's now the day of "end" date?
// in this case the following is enough:
if (now < end_date) {
return true;
}
// well, that seems not to be the case. ok,
// option 2: it's the day of "start" date:
if (now >= start_date) {
return true;
}
}
return false;
}
function checkSchedule(schedule, now) {
if (now == undefined) {
now = new Date();
}
for (var i = 0; i < schedule.intervals.length; ++i) {
var item = schedule.intervals[i];
if (checkScheduleInterval(now, item[0], item[1])) {
log("found matching schedule interval at {}".format(item));
return true;
}
}
log("NOT found matching schedule interval at {}".format(item));
return false;
}
function updateSingleScheduleDevStatus(schedule) {
log("updateSingleScheduleDevStatus {}".format(schedule.name));
dev["_schedules"][schedule.name] = checkSchedule(schedule);
};
function addScheduleDevCronTasks(schedule) {
for (var i = 0; i < schedule.intervals.length; ++i) {
var interval = schedule.intervals[i];
for (var j = 0; j < 2; ++j) { // either start or end of the interval
var month = interval[j][0];
var date = interval[j][1];
var hours = interval[j][2];
var minutes = interval[j][3];
log("cron at " + "0 " + minutes + " " + hours + " " + date + " " + month + " *");
defineRule("_schedule_dev_{}_{}_{}".format(schedule.name, i, j), {
when: cron("0 " + minutes + " " + hours + " " + date + " " + month + " *"),
then: function () {
log("_schedule_dev_ {}_{}_{}".format(schedule.name, i, j));
updateSingleScheduleDevStatus(schedule);
}
});
}
}
}
function addScheduleAutoUpdCronTask(schedule) {
defineRule("_schedule_auto_upd_{}".format(schedule.name), {
when: cron("@every " + schedule.autoUpdate),
then: function() {
//dev._schedules[schedule.name] = dev._schedules[schedule.name];
}
});
}
var _schedules = {};
Schedules.registerSchedule = function(schedule) {
_schedules[schedule.name] = schedule;
};
Schedules.initSchedules = function() {
var params = {
title: "Schedule Status",
cells: {}
};
for (var schedule_name in _schedules) {
if (_schedules.hasOwnProperty(schedule_name)) {
var schedule = _schedules[schedule_name];
params.cells[schedule_name] = {type: "switch", value: false, readonly: true};
}
};
defineVirtualDevice("_schedules", params);
for (var schedule_name in _schedules) {
if (_schedules.hasOwnProperty(schedule_name)) {
var schedule = _schedules[schedule_name];
// setup cron tasks which updates the schedule dev status at schedule
// interval beginings and ends
addScheduleDevCronTasks(schedule);
/*
// if needed, setup periodic task to trigger rules which use this schedule
if (schedule.autoUpdate) {
addScheduleAutoUpdCronTask(schedule);
}
// set schedule dev status as soon as possible at startup
(function(schedule) {
setTimeout(function() {
updateSingleScheduleDevStatus(schedule);
}, 1);
})(schedule);
*/
};
};
};
})(Schedules);