Using a power meter (sml) with openHAB

If you’re wanting to monitor your energy consumption (or your energy created from your solar panels), you probably have an smart meter in your home. I bought the sml reader from “Udo” (http://wiki.volkszaehler.org/hardware/controllers/ir-schreib-lesekopf), but every other sml reader should do.

So at first, connect the sml reader to your smart meter and unlock it with a lamp (they are usually PIN-locked, when installed). So if it’s unlocked proceed with the following:

  1. install libsml (a simple C-program for reading out the sml Reader)
  2. configure libsml
  3. add items to the openHAB
  4. add a rule for populating the items values

compile libsml
Normally in the raspbian distributions for a Raspberry Pi (wich is also used in openHABian), the essentials for compiling should be already installed, just to be sure, start with updating the packages and installing the building tools (I’m refering to a bebian-based package installation via apt-get, perhaps you have to adjust this, if you’re using a different OS) :
sudo apt-get update && sudo apt-get upgrade sudo apt-get install build-essentials

Now we’re going to install libsml in /usr/src, if you want it somewhere else, just change the line above:
sudo apt-get update && sudo apt-get upgrade sudo apt-get install uuid-dev uuid-runtime cd /usr/src git clone https://github.com/dailab/libsml.git cd libsml sudo make

you should now have the library installed, and we can proceed with tests. Before testing, you must check, whether your user is allowed to access the programm - and the device (in my case USB).
Be aware, that after Installation, you want openHAB to execute the program, just for the learning effect and simplicity, I’m using the pi-User for the tests until handing over to openHAB later.
cd /usr/src sudo chown pi:pi examples cd examples sudo chown pi:pi * dmesg |grep pl23

the last command shows you the (USB-)devices for the IR-readers. Usually it will be /dev/ttyUSB0

With that in mind, we can go over configuring libsml.

configuring libsml
In the Example directory is the code in a sml_server.c file, which we have to adjust:

  1. sudo nano sml_server.c
  2. change the line char *device="/dev/ttyUSB0"; with char *device=argv[1];
    with this change, we’re able to use the program with the device as an argument, useful for more than one reader
  3. change the whole function transport_receiver with:
void transport_receiver(unsigned char *buffer, size_t buffer_len) {
   // Danke an Axel (tuxedo) für seinen Beispielcode
   int i;
   double value;
   sml_file *file = sml_file_parse(buffer + 8, buffer_len - 16);
   // the sml file is parsed now
   for (i = 0; i < file->messages_len; i++) {
      sml_message *message = file->messages[i];
      if (*message->message_body->tag == SML_MESSAGE_GET_LIST_RESPONSE) {
         sml_list *entry;
         sml_get_list_response *body;
         body = (sml_get_list_response *) message->message_body->data;
         for (entry = body->val_list; entry != NULL; entry = entry->next) {
            switch (entry->value->type) {
               case 0x51: value= *entry->value->data.int8; break;
               case 0x52: value= *entry->value->data.int16; break;
               case 0x54: value= *entry->value->data.int32; break;
               case 0x58: value= *entry->value->data.int64; break;
               case 0x61: value= *entry->value->data.uint8; break;
               case 0x62: value= *entry->value->data.uint16; break;
               case 0x64: value= *entry->value->data.uint32; break;
               case 0x68: value= *entry->value->data.uint64; break;
               default:
                  value = 0;
            }
            int scaler = (entry->scaler) ? *entry->scaler : 1;
            if (scaler==-1)
               value *= 0.0001;
               if (value) {
               printf("%d-%d:%d.%d.%d*%d#%.3f#\n",
               entry->obj_name->str[0], entry->obj_name->str[1],
               entry->obj_name->str[2], entry->obj_name->str[3],
               entry->obj_name->str[4], entry->obj_name->str[5], value);
            }
         }
         sml_file_free(file);
         exit(0); // processed first message - exit
      }
   }
} 

at the end, we compile the programm again: sudo make

Testing the output:
/usr/src/libsml/examples/sml_server /dev/ttyUSB0
should now result in a reading like this:

pi@raspberrypi:~ $ /usr/src/libsml/examples/sml_server /dev/ttyUSB0
1-0:1.8.0*255#19210.031#
1-0:1.8.1*255#19210.031#
1-0:16.7.0*255#0.484#

So I figure, the first two lines tell me the overall meter consumption and the last and third line tell me the actual power consumption at the moment.

With this information in mind, we can now configure openHAB to execute the programm, read the output and parse it to update the items.

items and rules in openHAB
as mentioned above, we want openHAB to execute the sml_server program, so we have to be sure, that our settings and rights are in line to do that. In my example, I concentrate on using Rasbian and more specific openHABian. Perhaps you have to adjust the users and rights to your needs, if using another OS or openHAB-installation.

configuring rasbian for letting openHAB execute the program
sudo addgroup openhab tty, dialout cd /usr/src/ copy /usr/src/libsml/examples/sml_server ./ sudo chown openhab:openhab sml_server
with this we added the openhab-user to the Groups “tty” and “dialout”. I’m not sure, at least the OH-user should be in the tty-group, but it doesn’t do damage, if he’s also in the dialout-group. Only then, the user is allowed to use USB-devices.
we also copied the program from examples to the /usr/src and changed the owner of the sml_server program to “openhab”, so, this user can execute the program.

So, wer’re ready to add the .items:

Number sensors_consumption_power	"power consumption [%.1f kwh]"
Number sensors_status_power		"power status [%.1f kwh]"

first one will tell the present power consumption, second one shows the status of the power meter.

lastly, we set up the rule for executing the program and updating the items:

rule "power meter"
	when
		Time cron "0,30 */1 * * * ?" // this one cycles every 30 seconds. depends on your needs
	then
		// getting the payload of the meter
		var String meter_payload = executeCommandLine("/usr/src/sml_server /dev/ttyUSB0", 5000) // note the argument /dev/ttyUSB0 - your meter-device-id goes here 

		// splitting the payload - first in lines, then getting counterStr and consumptionStr with delimiter "#"
		val lines = meter_payload.split('\n')
		val counterStr = lines.get(0).split('#').get(1)
	  	val consumptionStr = lines.get(2).split('#').get(1)

		// Updating the items
		if (sensors_status_power.state != counterStr) sensors_status_power.sendCommand(counterStr)
		sensors_consumption_power.postUpdate(consumptionStr)
end

That’s it. Now you should get an update on the power meter, regarding to the cycle-time you setup in the rule.

2 Likes

That´s great! working for me.

I have two-way-meters, so i changed the rule to get all of the values.

But one problem occurs:

My second Power meter is for pv only, so when it´s dark outside, there is no power from the pv modules. So i only get 4 lines instead of 5 from the sml_reader.

And when there is only 4 lines, i can see many errors in the openhab-log and the rule doesn´t work anymore.

Is there a way to change this, that i get no errors during the night?

And another question:
Can you explain me the sml_server.c program a little bit? You get 3 lines from your power meter, i get 5 lines with the same code. But i don´t know, if there are some more lines? On several forums in the internet i saw additional lines, like voltage, power separated for L1, L2 and L3 and so on.

How can i check, if there is no more additional information from the power meter than that i already get?

ok. Scripting 1on1! :wink:
val lines = meter_payload.split('\n')
this one splits the whole payload in lines (\n signifys a line break). So you have to count the number of lines you get, as the variable lines is a array, you can check how big the array is: lines.size() will tell you the array count.
with that in mind, you can do many things, I’ll explain to you the simplest: you won’t ask for every line, because you know, you always get at least 4 lines, and only by day you get the fifth. So there’s no need to cycle through everything, just make sure, the fifth line is present. (I’m aware, that’s nothing you would do in a professional Setup, but hey, we’re talking smart HOME, don’t we? ;))

