Acties:
  • 0 Henk 'm!

  • devastator83
  • Registratie: Januari 2012
  • Laatst online: 18:03
Hoi,

Ik probeer de checksum van een DSMR telegram te berekenen, maar het lukt me maar niet.
Ik heb gelezen dat het CRC16-IBM is met 0xA001, maar zelfs dan kom ik niet dezelfde CRC uit ...

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/FLU5\253769484_A

0-0:96.1.4(50217)
0-0:96.1.1(3153414733313030313239383636)
0-0:1.0.0(240606201844S)
1-0:1.8.1(007446.749*kWh)
1-0:1.8.2(009269.520*kWh)
1-0:2.8.1(010848.406*kWh)
1-0:2.8.2(004287.921*kWh)
0-0:96.14.0(0001)
1-0:1.4.0(00.062*kW)
1-0:1.6.0(240602103000S)(02.478*kW)
0-0:98.1.0(13)(1-0:1.6.0)(1-0:1.6.0)(230601000000S)(230508171500S)(02.162*kW)(230701000000S)(230601201500S)(03.496*kW)(230801000000S)(230720204500S)(03.140*kW)(230901000000S)(230819134500S)(02.424*kW)(231001000000S)(230913151500S)(02.576*kW)(231101000000W)(231022121500S)(04.257*kW)(231201000000W)(231129124500W)(03.465*kW)(240101000000W)(231215143000W)(03.437*kW)(240201000000W)(240106154500W)(04.855*kW)(240301000000W)(240226171500W)(03.339*kW)(240401000000S)(240313174500W)(03.056*kW)(240501000000S)(240427201500S)(03.043*kW)(240601000000S)(240530213000S)(02.764*kW)
1-0:1.7.0(00.263*kW)
1-0:2.7.0(00.000*kW)
1-0:21.7.0(00.051*kW)
1-0:41.7.0(00.057*kW)
1-0:61.7.0(00.154*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)
1-0:32.7.0(235.1*V)
1-0:52.7.0(231.5*V)
1-0:72.7.0(233.4*V)
1-0:31.7.0(000.71*A)
1-0:51.7.0(000.96*A)
1-0:71.7.0(001.79*A)
0-0:96.3.10(1)
0-0:17.0.0(999.9*kW)
1-0:31.4.0(999*A)
0-0:96.13.0()
0-1:24.1.0(003)
0-1:96.1.1(37464C4F32313139303532333035)
0-1:24.4.0(1)
0-1:24.2.3(240606201647S)(02673.890*m3)
!489F


Heeft iemand misschien een stuk python code die dezelfde CRC uitkomt ?

Alvast bedankt !

Acties:
  • 0 Henk 'm!

  • devastator83
  • Registratie: Januari 2012
  • Laatst online: 18:03
Reden voor mijn vraag:

ik wil het telegram aanpassen om het aan mijn laadpaal te voeden. Ik wil het loadbalancing feature gebruiken om de laadpaal te cappen met het capaciteitstarief in BE. Daarvoor zou ik de stromen per fase willen optellen en daarna updaten in het telegram.

Acties:
  • +1 Henk 'm!

  • nairolf
  • Registratie: Oktober 2019
  • Laatst online: 19:09
Als je een beetje Python kan lezen kan je eens hiernaar kijken: https://github.com/ndokter/dsmr_parser

Dat is code om DSMR telegrams te parsen naar een bruikbaar python object. Als je hem echt maar een klein beetje wil aanpassen kan je dit gebruiken als inspiratie voor je code.

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Ik heb een jaar of twee vier geleden ook een DSMR parser (.Net) geschreven. Die CRC staat talloze malen op het web (niet alle zijn even correct of voor elke versie geschikt). Maar er is meer dan zat te vinden.Zelfs op Tweakers: Slimme meter - CRC16 berekening -P1 - welke?.

[ Voor 15% gewijzigd door RobIII op 06-06-2024 20:22 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • devastator83
  • Registratie: Januari 2012
  • Laatst online: 18:03
nairolf schreef op donderdag 6 juni 2024 @ 20:04:
Als je een beetje Python kan lezen kan je eens hiernaar kijken: https://github.com/ndokter/dsmr_parser

Dat is code om DSMR telegrams te parsen naar een bruikbaar python object. Als je hem echt maar een klein beetje wil aanpassen kan je dit gebruiken als inspiratie voor je code.
Die had ik al geprobeerd, maar die geeft hetzelfde resultaat :-/

Downloaden van het telegram
code:
1
curl http://192.168.0.124:8000/api/v1/datalogger/dsmrreading -o outfile


De code om het te parsen:
Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import re
from ctypes import c_ushort

def validate_checksum(telegram):
        """
        :param str telegram:
        :raises ParseError:
        :raises InvalidChecksumError:
        """

        # Extract the part for which the checksum applies.
        checksum_contents = re.search(r'\/.+\!', telegram, re.DOTALL)

        # Extract the hexadecimal checksum value itself.
        # The line ending '\r\n' for the checksum line can be ignored.
        checksum_hex = re.search(r'((?<=\!)[0-9A-Z]{4})+', telegram)

        if not checksum_contents or not checksum_hex:
            raise ValueError(
                'Failed to perform CRC validation because the telegram is '
                'incomplete. The checksum and/or content values are missing.'
            )

        calculated_crc = crc16(checksum_contents.group(0))
        expected_crc = int(checksum_hex.group(0), base=16)

        if calculated_crc != expected_crc:
            raise ValueError(
                "Invalid telegram. The CRC checksum '{}' does not match the "
                "expected '{}'".format(
                    hex(calculated_crc),
                    hex(expected_crc)
                )
            )

def crc16(telegram):
        """
        Calculate the CRC16 value for the given telegram

        :param str telegram:
        """
        crcValue = 0x0000
        crc16_tab = []
        

        if len(crc16_tab) == 0:
            for i in range(0, 256):
                crc = c_ushort(i).value
                for j in range(0, 8):
                    if (crc & 0x0001):
                        crc = c_ushort(crc >> 1).value ^ 0xA001
                    else:
                        crc = c_ushort(crc >> 1).value
                crc16_tab.append(hex(crc))

        for c in telegram:
            d = ord(c)
            tmp = crcValue ^ d
            rotated = c_ushort(crcValue >> 8).value
            crcValue = rotated ^ int(crc16_tab[(tmp & 0x00ff)], 0)

        return crcValue

with open("../outfile", "r") as f: data = f.read()

validate_checksum(data)


En het resultaat:
ValueError: Invalid telegram. The CRC checksum '0x2751' does not match the expected '0x489f'

Acties:
  • 0 Henk 'm!

  • devastator83
  • Registratie: Januari 2012
  • Laatst online: 18:03
RobIII schreef op donderdag 6 juni 2024 @ 20:20:
Ik heb een jaar of twee vier geleden ook een DSMR parser (.Net) geschreven. Die CRC staat talloze malen op het web (niet alle zijn even correct of voor elke versie geschikt). Maar er is meer dan zat te vinden.Zelfs op Tweakers: Slimme meter - CRC16 berekening -P1 - welke?.
Ik heb natuurlijk eerst de topics doorzocht, maar ik krijg het helaas echt niet aan de praat ...

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
devastator83 schreef op donderdag 6 juni 2024 @ 20:24:
[...]


Ik heb natuurlijk eerst de topics doorzocht
Dat is wel handig om te vermelden (inc. linkjes) :)
Weet je welke DSMR versie je meter uitspuugt?
Denk eraan dat er een verschil is tussen \r, \n en \r\n bijv. Als je een "dump" kunt posten (dus niet in code tags, maar een rauwe dump van een telegram in een zipfile ofzo) dan wil ik wel eens kijken wat mijn parser er van vindt.

[ Voor 32% gewijzigd door RobIII op 06-06-2024 20:47 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • jeroen3
  • Registratie: Mei 2010
  • Laatst online: 16:27
Zoek eens op dsmr simulator. Software moet getest worden, en veel zullen een simulator bevatten of gebruiken. Daarmee moet je uit de voeten kunnen.

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
jeroen3 schreef op donderdag 6 juni 2024 @ 20:28:
Zoek eens op dsmr simulator. Software moet getest worden, en veel zullen een simulator bevatten of gebruiken.
Ik zeg niet dat het niet bestaat, maar dat soort zaken test je in een unittest :)

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • devastator83
  • Registratie: Januari 2012
  • Laatst online: 18:03
RobIII schreef op donderdag 6 juni 2024 @ 20:26:
[...]

Dat is wel handig om te vermelden (inc. linkjes) :)
Weet je welke DSMR versie je meter uitspuugt?
Denk eraan dat er een verschil is tussen \r, \n en \r\n bijv. Als je een "dump" kunt posten (dus niet in code tags, maar een rauwe dump van een telegram in een zipfile ofzo) dan wil ik wel eens kijken wat mijn parser er van vindt.
Versie 5 is dat

Acties:
  • +1 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Volgens mijn parser is het telegram uit je topicstart correct (en dus ook de CRC). Zorg wel dat je bestand eindigt op een Carriage Return en LineFeed (CrLf, ofwel \r\n dus), zie pagina 15, sectie 6.2:

