Поддержка счетчиков Энергомера

Прочел в буклете про WB5, что поддерживаются счетчики Энергомера, но на странице поддерживаемого оборудования информации нет. Поддерживается ли такой счетчик CE102M-R5?

пока нет. Скоро будет поддержка трёхфазных счётчиков CE303. У CE102, кажется, другой протокол. Поддержка пока не планируется.

Всё это касается стандартого ПО Wiren Board. Вы, естественно, можете сторонним скриптом считать данные. Похоже, что-то такое на просторах интернета есть: https://github.com/search?q=energomera

Попробую сторонним скриптом считать, спасибо за ссылку!

Вообще, код реализации не выглядит чем-то запредельно сложным. Надеюсь, найдете несколько дней и добавите в будущем :slight_smile:

#!/usr/bin/python
import time
import serial
import readline
import binascii
import logging
import re
import sys
import argparse
import os.path
import subprocess
import struct

def unhexlify(s):
    s = re.sub(r'[^0-9a-fA-F]','',s)
    return binascii.unhexlify(s)

def makehex(s):
    print "MAKEHEX get  %s" % s
    send_str=''
    for c in bytearray(s):
	cint =int(c)
	cint &=0x7f
	hvar=hex(cint)[2:4]
	if len(hvar)==1:
	    hvar='0'+hvar
	send_str+=hvar+' '
    print "MAKEHEX make  %s" % send_str
    return send_str

def ask(serial,timeout,s):
    send_bytes=unhexlify(makehex(s))
    print "ASK send %s" % send_bytes
    serial.write(send_bytes)
    out=''
    time.sleep(timeout)
    while serial.inWaiting() > 0:
	out += serial.read(1)
    print "ASK get %s" % out
    return out

def anspub(ans,subtop):
    rs = re.findall('\((.*?)\)',ans)
    print subtop+" ANSWER ",rs
    for idx,cs in enumerate(rs):
	topic="mosquitto_pub -t '/devices/energomera/controls/"+subtop+str(idx+1)+"' -m '"+str(cs)+"'"
	print "SUBPROC CALL ",topic
	subprocess.call(topic,shell='True')
    return 1