so, the line reading out the fifth would read something like this at present?
val solarpowerStr = lines.get(5).split('#').get(1)
Change it to

if (lines.size() >4) { 
	// it's day, and there's power from solar panel
	val solarpowerStr = lines.get(5).split('#').get(1) 
} else {
	// it's night (or too cloudy), so no power from solar panel
	solarpowerStr = 0
}

If sml_server doesn’t give out more Information, it could be of two Things:

  1. your power meter doesn’t have that information in its sml-response
  2. your power meter has to be configured to include more Information

I don’t know anything with this power meters and don’t know the sml-protocol. I found some bits of pieces here and there and put it together for my puzzle! :wink:
I’m afraid, you have to ask your electrician, what kind of information your power meter is capable of putting out. I guess, there must be some way to read this additional information, especially for power meters used in PV installations.

You didn´t understand, what i meant:

My power meter gives me some hex output, if i look to minimode in linux. sml_server prses this to readable values.

But i don´t know if in this hex-output is more information. So it could be that my power meter sends more information and sml_reader doens´t parse it, or my power meter only sends this information i get out of sml_reader.

My question is, if i have to expand sml_reader for more values or if i already get all of the values, my power meter sends?

Hope you understand, what i want to ask.

In german short:

Gibt mir sml_reader wirklich alle Werte aus, die gesendet werden oder parst das Programm nur die Werte, die in sml_reader.c fest einprogrammiert wurden? Also könnten da durchaus aktuell noch mehr Werte gelesen werden, welche nur sml_reader nicht kennt? In dem Fall müsste ich dann nur die sml_reader.c Datei entsprechend erweitern und würde den Rest auch noch sehen?

