Помогите с написанием правил!

Подскажите, пожалуйста как все-таки быть с включением в один день и отключением на следующий? Так тоже не помогает что-то:

     then: function () {
var date = new Date();
var date_start = new Date(date);
var date_end = new Date(today.getTime() + (24 * 60 * 60 * 1000));

date_start.setHours(23);
date_start.setMinutes(00);

date_end.setHours(06);
date_end.setMinutes(30);

Добрый день, alleon!
А что такое у вас “today” – вы хотели сказать “date_start”?

var date_end = new Date(date_start.getTime() + (24 * 60 * 60 * 1000));

Так все работает:

Оно работает, если date_start и date_end происходит в один день. А мне нужно, чтобы ночной свет включался при движении с 23.00 (например) до 7.00 следующего дня. Вот так не работает. Ищу разные функции, но до сих пор не нашел примера скрипта в безграничном Интернете.
да, забыл. если дальше вот так идет:
if ((date > date_start) && (date < date_end))
Или может быть подскажете, что нужно дописать, чтобы правило работало, например 6 часов после date_start.

1 Like

А можно, пожалуйста, прислать полный текст правила – я немного не понимаю, о чем идет речь.

Да, конечно. Взят тут: http://wirenboard.ru/wiki/index.php/Движок_правил_wb-rules

var motion_timer_1_timeout_ms = 5 * 1000;
var motion_timer_1_id = null;
 
defineRule("motion_detector_1", {
  whenChanged: "wb-gpio/A1_IN",
  then: function (newValue, devName, cellName) {
    var date = new Date();

    // time point marking the beginning of the interval
    // i.e. "today, at HH:MM". All dates are in UTC!
    var date_start = new Date(date);
    date_start.setHours(9);
    date_start.setMinutes(30);

    // time point marking the end of the interval
    var date_end = new Date(date);
    date_end.setHours(17);
    date_end.setMinutes(10);
    
    // if time is between 09:30 and 17:10 UTC
    if ((date > date_start) && (date < date_end)) {
      if (newValue) {
          dev["wb-gpio"]["EXT1_R3A1"] = 1;
   
          if (motion_timer_1_id) {
            clearTimeout(motion_timer_1_id);
         }
   
          motion_timer_1_id = setTimeout(function () {
             dev["wb-gpio"]["EXT1_R3A1"] = 0;            
             motion_timer_1_id = null;
          }, motion_timer_1_timeout_ms);              
      }
     }
   }
});

При чем, если date_start < date_end, то все работает.

Это вы нам наш же скрипт прислали! А нам ваш нужен.

Я немного не понимаю: условие date_start < date_end и должно выполняться, если это границы интервала, внутри которого все должно работать.

Пока суть да дело, посмотрите на форме: мы обсуждали, как управлять нагрузкой с астрономическими вычислениями захода и восхода солнца, там есть примерчик кода. Может он подойдет вам с доработками под ваши нужды: Пример кода. Вся полезная информация начинается со слов “Смотрите, вот код переписанной библиотеки:”

Там только координаты на местности поменяйте под свои.

При отладке используйте функцию log(); – она вам сильно облегчит понимание того, как все происходит. Вывод ее можно смотреть, нажав на иконку с гечным ключом внизу справа на странице редактирования правила.

Мой почти такой же:
var motion_timer_1_timeout_ms = 15 * 1000;
var motion_timer_1_id = null;

    defineRule("night_light", {
      whenChanged: "hs24bits_114844_114844/state",
      then: function (newValue, devName, cellName) {
        var date = new Date();
     
        // time point marking the beginning of the interval
        // i.e. "today, at HH:MM". All dates are in UTC!
        var date_start = new Date(date);
        date_start.setHours(0);
        date_start.setMinutes(01);
     
        // time point marking the end of the interval
        var date_end = new Date(date);
        date_end.setHours(7);
        date_end.setMinutes(30);
     
        // if time is between 00:01 and 07:00 UTC
        if ((date > date_start) && (date < date_end)) {
        if (dev["hs24bits_114844_114844"]["state"] == 1) {
              dev["wb-gpio"]["EXT3_HS1"] = 1;
     
              if (motion_timer_1_id) {
                clearTimeout(motion_timer_1_id);
             }
     
              motion_timer_1_id = setTimeout(function () {
                 dev["wb-gpio"]["EXT3_HS1"] = 0;            
              }, motion_timer_1_timeout_ms);              
          }
         }
       }
    });

Вот так скрипт работает. Но если установить date_start.setHours(23), то работать ничего не будет. Насколько я понимаю, из-за того что:
if ((date > date_start) && (date < date_end))

Правильно я понял,
создаю файл sun.js с кодом переписанной библиотеки, сохраняю его в скриптах и далее создаю свой скрипт:

var motion_timer_1_timeout_ms = 15 * 1000;
var motion_timer_1_id = null;
 
defineRule("night_light", {
  whenChanged: "hs24bits_114844_114844/state",
  then: function (newValue, devName, cellName) {
    var lat = 55.75;
    var lng = 37.51; 
    var date = new Date();
    now = new Date(); 
	//now = new Date("2017-01-20 23:22:30.719+03:00"); 
	log ("Заданная дата\t", now);
	log ("Восход\t\t", sunrise);
	log ("Закат\t\t", sunset);

    var sunrise = SunCalc.getRise(date, lat, lng);
    var sunset  = SunCalc.getSet(date, lat, lng);

    // if time is between from sunset to sunrise
    if ((now > sunset) && (now < sunrise)) {
    if (dev["hs24bits_114844_114844"]["state"] == 1) {
          dev["wb-gpio"]["EXT3_HS1"] = 1;
 
          if (motion_timer_1_id) {
            clearTimeout(motion_timer_1_id);
         }
 
          motion_timer_1_id = setTimeout(function () {
             dev["wb-gpio"]["EXT3_HS1"] = 0;            
          }, motion_timer_1_timeout_ms);              
      }
     }
   }
});

поменяв координаты местности на свои

Да, совершенно верно. Библиотека в одном файле .js, а другие скрипты/правила могут вызывать ее функции.

Раньше у вас фигурировало такое выражение, которое переносит границу диапазона справа на следующие сутки,

а в скрипте, который вы прислали, время меняется, а дата нет:

Это похоже на источник проблемы.

Нет. Я пробовал по-разному… Если временной промежуток происходит в один день, например с 7.00 до 19.00, то все работает, а вот если промежуток затрагивает два дня, то тут проблема.

Вот перед этим

выведите? пожалуйста, все значения в лог:

log(date_start);
log(date_end);```

и пришлите, что у вас получается. Разберемся, не переживайте.

Установил date_start.setHours(20);

2017-06-16 20:52:392017-06-16 20:52:37.643+03:00
2017-06-16 20:52:392017-06-16 20:01:37.643+03:00
2017-06-16 20:52:392017-06-16 06:00:37.643+03:00
2017-06-16 20:52:502017-06-16 20:52:48.422+03:00
2017-06-16 20:52:502017-06-16 20:01:48.422+03:00
2017-06-16 20:52:502017-06-16 06:00:48.422+03:00
2017-06-16 20:52:582017-06-16 20:52:56.490+03:00
2017-06-16 20:52:582017-06-16 20:01:56.490+03:00
2017-06-16 20:52:582017-06-16 06:00:56.490+03:00
2017-06-16 20:53:082017-06-16 20:53:06.765+03:00
2017-06-16 20:53:082017-06-16 20:01:06.765+03:00
2017-06-16 20:53:082017-06-16 06:00:06.765+03:00

И, кстати, по этой же причине не работает:

if ((date > sunset) && (date < sunrise))

Потому что время заката всегда больше времени восхода

Вот моё правило выключает воду вечером, включает следующим утром. Может быть вам поможет.

defineRule(“test3”, {
when: cron("*/59 * * * * "),
then: function () {
if(dev[“rule_switch”][“Rules status”] == 1){ //глобальное выключение правила
var date1 = new Date();
var date_start_11 = new Date(date1);
date_start_11.setHours(06);
date_start_11.setMinutes(30);
var date_end_11 = new Date(date1);
date_end_11.setHours(23);
date_end_11.setMinutes(59);
//log(“текущее время”,date1,v);

  		if((date_start_11 <= date1) &&( date1 <= date_end_11))  { // Время проверяется раз в 59 сек. и чтоб постоянно не срабатывало правило сравнения времени - введена переменная. - v
			if(v == 0){
				dev.valve_state["Valve_"] = 1; //для страницы Devices
				valve = 1;
  				log("Время включения крана",date1,v);
   		 		v = 1;
			}
		} else{
				if(v == 1){
					dev.valve_state["Valve_"] = 0;
					valve = 0;
					log("Время выключения крана",date1,v);
					v = 0;
				}
			}
		      
	}
}

});

Кажется разобрался, осталось дождаться заката

var motion_timer_1_timeout_ms = 25 * 1000;
var motion_timer_1_id = null;
 
defineRule("night_light", {
  whenChanged: "hs24bits_114844_6/state",
  then: function (newValue, devName, cellName) {
  
//координаты
    var lat = 55.55;
  	var lng = 37.23; 
  	
    var date = new Date();
  	now = new Date();

    var sunrise = SunCalc.getRise(date, lat, lng);
    var sunset  = SunCalc.getSet(date, lat, lng);
  
//в промежуток между рассветом и закатом  
    if ((now > sunrise) && (now < sunset)) {
    if (dev["hs24bits_114844_114844"]["state"] == 1) {
          dev["wb-gpio"]["EXT3_HS1"] = 0; //не включать свет 
    }
  }

//в остальное время при движении
    if (dev["hs24bits_114844_6"]["state"] == 1) {
          dev["wb-gpio"]["EXT3_HS1"] = 1; //включать свет
      
 
          if (motion_timer_1_id) {
            clearTimeout(motion_timer_1_id);
         }
 
          motion_timer_1_id = setTimeout(function () {
             dev["wb-gpio"]["EXT3_HS1"] = 0;            
          }, motion_timer_1_timeout_ms);              
      }
     }
});

Всем Спасибо за помощь!
upd. Ой, не работает после перезагрузки… всегда горит.

Добавил else, все заработало. Теперь другая грабля. Почему-то время восхода/заката не совпадает с реальным (где-то на час). Установил координаты Калининграда, чтобы “совпадало”. :wink:

Отлично, попробуйте apt-get update && apt-get install tzdata, а затем вернуться на MSK — у вас устаревшая информация о часовых поясах, скорее всего.

Попробовал, все равно закат на 1 час раньше:

Current default time zone: ‘Europe/Moscow’
Local time is now: Tue Jun 20 20:45:23 MSK 2017.
Universal Time is now: Tue Jun 20 17:45:23 UTC 2017.
Run ‘dpkg-reconfigure tzdata’ if you wish to change it.

2017-06-20 20:47:20Восход 2017-06-20 04:51:56.220+03:00
2017-06-20 20:47:20Закат 2017-06-20 20:15:44.566+03:00

Да, ошибка воспроизводится, но причина не ясна. В общем, пока Калининград – лучшее решение :slight_smile: или просто час добавлять к полученным результатам.

alleon, в теме про астрономические вычисления я запостил новый скрипт (от берется отсюда: SunCalc с небольшой модификацией, и новый пример его использования. Теперь все вычисляется верно. Простите, что ввел вас в заблуждение.

2 Likes