nrocco / smeterd Goto Github PK
View Code? Open in Web Editor NEWRead P1 smart meter packets in Python
License: MIT License
Read P1 smart meter packets in Python
License: MIT License
It seems the code is a bit too specific to be used with different meters. I've made a couple of modifications to make it work with my meter (Kaifa).
smeterd read-meter -vvv --serial-port /dev/ttyUSB0 --baudrate 9600 --serial-baudrate 9600 --serial-bytesize 8 --serial-parity N --serial-stopbits 1
[2020-01-04 11:27:59,029] DEBUG Open serial connect to /dev/ttyUSB0 with: parity=N, baudrate=9600, bytesize=8, xonxoff=False, timeout=10, stopbits=1.0
[2020-01-04 11:27:59,035] INFO New serial connection opened to /dev/ttyUSB0
[2020-01-04 11:27:59,037] INFO Start reading lines
[2020-01-04 11:27:59,103] ERROR 'ascii' codec can't decode byte 0xb7 in position 1: ordinal not in range(128)
[2020-01-04 11:27:59,104] ERROR Read a total of 0 lines
[2020-01-04 11:27:59,105] INFO Closing connection to /dev/ttyUSB0
.
Traceback (most recent call last):
File "/usr/local/bin/smeterd", line 9, in
load_entry_point('smeterd==2.8.1', 'console_scripts', 'smeterd')()
File "build/bdist.linux-armv7l/egg/smeterd/cli/init.py", line 22, in parse_and_run
File "build/bdist.linux-armv7l/egg/smeterd/cli/read_meter.py", line 73, in run
File "build/bdist.linux-armv7l/egg/smeterd/meter.py", line 79, in read_one_packet
smeterd.meter.SmartMeterError: 'ascii' codec can't decode byte 0xb7 in position 1: ordinal not in range(128)
Hello,
i got the following Error:
Traceback (most recent call last):
File "/usr/local/bin/smeterd", line 11, in
load_entry_point('smeterd==2.6.0', 'console_scripts', 'smeterd')()
File "/usr/local/lib/python2.7/dist-packages/pkg_resources/init.py", line 565, in load_entry_point
return get_distribution(dist).load_entry_point(group, name)
File "/usr/local/lib/python2.7/dist-packages/pkg_resources/init.py", line 2631, in load_entry_point
return ep.load()
File "/usr/local/lib/python2.7/dist-packages/pkg_resources/init.py", line 2291, in load
return self.resolve()
File "/usr/local/lib/python2.7/dist-packages/pkg_resources/init.py", line 2297, in resolve
module = import(self.module_name, fromlist=['name'], level=0)
ImportError: No module named cli
What i must install to solve this error ?
Hi,
Great code, works fine with a USB-Serial cable. However, i have moved my server out of my metercabinet, so i can't use a USB-Serial adapter anymore because of the distance.
I found this: http://romix.macuser.nl/ and made it with a ESP8266 i had lying around. When i use putty (with 'telnet' or 'raw' setting) i can connect to the ESP8266 and every 10s i receive a new P1-telegram. Nice!
Unfortunately my Python skills are equal to zero, would it be possible to create a variant of the script that can listen to a socket instead of a tty? See also here: https://gathering.tweakers.net/forum/list_message/48850001#48850001
The 2013+ meters are 115200 bps.
Is it possible to have the baud rate as a variable as well ?
I tried smeterd now with the following parameters:
smeterd -v read-meter --serial-port /dev/ttyUSB0 --serial-baudrate 9600 --serial-bytesize 8 --serial-parity N --serial-stopbits 1
[2016-12-12 21:50:12,761] INFO New serial connection opened to /dev/ttyUSB0
[2016-12-12 21:50:12,766] INFO Start reading lines
[2016-12-12 21:50:14,826] ERROR 'ascii' codec can't decode byte 0x82 in position 2: ordinal not in range(128)
[2016-12-12 21:50:14,830] ERROR Read a total of 1 lines
[2016-12-12 21:50:14,838] INFO Closing connection to /dev/ttyUSB0
.
Traceback (most recent call last):
File "/usr/local/bin/smeterd", line 11, in
load_entry_point('smeterd==2.7.1', 'console_scripts', 'smeterd')()
File "build/bdist.linux-armv6l/egg/smeterd/cli/init.py", line 22, in parse_and_run
File "build/bdist.linux-armv6l/egg/smeterd/cli/read_meter.py", line 64, in run
File "build/bdist.linux-armv6l/egg/smeterd/meter.py", line 76, in read_one_packet
smeterd.meter.SmartMeterError: 'ascii' codec can't decode byte 0x82 in position 2: ordinal not in range(128)
I have the following smartmeter: http://wiki.volkszaehler.org/hardware/channels/meters/power/edl-ehz/emh-ehz-h1
with regards
Bruno
Hello!
I'm trying to use your awesome lib to build a Prometheus exporter. :)
However, I've run into some issues.
First is that setRTS(False)
(meter.py:36 ) seems to break the program for me:
emil@fasadmatarskapet:~/smeterd $ python3 -m smeterd read-meter --serial-baudrate 115200 --serial-bytesize 8 --raw
DEBUG:smeterd.meter:Open serial connect to /dev/ttyUSB0 with: baudrate=115200, bytesize=8, parity=E, stopbits=1.0, xonxoff=False, timeout=10
INFO:smeterd.meter:New serial connection opened to /dev/ttyUSB0
INFO:smeterd.meter:Start reading lines
DEBUG:smeterd.meter:>>
DEBUG:smeterd.meter:>>
DEBUG:smeterd.meter:>>
DEBUG:smeterd.meter:>> (10s timeout on each of these lines)
DEBUG:smeterd.meter:>>
DEBUG:smeterd.meter:>>
Commenting this line "solves" this issue for me.
I'm not an expert in serial communication, but if this line is required for someone else, I think it should be a configuration option.
Also, the setRTS() parameter seems to have been deprecated:
https://pyserial.readthedocs.io/en/latest/pyserial_api.html#serial.Serial.setRTS
Best regards
As far as i can see, the code doesn't have a CRC check to look if the incoming telegram is correct. However, the modern >=DSMR4 meters include a CRC at the end of the telegrams. With the CRC16 these can be checked, see also: https://gathering.tweakers.net/forum/list_messages/1704755
Would be nice if this would be implemented, to prevent false data being imported.
(this may be related to #6)
Using v 2.4.0 when running smeterd read-meter -v
from my Raspbbery Pi for querying my Kaifa E0026, I get the following error message:
[2016-09-01 21:57:17,380] INFO New serial connection opened to /dev/ttyUSB0
[2016-09-01 21:57:17,399] INFO Start reading lines
[2016-09-01 22:04:07,813] INFO Closing connection to `/dev/ttyUSB0`.
Traceback (most recent call last):
File "/usr/local/bin/smeterd", line 11, in <module>
sys.exit(parse_and_run())
File "/usr/local/lib/python3.4/dist-packages/smeterd/command.py", line 85, in parse_and_run
args.func(args, parser=parser)
File "/usr/local/lib/python3.4/dist-packages/smeterd/command.py", line 46, in run
packet = meter.read_one_packet()
File "/usr/local/lib/python3.4/dist-packages/smeterd/meter.py", line 81, in read_one_packet
raise SmartMeterError('Received %d lines, we seem to be stuck in a loop, quitting.' % len(lines))
smeterd.meter.SmartMeterError: Received 41 lines, we seem to be stuck in a loop, quitting.
I'm using a P1 Converter Cable v2, I bought from https://sites.google.com/site/nta8130p1smartmeter/webshop
The USB device seems to be found (and briefly lights up when I connect it)
lsusb -t
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=dwc_otg/1p, 480M
|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/3p, 480M
|__ Port 1: Dev 3, If 0, Class=Vendor Specific Class, Driver=smsc95xx, 480M
|__ Port 2: Dev 5, If 0, Class=Vendor Specific Class, Driver=ftdi_sio, 12M
Any suggestions where to start looking?
Hi,
Thanks for this great tool! I've been using it a couple of weeks now. It was easy to implement on my Pi, thanks to the good documentation.
I've found that my gas readings turned to 0, since 2AM last sunday, when DST changed. The last successful readings were on 2016-10-30 02:55, then one on 2016-10-30 02:00, at 2016-10-30 02:05 the value returned was 0.
Now, when I run the smeterd command, both default and TSV output result in a gas reading of 0, while the raw output does give a meaningful gas output:
Raw output:
/KFM5KAIFA-METER
1-3:0.2.8(42)
0-0:1.0.0(161106184601W)
0-0:96.1.1(4530303235303030303531393734353135)
1-0:1.8.1(000608.303*kWh)
1-0:1.8.2(000598.271*kWh)
1-0:2.8.1(000000.000*kWh)
1-0:2.8.2(000000.000*kWh)
0-0:96.14.0(0001)
1-0:1.7.0(01.263*kW)
1-0:2.7.0(00.000*kW)
0-0:96.7.21(00001)
0-0:96.7.9(00001)
1-0:99.97.0(1)(0-0:96.7.19)(000101000001W)(2147483647*s)
1-0:32.32.0(00000)
1-0:32.36.0(00000)
0-0:96.13.1()
0-0:96.13.0()
1-0:31.7.0(005*A)
1-0:21.7.0(01.263*kW)
1-0:22.7.0(00.000*kW)
0-1:24.1.0(003)
0-1:96.1.0(4730303332353631323639323539363136)
0-1:24.2.1(161106180000W)(00230.576*m3)
!65F2
Default output:
Total kWh High consumed 598271
Total kWh Low consumed 609156
Total gas consumed 0
Current kWh tariff 1
TSV output:
2016-11-06 19:09:43.188895 598271 609191 0 1
I can't figure out what to do to solve this. I am using version 2.5.0 and connect via serial (ttyAMA0) at 115200 baud rate.
I will soon get a new 3-phase meter supporting DSMR5.02. Is this version of the standard supported?
I've looked at the (very nice) code but can't find a way to extract the gas meter timestamp. Am I correct in that this is not available? If I'm wrong, please let me know how to get it. If not available then please consider this as a feature request with the timestamp preferably as a UNIX timestamp (seconds since epoch)
Hello!
Next issue (after solving #29 ) is that the P1Packet class does not seem to work as expected.
Full output running the CLI:
emil@fasadmatarskapet:~/smeterd $ python3 -m smeterd read-meter --serial-baudrate 115200 --serial-bytesize 8
DEBUG:smeterd.meter:Open serial connect to /dev/ttyUSB0 with: baudrate=115200, bytesize=8, parity=E, stopbits=1.0, xonxoff=False, timeout=10
INFO:smeterd.meter:New serial connection opened to /dev/ttyUSB0
INFO:smeterd.meter:Start reading lines
DEBUG:smeterd.meter:>> /AUX5U18SEH13F10029
DEBUG:smeterd.meter:>>
DEBUG:smeterd.meter:>> 0-0:96.1.0(38303034363937333432383437313031303137333437)
DEBUG:smeterd.meter:>> 0-0:1.0.0(221104214240W)
DEBUG:smeterd.meter:>> 1-0:1.8.0(004715.829*kWh)
DEBUG:smeterd.meter:>> 1-0:2.8.0(000000.000*kWh)
DEBUG:smeterd.meter:>> 1-0:3.8.0(000000.024*kvarh)
DEBUG:smeterd.meter:>> 1-0:4.8.0(003708.969*kvarh)
DEBUG:smeterd.meter:>> 1-0:1.7.0(0000.742*kW)
DEBUG:smeterd.meter:>> 1-0:2.7.0(0000.000*kW)
DEBUG:smeterd.meter:>> 1-0:3.7.0(0000.000*kvar)
DEBUG:smeterd.meter:>> 1-0:4.7.0(0000.782*kvar)
DEBUG:smeterd.meter:>> 1-0:21.7.0(0000.156*kW)
DEBUG:smeterd.meter:>> 1-0:22.7.0(0000.000*kW)
DEBUG:smeterd.meter:>> 1-0:41.7.0(0000.440*kW)
DEBUG:smeterd.meter:>> 1-0:42.7.0(0000.000*kW)
DEBUG:smeterd.meter:>> 1-0:61.7.0(0000.144*kW)
DEBUG:smeterd.meter:>> 1-0:62.7.0(0000.000*kW)
DEBUG:smeterd.meter:>> 1-0:23.7.0(0000.000*kvar)
DEBUG:smeterd.meter:>> 1-0:24.7.0(0000.123*kvar)
DEBUG:smeterd.meter:>> 1-0:43.7.0(0000.000*kvar)
DEBUG:smeterd.meter:>> 1-0:44.7.0(0000.470*kvar)
DEBUG:smeterd.meter:>> 1-0:63.7.0(0000.000*kvar)
DEBUG:smeterd.meter:>> 1-0:64.7.0(0000.189*kvar)
DEBUG:smeterd.meter:>> 1-0:32.7.0(232.0*V)
DEBUG:smeterd.meter:>> 1-0:52.7.0(234.5*V)
DEBUG:smeterd.meter:>> 1-0:72.7.0(236.1*V)
DEBUG:smeterd.meter:>> 1-0:31.7.0(001.0*A)
DEBUG:smeterd.meter:>> 1-0:51.7.0(002.8*A)
DEBUG:smeterd.meter:>> 1-0:71.7.0(001.0*A)
DEBUG:smeterd.meter:>> !C956
INFO:smeterd.meter:Done reading one packet (containing 31 lines)
DEBUG:smeterd.meter:Total lines read from serial port: 31
DEBUG:smeterd.meter:Constructing P1Packet from raw data
INFO:smeterd.meter:Closing connection to `/dev/ttyUSB0`.
Traceback (most recent call last):
File "/usr/lib/python3.9/runpy.py", line 197, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/usr/lib/python3.9/runpy.py", line 87, in _run_code
exec(code, run_globals)
File "/home/emil/smeterd/smeterd/__main__.py", line 3, in <module>
cli()
File "/home/emil/.local/lib/python3.9/site-packages/click/core.py", line 829, in __call__
return self.main(*args, **kwargs)
File "/home/emil/.local/lib/python3.9/site-packages/click/core.py", line 782, in main
rv = self.invoke(ctx)
File "/home/emil/.local/lib/python3.9/site-packages/click/core.py", line 1259, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/home/emil/.local/lib/python3.9/site-packages/click/core.py", line 1066, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/home/emil/.local/lib/python3.9/site-packages/click/core.py", line 610, in invoke
return callback(*args, **kwargs)
File "/home/emil/smeterd/smeterd/cli/read_meter.py", line 74, in read_meter
('Total electricity consumed (high, {})'.format(elec_unit), int(packet['kwh']['high']['consumed'] * elec_unit_factor[elec_unit])),
TypeError: unsupported operand type(s) for *: 'NoneType' and 'int'
If I'm using the --raw
flag it just prints the packet and exits successfully.
I'm also trying to use the lib as a module, but I'm missing some examples of how to access the class variables.
The following works:
packet = meter.read_one_packet()
# Print L1 voltage:
print(packet.__getitem__('instantaneous')['l1']['volts']
But first using a function, then digging into a list feels a bit complicated. Is there a better way (using (vars() perhaps?), or is there any example somewhere?
Hope you can point me in the right direction, I'm not a Python expert. :)
Best regards
Hi @nrocco,
just fyi: I've made a P1 plugin for our Venus OS:
https://github.com/mpvader/dbus-p1/
Thanks for the nice & simple code, especially for making it so easy to use as a module in Python.
Hi Nrocco,
I am a happy user of your library in the house where we are living but I noticed that in our holiday home (up North in Holland) we use a different type of meter which comes with different serial settings: serial_defaults = {'baudrate': 115200, 'bytesize': 8, 'parity': 'N', 'stopbits': 1, 'xonxoff': 1, 'timeout': 20}
Would it be possible to parameterise these settings?
Regards,
Frank
Got a new meter friday, however I can't get this to work.
Every time I fix something the next thing pops up.
My meter is the latest protocol version, so runs at 115200 baud. Similarly, if the meter isn't on /dev/ttyUSB0, the program is a hassle to use if that cannot be configured but has to be provided on each commandline.
I got it so far as to start parsing stuff but then when it tried to convert stuff to kwh by multiplying by 1000, I get a "nonetype" that cannot be multiplied. This means that the error is somewhere else and my python is iinsufficient to trace where things go wrong.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.