Afbeeldingslocatie: https://tweakers.net/i/k0nb82_wtax1gW21V8YWcII_zYc=/full-fit-in/4000x4000/filters:no_upscale():fill(white):strip_exif()/f/image/G0Atps3IDhUlys4XAjNZliad.png?f=user_large

[ Voor 53% gewijzigd door RobIII op 06-06-2024 21:01 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • +1 Henk 'm!

  • Kristofferson
  • Registratie: Maart 2012
  • Niet online
Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import re

telegram = b"/FLU5\\253769484_A\r\n\r\n0-0:96.1.4(50217)\r\n0-0:96.1.1(3153414733313030313239383636)\r\n0-0:1.0.0(240606192126S)\r\n1-0:1.8.1(007446.606*kWh)\r\n1-0:1.8.2(009269.520*kWh)\r\n1-0:2.8.1(010848.387*kWh)\r\n1-0:2.8.2(004287.921*kWh)\r\n0-0:96.14.0(0001)\r\n1-0:1.4.0(00.000*kW)\r\n1-0:1.6.0(240602103000S)(02.478*kW)\r\n0-0:98.1.0(13)(1-0:1.6.0)(1-0:1.6.0)(230601000000S)(230508171500S)(02.162*kW)(230701000000S)(230601201500S)(03.496*kW)(230801000000S)(230720204500S)(03.140*kW)(230901000000S)(230819134500S)(02.424*kW)(231001000000S)(230913151500S)(02.576*kW)(231101000000W)(231022121500S)(04.257*kW)(231201000000W)(231129124500W)(03.465*kW)(240101000000W)(231215143000W)(03.437*kW)(240201000000W)(240106154500W)(04.855*kW)(240301000000W)(240226171500W)(03.339*kW)(240401000000S)(240313174500W)(03.056*kW)(240501000000S)(240427201500S)(03.043*kW)(240601000000S)(240530213000S)(02.764*kW)\r\n1-0:1.7.0(00.000*kW)\r\n1-0:2.7.0(00.227*kW)\r\n1-0:21.7.0(00.051*kW)\r\n1-0:41.7.0(00.000*kW)\r\n1-0:61.7.0(00.000*kW)\r\n1-0:22.7.0(00.000*kW)\r\n1-0:42.7.0(00.222*kW)\r\n1-0:62.7.0(00.055*kW)\r\n1-0:32.7.0(235.0*V)\r\n1-0:52.7.0(231.6*V)\r\n1-0:72.7.0(235.1*V)\r\n1-0:31.7.0(000.70*A)\r\n1-0:51.7.0(001.38*A)\r\n1-0:71.7.0(001.48*A)\r\n0-0:96.3.10(1)\r\n0-0:17.0.0(999.9*kW)\r\n1-0:31.4.0(999*A)\r\n0-0:96.13.0()\r\n0-1:24.1.0(003)\r\n0-1:96.1.1(37464C4F32313139303532333035)\r\n0-1:24.4.0(1)\r\n0-1:24.2.3(240606192004S)(02673.858*m3)\r\n!63B7"

def check_crc(telegram):
    # Split telegram in contents and CRC16 checksum (format:contents!crc)
    for match in re.compile(b'\r\n(?=!)').finditer(telegram):
        contents = telegram[:match.end() + 1]
        # print(contents)
        # CRC is in hex, so we need to make sure the format is correct
        crc_rec = hex(int(telegram[match.end() + 1:].decode('ascii').strip(), 16))

    # Calculate checksum of the contents
    crc_calc = hex(calc_crc16_p1(contents))
    print(f"Checksum Received: {crc_rec} - Calculated: {crc_calc}")
    return crc_rec == crc_calc


def calc_crc16_p1(data: bytes):
    crc = 0x0000
    for pos in range(len(data)):
        crc ^= data[pos]
        for i in range(8):
            if ((crc & 0x0001) != 0):
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
    return crc;

print(check_crc(telegram))


code:
1
2
Checksum Received: 0x63b7 - Calculated: 0x63b7
True


Belangrijk inderdaad de line endings kloppen (<CRLF>). Ik heb ze zichtbaar gemaakt via een Python bytes string maar dan moet je de backslash na FLU5 wel escapen. :)

12 kWh Victron ESS | 4,86 kWp ZP


Acties:
  • 0 Henk 'm!

  • devastator83
  • Registratie: Januari 2012
  • Laatst online: 18:03
Thx @Kristofferson, daarmee kan ik verder !
Pagina: 1