I’m no developer and I don’t know the SML-protocol, but I (think I) understand: the code from the dailab reads the SML output and transforms it in seperate ASCII-lines for every entity, that’s found in the stream. Therefore I assume, the hex-code you see with mincom doesn’t include the additional information also.


That’s why, I suggested talking to your electricion, if your power meter is basically capable of giving out that information, and perhaps only has to be configured to do so in the first place. If he says, it should append those information also, and it’s still not coming through, you’ll have to analyze the output. My examples relies on the information, which is coming from libsml. So, if the power meter should also include the addititional fields, you have to get in touch with the dailab developers, if there’s a possibility to get that into libsml also.

Doesn´t work for me. I get many errors.

There is one error i corrected myself: lines.get(5)

This must be lines.get(4), because it counts from 0 to 4 (5 lines), not from 1 to 5. But with this corrected, there are also many errors.


I was thinking, the changes to sml_server.c you made before the make-command, are the variables to read out the values? Is this not controlled through this?


One more question:
In the last few lines of the rules-code, one time you used xyz.sendCommand and two times you used xyz.postUpdate.

Can you explain why you changed it there?

I did some loggings:

val lines = meter_payload.split('\n')
logInfo("Power Meter PV lines", "PV lines ---> " + lines.toString() + " lines")
2017-02-06 08:21:05.092 [INFO ] [.m.script.Power Meter PV lines] - PV lines ---> [Ljava.lang.String;@10b4bda lines

Can someone explain me this? It should be 5 lines at this time.

The new transport_receiver function I found (I didn’t write it…) cycles through the payload of the sml_reader and looks for specific types. As I don’t know the SML-protocol of the power meters, I don’t know, whether the list (0x51, 0x52, …) is exhaustive or your specific attributes are missing. Again, at first, I would make sure with my electrician, that the power meter’s readout contains all attributes. If they’re still missing, you should have a closer look at the SML-protocol.

the difference between “sendCommand” and “postUpdate” is, that postUpdate just changes the state of the item internally with openHAB, whereas sendCommand involves the relevant binding. In most cases, the effect is be the same. In our case it should be regardless, because it’s just reading values, so it should be irrelevant, whether the command reaches the device or not. (to be honest, I just copied sendCommand from @rlkoshak’s code… ;))

Please dump the errors in the log, I can take a look on them.

Ljava.lang.String;@ is returned where you use string arrays as strings. the val lines is an array, you either have to cycle through each array-key and print the value - or you just print the meter_payload:
logInfo("Power Meter PV lines", "PV lines ---&gt; " + meter_payload.toString() + " lines")

I did some more testings and corrected some errors, also i included some if´s to prevent the rule to go into error.

Here are my rules for my two powermeters:

Now they are working and i don´t get any error. Sometimes the value from the powermeter was empty, so i got errors. This is fixed in this rules already.

// Stromzähler Haus ---> 2-Richtungszähler Bezug-Einspeisung
rule "power meter 0"
	when
		Time cron "0/30 * * * * ?" // this one cycles every 30 seconds. depends on your needs
	then
		// getting the payload of the meter
		var String meter_payload = executeCommandLine("ssh -i /home/openhab/.ssh/key_openhab debian@192.168.102.73 /usr/src/libsml/examples/sml_server /dev/lesekopf0", 5000) // note the argument /dev/ttyUSB0 - your meter-device-id goes here 
		// splitting the payload - first in lines, then getting counterStr and consumptionStr with delimiter "#"
		val lines = meter_payload.split('\n')
		if (lines.size('\n') > 3) { 
				val counterStr = lines.get(0).split('#').get(1)
				val supplyStr = lines.get(1).split('#').get(1)
				val consumptionStr = lines.get(4).split('#').get(1)

				// Updating the items
				stromzaehler0_bezug.sendCommand(counterStr)
				stromzaehler0_einspeisung.postUpdate(supplyStr)
				stromzaehler0_leistung.postUpdate(consumptionStr)
		}
