Laden...

Gepackten Datumswert (binär) in DateTime umwandeln

Erstellt von TheBrainiac vor 9 Jahren Letzter Beitrag vor 9 Jahren 3.799 Views
TheBrainiac Themenstarter:in
795 Beiträge seit 2006
vor 9 Jahren
Gepackten Datumswert (binär) in DateTime umwandeln

Hi @ All 😃

Habe ein kleines Problem:

Ich lese von einer TCP/IP-Verbindung (FixedWidth-)Daten aus einem Gerät aus.

Die Datensätze sehen wie folgt aus:

 ?  |uid | ?  | date    | ?  
000B 0100 0000 DE97 93E5 02A1
0011 0100 0000 DE97 93E5 0261
0016 0100 0000 DE97 93E5 02E1
001C 0100 0000 DE97 93E5 0121
002C 0100 0000 DE97 B3B9 0121

003A 0300 0000 DE97 9699 0121
0001 0300 0000 DE97 969D 0121
0002 0300 0000 DE97 969D 0121
0004 0400 0000 DE97 969D 0121
0006 0400 0000 DE97 969D 0121
0009 0300 0000 DE97 969D 0121
000B 0300 0000 DE97 969D 0121
000E 0400 0000 DE97 969D 0121
0010 0300 0000 DE97 969D 0121

001B 0300 0000 DE97 B77D 0121
001F 0300 0000 DE97 B77D 0121
001E 0300 0000 DE97 B7BD 0121
001F 0300 0000 DE97 B7BD 0121
0020 0300 0000 DE97 B7BD 0121
0021 0300 0000 DE97 B7BD 0000

