New DSMR-binding for OpenHAB 2

I have created a OpenHAB 2 DSMR-binding.

This alpha version can be downloaded here: OpenHAB2 DSMR binding (Alpha!)

This version does not support Gas, Water, Heating and Cooling meters voor DSMR meters V4.x and V5 and Heating, Cooling and Generic Meter voor DSMR V3.

Please let me know in this topic:

  • Which meters are detected automatically and do work correctly
  • If there are warnings and errors in the log
  • Any other things of interest

If you have problems please set the debug level to DEBUG and post the log information

1 Like

Great job!

I will try to find some time to test the new binding but can/will only start using it in production once Gas has been implemented for my v4 meter. If you confirm this is on your roadmap soon, I will gladly be of help.

Thanks for your help. On the Github issue thread i have uploaded an updated version in which all meters should be supported.
You can test it. If you have a complete P1 telegram from your setup i can also do the first tests for you.

How do I get that telegram?

Capture the raw output from the serial port where the DSMR is connected to.

It should look something like this:
/ISk5\2MT382-1000
1-3:0.2.8(50)
0-0:1.0.0(101209113020W)
0-0:96.1.1(4B384547303034303436333935353037)
1-0:1.8.1(123456.789kWh)
1-0:1.8.2(123456.789
kWh)
1-0:2.8.1(123456.789kWh)
1-0:2.8.2(123456.789
kWh)
0-0:96.14.0(0002)
1-0:1.7.0(01.193kW)
1-0:2.7.0(00.000
kW)
0-0:96.7.21(00004)
0-0:96.7.9(00002)
1-0:99.97.0(2)(0-0:96.7.19)(101208152415W)(0000000240s)(101208151004W)(0000000301s)
1-0:32.32.0(00002)
1-0:52.32.0(00001)
1-0:72.32.0(00000)
1-0:32.36.0(00000)
1-0:52.36.0(00003)
1-0:72.36.0(00000)
0-0:96.13.0(303132333435363738393A3B3C3D3E3F303132333435363738393A3B3C3D3E3F303132333435363738393A3B3C3D3E3F303132333435363738393A3B3C3D3E3F303132333435363738393A3B3C3D3E3F)
1-0:32.7.0255(220.1V)
1-0:52.7.0255(220.2V)
1-0:72.7.0255(220.3V)
1-0:31.7.0255(001A)
1-0:51.7.0255(002A)
1-0:71.7.0255(003A)
1-0:21.7.0255(01.111kW)
1-0:41.7.0255(02.222kW)
1-0:61.7.0255(03.333kW)
1-0:22.7.0255(04.444kW)
1-0:42.7.0255(05.555kW)
1-0:62.7.0255(06.666kW)
0-1:24.1.0(003)
0-1:96.1.0(3232323241424344313233343536373839)
0-1:24.2.1(101209112500W)(12785.123*m3)
!62FD

Will I get this if I set the log level to DEBUG or TRACE or should I manually cat the serial port?

Just manual cat the serial port (make sure you use the correct serial
settings).

I’m not very familiair with Linux and serial ports. I’m afraid I will mess up my system. I set the log level to TRACE and retrieved this for you:

log:set TRACE org.openhab.binding.dsmr
21:40:01.564 [TRACE] [internal.p1telegram.P1TelegramParser] - Data: /KFM5KAIFA-METER

1-3:0.2.8(42)
0-0:1.0.0(170119214004W)
0-0:96.1.1(4530303235313030303332373437333135)
1-0:1.8.1(002554.293*kWh)
1-0:1.8.2(002682.151*kWh)
1-0:2.8.1(000000.000*kWh)
1-0:2.8.2(000000.000*kWh)
0-0:96.14.0(0002)
1-0:1.7.0(00.364*kW)
1-0:2.7.0(00.000*kW)
0-0:96.7.21(00007)
, state before parsing: WAIT_FOR_START, header = , obisId = , obisValue = 
21:40:01.567 [TRACE] [internal.p1telegram.P1TelegramParser] - State after parsing: DATA_OBIS_VALUE_END, header = /KFM5KAIFA-METER, obisId = 0-0:96.7.21, obisValue = 00007
21:40:01.570 [TRACE] [internal.p1telegram.P1TelegramParser] - Data: 0-0:96.7.9(00003)
, state before parsing: DATA_OBIS_VALUE_END, header = /KFM5KAIFA-METER, obisId = 0-0:96.7.21, obisValue = 00007
21:40:01.571 [TRACE] [internal.p1telegram.P1TelegramParser] - State after parsing: DATA_OBIS_VALUE_END, header = /KFM5KAIFA-METER, obisId = 0-0:96.7.9, obisValue = 00003
21:40:01.574 [DEBUG] [ab.binding.dsmr.internal.DSMRBinding] - Received 0 messages
21:40:02.091 [TRACE] [internal.p1telegram.P1TelegramParser] - Data: 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(002*A)
1-0:21.7.0(00.364*kW)
1-0:22.7.0(00.000*kW)
0-1:24.1.0(003)
0-1:96.1.0(4730303139333430323539323532313135)
, state before parsing: DATA_OBIS_VALUE_END, header = /KFM5KAIFA-METER, obisId = 0-0:96.7.9, obisValue = 00003
21:40:02.093 [TRACE] [internal.p1telegram.P1TelegramParser] - State after parsing: DATA_OBIS_VALUE_END, header = /KFM5KAIFA-METER, obisId = 0-1:96.1.0, obisValue = 4730303139333430323539323532313135
21:40:02.098 [TRACE] [internal.p1telegram.P1TelegramParser] - Data: 0-1:24.2.1(170119210000W)(01986.323*m3)
!8E80
, state before parsing: DATA_OBIS_VALUE_END, header = /KFM5KAIFA-METER, obisId = 0-1:96.1.0, obisValue = 4730303139333430323539323532313135