end

// Stromzähler PV ---> Erzeugung
rule "power meter 1"
	when
		Time cron "5,35 * * * * ?" // this one cycles every 30 seconds on second 5 and 35. depends on your needs
	then
		// getting the payload of the meter
		var String solar_meter_payload = executeCommandLine("ssh -i /home/openhab/.ssh/key_openhab debian@192.168.102.73 /usr/src/libsml/examples/sml_server /dev/lesekopf1", 5000) // note the argument /dev/ttyUSB0 - your meter-device-id goes here 
		// splitting the payload - first in lines, then getting counterStr and consumptionStr with delimiter "#"
		val solar_lines = solar_meter_payload.split('\n')
		if (solar_lines.size('\n') > 3) {
				val solarcounterStr = solar_lines.get(0).split('#').get(1)
				val solar1Str = solar_lines.get(1).split('#').get(1)
				if (solar_lines.size('\n') > 4) { 
						val solarpowerStr = solar_lines.get(4).split('#').get(1)
						stromzaehler1_leistung.postUpdate(solarpowerStr)
				}
				if (solar_lines.size('\n') < 5) {
						val solarpowerStr = 0
						stromzaehler1_leistung.postUpdate(solarpowerStr)
				}
				// Updating the items
				stromzaehler1_erzeugung.sendCommand(solarcounterStr)
				stromzaehler1_ungenutzt.postUpdate(solar1Str)				
		}
end

This two rules run with the same instance of the sml_server. So only one reding at same time. I can read out the power meters only with about 5 seconds difference.

I will change this in the future and start 2 instances of sml_server to read out the two power meters at the same time.

1 Like

Here is my latest rule for reading out my two power meters at the same time:

Tested with OH2. I moved my Openhab Instalation to the same machine where the opto-readers are connected, so no more ssh… I duplicated the sml_server, so i can start a second instance at the same time.

Now with the power consumption of both readers from the same time, i can calculate the power, which consumes my house, even when there is solar-power injected. Before the changes, i only got the real consumption at night, when there was no sun. So now i don´t need an extra power meter anymore to only get the power consumption of my house.

I tested with every 10 seconds also, this was working too. Shorter intervals i haven´t tried. If you make the intervals too low, you will get more errors or only get values from one power meter at same time.

// Alle Stromzähler auslesen
rule "Alle Stromzähler auslesen"
	when
		Time cron "0/30 * * * * ?" // this one cycles every 30 seconds. depends on your needs
	then
		// getting the payload of the meter
		var String meter_payload = executeCommandLine("/usr/src/sml_server /dev/lesekopf0",5000) // note the argument /dev/ttyUSB0 - your meter-device-id goes here
		var String solar_meter_payload = executeCommandLine("/usr/src/sml_server1 /dev/lesekopf1",5000)
		val lines = meter_payload.split('\n')
		val solar_lines = solar_meter_payload.split('\n')
		if ((lines.size('\n') == 5) && ((solar_lines.size('\n') == 5)) { 
				val counterStr = lines.get(0).split('#').get(1)
				val supplyStr = lines.get(1).split('#').get(1)
				val consumptionStr = lines.get(4).split('#').get(1)
				val solarcounterStr = solar_lines.get(0).split('#').get(1)
				val solar1Str = solar_lines.get(1).split('#').get(1)
				val solarpowerStr = solar_lines.get(4).split('#').get(1)
				// Updating the items
				stromzaehler0_bezug.sendCommand(counterStr)
				stromzaehler0_einspeisung.postUpdate(supplyStr)
				stromzaehler0_leistung.postUpdate(consumptionStr)
				stromzaehler1_leistung.postUpdate(solarpowerStr)
				stromzaehler1_erzeugung.sendCommand(solarcounterStr)
				stromzaehler1_ungenutzt.postUpdate(solar1Str)
				var hausverbrauch_aktuell = (Double::parseDouble(consumptionStr)) + (Double::parseDouble(solarpowerStr))
				stromzaehler_haus_leistung.postUpdate(hausverbrauch_aktuell)
		}
		else if ((lines.size('\n') == 5) && ((solar_lines.size('\n') == 4)) { 
				val counterStr = lines.get(0).split('#').get(1)
				val supplyStr = lines.get(1).split('#').get(1)
				val consumptionStr = lines.get(4).split('#').get(1)
				val solarcounterStr = solar_lines.get(0).split('#').get(1)
				val solar1Str = solar_lines.get(1).split('#').get(1)
				val solarpowerStr = 0
				// Updating the items
				stromzaehler0_bezug.sendCommand(counterStr)
				stromzaehler0_einspeisung.postUpdate(supplyStr)
				stromzaehler0_leistung.postUpdate(consumptionStr)
				stromzaehler1_leistung.postUpdate(solarpowerStr)
				stromzaehler1_erzeugung.sendCommand(solarcounterStr)
				stromzaehler1_ungenutzt.postUpdate(solar1Str)
				var hausverbrauch_aktuell = (Double::parseDouble(consumptionStr))
				stromzaehler_haus_leistung.postUpdate(hausverbrauch_aktuell)
		}
		else if ((lines.size('\n') == 5) && ((solar_lines.size('\n') == 1)) {
				logInfo("Fehler Power Meter auslesen", "nur Haus Update --- Haus lines ---> " + lines.size('\n') + " Zeilen " + "PV lines ---> " + solar_lines.size('\n') + " Zeilen")
				val counterStr = lines.get(0).split('#').get(1)
				val supplyStr = lines.get(1).split('#').get(1)
				val consumptionStr = lines.get(4).split('#').get(1)
				// Updating the items
				stromzaehler0_bezug.sendCommand(counterStr)
				stromzaehler0_einspeisung.postUpdate(supplyStr)
				stromzaehler0_leistung.postUpdate(consumptionStr)
		}
		else if ((lines.size('\n') == 1) && ((solar_lines.size('\n') == 5)) {
				logInfo("Fehler Power Meter auslesen", "nur PV Update --- Haus lines ---> " + lines.size('\n') + " Zeilen " + "PV lines ---> " + solar_lines.size('\n') + " Zeilen")
				val solarcounterStr = solar_lines.get(0).split('#').get(1)
				val solar1Str = solar_lines.get(1).split('#').get(1)
				val solarpowerStr = solar_lines.get(4).split('#').get(1)
				// Updating the items
				stromzaehler1_leistung.postUpdate(solarpowerStr)
				stromzaehler1_erzeugung.sendCommand(solarcounterStr)
				stromzaehler1_ungenutzt.postUpdate(solar1Str)
		}
		else {
				logInfo("Fehler Power Meter auslesen", "kein Update --- Haus lines ---> " + lines.size('\n') + " Zeilen " + "PV lines ---> " + solar_lines.size('\n') + " Zeilen")
		}		
end

Can someone tell my, what´s the meaning of “,5000” in this line on top of the rule:

var String meter_payload = executeCommandLine("/usr/src/sml_server /dev/lesekopf0",5000)

Is the exec-command waiting for max. 5 seconds for an answer?

I often got error messages or one of the two powermeter wasn´t read out the right way (got empty string). So i added a little wait-time and now it seems to work much better.

I only added the line with the “Thread Sleep” command:

// Alle Stromzähler auslesen
rule "Alle Stromzähler auslesen"
	when
		Time cron "0/30 * * * * ?" // this one cycles every 30 seconds. depends on your needs
	then
		// getting the payload of the meter
		var String meter_payload = executeCommandLine("/usr/src/sml_server /dev/lesekopf0",5000)
		var String solar_meter_payload = executeCommandLine("/usr/src/sml_server1 /dev/lesekopf1",5000)
		Thread::sleep(500) // wait some time **// <---- this one is new**
		val lines = meter_payload.split('\n')
		val solar_lines = solar_meter_payload.split('\n')

Attention: The old libsml repository is dead!

It still worked but created a compile error on my new and plain Debian Stretch 9.0 box. After opening a bug report I found out about it.

Just pulled the new libsml repository. Compiling works, also modifying sml_server.c works, but you no longer need to modify the line char *device="/dev/ttyUSB0"; with char *device=argv[1]; as it is already in the code.

If you like you can download the already modified sml_server.c file here. I pulled it from the new repository and modified it today.

I changd to smlreader-binding from marketplace some time ago, so no need for this external programm anymore. Now i can read out the powermeter directly from openhab.

My power meter needs Baud rate 300, parity even 7E1
I can’t find the right parameters for this?

Hi together,
first of all, many thanks to @binderth for this tutorial.

I did everything as described (with the newest repo files mentioned by @Roi).
Unfortunately, the query on the sml-server does not work as expected. The command does not return with any output values. It just stuck and have to be aborted.

It is strange that when I call “cat / dev / ttyUSB0” the USB interface returns the first time all data as binary. If I then execute the sml_server command, the data switches to ASCII letters at the cat command. However, as I said, the sml_server command never returns a value, the command simply hangs and must be aborted with CTRL + C. And if the connection to the smart meter goes lost, the data will be returned one more time as binary until the sml_server command will be executed one more time.

Does any of you have some hint or trick for me? What am I doing wrong?
Thx a lot
David

I’m sorry, I don’t know an answer to that. I since switched to powermeter-binding.
It’s not (yet) in the normal distro, but if I understand correctly, it could be in 2.4 (if the merge is successful…)

In the meantime, you can download it from the Marketplace - please follow the

I hope your powermeter is compatible with the binding (but should be, if using SML).

It’s a bit of a mess at first - but please read the above thread… :wink:

1 Like

Hi together!

To record this for documentation:
Because I do not like to use “beta” software and therefore (still) did not want to rely on the “powermeter-binding”, I just went the way on the “serial binding”. I simply configured my USB device in advance with the Linux command “stty” and the corresponding configuration of my adapter and then simply read the values ​​via the “serial binding” as plain text via rule (REGEX in item didn’t work as expected).

If it helps someone, here my configuration (hardware and settings) - this should not be an advertisement, but I know that it would have helped me in the search for it in conjunction with Openhab (especially for German users):

  • smart meter LOGAREX LK13B (from “Bayernwerk” for our heat pump)
  • “IR Schreib/Lesekopf USB (Optokopf)” by Weidmann-Elektronik
  • configured with: “stty -F /dev/ttyUSB0 9600 -parenb cs8 -cstopb -ixoff -crtscts -hupcl -ixon -opost -onlcr -isig -icanon -iexten -echo -echoe -echoctl -echoke”

For safety, I will run the “stty” command on startup via a rule, to ensure correct settings for the usb device.

I hope this will help some following readers.

2 Likes

Hi Dave, thanks for sharing your experience. As the serial binding doc does not mention how to read text via rules can you share the code of this rule…

then simply read the values ​​via the “serial binding” as plain text via rule (REGEX in item didn’t work as expected).

Thx

Of course, no problem!

Here it is:

/---------------------------------
// Serial binding
//---------------------------------
String ttyUSB0      "ttyUSB0: [%s]"     { serial="/dev/ttyUSB0@9600" }
Group smartMeterHeatingGroup    "Smartmeter"
Number:Energy smartMeterHeatingReadingTotal    "Zählerstand Gesamt [%.4f kWh]"     <consumption>    (smartMeterHeatingGroup)
Number:Energy smartMeterHeatingReadingHT                  "Zählerstand HT [%.4f kWh]"                  <consumption>    (smartMeterHeatingGroup)
Number:Energy smartMeterHeatingReadingNT                  "Zählerstand NT [%.4f kWh]"                  <consumption>    (smartMeterHeatingGroup)





//-----------------------
// Serial binding
//-----------------------
rule "Serial input (Smartmeter)"
when
    Item ttyUSB0 received update
then
    _lockSerialInput.lock()
    try
    {
		if (ttyUSB0.state === null) return;
		var String rawString = ttyUSB0.state.toString
		var Double total = Double::parseDouble(rawString.substringBetween("1-0:1.8.0*255(", "*kWh)"))
		var Double ht = Double::parseDouble(rawString.substringBetween("1-0:1.8.1*255(", "*kWh)"))
		var Double nt = Double::parseDouble(rawString.substringBetween("1-0:1.8.2*255(", "*kWh)"))
		smartMeterHeatingReadingTotal.postUpdate(total)
		smartMeterHeatingReadingHT.postUpdate(ht)
		smartMeterHeatingReadingNT.postUpdate(nt)
    }
    finally
    {
        _lockSerialInput.unlock()
    }
end

2 Likes