Darin stecken folgende Informationen (die UserID's stimmen auch in den jeweiligen Zeilen überein und zwischen entsprechenden Zeilen mit Sprung im Datum gibt es auch im Hex-Code einen entsprechenden Sprung):

uid | date              | dir
1    2014-09-19 12:57:11 in   
1    2014-09-19 12:57:17 in   
1    2014-09-19 12:57:22 out  
1    2014-09-19 12:57:28 out  
1    2014-09-19 13:46:44 in   

3    2014-09-22 12:38:58 in   
3    2014-09-22 12:39:01 in   
3    2014-09-22 12:39:02 in   
4    2014-09-22 12:39:04 in   
4    2014-09-22 12:39:06 in   
3    2014-09-22 12:39:09 in   
3    2014-09-22 12:39:11 in   
4    2014-09-22 12:39:14 in   
3    2014-09-22 12:39:16 in   

3    2014-09-23 13:31:27 in   
3    2014-09-23 13:31:31 in   
3    2014-09-23 13:47:30 in   
3    2014-09-23 13:47:31 in   
3    2014-09-23 13:47:32 in   
3    2014-09-23 13:47:33 in   

Allerdings finde ich keine Möglichkeit, das Datum zu parsen. Ich vermute, dass es irgendwie in den ersten beiden der letzten drei 4-Tupel eines jeden Datensatzes steckt, allerdings kriege ich es nicht geparst.

Ich habe auch leider keine Spezifikation des Geräts, das auf das verwendete Datumsformat schließen lässt. Habe schon einiges (wie Unix-TimeStamps etc.) probiert.

Hat von euch jemand einen Tipp / eine Anregung?

Gruß, Christian.

`There are 10 types of people in the world: Those, who think they understand the binary system Those who don't even have heard about it And those who understand "Every base is base 10"`
TheBrainiac Themenstarter:in
795 Beiträge seit 2006
vor 9 Jahren

Genauere Infos:

Die Ursprüngliche Anwendung für das Gerät liefert folgenden Output:

Device (1) - Connect tcpip    [192.168.178.123]    [5005]
    success

Device (1) - Lock
    success

Device (1) - Download Data
    2014-08-01 to 2014-09-23
    get to memory (1)
    User ID(1)    Date Time(2014-09-19 12:57:11)    Direction(in)    (no record)    (database)
    User ID(1)    Date Time(2014-09-19 12:57:17)    Direction(in)    (no record)    (database)
    User ID(1)    Date Time(2014-09-19 12:57:22)    Direction(out)    (no record)    (database)
    User ID(1)    Date Time(2014-09-19 12:57:28)    Direction(out)    (no record)    (database)
    User ID(1)    Date Time(2014-09-19 13:46:44)    Direction(in)    (no record)    (database)
    User ID(3)    Date Time(2014-09-22 12:38:58)    Direction(in)    (no record)    (database)
    User ID(3)    Date Time(2014-09-22 12:39:01)    Direction(in)    (no record)    (database)
    User ID(3)    Date Time(2014-09-22 12:39:02)    Direction(in)    (no record)    (database)
    User ID(4)    Date Time(2014-09-22 12:39:04)    Direction(in)    (no record)    (database)
    User ID(4)    Date Time(2014-09-22 12:39:06)    Direction(in)    (no record)    (database)
    User ID(3)    Date Time(2014-09-22 12:39:09)    Direction(in)    (no record)    (database)
    User ID(3)    Date Time(2014-09-22 12:39:11)    Direction(in)    (no record)    (database)
    User ID(4)    Date Time(2014-09-22 12:39:14)    Direction(in)    (no record)    (database)
    User ID(3)    Date Time(2014-09-22 12:39:16)    Direction(in)    (no record)    (database)
    User ID(3)    Date Time(2014-09-23 13:31:27)    Direction(in)    (no record)    (database)
    User ID(3)    Date Time(2014-09-23 13:31:31)    Direction(in)    (no record)    (database)
    User ID(3)    Date Time(2014-09-23 13:47:30)    Direction(in)    (no record)    (database)
    User ID(3)    Date Time(2014-09-23 13:47:31)    Direction(in)    (no record)    (database)
    User ID(3)    Date Time(2014-09-23 13:47:32)    Direction(in)    (no record)    (database)
    User ID(3)    Date Time(2014-09-23 13:47:33)    Direction(in)    (no record)    (database)
    done (0)

Device (1) - Set Time
    2014-09-23 13:48:03

Der TCP/IP-Data-Traffic sieht wie folgt aus (Jeweils Request und Response):

55aa0180000000000000ffff00000100
aa550101000000000000

55aa0113000000000000000030000200
aa55010100000000000055aa0201300035092804ee0400000201010201010101b80b0000b80b0000b80b0000e8030000a086010002010201020000000121

55aa0181000000000000ffff00000300
aa550101000000000000

55aa01b4080000000000ffff00000400
aa550101140000000000

55aa01a40000000014000000f0000500
aa55010100000000000055aa0221000b01000000de9793e502a1001101000000de9793e50261001601000000de9793e502e1001c01000000de9793e50121002c01000000de97b3b90121003a03000000de9796990121000103000000de97969d0121000203000000de97969d0121000404000000de97969d0121000604000000de97969d0121000903000000de97969d0121000b03000000de97969d0121000e04000000de97969d0121001003000000de97969d0121001b03000000de97b77d0121001f03000000de97b77d0121001e03000000de97b7bd0121001f03000000de97b7bd0121002003000000de97b7bd0121002103000000de97b7bd0000

55aa01b300000000000000000800060055aade070917020d30030000
aa550101000000000000

55aa0181010000000000ffff00000700
aa550101000000000000

Meine Daten oben stammen aus der 5. Response (abzüglich der Konstante [aa55010100000000000055aa0221]am Anfang).

`There are 10 types of people in the world: Those, who think they understand the binary system Those who don't even have heard about it And those who understand "Every base is base 10"`
5.658 Beiträge seit 2006
vor 9 Jahren

Hi TheBrainiac,

die DateTime.ParseExact-Methode sollte dir weiterhelfen. (Offenbar habe ich da etwas falsch verstanden. Sorry.

Christian

Weeks of programming can save you hours of planning

16.835 Beiträge seit 2008
vor 9 Jahren

Bringt ihm ja nicht, wenn er nicht weiß, wie er 0300 0000 DE97 969D in nen Zeitstempel kriegt, weil er das Format nicht (er)kennt.

C
2.121 Beiträge seit 2010
vor 9 Jahren

und zwischen entsprechenden Zeilen mit Sprung im Datum gibt es auch im Hex-Code einen entsprechenden Sprung

Aber nicht in der Zeit.

Die erste Spalte sieht nach den Sekunden aus.
Wenn die Minute sich um 1 erhöht wird das letzte Byte deiner Datumsspalte um 4 erhöht z.B. von 99 auf 9D. Die ersten 6 Bit dieses Bytes sind also wahrscheinlich die Minuten.
Bei 12 Uhr steht als 2.letztes Byte in der Datumsspalte eine 9 (in 93), bei 13 Uhr ein B (in B3). Daher könnte das hier unterschiedliche Bit dem Einser der Stunden entsprechen.
9 = 1001, B = 1011 und wenn hier die ersten 3 Bit für die Stunden zählen, fehlen noch zwei andere Bit. Die müssten in dem Fall 01 sein denn 01 100 = 12 und 01 101 = 13.
In der auf die 9 folgenden 3 passt das nicht. In der davor stehenden 7 (0111) wären die Bits drin. Allerdings als erstes, das wäre also ein grusliges Durcheinander.

---- ---- --ss ssss
---- ---- ---- ----
---- ---- ---- ----
---- ---- ---- hh--
hhh- ---- mmmm mm--
---- ---- ---- ----

???

Vielleicht denk ich auch viel zu kompliziert. Würde jedenfalls die einzelnen Zahlen als Bitfolge darstellen, nur so viele wie man tatsächlich für den Wertebereich braucht. Also Stunde bis max. 24 => 5 Bit. Minute bis max 60 => 6 Bit.
Dann stelle die Daten ebenfalls als Bitfolge dar und such die Zahlen darin.

771 Beiträge seit 2009
vor 9 Jahren

Hi,

die Sekunden scheinen auf jeden Fall schon mal im 2. Byte zu stecken. Und die Uhrzeit (h und m) dann wohl in den Bytes 9 und 10.
Und wenn ich richtig gerechnet habe, dann müsste das 10. Byte die Minuten darstellen und zwar als 1/241 Anteil (warum auch immer dieser Wert und nicht 255 oder 256), z.B.
0xE5 = 229 -> 229 * 60 / 241 = 57
0x9D = 157 -> 157 * 60 / 241 = 39

Nur beim 9. Byte komme ich nicht einfach auf die Stunden oder das Datum:
93 -> 2014-09-19 12h
B3 -> 2014-09-19 12h

96 -> 2014-09-22 12h
B7 -> 2014-09-23 13h

???

5.658 Beiträge seit 2006
vor 9 Jahren

Da es sich offenbar um einen 32-Bit-Wert pro Datum handelt, wird das Datenformat sicherlich so in etwa aussehen:

#pragma pack(1)
typedef struct TIMESTAMP_32_B_S
   {
   uint8_t   minutes    : 6; // 0-60 (0-63 max)
   uint8_t   hours24    : 5; // 0-23 (0-31 max)
   uint8_t   dayOfMonth : 5; // 1-31 (0-31 max)
   uint8_t   month      : 4; // 1-12 (0-15 max)
   uint16_t  year       : 12; // Epoch start: 2014, Range: 2014 thru 4061
   } TIMESTAMP_32_B_T;
#pragma pack()

Quelle: How to save date time stamp within 4 bytes

Die einzelnen Werte sind dann eben nicht an Byte-Grenzen gebunden. Ich würde es so mal versuchen, und einfach mal die Anordnung variieren, bis das erwartete Ergebnis bei rauskommt. Kann man ja auch automatisieren.

Christian

PS: Da du nicht schreibst, was du schon getestet hast: Hast du schonmal DateTime.FromBinary-Methode probiert?

Weeks of programming can save you hours of planning

Gelöschter Account
vor 9 Jahren

Würde jedenfalls die einzelnen Zahlen als Bitfolge darstellen, nur so viele wie man tatsächlich für den Wertebereich braucht. Also Stunde bis max. 24 => 5 Bit. Minute bis max 60 => 6 Bit.
Dann stelle die Daten ebenfalls als Bitfolge dar und such die Zahlen darin.

So würde ich es auch erstmal versuchen, also einfach mal (Beispiel 5. Datensatz)
die Zahlen 2014,09,19,12,57,28 durch die BitConverter.GetBytes Methode schicken und schauen ob die Ergebnisse dicht zusammen im Traffic des Datensatzes vorkommen.

(Mir ist klar das Zeitstempel nicht unbedingt so vorliegen aber ein Versuch ist es wert. Ist ja nicht gesagt das sich die Fremdanwendung hier nicht irgendwas zurecht bastelt)