Will this do?

Perfect! I will do some testing

I have done some testing with your data. I looks good on the binding you
can download here:

Haven’t had the time to install the binding yet. Wil this work:

  • Uninstall old binding by removing it from addons.cfg
  • Copy new binding to addons folder

Is there a README for the new thing and channel definition? Can’t find a development branch in your personal github repo.

I think you also have to remove the old binding.

I have committed the binding to my own repository.

Furthermore i think the autodiscovery functionality of the binding in
combination with the Paper UI should be enough to create a setup for OH2.

After discovery the descriptions of the channel are in the Thing
configuration.

This is it:

There is no README (yet). It should be, before you can submit a PR in the upstream repo. Mainly to have it included in the documentation website. I will gladly help you getting this written and/or improved.

I try to prevent using Paper UI as much as possible and use manual configuration whenever possible.

I will try to use Paper UI to get things going, however. It shouldn’t be too different from the current one I guess.

Ah Ok,

Can you point me indeed to some kind of guide lines that the readme must
follow or a good example?

Then i will get this written.

An example is the README from the RFXCOM binding.

You should be able to reuse most content from the old wiki page I guess.

Wow, this is great news! I’m currently testing the implementation and it seems to work fine. Installation was a breeze and my (dutch) P1 electricity meter was found instantly. Thank you.

Unfortunately, this will make my work obsolete. I started writing a 2.0 port about a month ago, but only noticed the new binding two days ago. Well, perhaps I can merge some of my changes into your codebase. I noticed you got the ESH thing definitions all written out in XML. That must’ve been quite a lot of work!

Thank you for your testing. Can you please let me know which devices OH2 detected automatically.

If you have any features or improvements from your development that are missing in the current code base, please let me know.

Defining all possible things in xml was quite some work, but i think it was worth it regarding your feedback about a ‘breeze installation’.

Well, a small thing that is an easy fix was something I noticed while profiling my openhab 2.0 installation. I noticed that the P1TelegramParser has a lot of expensive string concatenation leading to some load on the GC and slightly lowered performance. I’m trying to create a PR towards your fork, but it doesn’t seem to work somehow. Your repo doesn’t show up in the list of available PR targets. The commit is here: https://github.com/gedejong/openhab2-addons

Another change I made was to make the serial port reactive instead of polling. A first step towards that is in the ‘test-async’ branch in my repo. This still needs some work, but it would be nice to not have to do a ‘Thread.sleep()’, but use scheduled time-outs and such.

The last change I made was an auto-discovery for the serial port. In essence it would scan available serial ports, try to connect to each of them at different speeds and see if anything ‘responds’. Then again, to see how easy it is to install the binding as it is now, I don’t think it adds much value. Besides, it could actually mess with other serial devices.

Perhaps you could have a look at the ‘test-async’ branch and see what you think?

I incorporated the String concatenation commit. Thank you for this.

I like the asynchronous approach. I think it will solve some corner cases where the configuration or the binding is reloaded and the recovery period resulted in error messages in the log which don’t have a specific meaning since they will recover themselves.

I do however have some questions about the WIP version:

  • You add listeners to data available, CD and FE. As far as i understand all the DSMR-specifications only TxD and RxD are connected so other event triggers that come from a Serial pin will never be received (like CD, DTR, Ring etc.). The listener for framing error does nothing in your implementation. Adding listeners on FE, Overrun and parity errors could help identifying errors in an early stage and abort parsing till a new frame arrives. Besides that this is a nice pure implementation i don’t see any functional advantages.
    I don’t see any reason to listen for the breakinterruptevent’.
  • In your implementation you have chosen to support multiple listeners. I don’t see the advantage having this support. Do you have a particul reason for this choice?

I will start implementing an async version of the binding.

I agree to not incorporate the last suggestion for serial port detection. Meters < DSMR v4.2 only communicate once every 10 seconds. For reliable you have to wait at least > 10 seconds before the first frame is received. Port detection will claim the port for a minimum of 20 seconds (in the current implementation the detection period is 30 seconds resulting in a claim of 1 minute). This will result in the situation that if the wrong port is claimed it will be unavailable for other bindings. It is possible storing the correct parameters so the detection has only to be done during installation.
So for now i will not add this feature, but i find the idea very interesting.

Looking forward to your input regarding the async implementation

Hey, that’s really fast. I’ll do a bit more profiling with the new binding to see if I can find anything else.

The async commit I made is totally WIP, so the listeners to CD and FE were just to see if I got any signal on them (nope, like you said). But it would really help indeed in detecting errors before they occur during parsing (edit). BTW, I do see the kernel detecting a disconnect (via dmesg), so I was kind of wondering if that could be handled async as well.

The multiple listeners (subscribe and all) is there because I don’t really like ballooning constructors and it seems a bit strange to just add one setter/getter. I guess I get a bit OCD sometimes :slight_smile: Also, since it is WIP, I kind of imagined all the error detection to happen async, such that a discovery service and the DSMR meters themselves could be listeners to the state of the port. This would help create that architecture later. Or said in another way: I see the one-listener-per-class-design as a special, more specific case of the multiple listeners design.

Thanks, I hope this helps. If you have intermediate commits, or maybe something I could help with, that’d be fine.