AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

BDV001 Protokoll und CheckSum

Ein Thema von SvB · begonnen am 18. Jan 2008 · letzter Beitrag vom 18. Jan 2008
Antwort Antwort
SvB

Registriert seit: 21. Okt 2004
Ort: Eckenroth
426 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#1

BDV001 Protokoll und CheckSum

  Alt 18. Jan 2008, 00:08
Hallo,

ich muss für einen Verpflegungsautomaten eine Anbindung schreiben und habe jetzt ein Problem beim Berechnen der CheckSum des Protokolls.
Hier mal die Beschreibung aus der Doku des Protokolls
Zitat:
The checksum is 1 byte calculated such that the binary sum of the total Datafile, ignoring any overflow, has a value equal to 0.
Byte 1 bis 3 sind der Header und 4 bis 8 sind die Databytes. Alles zusammen inkl. der CheckSum ist das Datafile.
Mit einem Münzer habe ich mal mitgeloggt, was der an den Automaten sendet und folgendes kommt heraus.
Zitat:
Beispiel 1
10000001 Byte 1
00001010 Byte 2
00001011 Byte 3
00100000 Byte 4
00000000 Byte 5
10110000 Byte 6
00000101 Byte 7
00000000 Byte 8

10010101 Ergebnis
Zitat:
Beispiel 2
10000001 Byte 1
00001010 Byte 2
00001011 Byte 3
01000000 Byte 4
00000000 Byte 5
10110000 Byte 6
00000101 Byte 7
00000000 Byte 8

01110101 Ergebnis
Zitat:
Beispiel 3
10000001 Byte 1
00001010 Byte 2
00001011 Byte 3
01010000 Byte 4
00000000 Byte 5
10110000 Byte 6
00000101 Byte 7
00000000 Byte 8

01100101 Ergebnis
Zitat:
Beispiel 4
10000001 Byte 1
00001010 Byte 2
00001011 Byte 3
00000000 Byte 4
00000001 Byte 5
10110000 Byte 6
00000101 Byte 7
00000000 Byte 8

10110100 Ergebnis
Entweder bin ich zu doof oder vor lauter 0 und 1 sehe ich nichts mehr oder ich verstehe einfach nicht, was die meinen, wie das berechnet wird. Ich habe schon mit AND, OR und XOR versucht und bei AND und OR klappt es nie und bei XOR nicht jedesmal. Irgendwie bin ich da auf der falschen fährte.
Kann mir jemand weiterhelfen?

Danke
Sven
  Mit Zitat antworten Zitat
grenzgaenger
(Gast)

n/a Beiträge
 
#2

Re: BDV001 Protokoll und CheckSum

  Alt 18. Jan 2008, 00:34
am besten du frägst mal beim hersteller nach dem algo. nach. denke es macht nicht viel sinn, wenn wir hier herumraten... und unter "calculated" kann man einiges verstehen...
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.062 Beiträge
 
Delphi 12 Athens
 
#3

Re: BDV001 Protokoll und CheckSum

  Alt 18. Jan 2008, 00:44
bin ich jetzt zu doof, oder paßt XOR doch? wohl auch zuviele nullen gesehn

und eine Addition Ergebnis := Byte1 + Byte2 + Byte3 + ... + Byte8; paßt och nicht.

dieses "has a value equal to 0." scheint wohl Einfluß zu haben

vielleicht hilft ja sowas in der Richtung?
http://www.patentstorm.us/patents/5798958.html
http://www.freepatentsonline.com/5798958.html


Aber den Hersteller zu Fragen wäre wohl doch bestimmt einfacher.


PS: and und or kann so auf einfach verbindung nicht gehn
> bei AND wäre immer ein 0, sobald auch nur ein Wert 0 ist (also eigentlich fast immer)
> und bei OR wäre es immer 1, sobal auch nur ein Wert 1 ist (ebenfalls fast immer)

und XOR schaltet das Bit um, sobald eine 1 vorkommt (also immer hin und her ... ungerade 1-bits-Anzahl = 1)



"ignoring any overflow" weißt aber mehr auf eine Addition (oder andere Rechenweise) hin ... bei XOR/AND/OR gibt es ja keinen Überlauf.
wobei hier die Ergebnise auch teilweise übereinstimmen

