Support for SML protocol used by smart power meter (eg. ISKRA MT681)?

Hi there,

my power meter has been recently replaced by a new smart meter (ISKRA MT681). The new meter got an optical port (called D0) and transmits the data every few seconds over a serial interface (9600/8N1) as binary. As far as I know, the protocol is call SML (smart message language).

Does the HA has support for such devices?

regards,
Michael

1 Like

If you can’t find anything ready and the power meter spits out strings of data, you can use the serial sensor.

Ok, just tried cat /dev/ttyUSB0, but the output is binary encoded.

Google pointed me to https://github.com/sunny5/nodeehz, apt-getting node…

Take a look at this:

Node-Red can be installed as a plugin in Hassio, and is well integrated.

@namadori: thx for the input, i’ll take a look at it…

as a proof of work I modified the above mentioned js and I’m getting the right values…

    //*** Continuously read SML data from EHZ and output OBIS values 16.7.0 (Wirkleistung), (Bezug) 1.8.0 and (Einspeisung) 2.8.0

var serialport = require("serialport");
var util = require("util"), repl = require("repl");

var serial_port = new serialport("/dev/ttyUSB0", {baudRate: 9600, databits: 8, stopbits:1, parity:'none', buffersize:2048, parser: serialport.parsers.raw});
var regCompleteMsg = new RegExp('1b1b1b1b01010101.*1b1b1b1b.{8}');
var reg16_7_0 = new RegExp('070100100700ff.{16}(.{6})0177');
var reg1_8_0 =  new RegExp('070100010800ff.{24}(.{14})0177');
var reg2_8_0 =  new RegExp('070100020800ff.{16}(.{14})0177');
var arr16_7_0, arr1_8_0, arr2_8_0;
var int1_8_0=0, int1_8_0prev=0, int2_8_0=0, int16_7_0;
var chunk = "";

serial_port.on("data", function (data) {
   chunk += data.toString('hex');
   if (chunk.match(regCompleteMsg)) {
      arr16_7_0 = chunk.match(reg16_7_0);
      arr1_8_0 = chunk.match(reg1_8_0);
      arr2_8_0 = chunk.match(reg2_8_0);

      if (arr16_7_0 == null || arr1_8_0 == null || arr2_8_0 == null) {
         console.log("null");
         return;
      }

      int16_7_0 = parseInt(arr16_7_0[1],16);
      int1_8_0 = parseInt(arr1_8_0[1],16)/10000;
      int2_8_0 = parseInt(arr2_8_0[1],16)/10000;

      if (arr1_8_0[1] > int1_8_0prev) {
         int1_8_0prev = arr1_8_0[1];
      }
      else {
         int1_8_0prev = arr1_8_0[1];
         int16_7_0 = int16_7_0*-1;
      }

      console.log('---new data---');
      console.log("Wirkleistung momentan: " + int16_7_0  + " W");
      console.log("Gesamt Bezug: " + int1_8_0 + " kW");
      console.log("Gesamt Einspeisung: " + int2_8_0 + " kW");
      //console.log(chunk);
      chunk = "";
   }
})
serial_port.on("error", function (msg) {
  util.puts("error: "+msg);
})
repl.start("=>")

would be great, if home asssistant will support sml protocol in the future. currently it is only supporting dutch dsmr protocoll.

home assistant dsmr sensor:

openhab supports both protocolls:

