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.
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).
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
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.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
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.
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
???
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
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)