Плагин MegaD



  • Здравствуйте. Вопросы, вопросы по работе системы))) Мануальчика поописательней не хватает))

    Пытаюсь настроить нормально счетчики. Т.к. импульсы(пакеты) иногда теряются, да и реагировать на каждый импульс это немного бредово(можем получать по 10-40 импульсов в сек...)). Поэтому гораздо логичнее периодически считывать значение cnt и разницу записывать. И тут возникает вопросы:

    По идее на запрос
    /%pwd%/?pt=%adr%&cmd=get
    мега даст ответ
    OFF/61
    Можно было бы в функции обработки записать

    function (val, depo) {
    if (!depo.oldcnt) depo.oldcnt = 0;
    if (val.substr(0,2) =='OF'){
    cnt = val.substr(4));
    }else{
    cnt = val.substr(3));
    }
    //дальше обрабатываем cnt, был ли переход через 65535  и т.д.
         } 
    

    Но

    1. как понять какую ошибку выдает обработка скрипта? Где логи?
    2. Во вторых this.log(); сдесь не работает. Как понять в каком виде сейчас val ???

    Можно было бы пойти обходным путем, написать скрипт для опроса всех счетчиков в виде:

    let te = this.pluginCommand({unit:'megad3', command:'/sec/?pt=0&cmd=get'});
    //дальше уже обработаем ответ, но
            this.log('te = ' + te);
    

    но te в данном случае выдает = undefined , т.е. pluginCommand не выдает ответ от меги.

    Писать ради такого случая require('http').get('http://192.168.1.202/' ) и т.п. считаю крайне некрасивым вариантом.



  • @regabriel, лучше сделайте по такому принципу:

    У режима Mute есть одна важная особенность. Даже если он включен, контроллер отправит на сервер информацию при достижении счетчика порта максимального значения 65535.
    Это позволит серверу не пропустить факт обнуления счетчика. Но кроме того, эта особенность позволяет серверу в некоторых случаях отказаться от циклического опроса и получать информацию более оперативно.
    Например, программному обеспечению сервера необходимо знать о каждых 100 импульсах на входе.
    Сервер может задать начальное значение счетчика с помощью параметра "cnt": http://192.168.0.14/sec/?pt=0&cnt=65435.
    Когда счетчик порта достигнет 65535 (+100 относительно начального значения), контроллер отправит на сервер соответствующий GET-запрос, а сервер в ответ снова может установить нужное ему значение счетчика порта.
    

    В расширениях прописываем откликаться на событие pt=0 и при этом запускать сценарий. В сценарии первым делом "обнуляем" счетчик (http://192.168.0.14/sec/?pt=0&cnt=65435), ну и прибавляем значение у счетчика. При этом счетчиком может быть датчик аналоговый универсальный.

    В функции обработки лог только в виде return можно использовать (возвращать какое-то число, которое вы можете сами просчитать).



  • Пользователь @Alex_Jet написал в Плагин MegaD:

    лучше сделайте по такому принципу

    Моя задача сделать максимально точные показания. Поэтому такой подход считаю неправильным, т.к. между получением Get от меги и получением мегой команды " http://192.168.0.14/sec/?pt=0&cnt=65435" пройдет некоторая дельта времени, что в свою очередь дает вероятность пропуска импульсов. Mute понятно и так использую.

    1. Вопрос в другом, как получить CNT по запросу, а не обработкой входящих?

    Можно было бы привязать к каналу аналоговый датчик и в формуле расчета входного значения добавить "value = CNT", но так не работает. Увы(к счастью) у меги нет специальной команды для получения только параметра CNT.

    2 Вообще "формула расчета входного значения работает "? Такое ощущение, что нет.



  • @regabriel, get-запрос улетает за считанные МИЛЛИСЕКУНДЫ! О чем вы говорите? У вас за 25 мс только один счет пролетает! Поставьте очередь запросов в плагине 1 мс, сделайте скрипт и попробуйте выявить ошибку. Думаю, ее просто не будет! И да - у вас промышленное производство по дозированию компонентов для изготовления каких-то продуктов?

    Формула расчета конечно работает. Правда при вычислении разности или сложении нужно записывать в виде - "Number(value)-0.69"

    Чтобы устройству записывать значение в cnt, то нужно применять "Функцию обработки значения" - в ней парсить значение в ключе cnt и возвращать его в систему. Правда у меня это сделать сходу не получилось. Может @intrapro поможет?



  • @Alex_Jet

    У меня даже банальная функция не работает (Либо я дурак, либо лижи не едут)))

    function (val, depo) {
       	let result = 34;
      	return result; 
         } 
    

    канал - 0
    Тип порта - AI Analog Input(ADC,Dsen)
    Устройство - аналоговый универсальный датчик. (number_223_cnt_mega_electro)
    Период опроса 2 сек
    Строка запроса /%pwd%/?pt=%adr%&cmd=get

    В самой меге настроен порт IN
    Отладчик показывает:

    30.07 11:59:18.007 megad3: localhost => 192.168.1.213 HTTP GET /gos/?pt=0&cmd=get
    30.07 11:59:18.014 megad3: localhost <= 192.168.1.213  response: statusCode=200 contentType = text/html
    30.07 11:59:18.015 megad3:  body: OFF/5242
    30.07 11:59:18.016 IH: get [ { id: '0', value: '0' } ]
    set { number_223_cnt_mega_electro: { aval: 0, err: 0 } }
    

    В исходниках модуля попытался разобраться, но быстро понять хитросплетения не получилось, времени жалко на полный разбор))



  • @regabriel, если вы название канала указываете как 0 - 37, то они плагином парсятся в стандартном режиме - различаются состояния OFF=0 и ON=1.
    Если название канала задать типа "QWERTY", то стандартный парсинг не будет использоваться и по идее все что есть в body мы можем разбирать. Однако у меня сходу не получилось разобрать split-ом на Val и Cnt (OFF/1)...



  • @Alex_Jet
    Ставлю канал - 223 (тоже и если поставить qweds)
    строку запроса /%pwd%/?pt=0&cmd=get

    функцию "function (val, depo) {
    let result = 34;
    return result;
    } "

    Лижи все равно не едут. Результат не изменился вообще ни по логам ни где.

    В плагине(v 1.1.16) Нет цифр 36-37-38 обычным поиском по содержимому файлов это легко проверяется.
    Т.е. я очень сомневаюсь "название канала указываете как 0 - 37" в истинности этой версии



  • @regabriel, в исходниках как минимум в двух местах прописано преобразование "по умолчанию"...еще с cnt никто не работал в iH! Нужно поправить где-то здесь, но как именно, наверное, только @intrapro знает)))

    if (isNaN(str)) {
          if (str.substr(0, 2) == 'OF') {
            val = 0;
          } else if (str.substr(0, 2) == 'ON') {
            val = 1;
          } else {
            res = tryReadSome(str, adrx);
          }
        } else {
          if (channelId) adrx = channelId;
          val = getResultValue(Number(str), adrx);
    

    По мне так - преобразование не нужно делать при if(isNaN(channelid))..



  • Пользователь @regabriel написал в Плагин MegaD:

    1. Вопрос в другом, как получить CNT по запросу, а не обработкой входящих?

    Можно было бы привязать к каналу аналоговый датчик и в формуле расчета входного значения добавить "value = CNT", но так не работает. Увы(к счастью) у меги нет специальной команды для получения только параметра CNT.

    Добрый день!
    К сожалению, штатно в каналах CNT не обрабатывается (просто откидывается).

    Поскольку CNT не сохраняется при перезагрузке меги, с использованием CNT счетчики пока не делали (возможно, с сохранением ситуация изменилась?)

    Вы можете решить задачу через pluginCommand.
    Нужно только указать имя функции - обработчика, как второй аргумент

    Когда придет ответ от меги, будет вызвана эта функция - обработчик с body на входе

    this.pluginCommand({unit:'megad3', command:'/sec/?pt=0&cmd=get'}, 'onGetResponse');
    },
    
    onGetResponse(body) {
    //дальше уже обработаем ответ
            this.log('te = ' + body);
    }
    
    

    2 Вообще "формула расчета входного значения работает "? Такое ощущение, что нет.

    Она работает, есть даже 2 варианта:

    • "Использовать функцию обработки при получении данных от контроллера" - и дальше пишете функцию, которая работает на уровне плагина, можно собирать и преобразовывать до передачи ядру системы, и вернуть можно что угодно.

    • "Формула расчета входного значения" работает уже при получении данных от плагина на уровне ядра.

    Но Вы правы, в вашем случае это не работает, так как функцию делали для обработки числовых значений, и значения типа OFF/xx ON/yy просто преобразуются в 0/1.
    Функция, которая вызовет обработчик (getResultValue) даже не вызывается, как верно указал @Alex_Jet в процитированном коде
    Если есть желание адаптировать плагин, то место указано верно.
    Можно блок isNaN(str) закрыть, выполнять для всех каналов getResultValue. Но тогда нужно обрабатывать ON/OFF и другие строки (tryReadSome) в getResultValue либо на каждый канал вешать функцию

    function getResultValue(val, adrx) {
        if (isNaN(val)) return;  // Это нужно закрыть
    
        // Здесь парсить val
        let res = val;
        adrx = String(adrx);
        if (prefun[adrx]) {
          res = prefun[adrx].fun(val, prefun[adrx].depo);   // Это вызов пользовательского обработчика
        }
        return res;
      }
    


  • Пользователь @intrapro написал в Плагин MegaD:

    Если есть желание адаптировать плагин, то место указано верно.
    Можно блок isNaN(str) закрыть, выполнять для всех каналов getResultValue. Но тогда нужно обрабатывать ON/OFF и другие строки (tryReadSome) в getResultValue либо на каждый канал вешать функцию

    Помнится мне, что парсинг ON/OFF, temp/hum и прочее происходил "по умолчанию" только у каналов, у которых ID=0...37, либо X_1/X_2? А вот если канал имеет какое-нибудь отличное от числа значение, то этот парсинг не выполняется? Или это было с чем-то другим связано?
    Может сделать, что если ID-канала не подпадает под критерии

    1. 0....37
    2. X_
    3. XX_

    То в качестве результата будет возвращаться содержимое body, которое можно обработать с помощью функции обработки на уровне плагина?
    Или уже нет смысла переписывать код плагина поскольку в версии 5 все будет совсем по другому? Вообще, код плагина MegaD просто ужасен... по мне так легче все заново написать. Было бы время и знания по API iH....



  • Пользователь @Alex_Jet написал в Плагин MegaD:

    Пользователь @intrapro написал в Плагин MegaD:
    Помнится мне, что парсинг ON/OFF, temp/hum и прочее происходил "по умолчанию" только у каналов, у которых ID=0...37, либо X_1/X_2? А вот если канал имеет какое-нибудь отличное от числа значение, то этот парсинг не выполняется? Или это было с чем-то другим связано?

    Числовой номер канала нужен только для извлечения данных из строки all

    Или уже нет смысла переписывать код плагина поскольку в версии 5 все будет совсем по другому?

    Планируется, что все плагины и сценарии из v4 будут работать в v5

    Вообще, код плагина MegaD просто ужасен... по мне так легче все заново написать. Было бы время и знания по API iH....

    С прагматичной точки зрения, код плохой, если:

    • программа работает нестабильно: зависает или вылетает, игнорирует ошибки
    • требует постоянной поддержки, так как нестандартные ситуации не обрабатывает или реагирует неадекватно
    • хорошо работает на компьютере разработчика, но при установке в мало-мальски другое окружение нужны ритульные пляски и сакральные знания
    • при необходимости доработки нужно не забыть внести изменения в несколько мест (искать всюду 37 канал, например 🙂

    Про плагин MegaD ничего такого сказать нельзя. Он работает стабильно, надежно уже несколько лет.
    Вопросы от пользователей и доработки связаны с расширением функционала - (MCP, _A и _B,.. Плюс эпопеи с контроллером, но это другая история)
    Есть также плюс, который не очевиден для людей, любящих покодить - порог вхождения при использовании плагина MegaD очень низкий, простой функционал настраивается очень просто.

    Также можно рассмотреть вариант, предлагаемый во многих системах - нет плагина MegaD, вот вам http-клиент, дальше сами.
    Эта возможность в IH тоже есть, даже 2 варианта:

    • создавать сниппеты для каждого устройства и запускать их периодически;
    • использовать плагин http

    Для чтения CNT, кстати, это тоже решение (но не забыть при этом обрабатывать ошибки связи, если хочется сделать не поделку, которая работает при демонстрации, а реально работающий проект). И если на MegaD идет одновременно очень много независимых запросов, помнится, тоже были проблемы. Ну и по поводу CNT для счетчика - просто интересно, как решается вопрос, когда контроллер при потере питания сбрасывает значение?
    Если порт заявляется как счетчик, он IMHO должен хранить значение при отключении питания. Например в оборудовании KernelChip счетчик - это счетчик, ему можно доверять.

    С позиции чистого искусства - да, соглашусь, код выглядит несовременно и не очень консистентно, API v4 работы с плагинами не используется. Также выглядит не очень понятно работа с входящими сообщениями.

    Хорошо бы все переписать на ES6 и с применением API. И придумать понятный механизм. И чтобы любая новинка MegaD сразу была реализована 🙂 И чтобы этим занимался специалист по MegaD.
    В v5 мы планируем предложить сообществу активнее разрабатывать плагины. Со стороны системы будет обеспечено:

    • открытое API для создания плагинов;
    • возможность декларативного описания настройки каналов и свойств, в том числе древовидные структуры
    • простой механизм подключения плагина к системе и отладка;
    • продвижение плагинов сторонних разработчиков через портал

    И пусть каждый желающий напишет плагин своей мечты 🙂



  • Пользователь @intrapro написал в Плагин MegaD:

    С прагматичной точки зрения, код плохой, если:

    программа работает нестабильно: зависает или вылетает, игнорирует ошибки
    требует постоянной поддержки, так как нестандартные ситуации не обрабатывает или реагирует неадекватно
    хорошо работает на компьютере разработчика, но при установке в мало-мальски другое окружение нужны ритульные пляски и сакральные знания
    при необходимости доработки нужно не забыть внести изменения в несколько мест (искать всюду 37 канал, например

    Про плагин MegaD ничего такого сказать нельзя. Он работает стабильно, надежно уже несколько лет.
    Вопросы от пользователей и доработки связаны с расширением функционала - (MCP, _A и _B,.. Плюс эпопеи с контроллером, но это другая история)
    Есть также плюс, который не очевиден для людей, любящих покодить - порог вхождения при использовании плагина MegaD очень низкий, простой функционал настраивается очень просто.
    Также можно рассмотреть вариант, предлагаемый во многих системах - нет плагина MegaD, вот вам http-клиент, дальше сами.
    Эта возможность в IH тоже есть, даже 2 варианта:

    создавать сниппеты для каждого устройства и запускать их периодически;
    использовать плагин http

    Для чтения CNT, кстати, это тоже решение (но не забыть при этом обрабатывать ошибки связи, если хочется сделать не поделку, которая работает при демонстрации, а реально работающий проект). И если на MegaD идет одновременно очень много независимых запросов, помнится, тоже были проблемы. Ну и по поводу CNT для счетчика - просто интересно, как решается вопрос, когда контроллер при потере питания сбрасывает значение?
    Если порт заявляется как счетчик, он IMHO должен хранить значение при отключении питания. Например в оборудовании KernelChip счетчик - это счетчик, ему можно доверять.
    С позиции чистого искусства - да, соглашусь, код выглядит несовременно и не очень консистентно, API v4 работы с плагинами не используется. Также выглядит не очень понятно работа с входящими сообщениями.
    Хорошо бы все переписать на ES6 и с применением API. И придумать понятный механизм. И чтобы любая новинка MegaD сразу была реализована И чтобы этим занимался специалист по MegaD.
    В v5 мы планируем предложить сообществу активнее разрабатывать плагины. Со стороны системы будет обеспечено:

    открытое API для создания плагинов;
    возможность декларативного описания настройки каналов и свойств, в том числе древовидные структуры
    простой механизм подключения плагина к системе и отладка;
    продвижение плагинов сторонних разработчиков через портал

    И пусть каждый желающий напишет плагин своей мечты

    Моя реплика по поводу "код.. просто ужасен..." не в обиду сказана! И да, относится как раз скорее к "позиции чистого искусства" нежели чем к работе плагина! Просто пытался сам разобраться в некоторых вещах, попробовать самостоятельно доработать плагин до "плагин своей мечты", но плюнул на эту затею поскольку все это трудно переварить и связать друг с другом, особенно не имея комментарии в коде и достаточного количества времени.



  • Пользователь @intrapro написал в Плагин MegaD:

    Ну и по поводу CNT для счетчика - просто интересно, как решается вопрос, когда контроллер при потере питания сбрасывает значение?

    1. Опрос каждые несколько секунд.
    2. Так как при переходе через 65535 идет get запрос, то данный факт фиксируем
    3. Если текущее значение cnt меньше предыдущего(т.е. счет пошел заново),
      и был зафиксированн факт перехода
      или (мало-ли get запрос потерялся) предыдущее значение было больше 65XXX ( в зависимости от счетчиков, насколько допустима погрешность)
      то учитываем еще импульсы которые до 65535

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



  • @regabriel Наверно и сообщение о перезагрузке контроллера st=1 нужно слушать.
    И на старте как-то синхронизировать. Напишите по результату, интересный опыт использования.



  • @regabriel, не получилось у меня получить значение CNT с помощью плагина MegaD, но гораздо быстрее и легче получилось с помощью плагина http):
    http_get_cnt-key.png



  • @Alex_Jet
    У меня все получилось. Есть такой файлик в плагине CHANGELOG.md
    Так вот там описано как получать данные.

    #### 2. Добавлена функция-обработчик для pluginCommand
    
     При отправке команды плагину из сценария (любые запросы, которые принимает MegaD) ответ от контроллера можно получить и обработать прямо в сценарии 
    
       Например, было можно отправить команду из сценария:
      
       ```this.pluginCommand({unit:'megad1', command:{url:'/sec/?cmd=7:1', onResponse:[{id:"7",value:1}]});```
    
       Здесь отправляем запрос на включение выхода 7. 
    
       onResponse задает массив - какие каналы (и соответственно связанные с ними устройства) нужно установить после получения положительного ответа от MegaD 
      
      Теперь добавлена возможность отправлять запросы и анализировать ответ на уровне сценария
      Таким образом можем, например,  читать состояния портов внутри сценария
    
      ```this.pluginCommand({unit:'megad1', command:{url:'/sec/?pt=7&cmd=get', onResponse:'raw'}}, 'getResponse');```
      
      onResponse:'raw' означает, что нужно вернуть сценарию ответ контроллера напрямую 
      Второй параметр - имя функции обработчика
      
      Ответ придет, если контроллер доступен и вернул статус 200, иначе ответа не будет, функция-обработчик не сработает, а сценарий останется активным.
      Чтобы сценарий завершился, предусмотрен выход по таймауту.
    
        script({
          start() {
            // Передать запрос на megad1, ответ без обработки пусть придет в сценарий (onResponse:'raw')
            this.pluginCommand({unit:'megad1', command:{url:'/sec/?pt=7&cmd=get', onResponse:'raw'}}, 'getResponse');
            // Взвести таймер на случай, если ответа от контроллера нет
            this.startTimer('T1', 3, 'onTimeout');
          },
        
          getResponse(body) {
            // body 
            this.log('getResponse body= '+body);
            this.exit();
         },
        
          onTimeout() {
            this.log('Истек таймаут, ответ от megad1 не получен');
            this.exit();
          }
        });
    
    

    А @intrapro ошибся в строке
    this.pluginCommand({unit:'megad3', command:'/sec/?pt=0&cmd=get'}, 'onGetResponse');
    },
    нехватает onResponse:'raw'

    ну а дальше обработка полученных данных в скрипте, думаю все не сложно



  • @regabriel, действительно, ошибочка вышла 😢



  • @regabriel, это тоже решение, однако сценарий в таком случае будет всегда в работе? Или вы его чем-то будете запускать?



  • @Alex_Jet
    Делаю сценарий мульти и в зависимости от типов счетчиков, ставлю разное расписание(каждые 5-60 сек). Так же запуск его(их) при перезагрузке контроллера.



  • Пользователь @sergeyygr написал в Плагин MegaD:

    Доброго времени суток. Подскажите пожалуйста как значение передаваемое в канале MegaD перевести из 16-тиричного значения в десятичное?

    Добрый вечер, в javascript можно по разному

    parseInt(value,16)  // value = 'ff' =>  255
    

    Другой вариант: перед значением поставить '0x'

    parseInt(value)  // value = '0xff' =>  255
    // Первый вариант здесь тоже работает
    parseInt(value,16)  // value = '0xff' =>  255
    

    Но в плагине MegaD уже есть преобразование в число и формула может не сработать. В каком случае в канале приходят 16-ричные значения?


Авторизуйтесь, чтобы ответить