def main():
    parser = argparse.ArgumentParser(description='enerogemera whm poller',
                                     add_help=True, formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument('-b', '--baud', dest='baud', type=int,
                     help='Baud rate', default=9600)
    parser.add_argument('-p', '--parity', dest='parity', type=str,
                     help='set parity, one of [%s]' % ", ".join(serial.Serial.PARITIES), default='E')
    parser.add_argument('-d', '--data-bits', dest='data_bits', type=int,
                     help='set number of data bits, i.e. bytesize', default=7)
    parser.add_argument('-s', '--stop-bits', dest='stop_bits', type=float,
                     help='set number of stop bits, one of [%s]' % ", ".join(
                            str(x) for x in serial.Serial.STOPBITS
                        ), default=1)
    parser.add_argument('-t', '--timeout', dest='read_timeout', type=float,
                     help='number of seconds to wait for answer', default=1)
    parser.add_argument('-a', '--address', dest='read_address', type=str,
                     help='device address to connect', default='777777')
    parser.add_argument('-P', '--PORT', dest='port', type=str,
                     help='Serial port to open, i.e. /dev/ttyXXX', default='/dev/ttyAPP4')

    args = parser.parse_args()
    if args.baud not in serial.Serial.BAUDRATES:
        print "incorrect baudrate %d" % args.baud
        return 1
    if args.parity not in serial.Serial.PARITIES:
        print "incorrect parity %d" % args.partity
        return 1
    if args.stop_bits not in serial.Serial.STOPBITS:
        print "incorrect stop bits setting %d" % args.stop_bits
        return 1
    if not args.read_address:
        print "no device address %s" % args.read_address
        return 1
    if not args.port:
        print "no PORT to connect %s" % args.port
	return 1

    ser = serial.Serial(
        port=args.port,
        baudrate=args.baud,
        parity=args.parity,
        stopbits=args.stop_bits,
        bytesize=args.data_bits)

    print "serial Energomera WHM adr=%s on %s: %d %s%s%s" % (
	args.read_address,
        ser.portstr,
        ser.baudrate,
        ser.bytesize,
        ser.parity,
        ser.stopbits)

    ans=ask(ser,args.read_timeout,'/?'+args.read_address+'!\r\n')
    if ans != '':
	ans=ask(ser,args.read_timeout,chr(6)+'051\r\n')
	if ans != '':
	    ans=ask(ser,args.read_timeout,chr(1)+'R1'+chr(2)+'POWEP()'+chr(3)+'d')
	    if ans != '':
		anspub(ans,'power')
		ans=ask(ser,args.read_timeout,chr(1)+'R1'+chr(2)+'ET0PE()'+chr(3)+'7')
		if ans != '':
		    anspub(ans,'energy')
		    ans=ask(ser,args.read_timeout,chr(1)+'R1'+chr(2)+'CURRE()'+chr(3)+'Z')
		    if ans != '':
			anspub(ans,'current')
			ans=ask(ser,args.read_timeout,chr(1)+'R1'+chr(2)+'VOLTA()'+chr(3)+'_')
			if ans != '':
			    anspub(ans,'voltage')
		    	    ans=ask(ser,args.read_timeout,chr(1)+'B0'+chr(3)+'u')
		    	    return 1
    print "Energomera answer timeout"
    return 0


if __name__ == '__main__':
    rc = main()
    sys.exit(rc)

вобщем хотел простенький скрипт на питоне для опроса энергомеры приложить - чего-то не понял как это вышло так…ну разберетесь если надо - работает давно на WB5 запуск по крону

1 Симпатия

Добрый день, Евгений! а ориентировочные сроки можете сказать?
а то реально, на объект пытались найти Меркурий поставить, но к нам их ни кто не возит (еще и проблема часового пояса)

спасибо!

Спасибо! Как счетчик привезут, протестирую. Немного удивило, что многие на Питоне пишут. А официальные адаптеры на чем пишутся?

Лучше сначала подключиться к счетчику штатной программой через преобразователь в rs485, убедиться в настройках интерфейса и адресации, в принципе если счетчик один то отвечает без адреса, можно скрипт подправить…

добрый день!
нет информации?

пока нет

как это сделать? поставил admin tools 11, а там нет 485 канала связи…

ээ, к программе существует руководство оператора - там все написано…

Наконец-то дошли руки до скрипта. Как понимаю, счетчик нужно регистрировать как serial device с указанием id и device type. Откуда взять эти значения?

Пока что запуск выглядит так:

serial Energomera WHM adr=777777 on /dev/ttyRS485-2: 9600 7E1
MAKEHEX get  /?777777!

MAKEHEX make  2f 3f 37 37 37 37 37 37 21 0d 0a
ASK send /?777777!

ASK get
Energomera answer timeout

Это только в случае наличия шаблона (и поддержки) счетчика.
Если напишете шаблон - то можно так, да.

Используемый для подключения порт свободен в wb-mqtt-serail?
Для уверенности - остановите его перед экспериментами.

systemctl stop wb-mqtt-serial

Скорее всего этот скрипт для счетчика CE102, а не CE102M, у которого другой протокол. С CE102M работает этот скрипт Считывание показаний и программирование электросчетчика "Энергомера СЕ102М" по rs-485, только таймаут нужно больше 0,2 с выставить.

Полученные значения периодически отправляю в топики. Напр.:

mosquitto_pub -t '/devices/energomera-ce102m/controls/VOLTA' -m '209.52'

В веб-интерфейсе данные видны

Вопрос. Как это описать в шаблоне? Откуда взять поле address? Или по-другому всё делается?

Счетчик, этот счетчик, не через modbus rtu работает- для него шаблон не напишешь.

А разве нельзя эмулировать modbus на самом контроллере? Создать виртуальное устройство, например, и к нему обращаться как к реальному? Или как-то получать эти данные в js-скрипте другим способом?

Модбас - это просто транспорт. Данные - хранятся в mqtt топиках. Если скрипт на питоне туда их уже поместил - то к ним уже можно обратиться. Для удобства - да, можно создать еще и виртуальное устройство Но оно всего лишь служит для отображения mqtt.

На самом деле устройство и так автоматически создается, когда в mqtt-топик приходят данные, так что виртуальное устройство будет лишь его дублировать, так что я присвоил типы с помощью мета-топиков

И ещё питоновский скрипт получает и передает данные от счетчика с некоторой периодичностью. Какую частоту опроса принято выставлять для электрических счетчиков? Раз в секунду, чаще, реже?

Исключительно в зависимости от потребностей. Мне, например, для графиков достаточно значений вообще раз в минуту.
Если нужно засекать пики потребления - то чаще.