Требуется помощь со скриптом

Добрый день.
Использую следующую конфигурацию: контроллер 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);

Добрый день

Скорее всего у вас при срабатывании таймера «pingTimer» происходит просмотр правил и соответственно происходит переключение. Попробуйте добавить условия:

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) {
      if (!timers.pingTimer.firing) {
          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) {
      if (!timers.pingTimer.firing) {
          log("streetlightsk2OnOff  newValue={}, devName={}, cellName={}", newValue, devName, cellName);
          var on = dev._schedules.streetlightsk2; 
          dev["wb-mr6cu_23/K2"] = on;
      }
    }
  });

})() 
1 лайк

Добрый день, обнаружился еще один нюанс: при сохранении правила с расписанием и при перезагрузке контроллера, включаются контакторы, даже если удалить все интервалы из правила, как это исправить?

Но очевидно что при сохрнении виртуальное устройство пересоздается и dev._schedules.streetlightsk1 возвращает истину.

Эта тема помечена решенной и закрыта. Рекомендую создать новую если есть новый вопрос.