NEWS
Скрипт для счетчика Меркурий 230
-
Адаптер:
https://ru.aliexpress.com/item/1-pcs-US … 0.0.fzI5Kj
createState('Uv1'); createState('Uv2'); createState('Uv3'); createState('Ia1'); createState('Ia2'); createState('Ia3'); createState('Pw_total'); createState('Pw1'); createState('Pw2'); createState('Pw3'); createState('E_total'); createState('E_T1'); createState('E_T2'); var device_port = '/dev/ttyUSB0'; var buflen = 64; var sleep_time = 200; // Sleep time between request and wait for response. var SerialPort = require('serialport'); var ByteLength = SerialPort.parsers.ByteLength; var ret = Array(); var cmd_init = new Buffer ([0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x77,0x81]); var cmd_total = new Buffer ([0x00,0x05,0x00,0x00,0x10,0x25]); //общее потребление var cmd_T1 = new Buffer ([0x00,0x05,0x00,0x01,0xD1,0xE5]); //потребление T1 var cmd_T2 = new Buffer ([0x00,0x05,0x00,0x02,0x91,0xE4]); //потребление T2 var cmd_total_day = new Buffer ([0x00,0x05,0x40,0x00,0x21,0xE5]); //общее потребление за текщие сутки var cmd_T1_day = new Buffer ([0x00,0x05,0x40,0x01,0xE0,0x25]); //потребление T1 за текщие сутки var cmd_T2_day = new Buffer ([0x00,0x05,0x40,0x02,0xA0,0x24]); //потребление T2 за текщие сутки var cmd_pw = new Buffer ([0x00,0x08,0x16,0x00,0x8F,0x86]); //мощность по фазам var cmd_uv = new Buffer ([0x00,0x08,0x16,0x11,0x4F,0x8A]); //Напряжение по фазам var cmd_ia = new Buffer ([0x00,0x08,0x16,0x21,0x4F,0x9E]); //Сила тока по фазам var cmd_cos = new Buffer ([0x00,0x08,0x16,0x30,0x8F,0x92]); //Cosf по фазам function crc16MODBUS(string){ var CrcTable = [ 0X0000, 0XC0C1, 0XC181, 0X0140, 0XC301, 0X03C0, 0X0280, 0XC241, 0XC601, 0X06C0, 0X0780, 0XC741, 0X0500, 0XC5C1, 0XC481, 0X0440, 0XCC01, 0X0CC0, 0X0D80, 0XCD41, 0X0F00, 0XCFC1, 0XCE81, 0X0E40, 0X0A00, 0XCAC1, 0XCB81, 0X0B40, 0XC901, 0X09C0, 0X0880, 0XC841, 0XD801, 0X18C0, 0X1980, 0XD941, 0X1B00, 0XDBC1, 0XDA81, 0X1A40, 0X1E00, 0XDEC1, 0XDF81, 0X1F40, 0XDD01, 0X1DC0, 0X1C80, 0XDC41, 0X1400, 0XD4C1, 0XD581, 0X1540, 0XD701, 0X17C0, 0X1680, 0XD641, 0XD201, 0X12C0, 0X1380, 0XD341, 0X1100, 0XD1C1, 0XD081, 0X1040, 0XF001, 0X30C0, 0X3180, 0XF141, 0X3300, 0XF3C1, 0XF281, 0X3240, 0X3600, 0XF6C1, 0XF781, 0X3740, 0XF501, 0X35C0, 0X3480, 0XF441, 0X3C00, 0XFCC1, 0XFD81, 0X3D40, 0XFF01, 0X3FC0, 0X3E80, 0XFE41, 0XFA01, 0X3AC0, 0X3B80, 0XFB41, 0X3900, 0XF9C1, 0XF881, 0X3840, 0X2800, 0XE8C1, 0XE981, 0X2940, 0XEB01, 0X2BC0, 0X2A80, 0XEA41, 0XEE01, 0X2EC0, 0X2F80, 0XEF41, 0X2D00, 0XEDC1, 0XEC81, 0X2C40, 0XE401, 0X24C0, 0X2580, 0XE541, 0X2700, 0XE7C1, 0XE681, 0X2640, 0X2200, 0XE2C1, 0XE381, 0X2340, 0XE101, 0X21C0, 0X2080, 0XE041, 0XA001, 0X60C0, 0X6180, 0XA141, 0X6300, 0XA3C1, 0XA281, 0X6240, 0X6600, 0XA6C1, 0XA781, 0X6740, 0XA501, 0X65C0, 0X6480, 0XA441, 0X6C00, 0XACC1, 0XAD81, 0X6D40, 0XAF01, 0X6FC0, 0X6E80, 0XAE41, 0XAA01, 0X6AC0, 0X6B80, 0XAB41, 0X6900, 0XA9C1, 0XA881, 0X6840, 0X7800, 0XB8C1, 0XB981, 0X7940, 0XBB01, 0X7BC0, 0X7A80, 0XBA41, 0XBE01, 0X7EC0, 0X7F80, 0XBF41, 0X7D00, 0XBDC1, 0XBC81, 0X7C40, 0XB401, 0X74C0, 0X7580, 0XB541, 0X7700, 0XB7C1, 0XB681, 0X7640, 0X7200, 0XB2C1, 0XB381, 0X7340, 0XB101, 0X71C0, 0X7080, 0XB041, 0X5000, 0X90C1, 0X9181, 0X5140, 0X9301, 0X53C0, 0X5280, 0X9241, 0X9601, 0X56C0, 0X5780, 0X9741, 0X5500, 0X95C1, 0X9481, 0X5440, 0X9C01, 0X5CC0, 0X5D80, 0X9D41, 0X5F00, 0X9FC1, 0X9E81, 0X5E40, 0X5A00, 0X9AC1, 0X9B81, 0X5B40, 0X9901, 0X59C0, 0X5880, 0X9841, 0X8801, 0X48C0, 0X4980, 0X8941, 0X4B00, 0X8BC1, 0X8A81, 0X4A40, 0X4E00, 0X8EC1, 0X8F81, 0X4F40, 0X8D01, 0X4DC0, 0X4C80, 0X8C41, 0X4400, 0X84C1, 0X8581, 0X4540, 0X8701, 0X47C0, 0X4680, 0X8641, 0X8201, 0X42C0, 0X4380, 0X8341, 0X4100, 0X81C1, 0X8081, 0X4040 ]; var crc = 0xFFFF; for(var i = 0, l = string.length; i < l; i++){ crc = ((crc >> 8) ^ CrcTable[(crc ^ string[i]) & 0xFF]); } return crc.toString(16); } function toHexString(byteArray) { return Array.from(byteArray, function(byte) { return ('0' + (byte & 0xFF).toString(16)).slice(-2); }).join(''); } function merc_gd(cmd,buflen,factor,total,callback) { var port = new SerialPort(device_port,{ baudrate: 9600, dataBits: 8, parity: 'none' }); const parser = port.pipe(new ByteLength({length: buflen})); port.pipe(parser); port.write(cmd); //sleep(sleep_time); setTimeout(readport, sleep_time); function readport (){ parser.on ('data', function (result_double) { var result = result_double.slice(0,buflen/2); var resp_crc=result.slice(0,buflen/2-2); var crc_get=toHexString(result.slice(buflen/2-1,buflen/2)) + toHexString(result.slice(buflen/2-2,buflen/2-1)); var crc_calc=crc16MODBUS(resp_crc).toString(16); //log ('CRC='+parseInt(crc_get,16)); if (parseInt(crc_get,16) != parseInt(crc_calc,16) ){ log ('CRC is ERROR!'); log ('resultdouble='+JSON.stringify(result_double)); log ('result='+JSON.stringify(result)); log('CRCget='+crc_get); log('CRCcalc='+crc_calc); } if (cmd == cmd_init) { //log ('cmd_init='+JSON.stringify(cmd)); } if (cmd != cmd_init) { var b1 = toHexString(result.slice(1,2)); var b2 = toHexString(result.slice(2,3)); var b3 = toHexString(result.slice(3,4)); var b4 = toHexString(result.slice(4,5)); var b5 = toHexString(result.slice(5,6)); var b6 = toHexString(result.slice(6,7)); var b7 = toHexString(result.slice(7,8)); var b8 = toHexString(result.slice(8,9)); var b9 = toHexString(result.slice(9,10)); if (total === 0) { var resp1 = b1.slice(1,2)+b3.slice(0,2)+b2.slice(0,2); var resp2 = b4.slice(1,2)+b6.slice(0,2)+b5.slice(0,2); var resp3 = b7.slice(1,2)+b9.slice(0,2)+b8.slice(0,2); ret[0]= parseInt(resp1, 16)*factor; ret[1]= parseInt(resp2, 16)*factor; ret[2]= parseInt(resp3, 16)*factor; if (cmd == cmd_pw || cmd == cmd_cos){ var b10 = toHexString(result.slice(10,11)); var b11 = toHexString(result.slice(11,12)); var b12 = toHexString(result.slice(12,13)); var resp4 = b10.slice(1,2)+b12.slice(0,2)+b11.slice(0,2); ret[3]= parseInt(resp4, 16)*factor; } } //if total === 0 if (total == 1) { var respt = b2.slice(0,2)+b1.slice(0,2)+b4.slice(0,2)+b3.slice(0,2); ret[0]= parseInt(respt, 16)*factor; } //if total===1 } // if cmd != cmd_init if (callback && typeof(callback) === "function") { callback(ret); } }); //parser.on port.pause(); port.close(); return (ret); } //end function portread } //end function merc_gd schedule("* * * * *", function () { merc_gd(cmd_init,8,0,0, function(data) { // console.log('data='+data[0]); setTimeout(merc_gd(cmd_uv,24,0.01,0, function(data) { setState('Uv1',Number(data[0]).toFixed(2)); setState('Uv2',Number(data[1]).toFixed(2)); setState('Uv3',Number(data[2]).toFixed(2)); setTimeout(merc_gd(cmd_ia,24,0.001,0, function(data) { setState('Ia1',Number(data[0]).toFixed(2)); setState('Ia2',Number(data[1]).toFixed(2)); setState('Ia3',Number(data[2]).toFixed(2)); setTimeout(merc_gd(cmd_pw,30,0.01,0, function(data) { setState('Pw_total',Number(data[0]).toFixed(2)); setState('Pw1',Number(data[1]).toFixed(2)); setState('Pw2',Number(data[2]).toFixed(2)); setState('Pw3',Number(data[3]).toFixed(2)); setTimeout(merc_gd(cmd_total,38,0.001,1, function(data) { setState('E_total',Number(data[0]).toFixed(2)); setTimeout(merc_gd(cmd_T1,38,0.001,1, function(data) { setState('E_T1',Number(data[0]).toFixed(2)); setTimeout(merc_gd(cmd_T2,38,0.001,1, function(data) { setState('E_T2',Number(data[0]).toFixed(2)); }), sleep_time); }), sleep_time); }),sleep_time); }), sleep_time); }), sleep_time); }), sleep_time); }); });
-
а через TCP можно использовать этот скрипт? Как он тогда будет выглядит?
-
а через TCP можно использовать этот скрипт? Как он тогда будет выглядит? `
Что значит через TCP? У счётчика подключение CAN/RS485.
Ещё у меня есть кастомная прошивка espeasy для esp8266 с поддержкой Меркурий 230, можно через wifi по mqtt забирать данные.
-
Адаптер:
https://ru.aliexpress.com/item/1-pcs-US … 0.0.fzI5Kj `
Спасибо за скрипт!Взлетел, но не сразу. Хочу добавить пару моментов.
В настройках адаптера javascript, добавить модуль serialport.
Вылезла ошибка с предложением> Error in callback: TypeError: "baudrate" is an unknown option, did you mean "baudRate"?
Мне потребовалось изменить в скрипте функцию merc_gdfunction merc_gd(cmd,buflen,factor,total,callback) { var port = new SerialPort(device_port,{ baudRate: 9600, dataBits: 8, parity: 'none' });
baudrate на baudRate
-
а через TCP можно использовать этот скрипт? Как он тогда будет выглядит? `
Что значит через TCP? У счётчика подключение CAN/RS485.
Ещё у меня есть кастомная прошивка espeasy для esp8266 с поддержкой Меркурий 230, можно через wifi по mqtt забирать данные. `
Доброго времени !
Поделитесь прошивкой для esp8266
-
Инструкция по компиляции прошивки espeasy с плагином Меркурий 230.
1. Ставим atom по инструкции: https://letscontrolit.com/wiki/index.ph … Platformio
2. Скачиваем последний релиз espeasy https://github.com/letscontrolit/ESPEasy/releases
3. Разархивируем архив релиза, в папку src записываем файл https://github.com/Andrey2509/ESPEasy/b ... ury230.ino
4. В файле platformio.ini раскомментировать тип прошивки, например: env_default = normal_ESP8266_4096
5. В файле define_plugin_sets.h в секции #ifdef PLUGIN_SET_STABLE (соответствует прошивке normal) добавляем строку:
#define USES_P220 //Mercury 230
6. Компилируем.
Так как данных много, а в espeasy жёсткое ограничение по количеству значений для каждого плагина, в плагине меркурий 230 вшита отправка данных только по mqtt. При этом Надо обязательно создать подключение в настройках "Controllers" (OpenHAB MQTT).
На стороне иоброкера парсим mqtt строку в js:
on({id: "mqtt.0.Mercury230.Merc_data_json", change: 'any'}, function (obj) { var myjson=JSON.parse(obj.state.val); setState("javascript.0.Uv1",myjson['Uv1']); setState("javascript.0.Uv2",myjson['Uv2']); setState("javascript.0.Uv3",myjson['Uv3']); setState("javascript.0.Ia1",myjson['Ia1']); setState("javascript.0.Ia2",myjson['Ia2']); setState("javascript.0.Ia3",myjson['Ia3']); setState("javascript.0.Pw_total",myjson['Pw0']); setState("javascript.0.Pw1",myjson['Pw1']); setState("javascript.0.Pw2",myjson['Pw2']); setState("javascript.0.Pw3",myjson['Pw3']); setState("javascript.0.E_T1",myjson['T1']); setState("javascript.0.E_T2",myjson['T2']); }); on({id: "mqtt.0.Mercury230.Merc_stat_json", change: 'any'} || {id: "javascript.0.Energy_tarif", change: 'any'}, function (obj) { var myjson=JSON.parse(getState("mqtt.0.Mercury230.Merc_stat_json").val); var tarrif=getState("javascript.0.Energy_tarif").val; if (JSON.stringify(myjson).length>24) { var table_mer230 = [{"month":1,"T1":0,"T2":0,"T1_potr":0,"T2_potr":0,"Total":0}, {"month":2,"T1":0,"T2":0,"T1_potr":0,"T2_potr":0,"Total":0}, {"month":3,"T1":0,"T2":0,"T1_potr":0,"T2_potr":0,"Total":0}, {"month":4,"T1":0,"T2":0,"T1_potr":0,"T2_potr":0,"Total":0}, {"month":5,"T1":0,"T2":0,"T1_potr":0,"T2_potr":0,"Total":0}, {"month":6,"T1":0,"T2":0,"T1_potr":0,"T2_potr":0,"Total":0}, {"month":7,"T1":0,"T2":0,"T1_potr":0,"T2_potr":0,"Total":0}, {"month":8,"T1":0,"T2":0,"T1_potr":0,"T2_potr":0,"Total":0}, {"month":9,"T1":0,"T2":0,"T1_potr":0,"T2_potr":0,"Total":0}, {"month":10,"T1":0,"T2":0,"T1_potr":0,"T2_potr":0,"Total":0}, {"month":11,"T1":0,"T2":0,"T1_potr":0,"T2_potr":0,"Total":0}, {"month":12,"T1":0,"T2":0,"T1_potr":0,"T2_potr":0,"Total":0}]; console.log('start'); for(var i=1;i<13;i++) { table_mer230[i-1]["month"]=i; table_mer230[i-1]["T1"]=myjson['M'+i+'T1'];; table_mer230[i-1]["T2"]=myjson['M'+i+'T2']; table_mer230[i-1]["T1_potr"]=Math.round(myjson['M'+i+'T1']*tarrif); table_mer230[i-1]["T2_potr"]=Math.round(myjson['M'+i+'T2']*tarrif/2); table_mer230[i-1]["Total"]=Math.round(myjson['M'+i+'T1']*tarrif)+Math.round(myjson['M'+i+'T2']*tarrif/2); } //console.log('table='+JSON.stringify(table_mer230)); setState("javascript.0.History_mer230", JSON.stringify(table_mer230)); } });
-
Инструкция по компиляции прошивки espeasy с плагином Меркурий 230.
1. Ставим atom по инструкции: https://letscontrolit.com/wiki/index.ph … Platformio
2. Скачиваем последний релиз espeasy https://github.com/letscontrolit/ESPEasy/releases
3. Разархивируем архив релиза, в папку src записываем файл https://github.com/Andrey2509/ESPEasy/b ... ury230.ino
4. В файле platformio.ini раскомментировать тип прошивки, например: env_default = normal_ESP8266_4096
5. В файле define_plugin_sets.h в секции #ifdef PLUGIN_SET_STABLE (соответствует прошивке normal) добавляем строку:
#define USES_P220 //Mercury 230
6. Компилируем.
Так как данных много, а в espeasy жёсткое ограничение по количеству значений для каждого плагина, в плагине меркурий 230 вшита отправка данных только по mqtt. При этом Надо обязательно создать подключение в настройках "Controllers" (OpenHAB MQTT).
Добрый день, Сергей.
Ваш плагин для ESPEASY очень понравился, но у меня не получилось его запустить.
Все сделал по пунктам, прошил и достучался до espeasy. Подключил его к домашнему роутеру и даже но MQTT что то увидел НО главное включение плагина MERCURY 230 не происходит. Т.е. при выборе плагина, в его настройках указываю:
Device: Mercury 230
Name: d1
Enabled: YES
Sensor
1st GPIO: GPIO 12
2nd GPIO: GPIO 14
Read month stat: NO
Start time to read stat for every month, hour: 0
Start time to read stat for every month, min: 0
End time to read stat for every month, hour: 0
End time to read stat for every month, min: 0
Select MQTT controller to publish data in json format : 1
Note: MQTT topic to publish runtime data is: "Mercury230/Merc_data_json"
Note: MQTT topic to publish history data is: "Mercury230/Merc_stat_json"
Note: Interval (below) must be shorter then period between end and start
Data Acquisition
Send to Controller YES
❶
Interval: 5 [sec]
Давлю SUBMIT потом возвращаюсь в DEVICES и вижу что у меня напротив плагина Меркурий в столбце ENABLED стоит Х (не включено)
В MQTT ничего не видно
что делать? `
-
В дополнение у меня Nodemcu V3
-
В дополнение у меня Nodemcu V3 `
Плагин автодисейблиться может по причине:
1.В espeasy должен быть создан MQTT контроллер в соответствующей закладке (тестировал только тип Openhab).
2. Не правильно указаны GPIO RX/TX или неправильно подключен к конвертору RS232/RS485.
Я использую такой:
https://ru.aliexpress.com/item/Single-C … 57602.html
Напрямую к счётчику подключать нельзя!
-
Андрей, большое спасибо за быстрый отзыв.
У меня такой же модуль 485.
Все заработало.
Через 6 часов перестал работать опрос, перезагрузка (отключением питания) помогла
Сейчас опять стоит испытывается.
Скажите получилось победить утечку памяти?
В остальном у меня все передается, правда мне нужны были прямые топики в MQTT - переделал передачу отдельными командами.
Иногда не успевает передать. Перешел на Domoticz MQTT и убрал все задержки - стало лучше но некоторые параметры не проходят. Но это не проблема - у меня частота передачи сейчас стоит 10с (на 5с больше глюков). На верху у меня RapidScada с драйвером MQTT.
В любом случае спасибо за Вашу работу!!!
Для меня espeasy новое и с титаном не работал поэтому пришлось помучатся.
-
Скажите получилось победить утечку памяти? `
Та версия, которая на github (ссылка выше) - без утечки памяти.Проверяется просто - в espeasy ставится девайс "Generic - System Info ". Индикатор "Free RAM". далее штатно передаём через mqtt иоброкеру и сохраняем историю. У меня uptime уже 22 дня, память не уменьшается.
Были короткие uptime до замены БП, esp(nodemcu) оказалась очень чувствительна и к самому БП, и к проводам подводящим питание.
Сейчас БП и питание RS485 конвертора выставил ровно на 5.0 Вольт.
Частота запросов 10 с - на ней не тестировал, у меня 60 сек.
-
Обновил версию на github для espeasy.
Изменения:
-замена опасных функций (с указателями на данные) на безопасные,
-поддержка hardware serial (необходимо убрать галку использования serial самой espeasy),
-статистика передаётся в 2-х топиках: по месяцам и по предыдущему дню,
-период сбора статистики потребления задаётся в минутах, независимо от сбора оперативных данных.
-
Добрый день! Как вы считаете, реально переделать скетч под software serial или hardware? Хочу использовать в связке с Меркурий 231 (с ИК портом) - ествественно, через переходник...
-
Ау..есть кто живой?
-
Всем привет!
Пробовал заводской прогой опросить Меркурий 230, все получилось.
Теперь хочу запустить опрос счетчика Меркурий 230 через скрипт, что выше приведен.Копипастом не заработал...
Сейчас стоит Script Ingine 4.1.12.
В настройках прописал пакет serialport. Перезапустил службу, так же пробовал в ручную ставить через npm install serialport.В редакторе JS подсвечивает ошибки
Подскажите что не так делаю, и как заставить редактор видеть (установить) недостающие пакеты...
В ручную пробовал в папку iobroker ставить, ничего не меняется...