als an alternative you could use volkszaehler (https://www.volkszaehler.org/) - it comes with own database and some basic chartings. I Integrated it into my homeassistant reading the json from an url:

Update: this is my current state of implementation based on https://gist.github.com/Tafkas/5dfc85fcb9b23e9cf9f08e9b4c143889

- platform: command_line
    name: sml_output
    command: python /home/homeassistant/.homeassistant/python_scripts/sml.py
    scan_interval: 15  
    
  # SML Output zerlegen
  - platform: template
    sensors:
      sml_output_bezug:
        value_template: "{% set list = states.sensor.sml_output.state.split(':') %} {{ list[0] | float | round(2) }}"
      sml_output_einspeisung:
        value_template: "{% set list = states.sensor.sml_output.state.split(':') %} {{ list[1] | float | round(2) }}"
      sml_output_aktueller_verbrauch:
        value_template: "{% set list = states.sensor.sml_output.state.split(':') %} {{ list[2] | int }}"

sml.py

#!/usr/bin/env python
# encoding: utf-8
"""
pysml.py
Created by Christian Stade-Schuldt on 2014-10-25.
"""

import sys
import os
import datetime
import serial
import time
import re


# SML regexes
complete_message_regex = '1b1b1b1b01010101.*1b1b1b1b.{8}'
meter_108_regex = '070100010800ff.{24}(.{14})0177'
meter_208_regex = '070100020800ff.{16}(.{14})0177'
meter_167_regex = '070100100700ff.{16}(.{6})0177'

def main():
    ser = serial.Serial('/dev/ttyUSB0', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=0 )
    tty_error = 0
    t = 30
    if tty_error == 0:
        while t > 0:
            t -=1
            data = ser.read(4096)
            data = data.encode('hex')
            if re.match(complete_message_regex, data):

                m108 = re.search(meter_108_regex, data)
                m208 = re.search(meter_208_regex, data)
                m167 = re.search(meter_167_regex, data)

                if m108 and m208 and m167:
                    m167 = int(m167.group(1),16)
		    # check if value is negative
                    if m167 > 0x7FFFF:
                        m167 -= 0x1000000
                    d108 = int(m108.group(1),16)/10000.0
                    d208 = int(m208.group(1),16)/10000.0
                    d167 = m167

                    print("{0}:{1}:{2}:{3}".format(d108,d208,d167,datetime.datetime.now().strftime('%d.%m.%Y')))
                    t = 0

            time.sleep(1)

if __name__ == '__main__':
    main()

hello Christian,

I am very interested what you did in order to get the values of a smart meter.
Which device do you have?
How do you get the sml values?
I tried to use the https://flows.nodered.org/node/node-red-contrib-smartmeter module, but installation fails.
How did you manage it? Or did you something else?

If you like, you can respond in German :wink:

I noticed the similar problem. Can‘t install node-red-contrib-smartmeter. How did you solve the problem?

Hi,

I use vzlogger (without volkszaehler middleware) to directly send to my MQTT broker. Works very well.
See also here:

yeah, but seems the insatllation of the smartmeter node fails with a python error

Any solution for taht so far ?

I’m using the same power meter and I got one of these. Works like a charm. Values are being transferred via mqtt.

As I also have a power meter with an SML protocol (Itron OpenWay 3.HZ), I wanted to describe my way to get to the values using a serial reader and sml2mqtt in Docker as an alternative.

Maybe this is helpful for others too:

sml2mqtt provides a good analyze functionality, so you don’t have to dive into details about your meter upfront.



First run a temporary copy of the container with the shell as entrypoint, as sml2mqtt will quit immediately without a valid conig.
That way we can rum sml2mqtt manually in the container to analyze the incoming data and create the config.
After that we can start another final copy of the container and remove the temporary one.

You need to map a directory from the host (or a docker volume) to the sml2mqtt folder inside the container, so the config can be persisted:

docker run -it --name sml2mqtt_analyze --volume /opt/sml2mqtt:/sml2mqtt --device=/dev/ttyUSB0 --entrypoint sh spacemanspiff2007/sml2mqtt:latest

Inside the shell run sml2mqtt with the analyze flag and a path where the config should be created:

sml2mqtt -c /sml2mqtt/config.yml --analyze

This will fail as the serial port inside the sample config it just created is most likely wrong.

So edit the config using vi /sml2mqtt/config.yml and press i to enter edit mode.
Remove one of the two port entries from the sample config and adjust the other one to your needs:

ports:
- url: /dev/ttyUSB0   # Device path
  timeout: 3  # Seconds after which a timeout will be detected (default=3)

Also edit the mqtt connection settings to your needs.

Then press Esc to leave edit mode and enter :wq to save and leave vi.

Now start sml2mqtt with the analyze flag again, so se can see the structure fo the incoming data:
(We don’t have to specify the config location again, as it now exists at the default location.)

sml2mqtt --analyze

Check the output for the value server_id.
Replace “DEVICE_ID_HEX” in the config with this value:

devices:   # Device configuration by ID or url
  0b013454760009893245:
    mqtt:    # Optional MQTT configuration for this meter.
    ...

In the device sample configuration, there’s also the possibility to filter out unwanted values by their OBIS code (skip section),
or to apply special settings to single OBIS values (values section).

If you don’t want to use this, simply remove the whole skip and values sections.

After that, run sml2mqtt without the –analyze flag, which will result in continous reading and also the reporting to your MQTT server.
If everything works, stop sml2mqtt by pressing CTRL+C and exit the temporary container by leaving the shell with exit .

Now setup the final container, which will autorun sml2mqtt instead of a shell when it starts:

docker run --detach --name sml2mqtt --volume /opt/sml2mqtt:/sml2mqtt --device=/dev/ttyUSB0 spacemanspiff2007/sml2mqtt:latest

After that you can delete the temporary container.