Guten Tag Zusammen,
ich habe folgendes Problem:
Meine SPS speichert das Datum im s.g. DTL format:
Min. DTL#1970-01-01-00:00:00.0
Max.: DTL#2554-12-31-23:59:59.999999999
also 96Bit breit.
Dieses lese ich mittels C# Byte-weise ein (hier im Falle vom Jahr):
private void HexDump(RichTextBox DumpBox, byte[] bytes, int Size)
{
if (bytes == null)
return;
byte[] tempByteArray0 = new byte[2] { bytes[1], bytes[0] }
Int16 jahr = BitConverter.ToInt16(tempByteArray0, 0);
}
Im Falle vom Jahr funktioniert das auch wunderbar.
Allerdings bekomme ich es jetzt nicht hin aus den ersten 4 Bytes ein korrektes Datum anzeigen zu lassen.
Ich wäre sehr Dankbar für eine Anregung, oder Hilfestellung!
Beste Grüße
Florian
verwendetes Datenbanksystem: <bitte immer angeben>
Es ist immer sehr hilfreich wenn man zeigt was man als Eingangsdaten hat und was man als Rückgabewert erwartet.
Also, was für eine Bytefolge hast du und welchen Datum/Zeitwert soll das darstellen?
Hi,
wenn ich gerade richtig recherchiert habe sind die Bytes die von der SPS kommen "unsigned" - ergo ist Int16 nur fast der richtige Datentyp - eigentlich bräuchtest du UInt16.
Denke dann kommst du auch auf die richtigen Werte.
Für alles weitere wäre die Bytefolge, sowie der daraus zu lesende Wert interessant.
LG
PS: Alles was zu diesem DTL-Format steht scheint in der SPS unsigned zu sein.
Hallo Sir Rufo,
Also ich möchte das in einem Datatable speichern Datum/Uhrzeit getrennt. Im Idealfall natürlich als DateTime Variable.
als String sieht das ganze so aus:
07-E1-09-04-02-0A-26-00-08-7F-C0-30
wobei gilt:
Byte 0&1 = Jahr
Byte 2 = Monat
Byte 3 = Tag
Byte 4 = Wochentag
Byte 5 = Stunde
Byte 6 = Minute
Byte 7 = Sekunde
Byte 8-11=Nanosekunde
@ Taipi88: werde ich probieren
Habe mal weiter geforscht
uint kennt der Bitkonverter nicht...
Hier die Variablendefinition in der SPS:
Byte 0&1 = Jahr = Uint
Byte 2 = Monat = USint
Byte 3 = Tag = USint
Byte 4 = Wochentag = USint
Byte 5 = Stunde = USint
Byte 6 = Minute = USint
Byte 7 = Sekunde = USint
Byte 8-11=Nanosekunde = UDint
Gruß und Danke schonmal
Hi,
ich sagte ja auch UInt16.
LG
PS: So würde ich das wohl lösen (ohne Nanosekunden):
using System;
namespace ConsoleApp1
{
internal class Program
{
private static void Main(string[] args)
{
var data = new byte[]
{
0x07, 0xE1, // 0,1: year
0x09, // 2: month
0x04, // 3: days
0x02, // 4: weekday
0x0A, // 5: hours
0x26, // 6: minutes
0x00, // 7: seconds
0x08, 0x7F, 0xC0, 0x30 // 8-1: nanoseconds?
};
Console.WriteLine(data.FromDlt());
Console.ReadLine();
}
}
public static class SpsHelper
{
public static DateTime FromDlt(this byte[] dltArray)
{
if (dltArray == null || dltArray.Length < 8)
throw new ArgumentException();
var year = BitConverter.ToUInt16(new[] { dltArray[1], dltArray[0] }, startIndex: 0);
return new DateTime(year, dltArray[2], dltArray[3], dltArray[5], dltArray[6], dltArray[7]);
}
}
}
OK, sorry, wer lesen kann.....
habe jetzt mal versucht mit der beschriebenen Methode den Monat auszulesen:
byte[] tempByteArray3 = new byte[1] {bytes[2]};
monat = BitConverter.ToUInt16(tempByteArray3, 0);
Mit dem Ergebnis: das ich folgende Fehlermeldung erhalte:
Fehlermeldung:
Fehlermeldung:
Additional information: Das Zielarray ist nicht lang genug, um alle Elemente in der Sammlung zu kopieren. Überprüfen Sie Arrayindex und -länge.
Hi,
siehe dazu auch meinen Edit obendrüber - KP was sich Siemens da mit den Angaben zu Datentypen gedacht hat - aber die ganzen anderen Werte sind ja offenkundig byte und da du ja am Ende sicher ohnehin ein DateTime haben möchtest - kannst du das ja implizit im Konstruktor einfach nehmen als wäre es ein int. (Der Wert zu deinem Hex-String kommt bei mir als 01.09.17 - 10:38 raus, was schon sinnvoll klang)
Falls du die Nanosekunden haben möchtest - schaust du dir mal am besten nachfolgenden Link an, da DateTime eben in Ticks (= 100 Nanosekunden) rechnet.
https://stackoverflow.com/questions/5358860/is-there-a-high-resolution-microsecond-nanosecond-datetime-object-available-f
LG
Edit:
Year ist der einzige UInt16 -der Rest sind Bytes - Nanosekunden sind demzufolge UInt32.
(int ist übrigens Int32)
Und man muss darauf achten, dass wir es hier mit BigEndian zu tun haben.
Mit einem passenden BinaryReader/Writer (der BigEndian verwendet) kann man so ein Byte-Array dann sehr schön lesen und schreiben.
Super so klappt es.
BigEndian ist in dieser Lösung kein Problem, bei meinem Ansatz musste ich die Bytes tatsächlich noch Umsortieren.
Edit:
Schon wieder nicht richtig hingeschaut... Natürlich werden hier die Bytes umsortiert:
BitConverter.ToUInt16(new[] { dltArray[1], dltArray[0] }, startIndex: 0);
Vielen Dank euch!
Gruß
Florian
Dafür ist eigentlich der Endian (endianness) verantwortlich.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code