This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

Norwegian HAN-interface - Kamstrup meter
#1
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

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
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


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  Smile

Will update this post when i have more info..
Reply


Messages In This Thread
Norwegian HAN-interface - Kamstrup meter - by oveh - 31.01.2019, 13:27

Forum Jump: