New DSMR-binding for OpenHAB 2

@mvolaart i noticed that you made a lot of enhancements to the OH2 DSMR binding. Your effort in this binding is very much appreciated :smile: Would you mind posting a new (alpha) .jar binding file so we can try it out? Thanks a lot!

Some very busy months, so excuse me not reply in the mean time.
Likely i have now some time to update the binding.

@QNimbus
In your dump i don’t see any gas data in the raw output. I expect the communication between the gas meter and the DSMR device is not working correctly. This is no binding issue however.

@pdiender
In my development version i see no more problems.

@ricadelic
I will make an new alpha version soon.

1 Like

Thanks for taking the time to reply, looking forward to try out your new alpha version!

@mvolaart Thanks for your response; it turned out to be a problem with my DSMR meter (no network connection via CDMA, so I had it replaced for a GPRS model and it’s now working correctly)

@mvolaart, looks like the binding, org.openhab.binding.dsmr-2.0.0-SNAPSHOT.zip, does not handle the ISKRA AM550 smart meter correctly.

The meter sends its data every second and a complete telegram is posted below:

/ISK5\2M550T-1012

1-3:0.2.8(50)
0-0:1.0.0(180104231941W)
0-0:96.1.1(4530303434303036393033333132393137)
1-0:1.8.1(000156.167*kWh)
1-0:1.8.2(000071.546*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(00.519*kW)
1-0:2.7.0(00.000*kW)
0-0:96.7.21(00009)
0-0:96.7.9(00005)
1-0:99.97.0(2)(0-0:96.7.19)(170609063239S)(0000000267*s)(170611001706S)(0000149657*s)
1-0:32.32.0(00000)
1-0:52.32.0(00000)
1-0:72.32.0(00000)
1-0:32.36.0(00002)
1-0:52.36.0(00002)
1-0:72.36.0(00002)
0-0:96.13.0()
1-0:32.7.0(234.8*V)
1-0:52.7.0(232.1*V)
1-0:72.7.0(235.3*V)
1-0:31.7.0(000*A)
1-0:51.7.0(001*A)
1-0:71.7.0(001*A)
1-0:21.7.0(00.122*kW)
1-0:41.7.0(00.237*kW)
1-0:61.7.0(00.158*kW)
1-0:22.7.0(00.000*kW)
1-0:42.7.0(00.000*kW)
1-0:62.7.0(00.000*kW)
0-1:24.1.0(003)
0-1:96.1.0(4730303339303031373633333738373137)
0-1:24.2.1(180104231507W)(00212.529*m3)
!D82C

I am using opehab2 and added the jar into the addons folder, next step was goto Inbox -> DSMR Binding enter the serial port /dev/ttyUSB1
I left the location field empty, not sure if that is correct??

I found four new things:
Dutch Smart Meter (Status: ONLINE)
Generic DSMR device (Status: OFFLINE)
Main electricity meter (Status: OFFLINE)
M3 meter

The first three I could add but the Generic DSMR device and the Main electricity meter are offline.

The M3 meter while adding it gives an error in paperUI (ERROR: 409 - Conflict)

The openhab.log gives every second the following message:

2018-01-04 23:58:38.178 [INFO ] [enhab.binding.dsmr.device.DSMRDevice] - There are unhandled messages, start autodetecting meters
2018-01-04 23:58:38.179 [INFO ] [enhab.binding.dsmr.device.DSMRDevice] - Detected the following new meters: [Meter type: DEVICE_V5, channel: -1, identification: unknown_id, Meter type: M3_V5_0, channel: 1, identification: 4730303339303031373633333738373137, Meter type: ELECTRICITY_V5_0, channel: 0, identification: 4530303434303036393033333132393137]
2018-01-04 23:58:39.174 [INFO ] [enhab.binding.dsmr.device.DSMRDevice] - There are unhandled messages, start autodetecting meters
2018-01-04 23:58:39.175 [INFO ] [enhab.binding.dsmr.device.DSMRDevice] - Detected the following new meters: [Meter type: DEVICE_V5, channel: -1, identification: unknown_id, Meter type: M3_V5_0, channel: 1, identification: 4730303339303031373633333738373137, Meter type: ELECTRICITY_V5_0, channel: 0, identification: 4530303434303036393033333132393137]
2018-01-04 23:58:40.205 [INFO ] [enhab.binding.dsmr.device.DSMRDevice] - There are unhandled messages, start autodetecting meters
2018-01-04 23:58:40.207 [INFO ] [enhab.binding.dsmr.device.DSMRDevice] - Detected the following new meters: [Meter type: DEVICE_V5, channel: -1, identification: unknown_id, Meter type: M3_V5_0, channel: 1, identification: 4730303339303031373633333738373137, Meter type: ELECTRICITY_V5_0, channel: 0, identification: 4530303434303036393033333132393137]
2018-01-04 23:58:41.179 [INFO ] [enhab.binding.dsmr.device.DSMRDevice] - There are unhandled messages, start autodetecting meters
2018-01-04 23:58:41.180 [INFO ] [enhab.binding.dsmr.device.DSMRDevice] - Detected the following new meters: [Meter type: DEVICE_V5, channel: -1, identification: unknown_id, Meter type: M3_V5_0, channel: 1, identification: 4730303339303031373633333738373137, Meter type: ELECTRICITY_V5_0, channel: 0, identification: 4530303434303036393033333132393137]

The three added Things in PaperUI:
image
image

The remaining Thing in Inbox which cant be added:
image

Does something needs to be changed into the binding? Or did I made some mistakes from my end?

Thanks,

Maarten

1 Like

Would it be bood idea to put the binding in the marketplace until it is included in the official repo?

1 Like

Exactly the same problem :-/

Hi Jaap,

I worked around it by simply writing a few lines in GO reading from the serial port and post messages on the local MQTT bus updating the OpenHAB items.

It works for me just fine.

Maarten

Hi Maarten,

Can you elaborate what you wrote in Go (I presume the programming language)… where you stored it, how you let it call the serial bus and how you made the OH2 binding listen to the output from you program instead of a serial bus?

Lots of thanks for the help :slight_smile:
Kindest regards,
Jaap.

Hi Jaap,

Yeah, its nothing fancy, but it simple does the trick for me to get what I want.

I simply run the executable in the background (for a nice init.d script I was way to lazy).

See the attached go code.

Maarten

1 Like

Hi Maarten,

I am probably blind… but I do not see any “attached go code” … Can you past it inline in the message?
Me being a ‘snowbird’ means I am still working out how this site works ;-p

Regards,
Jaap.

package main

import (
    "bufio"
    "fmt"
    "regexp"
    "strings"

    MQTT "[github.com/eclipse/paho.mqtt.golang](http://github.com/eclipse/paho.mqtt.golang)"
    "[github.com/tarm/goserial](http://github.com/tarm/goserial)"
)

var LastReadingTariff1 string
var LastReadingTariff2 string
var LastTariff string
var LastCurrentUsage string
var counter int


var LastReadingGas string

//define a function for the default message handler
var f MQTT.MessageHandler = func(client MQTT.Client, msg MQTT.Message) {
    fmt.Printf("TOPIC: %s\n", msg.Topic())
    fmt.Printf("MSG: %s\n", msg.Payload())
}

func main() {
    c := &serial.Config{Name: "/dev/ttyUSB1", Baud: 115200}
    s, err := serial.OpenPort(c)

    if err != nil {
        fmt.Println(err)
    }

    //create a ClientOptions struct setting the broker address, clientid, turn
    //off trace output and set the default message handler
    opts := MQTT.NewClientOptions().AddBroker("tcp://<<IPADDRESS>>:1883")
    opts.SetUsername("<<USERNAME>>")
    opts.SetPassword("<<PASSWORD>>")
    opts.SetClientID("dsmr-client")
    opts.SetDefaultPublishHandler(f)

    //create and start a client using the above ClientOptions
    client := MQTT.NewClient(opts)
    if token := client.Connect(); token.Wait() && token.Error() != nil {
        panic(token.Error())
    }

    r := bufio.NewReader(s)
    t, e := Readln(r)
    counter = 0
    for e == nil {

        // Meterstand tarief 1
        if strings.HasPrefix(t, "1-0:1.8.1(") && strings.HasSuffix(t, ")") {
            re := regexp.MustCompile(`(.*1-0:1.8.1\()(.*)(\*kWh\))`)
            match := re.FindStringSubmatch(t)
            if LastReadingTariff1 != match[2] {
                token := client.Publish("dsmr/electric/usagetariff1", 0, false, match[2])
                token.Wait()
                fmt.Print("Meterstand Tarief 1: ", match[2], " kWh\n")
                LastReadingTariff1 = match[2]
            }
        }
        // Meterstand tarief 2
        if strings.HasPrefix(t, "1-0:1.8.2(") && strings.HasSuffix(t, ")") {
            re := regexp.MustCompile(`(.*1-0:1.8.2\()(.*)(\*kWh\))`)
            match := re.FindStringSubmatch(t)
            if LastReadingTariff2 != match[2] {
                token := client.Publish("dsmr/electric/usagetariff2", 0, false, match[2])
                token.Wait()
                fmt.Print("Meterstand Tarief 2: ", match[2], " kWh\n")
                LastReadingTariff2 = match[2]
            }
        }
        // Tarief 1=laag 2=hoog
        if strings.HasPrefix(t, "0-0:96.14.0(") && strings.HasSuffix(t, ")") {
            re := regexp.MustCompile(`(.*0-0:96.14.0\()(.*)(\))`)
            match := re.FindStringSubmatch(t)
            if LastTariff != match[2] {
                token := client.Publish("dsmr/electric/tariff", 0, false, match[2])
                token.Wait()
                fmt.Print("Huidig Tarief: ", match[2], "\n")
                LastTariff = match[2]
            }
        }
        // Huidig stroomverbruik
        if strings.HasPrefix(t, "1-0:1.7.0(") && strings.HasSuffix(t, ")") {
            re := regexp.MustCompile(`(.*1-0:1.7.0\()(.*)(\*kW\))`)
            match := re.FindStringSubmatch(t)
            if LastCurrentUsage != match[2] && counter >= 350 {
                token := client.Publish("dsmr/electric/currentusage", 0, false, match[2])
                token.Wait()
                fmt.Print("Huidig stroomverbruik: ", match[2], " kW\n")
                LastCurrentUsage = match[2]
                counter = 0
            }
        }


        // Gasmeterstand
        if strings.HasPrefix(t, "0-1:24.2.1(") && strings.HasSuffix(t, ")") {
            re := regexp.MustCompile(`(.*0-1:24.2.1\(.*\)\()(.*)(\*m3\))`)
            match := re.FindStringSubmatch(t)
            if LastReadingGas != match[2] {
                token := client.Publish("dsmr/gas/usage", 0, false, match[2])
                token.Wait()
                fmt.Print("Gasmeterstand: ", match[2], " m3\n")
                LastReadingGas = match[2]
            }
        }

        //        fmt.Println(t)
        counter++
        t, e = Readln(r)
    }

    s.Close()
    client.Disconnect(250)

}

// Readln returns a single line (without the ending \n)
// from the input buffered reader.
// An error is returned iff there is an error with the
// buffered reader.
func Readln(r *bufio.Reader) (string, error) {
    var (
        isPrefix bool  = true
        err      error = nil
        line, ln []byte
    )
    for isPrefix && err == nil {
        line, isPrefix, err = r.ReadLine()
        ln = append(ln, line...)
    }
    return string(ln), err
}

Hi Maarten,

After installing mosquitto, golang ths little gem worked like a charm :sunglasses:
Could you post you .item list for this pub/sub?
That would help loads with the last problems :stuck_out_tongue_winking_eye:

Grts,
Jaap.

Sure, will post the item and mqtt openhab config tonight. Will be around 22 CET.

Maarten

Hi Jaap,

below you will find the items, I also used a rules to calculcate the gas usage per 5 minutes, its not that useful at all, but just post it here as well.

If you want to create some graphs, you could use persistence.

ITEMS

Number CurrentPowerUsage “Power [%.1f]” {mqtt="<[mosquitto:dsmr/currentpowerusage:state:default]"}

Number MeterstandT1 “Meterstand T1 [%.2f]” {mqtt="<[mosquitto:dsmr/electric/usagetariff1:state:default]"}

Number MeterstandT2 “Meterstand T2 [%.2f]” {mqtt="<[mosquitto:dsmr/electric/usagetariff2:state:default]"}

Number Huidigverbruik “Stroomverbruik [%.2f]” {mqtt="<[mosquitto:dsmr/electric/currentusage:state:default]"}

Number Tarief “Huidig Tarief” {mqtt="<[mosquitto:dsmr/electric/tariff:state:default]"}

Number MeterstandGas “Meterstand Gas [%.2f]” {mqtt="<[mosquitto:dsmr/gas/usage:state:default]"}

Number GasVerbruik “Meterstand Gas [%.2f]”

Number LastGasVerbruik “Meterstand Gas [%.2f]”

RULES

rule “Gasverbruik-5minutes”

when

Time cron "0 0/5 * * * ?"

then

if (gasLast5min == 0) {

	gasLast5min = (MeterstandGas.state as DecimalType).doubleValue

	GasVerbruik.postUpdate(0.0)

}

if (gasLast5min != 0) {

	GasVerbruik.postUpdate((MeterstandGas.state as DecimalType).doubleValue - gasLast5min)

	logInfo("energy.rules", "gasLast5min: " + gasLast5min + "MeterstandGas: " + MeterstandGas.state + "Gebruik5min: " + ((MeterstandGas.state as DecimalType).doubleValue - gasLast5min))

	gasLast5min = (MeterstandGas.state as DecimalType).doubleValue

}

end

PERSISTENCE

	Huidigverbruik : strategy = everyChange

	GasVerbruik : strategy = everyMinute

good luck,

Maarten

The issue with the M3 meter is because of the following errors (found in the logs):

[DEBUG] [ing.dsmr.internal.DSMRHandlerFactory] - Doesn't support  dsmr:m3_v5_0
[ERROR] [home.core.thing.binding.ThingFactory] - Thing factory (class org.openhab.binding.dsmr.internal.DSMRHandlerFactory) returned null on create thing when it reports to support the thing type (dsmr:m3_v5_0).
[WARN ] [g.discovery.internal.PersistentInbox] - Cannot create thing. No binding found that supports creating a thing of type dsmr:m3_v5_0.

OpenHAB reports the M3 as a “dsmr:m3_v5_0:1_” followed by a long set of numbers.

@mvolaart Is there any chance this V2 binding will ever be pulled into the main repo? What is blocking this?

Just my words… Would have loved to see it in 2.3!

I started making changes to the binding code as posted in the pull request. Because I wanted it to work for me. My code seems fairly stable (but needs some cleaning up), and I think I should be letting other people know I made these changes. Among other things they fix my review comments in the pr. So that work would not have to be done twice. On the other hand I did make some significant changes in parts of the code that might not necessarily be in line with the intention of the original code. Give these differences and the lack of progress regarding the current pr I’m somewhat reluctant to add my code (when finished) as a pull request to the original pull request. Therefor if @mvolaart can give some insight in his intentions or otherwise what would be a good way to proceed?

@hilbrand Ah, I just read your comment two days ago. After seeing no progress on the PR for a while, I decided to work on your CR requests and see how far I can get. Unfortunately, it seems our two branches must have diverged. Would it be possible for you to push your branch somewhere so I can CR it?

I would like to add that I regret the current process on this PR. A year ago @mvolaart offered his PR, working the steep learning curve of the Eclipse SmartHome, Openhab 2 and the peculiarities of the CR process itself. Some comments were made a month after and addressed quickly. At one point we should decide to either merge or if anything is still amiss, to make the fixes ourselves.

Because the PR was not merged. It took four (!) months for a major maintainer to review this PR. After these issues had been addressed, you decide to add another round of CRs, seven months after the original PR was posted. Even though these are valid points, it cannot be expected of first-time committers (to the openHAB 2 codebase) to keep fixing every single point. I can look at a piece of Linux kernel source-code and find dozens of possible CR issues in each file. Yet, Linux runs on billions of devices.

I know this is an open source community, and we cannot always find similar short time-windows to do PRs, but 4 and 7 months seems excessive and a good method to create hostility to new contributors.