Экземпляры мигалок на Timer


#8

timers[timer1Name]
Советую почитать про синтаксис JavaScript, например https://javascript.ru/tutorial/foundation/structure


#9

Flagman, всё можно. Поясню на примере safonic, как это реализуемо.

  1. После вызова startTimer (имя_таймера, длительность) у нас появляется экземпляр объекта timers.имя_таймера. У этого объекта после создания по умолчанию есть
    свойство
    firing’ => “true” или “false”
    и метод
    ‘stop’ => “function anon() {/* source code */}”

  2. Мы можем добавить этому таймеру свойство “name” в тот момент, когда мы запускаем таймер и точно знаем его имя.Но если мы напишем
    timers.timer1Name.name=timer1Name;
    то timer1Name будет восприниматься как имя таймера, а не как переменная.
    Поэтому стоит записать так, как предложил safonic:
    startTimer(timer1Name, 0.125*1000); timers[timer1Name].name=timer1Name;

Тут происходит уже подстановка переменной, свойство name добавляется к нужному таймеру.

Соответственно, имя таймера внутри функции обработчика можно получить так:
dev[relay] = 0; // отключаем "положительную" полуволну после срабатывания таймера log(timers[timer1Name].name);

Это возможно, поскольку объект таймера не разрушается после его срабатывания (до перезагрузки движка). Количество таймеров не увеличивается, поскольку мы взводим одни и те же таймеры, так что проблем с памятью быть не должно.


#10

safonik
Kilpio
Очень ценю вашу помощь!

В окончательном виде код получился такой:

var cycle = 3 * 1000;
heater_pwm ("heater_1", 0, 1, "wb-gpio/A1_OUT");
heater_pwm ("heater_2", 1, 1, "wb-gpio/A2_OUT");
heater_pwm ("heater_3", 2, 1, "wb-gpio/A3_OUT");

startTicker("period", cycle); // основной цикл переключений

function heater_pwm (name, delay_sec, on_sec, relay){
	var count = 0;											// контроль непрерывности работы
	var timer1Name = "timer1_" + name;						// задаем уникальное текстовое значение имени таймера внутри каждого экземпляра функции
	var timer2Name = "timer2_" + name;						// задаем уникальное текстовое значение имени таймера внутри каждого экземпляра функции
	defineRule("pwmCycle_" + name, {						// правило для запуска таймера на окончание "положительной" полуволны
		when: function () { return timers.period.firing; }, // начало отсчета основного цикла
		then: function () { 
			log(count++);
			startTimer(timer1Name, delay_sec * 1000);  		// запустили таймер на отключение "положительной" полуволны	
			timers[timer1Name].name = timer1Name;			// присвоили уникальное имя таймеру, чтбы его окончание отследить
		}
	});
	defineRule("pwmDelay_" + name, {
		when: function () { return timers[timer1Name].firing; }, // отследили срабатывание таймера на задержку начала "положительной" полуволны
		then: function () { 
			dev[relay] = 1;									// включили "положительную" полуволну
			startTimer(timer2Name, on_sec * 1000);  		// запустили таймер на отключение "положительной" полуволны	
			timers[timer2Name].name = timer2Name;			// присвоили уникальное имя таймеру, чтбы его окончание отследить
		}
	});	
		defineRule("pwmOn_" + name, {
		when: function () { return timers[timer2Name].firing; }, // отследили срабатывание таймера на окончание "положительной" полуволны
		then: function () {
			dev[relay] = 0;									// закончили "положительную" полуволну
		}
	});	
}

С такими параметрами можно использовать для “бегущих огней” :slight_smile:
Обнаружил, что если частоту переключения поставить слишком большую (период 0,5 сек), то рано или поздно контроллер зависает.

Может быть посоветуете диагностический инструмент, чтобы отследить какой параметр достигает предельного? Пока подозреваю температуру процессора, так как она в этом режиме переваливает за 62 градуса.


#11

Рад, что мы смогли со всем этим разобраться!

Завешивание контроллера движком правил – неприятная проблема. Первое, что можно подозревать – это утечки памяти. Второе – перегрев. Я попробую воспроизвести проблему с вашим правилом, а вы можете смотреть в консоли за загрузкой процессора и потреблением памяти с помощью top, также интересно, появляется ли какая-то информация в отладочной консоли (USB Debug Console).


#12

htop загрузку памяти и процессора указывает на приемлемые (в пределах 20-30%).

USB Debug Console это то что в WebUI внизу появляется при нажатии Rule debugging?

