Сценарии - новая версия API



  • @intrapro , спасибо за быстрый ответ. Жаль, конечно, что нет возможности использовать в условии, но так тоже пойдет. Буду иметь в виду



  • Подскажите как можно во время работы сценария блокировать повторный запуск сценария? Есть физическая кнопка которая запускает сценарий, нужно что бы во время работы сценария не было возможности повторного запуска сценария.



  • Пользователь @amgstone написал в Сценарии - новая версия API:

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

    Через доп актуатор. Это прекрасная замена глобальным переменным.

    На старте скрипта проверяете значение этого актуатора. Если 1 - сразу выходите из скрипта. Если 0 - присваиваете ему значение 1, и продолжаете дальше. Потом делаете все, что должен сделать скрипт, а последгним шагом возвращаете этому актуатору значение 0.



  • Не совсем то что надо, у меня ролокасеты, актуатор должен блокироватся на опредиленое время, чтобы ролета могла опустится или поднятся.



  • @amgstone
    Добавьте в конце перед возвращением актуатору значения 0 таймер на нужное время.



  • Команда this.exit() может применяться для прерывания сценария в любом его месте?

    столкнулся с тем, что

    if (device.isOff() )  this.exit() ;  // если выключено - выйти из сценария
    
    

    в основном теле сценария не работает - сценарий бодро шлепает по коду дальше.
    В то же время this.exit() помещенная , например, в функцию таймера прерывает сценарий.



  • @alesle Да, Вы правы, внутри функции start this.exit() не работает. Чтобы завершить функцию start, достаточно сделать return.

    this.exit() предназначен, чтобы завершить асинхронную деятельность сценария из функций - обработчиков (запущенных из start). Логика такая:

    • Метод start() вызывается, когда движок запускает сценарий (по триггерам, по расписанию, интерактивно) и тот становится активным.

    • Если внутри сценария просто последовательность действий, он отработает и сразу завершится (станет не активным). При следующем запуске он опять начнется со start(). Большая часть сценариев работает именно так и 99,9% времени находятся в неактивном состоянии. Напротив таких сценариев не бывает зеленых галочек в Рабочих сценариях.

    • Но если сценарий взводит таймеры и/или устанавливает слушателей событий, сценарий не завершается, а остается активным, следит за своими таймерами и устройствами "изнутри", запускает функции-обработчики как реакцию на отслеживаемые события. Пока сценарий активен (зеленая галочка), start по триггеру уже не работает.

    Чтобы завершить такой сценарий, из обработчика нужно выполнить команду this.exit().
    По этой команде все его таймеры и слушатели удаляются и сценарий станет не активным. При следующем запуске опять выполнится start()



  • @intrapro ,
    Огромное спасибо за разяснения!!!



  • @sergeyygr, думаю, что нужно делать так же как для счётчика газа. Писал об этом - тут
    Главное верно определить вес импульса чтобы получить значения сразу в м/с или км/ч.
    Хотя мне не до конца понятен принцип работы такого датчика. Он самостоятельно каждую секунду выдает сколько то импульсов, которые соответствуют скорости ветра в текущую единицу времени? Если так, то лучше "захватывать" эти показания сценарием, пересчитывать и присваивать датчику. Покажите что выдает отладчик на канале к которому подключен датчик?
    Но опять же если все так как я написал выше, то можно пересчитывать показания с помощью формулы или через вкладку "Обработка значений" канала.



  • @sergeyygr, так может быть просто сервером каждую секунду опрашивать канал 5 раз, вычисляя приращение счётчика канала. Далее сортировать значения, откидывать "боковые", усреднять оставшиеся - то есть будем получать "правильное" усреднённое значение в м/с каждые 5 секунд. Причем все это действие можно проводить раз в минуту/5минут.
    Если вам удобнее км/ч, то в формуле можно усреднённое значение в м/с умножать на 3.6

    А вообще нужно в iH либо написать скрипт подобный или сделать то же средствами канала плагина MegaD.
    Коллеги, @intrahouse, @intrapro, помогите с помощью iH разрешить вот такой скрипт:

    <?
    $last_cnt = 0;
    while(true)
    {
        $state = explode("/", file_get_contents("http://192.168.0.14/sec/?pt=7&cmd=get"));
        $cnt = $state[1];
        if ( $last_cnt != $cnt )
        $wind_speed = ($cnt - $last_cnt) * 0.0875 + 0.1;
        else
        $wind_speed = 0;
        echo $cnt." - $wind_speed m/s";
        $last_cnt = $cnt;
        if ( $cnt > 1000 )
        {
            $state = explode("/", file_get_contents("http://192.168.0.14/sec/?pt=7&cnt=0"));
            $last_cnt = 0;
        }
        sleep(1);
    }
    ?>
    


  • @sergeyygr Добрый день!
    Пока не совсем в теме по датчику. Но если воспроизвести скрипт от @Alex_Jet, то получится примерно так:

    1. Опрашиваем датчик с заданным интервалом из сценария (в каналах опрос не нужен, т е период =0)
    2. По магической формуле 🙂 считаем значение, используя значение счетчика
    3. Периодически сбрасываем счетчик
    const WindSensor = Device('MyWindSensor');
    
    script({
      last_cnt:0,  // Эту переменную нужно сохранять, поэтому ее выносим и далее исп как this.last_cnt
    
      boot() {
          return true; // Сценарий будет запускаться при старте сервера
      }, 
    
      start() {
          this.resetCount();
          // Взвести таймер - опрос раз в секунду, можно чаще (0.5 = 500 мсек)
          this.startTimer('T1', 1, 'onTimer');
      },
      
      resetCount() {
        // Передать запрос на сброс счетчика
        this.pluginCommand({unit:'megad1', command:{url:'/sec/?pt=7&cnt=0'}});
      }, 
    
      onTimer() {
        // Передать запрос на чтение, ответ придет в функцию  getResponse
        this.pluginCommand({unit:'megad1', command:{url:'/sec/?pt=7&cmd=get', onResponse:'raw'}}, 'getResponse');
        this.startTimer('T1', 1, 'onTimer'); // Следующий запрос 
      },
    
      getResponse(body) {
        // body = OFF/2
        this.log('getResponse body= '+body); // Для отладки
        if (!body) return;
    
        const arr = body.split('/');
        if (arr.length<2) {
          this.log('Ожидается значение счетчика после символа  "/"');
          return; // Ошибка, значение не получено
        }  
    
        let cnt = arr[1];
        if ( this.last_cnt != cnt ) {
          let wind_speed = (cnt - this.last_cnt) * 0.0875 + 0.1;
          this.last_cnt = cnt;
          this.assign(WindSensor, 'value', wind_speed);
        }
      
        if ( cnt > 1000 ) {
          this.resetCount();
          this.last_cnt = 0;
        }
      }
    });
    
    • Сценарий будет запускаться при старте сервера
    • будет работать постоянно, потому что таймер все время перевзводится
    • не имеет триггеров, то есть при необходимости его надо взводить/останавливать вручную (Запустить сценарий/ Остановить сценарий)

    Потестируйте, возможно есть косяки или не все учтено



  • @sergeyygr А у вас тип устройства какой? Счетчик? Нужен обычный аналоговый датчик.



  • @sergeyygr Хорошо, что заработало. А скорость то считает правильно? Датчик непростой ☹



  • Пользователь @sergeyygr написал в Сценарии - новая версия API:

    Пользователь @sergeyygr написал в Сценарии - новая версия API:

    Пользователь @intrapro написал в Сценарии - новая версия API:

    @sergeyygr Хорошо, что заработало. А скорость то считает правильно?

    Эталонного измерителя нет). Только формула в паспорте

    Считает - это сейчас КЛЮЧЕВОЙ результат!!!

    Если будет время, опишите задачу и решение в разделе Решения пользователей
    Будем пользоваться 😉



  • @intrapro, ИМХО нужно все же не каждую секунду опрашивать канал, а 1 раз в минуту/5 минут делать 5 измерений и усреднять их. Наверное, это можно сделать с помощью "Функции обработки" в канале?



  • @Alex_Jet, сценарий воспроизводит предложенный вами вариант скрипта php, там идет опрос каждую секунду (while(true) { file_get_contents ... sleep(1)} и периодически сброс счетчика на MegaD

    Если можно опрашивать реже и усреднять - не проблема, усреднятьможно и в сценарии. Без сценария непонятно как сбрасывать счетчик, поэтому в канале опроса нет



  • Коллеги, помогите решить задачу. Имеем - кнопку ( не фиксируемую) для включения/выключения света. Причем кнопка имеет 3 варианта нажатия (1 клик, 2 клика, удержание) и каждый вариант работает по своему. Так же имеем датчик движения. Хочется чтобы освещение работало по датчику движения (появилось движение - лампа загоралась, исчезло движение и через N-минут лампа потухла), но! чтобы его можно было принудительно и на неограниченное время включить с помощью вышеописанной кнопки! Пока идей нет. Подкиньте чтобы я сделал мультисценарий.



  • @Alex_Jet, мне тоже хотелось сделать что-то подобное, но так и не придумал как. В качестве идеи предлагаю следующую. Кнопка управляет бинарным актуатором, а в основном сценарии кроме отслеживания состояния motion и lamp добавить отслеживание этого актуатора. При его включении например останавливать таймер выключения лампы, при выключении наоборот. Как-то так



  • @int144, у меня тоже была такая идея. Хотя вот сейчас родилась мысль!!! В плагине megad можно сделать любой номер канала. Например, для порта 3 (висит кнопка) сделать каналы SW3_1, SW3_2, SW3_3. К ним привязать свои актуаторы (они будут виртуальными - на мнемосхеме не нужны). В расширениях пишем SW3_1=TOGGLE. А в сценарии, в котором участвует датчик движения, лампа и кнопка проверяем в каком состоянии находится SW3_1. Сейчас попробую сделать.



  • @Alex_Jet, не совсем понял. Канал SW3_1 в качестве актуатора? А еще можно попробовать, чтобы кнопка управляла свойством auto, но в примере сценария был оператор выключающий lamp, т.е. его тогда надо корректировать


Log in to reply