Code:
Beispiel 1
10000001 Byte 1
00001010 Byte 2
00001011 Byte 3
00100000 Byte 4
00000000 Byte 5
10110000 Byte 6
00000101 Byte 7
00000000 Byte 8

1[color=#ff0000]0010101[/color] Ergebnis

hi....lo-bit
wis auf das Linke/Hi-Bit stimmt es doch mit einer addition (glaub ich) überein
und wenn ich beim Hi-Bit keinen überlauf zulasse und nicht weiterrechne, dann kommt daauch die eins raus

Delphi-Quellcode:
// für Beispiel 1 ... bei Bsp2 paßt es wieder nicht :(
W: Word;
W := Word(Byte1) + Byte2 + Byte3 + Byte3 + ... + Byte8;
If W > $FF Then W := Byte(W) or $80 Else W := Byte(W);
W :=

[add]
ja, hab grad mal lange Weile ... also besser fragst du mal beim Hersteller
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#4

Re: BDV001 Protokoll und CheckSum

  Alt 18. Jan 2008, 01:44
Ich verstehe die Anleitung so: Du addierst alle Bytes bis auf das Checksum Byte zusammen. Dabei darfst du nur immer Byte-weise addieren, irgendwelcher Überlauf geht wieder auf 0 + Rest. Wenn du das alles zusammen hast, dann ist die Checksum genau die Differenz die du brauchst, damit durch Addition direkt 0 rauskommt.

Also ein wenig Pseudocode:
Delphi-Quellcode:
function CalcChecksum(const AData: pointer; const ADataSize: integer): Byte;
var
  lPtr: PByte;
  lCheckSum: Integer;
begin
  lPtr := AData;
  lCheckSum := 0;

  for i := 1 to ADataSize do
  begin
    Inc(lCheckSum, lPtr^);
    Inc(lPtr);

    lCheckSum := lCheckSum mod 256;
  end;

  result := 256 - lCheckSum;
end;
Die übergebenen Datengröße müssen die reinen Rohdaten sein, ohne das Feld für die Checksumme (oder wenn doch mit Checksummenfeld, dann muss dieses mit 0 gefüllt sein).

Diese Methode gibt's vor allem bei seriellen Protokollen und ein paar Dateiformaten.
  Mit Zitat antworten Zitat
SvB

Registriert seit: 21. Okt 2004
Ort: Eckenroth
426 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#5

Re: BDV001 Protokoll und CheckSum

  Alt 18. Jan 2008, 11:04
Danke für Eure Hilfe.

@Muetze1
Irgendwie habe ich ein Brett vor dem Kopf. Ich komme nicht drauf, wie ich Deine funktion benutzen soll, wie rufe ich die auf? Mit Pointern usw. habe ich es nicht so.
Ich habe mal alle Bytes als Bits (0+1) nacheinander in ein Memo gestellt.
10000001000010100000101100100000000000001011000000 00010100000000

Die Funktion rufe ich dann wie folgt auf:
Edit1.Text := IntToStr(CalcChecksum(PChar(Memo1.Lines[0]), Length(Memo1.Lines[0]))) Kann man das so machen? Als Ergebnis kommt dann dezimal 88 raus. Beim Beispiel 1 ist die Prüfsumme aber dezimal 149.

Ich werde mal einen Kollegen anhauen, der das Protokoll besorgt hat, der soll da mal nachfragen.

Sven
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#6

Re: BDV001 Protokoll und CheckSum

  Alt 18. Jan 2008, 11:22
Zitat von SvB:
@Muetze1
Irgendwie habe ich ein Brett vor dem Kopf. Ich komme nicht drauf, wie ich Deine funktion benutzen soll, wie rufe ich die auf? Mit Pointern usw. habe ich es nicht so.
Ich habe mal alle Bytes als Bits (0+1) nacheinander in ein Memo gestellt.
Du schickst doch keine solche strings über die Schnittstelle sondern Bytes. Diese musst du in der Funktion angeben.

Beispiel: Das Array sind die zu sendenden Daten, der letzte Eintrag im Array ist die Checksumme:
Delphi-Quellcode:
procedure SendData;
var
  lData: packed array[5] of byte;
begin
  lData[0] := $44;
  lData[1] := $55; // deine Daten halt
  lData[2] := $33;
  lData[3] := $33;

  lData[4] := CalcChecksum(lData[0], 4);

  Serial.SendBytes(lData);
end;
Wenn du die Daten mit 0 und 1 im Memo darstellst, dann machst du aus einem Bit 8 Bit, da 0 oder 1 jeweils ein Zeichen somit ein Byte darstellt. Dadurch verzerrst du die eigentlichen Informationen, du blähst die Daten auf das 8x ihrer eigentlichen Grösse auf. Somit kann da nichts richtiges mehr rauskommen, da du komplett andere Daten angibst.

Du musst zwischen den Daten und der Formatierung der Daten zur Ausgabe unterscheiden. Letzteres sollte immer nur in eine Richtung gehen, also nur zur Ausgabe.

Zitat von SvB:
Ich werde mal einen Kollegen anhauen, der das Protokoll besorgt hat, der soll da mal nachfragen.
Ich sehe eigentlich kein Problem. Berechne die Prüfsumme mal und schau nach ob es stimmt. Ich würde das erstmal probieren, bevor man sich als Firma blamiert, weil eigentlich ist es eindeutig beschrieben.
  Mit Zitat antworten Zitat
SvB

Registriert seit: 21. Okt 2004
Ort: Eckenroth
426 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#7

Re: BDV001 Protokoll und CheckSum

  Alt 18. Jan 2008, 11:55
Super Danke.

Ich mache schon seit zwei kompletten Tagen jeweils von ca. 09:00 bis ca. 23:00 Uhr da rum und hatte schon so viel getestet, dass ich im Moment wirklich nichts mehr verstehe.

Du hast natürlich vollkommen recht, dass ich die Bytes nicht als String übergeben kann.

Deine Funktion CalcChecksum funktioniert und die SendData musste ich wie folgt abändernund und habe sie mal für meine Beispiele angepasst und Dezimalzahlen anstatt Hexzahlen verwendet.
Delphi-Quellcode:
procedure SendData;
var
  lData: packed array[0..7] of byte;
begin
  lData[0] := 129;
  lData[1] := 10;
  lData[2] := 11;
  lData[3] := 0;
  lData[4] := 1;
  lData[5] := 176;
  lData[6] := 5;
  lData[7] := 0; // Checksum = 180

  Edit1.Text := CalcChecksum(@lData[0], 8);

end;
Meine vier Beispiel habe ich damit mal getestet und es kam immer die richtge Prüfsumme heraus. Ich werde das ganze mal in meine "richte" Applikation einbauen und dann noch mal direkt mit dem Automaten testen. Ich melde mich dann noch mal.

Sven
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#8

Re: BDV001 Protokoll und CheckSum

  Alt 18. Jan 2008, 12:01
Zitat von SvB:
Deine Funktion CalcChecksum funktioniert und die SendData musste ich wie folgt abändernund und habe sie mal für meine Beispiele angepasst und Dezimalzahlen anstatt Hexzahlen verwendet.
Na, Hauptsache es funktioniert. Wie die Daten vom der Darstellungsform angegeben werden, ist ja egal. Es sind ja die gleichen Daten.

Ansonsten musst du natürlich keine festen Arrays verwenden. Du hast ja bestimmt unterschiedlich Lange Daten. Dort wäre die Arbeit mit Pointern genauso möglich wie mit einem dynamischen Array. Nur nochmal zur Vollständigkeit:

Delphi-Quellcode:
procedure SendData;
var
  lData: packed array of byte;
begin
  SetLength(lData, 8);

  lData[0] := 129;
  lData[1] := 10;
  lData[2] := 11;
  lData[3] := 0;
  lData[4] := 1;
  lData[5] := 176;
  lData[6] := 5;
  lData[7] := 0; // Checksum = 180

  Edit1.Text := CalcChecksum(@lData[0], length(lData));
end;
Und wenn ich das richtig sehe, sollte das 8. Byte (Index 7) die Checksumme sein? dann kann man es in der Endapplikation gleich so zusammenfassen.


Delphi-Quellcode:
procedure SendData;
var
  lData: packed array of byte;
begin
  SetLength(lData, 8);

  lData[0] := 129;
  lData[1] := 10;
  lData[2] := 11;
  lData[3] := 0;
  lData[4] := 1;
  lData[5] := 176;
  lData[6] := 5;
  lData[7] := CalcChecksum(@lData[0], length(lData)-1);
end;
Wie ich zuvor schon geschrieben hatte: Das Byte mit der zu berechnenden CRC muss 0 sein, dann kann man den CRC Berechnungscode mit darüber laufen lassen. Man kann sich das auch sparen und das Byte nicht initialisieren und einfach direkt die CRC berechnen und zuweisen. Von daher auch length(lData)-1. Alternativ kann man sich die Subtraktion noch ersparen, wenn man high(lData) verwendet.

Viel Erfolg!
  Mit Zitat antworten Zitat
SvB

Registriert seit: 21. Okt 2004
Ort: Eckenroth
426 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#9

Re: BDV001 Protokoll und CheckSum

  Alt 18. Jan 2008, 15:15
Alles OK. Es funktioniert jetzt auch in meiner Anwendung.

Ganz so einfach ist das ganze dann aber doch nicht, das Protokoll (von 1984 glaube ich) doch etwas umständlich ist. Heute würde ich das etwas anders machen.

Hier mal der Code, mit dem ich das gesamte "DataFile" für Filetype 11 zusammenbaue.

Delphi-Quellcode:
procedure EncodeBDVMoney(Value: Real);
var
  cDigits: String;
  lData: array[0..7] of Byte;
  n: Byte;
  CheckSum: Byte;
begin
  // Hier wird der Preis als 5 Digits übergeben
  FMessageList := FMessageList + AcceptBlockChar; //3Dh

  lData[0] := 129; // 1000 0001 - Low Nibble 0001 = Receiving Pripheral ident, 001 = VMC
                       // - High Nibble 1000 = Transmitting Pripheral ident, 1000 = Master
  lData[1] := 10; // 0000 1010 - Datafile length in Bytes
  lData[2] := 11; // 0000 1011 - Filetype Identification Number = Filetype 11

  // Wenn z.B. 20 Cent (€ 0,20) eingeworfen sind, dann soll das herauskommen 00020
  cDigits := StrRight( '00000' + IntToStr(Round(Value * 100)), 5);

  lData[3] := (StrToInt(cDigits[4]) shl 4) or StrToInt(cDigits[5]); // Digit 2 + Digit 1
  lData[4] := (StrToInt(cDigits[2]) shl 4) or StrToInt(cDigits[3]); // Digit 4 + Digit 3

  // ExactChangeFlag + Dezimal Point Position
  if FExactChangeFlag then begin
    lData[5] := (11 shl 4) or StrToInt(cDigits[1]); // 11 = 1011 + Digit 5
  end else begin
    lData[5] := (3 shl 4) or StrToInt(cDigits[1]);; // 3 = 0011 + Digit 5
  end;

  // immer fest auf 5 Cent
  lData[6] := 5; // 0000 0101 Lowest Coin Real Currency Value BCD Digits 1 + 0
  lData[7] := 0; // 0000 0000 Lowest Coin Real Currency Value BCD Digits 3 + 2

  CheckSum := CalcChecksum(@lData[0], 8);

  // PID = Peripheral Identifier = $20
  for n := 0 to 7 do begin
    FMessageList := FMessageList + chr( PID + (lData[n] and 15)); // + Low Nibble - Fh
    FMessageList := FMessageList + chr( PID + ((lData[n] and 240) shr 4)); // + High Nibble - F0f
  end;

  FMessageList := FMessageList + chr(PID + (CheckSum and 15));
  FMessageList := FMessageList + chr(PID + 0);
  FMessageList := FMessageList + chr(PID + 0);
  FMessageList := FMessageList + chr(PID + ((CheckSum and 240) shr 4));

  FMessageList := FMessageList + DataSyncChar; //39h
end;
Nochmals vielen Dank an Dich Muetze1. Ich habe zwar Deine Funktion noch nicht ganz verstanden, aber das versuche ich noch mal, wenn ich etwas klarer im Kopf bin. Heute mache ich da jetzt nichts mehr dran, am Montag geht es damit weiter.

Grüße
Sven
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:58 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz