31.01.2019, 13:27
Hello
I am planing to make a script that receives the power data from a Kamstrup Power meter.
In Norway all the power meters has been changed to smart meters, and one of the requirement from the government, was that customer should have access to the data.
Google translate this site for more info:
https://www.nek.no/info-ams-han-utviklere/
As far as i know there is 3 types of power meters used, Kamstrup, Aidon and Kaifa.
They are all sending (pushing) data on a port (Physical interface is MBUS), and the data can be read with a Mbus to serial converter (slave type). I am using this, to connect LM to my Kamstrup meter:
https://www.aliexpress.com/item/USB-tran...62958.html
Since i have a Kamstrup meter, i will focus on that type in this thread.
More info about Kamstrup HAN interface
https://www.nek.no/wp-content/uploads/20...181022.pdf
https://www.nek.no/wp-content/uploads/20...ev_3_1.pdf
Here is a residential script that reads the data, pushed from the kamstrup meter.
There is two types of packages:
- every 10 sec we get the basic data
- every 1 hr we get the basic + a little bit more.
Example of a basic data (ID replaced with XX):
* hexstring [228]: 7E A0 E2 2B 21 13 23 9A E6 E7 00 0F 00 00 00 00 0C 07 E3 01 1F 04 0D 24 0A FF 80 00 00 02 19 0A 0E 4B 61 6D 73 74 72 75 70 5F 56 30 30 30 31 09 06 01 01 00 00 05 FF 0A 10 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX 09 06 01 01 60 01 01 FF 0A 12 36 38 34 31 31 32 31 42 4E 32 34 33 31 30 31 30 34 30 09 06 01 01 01 07 00 FF 06 00 00 0E BB 09 06 01 01 02 07 00 FF 06 00 00 00 00 09 06 01 01 03 07 00 FF 06 00 00 01 C4 09 06 01 01 04 07 00 FF 06 00 00 00 00 09 06 01 01 1F 07 00 FF 06 00 00 05 C1 09 06 01 01 33 07 00 FF 06 00 00 03 27 09 06 01 01 47 07 00 FF 06 00 00 03 91 09 06 01 01 20 07 00 FF 12 00 DC 09 06 01 01 34 07 00 FF 12 00 DE 09 06 01 01 48 07 00 FF 12 00 DD F7 9B 7E
CRC
The checksum is the same as the CRC-16/X-25 on this site: https://crccalc.com/
Remove start and end byte (7E) + CRC bytes.
Both of the following functions should work:
I am new to LUA, so please help optimize the code
Will update this post when i have more info..
I am planing to make a script that receives the power data from a Kamstrup Power meter.
In Norway all the power meters has been changed to smart meters, and one of the requirement from the government, was that customer should have access to the data.
Google translate this site for more info:
https://www.nek.no/info-ams-han-utviklere/
As far as i know there is 3 types of power meters used, Kamstrup, Aidon and Kaifa.
They are all sending (pushing) data on a port (Physical interface is MBUS), and the data can be read with a Mbus to serial converter (slave type). I am using this, to connect LM to my Kamstrup meter:
https://www.aliexpress.com/item/USB-tran...62958.html
Since i have a Kamstrup meter, i will focus on that type in this thread.
More info about Kamstrup HAN interface
https://www.nek.no/wp-content/uploads/20...181022.pdf
https://www.nek.no/wp-content/uploads/20...ev_3_1.pdf
Code:
-- Check if port is open, open serial port if not
if not port then
require('serial')
port = serial.open('/dev/ttyUSB0', { baudrate = 2400 })
port:flush()
data = ''
end
-- Read on byte, or time out after 1 sec
byte = port:read(1, 1)
if byte then
-- if byte read, add byte to data array
data = data .. byte
else
-- read timeout: No more data in this package
if string.len(data) > 1 then
loghex(data)
end
data = ""
end
There is two types of packages:
- every 10 sec we get the basic data
- every 1 hr we get the basic + a little bit more.
Example of a basic data (ID replaced with XX):
* hexstring [228]: 7E A0 E2 2B 21 13 23 9A E6 E7 00 0F 00 00 00 00 0C 07 E3 01 1F 04 0D 24 0A FF 80 00 00 02 19 0A 0E 4B 61 6D 73 74 72 75 70 5F 56 30 30 30 31 09 06 01 01 00 00 05 FF 0A 10 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX 09 06 01 01 60 01 01 FF 0A 12 36 38 34 31 31 32 31 42 4E 32 34 33 31 30 31 30 34 30 09 06 01 01 01 07 00 FF 06 00 00 0E BB 09 06 01 01 02 07 00 FF 06 00 00 00 00 09 06 01 01 03 07 00 FF 06 00 00 01 C4 09 06 01 01 04 07 00 FF 06 00 00 00 00 09 06 01 01 1F 07 00 FF 06 00 00 05 C1 09 06 01 01 33 07 00 FF 06 00 00 03 27 09 06 01 01 47 07 00 FF 06 00 00 03 91 09 06 01 01 20 07 00 FF 12 00 DC 09 06 01 01 34 07 00 FF 12 00 DE 09 06 01 01 48 07 00 FF 12 00 DD F7 9B 7E
Code:
Start flag 7E
A0 E2 2B 21 13 23 9A E6 E7 00
Date/time 0F 00 00 00 00 0C 07 E3 01 1F 04 0D 24 0A FF 80 00 00
02 19
0E 4B
Kamstrup_V0001 61 6D 73 74 72 75 70 5F 56 30 30 30 31
ID 09 06 01 01 00 00 05 FF 0A 10 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
Type 09 06 01 01 60 01 01 FF 0A 12 36 38 34 31 31 32 31 42 4E 32 34 33 31 30 31 30 34 30
(6841121BN243101040)
Act Pow+ 09 06 01 01 01 07 00 FF 06 00 00 0E BB
Act Pow- 09 06 01 01 02 07 00 FF 06 00 00 00 00
Rea Pow+ 09 06 01 01 03 07 00 FF 06 00 00 01 C4
Rea Pow- 09 06 01 01 04 07 00 FF 06 00 00 00 00
Current 09 06 01 01 1F 07 00 FF 06 00 00 05 C1
Current 09 06 01 01 33 07 00 FF 06 00 00 03 27
Current 09 06 01 01 47 07 00 FF 06 00 00 03 91
Voltage 09 06 01 01 20 07 00 FF 12 00 DC
Voltage 09 06 01 01 34 07 00 FF 12 00 DE
Voltage 09 06 01 01 48 07 00 FF 12 00 DD
CRC F7 9B
Stop flag 7E
CRC
The checksum is the same as the CRC-16/X-25 on this site: https://crccalc.com/
Remove start and end byte (7E) + CRC bytes.
Both of the following functions should work:
Code:
function crc16(data)
local crc = 0xFFFF
for i = 1, #data do
crc = bit.bxor(crc, data:byte(i))
for j = 1, 8 do
local k = bit.band(crc, 1)
crc = bit.rshift(crc, 1)
if k ~= 0 then
crc = bit.bxor(crc, 0x8408)
end
end
end
--return bit.bxor(crc, 0xFFFF)
return string.format("%X",bit.bxor(crc, 0xFFFF))
end
Code:
local crcTable = {
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
}
function crc16(v)
local crc = 0xffff
for i = 1, #v do
local j = bit.band( bit.bxor( v:byte(i), crc ), 0xFF )
crc = bit.band( bit.bxor(crcTable[j+1], bit.rshift(crc, 8)), 0xffff)
end
return bit.bxor(crc, 0xffff)
end
I am new to LUA, so please help optimize the code
Will update this post when i have more info..