Плагин MegaD
-
Пользователь @intrapro написал в Плагин MegaD:
Ну и по поводу CNT для счетчика - просто интересно, как решается вопрос, когда контроллер при потере питания сбрасывает значение?
- Опрос каждые несколько секунд.
- Так как при переходе через 65535 идет get запрос, то данный факт фиксируем
- Если текущее значение cnt меньше предыдущего(т.е. счет пошел заново),
и был зафиксированн факт перехода
или (мало-ли get запрос потерялся) предыдущее значение было больше 65XXX ( в зависимости от счетчиков, насколько допустима погрешность)
то учитываем еще импульсы которые до 65535
Такой подход все же считаю более надежным чем считать каждый импульс, так как замечено, что импульсы могут теряться(перезагрузка интрахауса, перезагрука свичей и т.п.), да и сеть нагружается куда меньше.
-
@regabriel Наверно и сообщение о перезагрузке контроллера st=1 нужно слушать.
И на старте как-то синхронизировать. Напишите по результату, интересный опыт использования.
-
@regabriel, не получилось у меня получить значение CNT с помощью плагина MegaD, но гораздо быстрее и легче получилось с помощью плагина http):
-
@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 сек). Так же запуск его(их) при перезагрузке контроллера.
-
Доброго времени суток. Подскажите пожалуйста как значение передаваемое в канале MegaD перевести из 16-тиричного значения в десятичное?
-
Пользователь @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-ричные значения?
-
@intrapro
Подключаю PZEM-016
-
Пользователь @intrapro написал в Плагин MegaD:
Пользователь @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-ричные значения?
После запроса http://192.168.1.151/sec/?uart_tx=010400030002&mode=rs485
в отладчике вот что
Вероятно нужен сценарий
Скрипт:
<?php
while (true)
{
$res = file_get_contents("http://192.168.1.151/sec/?uart_tx=010400030002&mode=rs485");
usleep(100000);
$res = file_get_contents("http://192.168.1.151/sec/?uart_rx=1&mode=rs485");
if ( $res != 'CRC Error' )
{
$data = explode("|", $res);
$power = number_format(hexdec($data[3].$data[4]) / 10000, 4);
echo " Мощность: ".$power."кВт";
}
else
echo "Ошибка CRC";sleep(1);
}
Выдает
А как будет выглядеть сценарий по скрипту?
-
@sergeyygr Если нужно два запроса передавать с интервалом 100 мсек, лучше сделать сниппет прямо на устройстве:
module.exports = callback => { const http = require('http'); http.get('http://192.168.1.151/sec/?uart_tx=010400030002&mode=rs485'); setTimeout(nextReq, 100); // 100 ms function nextReq() { http.get('http://192.168.1.151/sec/?uart_rx=1&mode=rs485', res => { let rawData = ''; res.on('data', chunk => { rawData += chunk; }); res.on('end', () => { const data = rawData; if (data.includes('CRC Error')) { callback('CRC Error'); // Контроллер вернул ошибку CRC return; } // 01|03|02|08|a1 - в таком виде ожидается ответ const arr = data.split("|"); if (arr && arr.length > 4) { const val = parseInt(arr[3]+arr[4], 16); callback(null, val/10000); } else { callback('Не удалось извлечь значение из строки: '+ data); // Данные получены, но парсинг неудачен } }); }); } };
Период опроса (запуска сниппета) настраивается также на устройстве
-
Можно конечно и сценарий использовать
const power = Device("SensorA", "Power"); script({ start() { this.pluginCommand({unit:'megad1', command:{url:'/sec/?uart_tx=010400030002&mode=rs485'}}); // Следующий запрос через 100 мсек this.startTimer('T1', 0.1, 'getNext'); // Взвести таймер на случай, если ответа от контроллера нет this.startTimer('T2', 2, 'onTimeout'); }, getNext() { // Передать запрос на megad1, ответ без обработки придет в сценарий (onResponse:'raw') this.pluginCommand({unit:'megad1', command:{url:'/sec/?pt=7&cmd=get', onResponse:'raw'}}, 'getResponse'); }, getResponse(body) { this.log('getResponse body= '+body); if (body.includes('CRC Error')) { this.log('CRC Error'); // Контроллер вернул ошибку CRC this.exit(); } // 01|03|02|08|a1 - в таком виде ожидается ответ const arr = body.split("|"); if (arr && arr.length > 4) { const val = parseInt(arr[3]+arr[4], 16); this.assign(power,"value",val/10000 ); } else { this.log('Не удалось извлечь значение из строки: '+ body); // Данные получены, но парсинг неудачен } this.exit(); }, onTimeout() { this.log('Истек таймаут, ответ от megad не получен'); this.exit(); } });
-
Пользователь @intrapro написал в Плагин MegaD:
@sergeyygr Если нужно два запроса передавать с интервалом 100 мсек, лучше сделать сниппет прямо на устройстве:
Период опроса (запуска сниппета) настраивается также на устройстве
Спасибо, получилось!
Однако не получается считывать несколько показаний.
Счетчик выдает несколько параметров, а именно:
http://192.168.1.151/sec/?uart_tx=010400000001&mode=rs485
http://192.168.1.151/sec/?uart_rx=1&mode=rs485 /Напряжение
http://192.168.1.151/sec/?uart_tx=010400030002&mode=rs485
http://192.168.1.151/sec/?uart_rx=1&mode=rs485 /Мощность
http://192.168.1.151/sec/?uart_tx=010400050002&mode=rs485
http://192.168.1.151/sec/?uart_rx=1&mode=rs485 /Накопленная электроэнергия (кВт/час)
http://192.168.1.151/sec/?uart_tx=010400070001&mode=rs485
http://192.168.1.151/sec/?uart_rx=1&mode=rs485 /Частота сети
http://192.168.1.151/sec/?uart_tx=010400080001&mode=rs485
http://192.168.1.151/sec/?uart_rx=1&mode=rs485 /Коэффициент мощности
http://192.168.1.151/sec/?uart_tx=010400010002&mode=rs485
http://192.168.1.151/sec/?uart_rx=1&mode=rs485 /Сила тока
И в связи стем, что запрос на вывод показаний для всех переключений на параметр один и тот-же происходит конфликт, показания замирают. Как быть?
Использую инструкции отсюда: https://ab-log.ru/smart-house/ethernet/megad-rs485
-
Пользователь @sergeyygr написал в Плагин MegaD:
Спасибо, получилось!
Однако не получается считывать несколько показаний.
Счетчик выдает несколько параметров, а именно:
http://192.168.1.151/sec/?uart_tx=010400000001&mode=rs485
http://192.168.1.151/sec/?uart_rx=1&mode=rs485 /Напряжение
http://192.168.1.151/sec/?uart_tx=010400030002&mode=rs485
http://192.168.1.151/sec/?uart_rx=1&mode=rs485 /Мощность
http://192.168.1.151/sec/?uart_tx=010400050002&mode=rs485
http://192.168.1.151/sec/?uart_rx=1&mode=rs485 /Накопленная электроэнергия (кВт/час)
http://192.168.1.151/sec/?uart_tx=010400070001&mode=rs485
http://192.168.1.151/sec/?uart_rx=1&mode=rs485 /Частота сети
http://192.168.1.151/sec/?uart_tx=010400080001&mode=rs485
http://192.168.1.151/sec/?uart_rx=1&mode=rs485 /Коэффициент мощности
http://192.168.1.151/sec/?uart_tx=010400010002&mode=rs485
http://192.168.1.151/sec/?uart_rx=1&mode=rs485 /Сила тока
И в связи стем, что запрос на вывод показаний для всех переключений на параметр один и тот-же происходит конфликт, показания замирают. Как быть?
Использую инструкции отсюда: https://ab-log.ru/smart-house/ethernet/megad-rs485Можно сценарий сделать. Который будет запущен на старте сервера и будет последовательно опрашивать с каким-то интервалом.
Примерно так, но надо тестировать// Здесь все датчики - для примера два первых: const voltage = Device("SensorA", "Voltage"); const power = Device("SensorA", "Power"); script({ boot() { return true; // Сценарий будет запускаться на старте и всегда будет активным }, step:0, start() { this.step = 1; this.getTx(); }, getTx() { let url; switch (this.step) { case 1: // Напряжение - voltage url = '/sec/?uart_tx=010400000001&mode=rs485'; break; case 2: // Мощность - power url = '/sec/?uart_tx=010400030002&mode=rs485'; break; // ... } // Отправить запрос на контроллер this.pluginCommand({unit:'megad1', command:{url}}); // запрос Rx через 100 мсек this.startTimer('T1', 0.1, 'getRx'); // Запрос следующего параметра через 1 сек this.startTimer('T2', 1, 'nextParam'); }, getRx() { // Передать запрос на megad1, ответ придет в сценарий (onResponse:'raw') // БЫЛО С ОПЕЧАТКОЙ this.pluginCommand({unit:'megad1', command:{url:'/sec/uart_rx=1&mode=rs485', onResponse:'raw'}}, 'getResponse'); this.pluginCommand({unit:'megad1', command:{url:'/sec/?uart_rx=1&mode=rs485', onResponse:'raw'}}, 'getResponse'); }, getResponse(body) { // body // this.log('getResponse body= '+body+' step='+this.step); if (body.includes('CRC Error')) { this.log('CRC Error'); // Контроллер вернул ошибку CRC - здесь нужно что-то решать, пока просто выход this.exit(); } // 01|03|02|08|a1 - в таком виде ожидается ответ const arr = body.split("|"); if (arr && arr.length > 4) { this.assignValue(arr); } else { this.log('Не удалось извлечь значение из строки: '+ body); // Данные получены, но парсинг неудачен this.exit(); } }, assignValue(arr) { const val = parseInt(arr[3]+arr[4], 16); // Если парсинг разный - перенести в case switch (this.step) { case 1: this.assign(voltage,"value", val ); return; case 2: this.assign(power,"value", val/10000 ); return; // ... } }, nextParam() { this.step = this.step < 7 ? this.step+1 : 1; this.getTx(); } });
UPD: В сценарии была опечатка! Был пропущен знак вопроса. Сейчас он скорректирован и полностью рабочий. После поиска ошибки в этом топике также разбирается, как ввести сдвиг значения для соответствия реальному счетчику
-
Можно сценарий сделать. Который будет запущен на старте сервера и будет последовательно опрашивать с каким-то интервалом.
Примерно так, но надо тестироватьНе работает. В отладчике "37 Now is NOT active."
-
Пользователь @sergeyygr написал в Плагин MegaD:
Не работает. В отладчике "37 Now is NOT active."
Нужно посмотреть, нет ли ошибки в таблице Рабочие сценарии.
Если нет - смотреть отладчик при запуске.Предлагаю для простоты сценарий превратить из мультисценария в обычный:
-
запуск для устройств убрать
-
прописать ваши названия устройств вместо SensorA:
const voltage = Device("VOLT1", "Voltage");
const power = Device("POWER1", "Power"); -
сохранить, обновить таблицу - теперь это обычный сценарий
-
Запустить отладчик для сценария. Окно пока будет пустое
Далее нужно открыть вторую вкладку с разделом Рабочие сценарии и запустить этот сценарий (кнопка для вызова - полосатый квадратик. Кстати, здесь же есть пункт Остановить сценарий)
Теперь в отладчике (в первой вкладке) будет трассировка прохождения сценария (либо в таблице в столбце Ошибка будет сообщение об ошибке, если сценарий не смог запуститься)
-
-
Подскажите, я новенький на форуме, хочу запустить сценарий по датчику движения подключенному к меге, но сценарий не запускается без постоянного опроса меги.
-
Пользователь @intrapro написал в Плагин MegaD:
Пользователь @sergeyygr написал в Плагин MegaD:
Не работает. В отладчике "37 Now is NOT active."
Нужно посмотреть, нет ли ошибки в таблице Рабочие сценарии.
Если нет - смотреть отладчик при запуске.Предлагаю для простоты сценарий превратить из мультисценария в обычный:
-
запуск для устройств убрать
-
прописать ваши названия устройств вместо SensorA:
const voltage = Device("VOLT1", "Voltage");
const power = Device("POWER1", "Power"); -
сохранить, обновить таблицу - теперь это обычный сценарий
-
Запустить отладчик для сценария. Окно пока будет пустое
Далее нужно открыть вторую вкладку с разделом Рабочие сценарии и запустить этот сценарий (кнопка для вызова - полосатый квадратик. Кстати, здесь же есть пункт Остановить сценарий)
Теперь в отладчике (в первой вкладке) будет трассировка прохождения сценария (либо в таблице в столбце Ошибка будет сообщение об ошибке, если сценарий не смог запуститься)
Попробовал. Сценарий не запускается. Сообщений об ошибках нет. В отладчике нажимал пуск, кнопка пуска становилась неактивной (серой), после запуска сценария из меню "рабочие сценарии" кнопка запуска сценария опять становится активной (белой).
Вот весь сценарий:
/**- @name Сценарий считывания показаний датчика PZEM
- @desc Считывает показания датчиков PZEM
- @version 4
*/
// Здесь все датчики - для примера два первых:
const volt = Device("PZEM_Volt");
const Watt = Device("PZEM_Watt");
const Hz = Device("PZEM_Hz");
const cos = Device("PZEM_cos");
const kWh = Device("PZEM_kWh");
const Amper = Device("PZEM_Amper");
script({
boot() {
return true; // Сценарий будет запускаться на старте и всегда будет активным
},step:0,
start() {
this.step = 1;
this.getTx();
},getTx() {
let url;
switch (this.step) {
case 1: // Напряжение - volt
url = '/sec/?uart_tx=010400000001&mode=rs485';
break;
case 2: // Мощность - kW
url = '/sec/?uart_tx=010400030002&mode=rs485';
break;
case 3: // Частота - Hz
url = '/sec/?uart_tx=010400070001&mode=rs485';
break;
case 4: // Коэффициент - cof
url = '/sec/?uart_tx=010400080001&mode=rs485';
break;
case 5: // Мощность накопленная - kWh
url = '/sec/?uart_tx=010400050002&mode=rs485';
break;
case 6: // Сила тока - Amp
url = '/sec/?uart_tx=010400010002&mode=rs485';
break;
// ...
}// Отправить запрос на контроллер
this.pluginCommand({unit:'megad1', command:{url}});// запрос Rx через 100 мсек
this.startTimer('T1', 0.1, 'getRx');// Запрос следующего параметра через 1 сек
this.startTimer('T2', 1, 'nextParam');
},getRx() {
// Передать запрос на megad1, ответ придет в сценарий (onResponse:'raw')
this.pluginCommand({unit:'megad1', command:{url:'/sec/uart_rx=1&mode=rs485', onResponse:'raw'}}, 'getResponse');
},getResponse(body) {
//body
//this.log('getResponse body= '+body+' step='+this.step);if (body.includes('CRC Error')) { this.log('CRC Error'); // Контроллер вернул ошибку CRC - здесь нужно что-то решать, пока просто выход this.exit(); } // 01|03|02|08|a1 - в таком виде ожидается ответ const arr = body.split("|"); if (arr && arr.length > 4) { this.assignValue(arr); } else { this.log('Не удалось извлечь значение из строки: '+ body); // Данные получены, но парсинг неудачен this.exit(); }
},
assignValue(arr) {
const val = parseInt(arr[3]+arr[4], 16); // Если парсинг разный - перенести в case
switch (this.step) {
case 1:
this.assign(volt,"value", val/10 );
return;
case 2:
this.assign(Watt,"value", val/1000 );
return;
case 3:
this.assign(Hz,"value", val/10 );
return;
case 4:
this.assign(cos,"value", val/10 );
return;
case 5:
this.assign(kWh,"value", val/10 );
return;
case 6:
this.assign(Amper,"value", val/10 );
return;
// ...
}
},nextParam() {
this.step = this.step < 7 ? this.step+1 : 1;
this.getTx();
}
});
-
-
@sergeyygr, посмотрите, в Рабочих сценариях для этого сценария есть что-то в графах: Число запусков, Последний запуск, Последний останов