2018-12-19 12:43:31 19
2018-12-19 12:43:31starting timer: timer1_heater_1
2018-12-19 12:43:31 19
2018-12-19 12:43:31starting timer: timer1_heater_2
2018-12-19 12:43:31 19
2018-12-19 12:43:31starting timer: timer1_heater_3
2018-12-19 12:43:31starting timer: timer2_heater_1
2018-12-19 12:43:32starting timer: timer2_heater_2
2018-12-19 12:43:32starting timer: timer2_heater_3
2018-12-19 12:43:32 20
2018-12-19 12:43:32starting timer: timer1_heater_1
2018-12-19 12:43:32 20
2018-12-19 12:43:32starting timer: timer1_heater_2
2018-12-19 12:43:32 20
2018-12-19 12:43:32starting timer: timer1_heater_3
2018-12-19 12:43:32starting timer: timer2_heater_1
2018-12-19 12:43:32starting timer: timer2_heater_2
2018-12-19 12:43:32starting timer: timer2_heater_3

#13

Я имел в виду то, что вы получите в терминале, подключившись к отладочной консоли USB/UART.
При падении иногда ядро успевает что-то интересное написать туда.


#14

В этой консоли никакой информации нет.

Именно поэтому и хотел спросить про дополнительные инструменты, которые вы используете в работе в консоли, кроме htop.


#15
var cycle = 3 * 1000;
var count = 0;                                                            // контроль непрерывности работы
// основной цикл переключений
setInterval(function () {
log(count++);
heater_pwm("heater_1", 0, 1, "wb-gpio/A1_OUT");
heater_pwm("heater_2", 1, 1, "wb-gpio/A2_OUT");
heater_pwm("heater_3", 2, 1, "wb-gpio/A3_OUT");
}, cycle);
function heater_pwm(name, delay_sec, on_sec, relay) {
setTimeout(function () {
    log("Включение положительной полуволны для " + name);
    dev[relay] = 1;                                                   // включили "положительную" полуволну
    setTimeout(function () {
        log("Отключение положительной полуволны для " + name);
        dev[relay] = 0;                                               // закончили "положительную" полуволну
    }, on_sec * 1000);                                        // запустили таймер на отключение "положительной" полуволны
}, delay_sec * 1000);                                         // запустили таймер на включение "положительной" полуволны                                        
}

Попробуйте так, без использования таймеров - будет тормозить меньше?


#16

Такой вариант значительно изящнее.
Я его также использовал, только не догадался вызов функций осуществлять в периодическом цикле, а все-таки ловил его запуск.
Но все-равно правило “крутится” только определенное количество циклов от 50 до 100, а затем зависает.
К тому же, если во время работы программы поменять параметры, то одни таймеры накладываются на другие (оставшиеся от предыдущих параметров) и начинается хаос.
То есть не чистятся старые таймеры.


#17

Это странно. С какими значениями параметров зависает?

Да. Как при изменении параметров останавливать запланированные setInterval и setTimeout идей нет. Тут похоже поможет только рестарт движка правил при изменении значений в скриптах, или делать на таймерах.
Лучше не менять значения в коде скриптов, а вынести это в виртуальные устройства и менять у них параметры через UI/MQTT, и в правилах при изменении этих значений останавливать старые таймеры и запускать новые с новыми значениями.


#18

Да, не зная номер таймаута или интервала я не смог грохнуть прошлый экземпляр. Только ребут помогал. Решение “влоб”, к ни странно, помогло:
for (var i = 0;i<20;i++)
{
log("сбиваю интервал " + i);
clearInterval(i);
clearInterval(interval_id);
}


#19

Присоединяюсь к вопросу. Есть ли возможность видеть наполнение памяти, например, или еще что-то, что позволит хотя бы таймеры отследить - появляются новые или нет? А то переполнят и завесят через месяц wb…


#20

Таких инструментов, насколько мне известно, нет. Но помогает перезагрузка движка правил по крону )


#21

перегружаются только правила или целиком ребутится? Пожалуйста, если есть такое, скиньте пример, наверняка в документации есть, но я не помню такого…


#22

service wb-rules restart


#23

дистанционно, по внешней команде
может в скрипте можно “выполнить” из комм строки что-то?


#24

runShellCommand()


#25

Ясно, буду изучать. Видите, мне не очень знакомы эти технологии, только собираю знания. Если у меня не получится самому, обращусь за уточнениями. Спасибо!


#26

Какое свойство таймера можно проверить, чтобы понять запущен он уже или нет?
Чтобы избежать повторного его перезапуска при наступлении события еще раз.


#27

Flagman, добрый день!
К сожалению, у таймера только одно свойство, firing:

startTimer("test", 10000);
str = JSON.stringify(timers.test);
log(str);

->

2019-08-14 15:50:48 starting timer: test
2019-08-14 15:50:48 {"firing":false}

Я бы делал через таймерные функции с коллбеками, и состояние отслеживал бы флагами.