From eb1fad93330ff9b51f51a63e457a63f8190c8587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20P=C4=85gowski?= Date: Wed, 23 Aug 2023 00:27:55 +0200 Subject: [PATCH] Add IEC date DataType --- S7.Net/Enums.cs | 5 +++ S7.Net/Helper/DateTimeExtensions.cs | 23 ++++++++++ S7.Net/Types/Date.cs | 70 +++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 S7.Net/Helper/DateTimeExtensions.cs create mode 100644 S7.Net/Types/Date.cs diff --git a/S7.Net/Enums.cs b/S7.Net/Enums.cs index 080dce6..3eb7e4b 100644 --- a/S7.Net/Enums.cs +++ b/S7.Net/Enums.cs @@ -202,6 +202,11 @@ /// DateTIme variable type /// DateTime, + + /// + /// IEC date (legacy) variable type + /// + Date, /// /// DateTimeLong variable type diff --git a/S7.Net/Helper/DateTimeExtensions.cs b/S7.Net/Helper/DateTimeExtensions.cs new file mode 100644 index 0000000..7e128c1 --- /dev/null +++ b/S7.Net/Helper/DateTimeExtensions.cs @@ -0,0 +1,23 @@ +using System; +using S7.Net.Types; +using DateTime = System.DateTime; + +namespace S7.Net.Helper +{ + public static class DateTimeExtensions + { + public static ushort GetDaysSinceIecDateStart(this DateTime dateTime) + { + if (dateTime < Date.IecMinDate) + { + throw new ArgumentException($"DateTime must be at least {Date.IecMinDate:d}"); + } + if (dateTime > Date.IecMaxDate) + { + throw new ArgumentException($"DateTime must be lower than {Date.IecMaxDate:d}"); + } + + return (ushort)(dateTime - Date.IecMinDate).TotalDays; + } + } +} \ No newline at end of file diff --git a/S7.Net/Types/Date.cs b/S7.Net/Types/Date.cs new file mode 100644 index 0000000..980742e --- /dev/null +++ b/S7.Net/Types/Date.cs @@ -0,0 +1,70 @@ +using System; +using S7.Net.Helper; + +namespace S7.Net.Types +{ + /// + /// Contains the conversion methods to convert Words from S7 plc to C#. + /// + public static class Date + { + /// + /// Minimum allowed date for the IEC date type + /// + public static readonly System.DateTime IecMinDate = new(year: 1990, month: 01, day: 01); + + /// + /// Maximum allowed date for the IEC date type + /// + public static readonly System.DateTime IecMaxDate = new(year: 2168, month: 12, day: 31); + + /// + /// Converts a word (2 bytes) to IEC date () + /// + public static System.DateTime FromByteArray(byte[] bytes) + { + if (bytes.Length != 2) + { + throw new ArgumentException("Wrong number of bytes. Bytes array must contain 2 bytes."); + } + + var daysSinceDateStart = Word.FromByteArray(bytes); + return IecMinDate.AddDays(daysSinceDateStart); + } + + /// + /// Converts a to word (2 bytes) + /// + public static byte[] ToByteArray(System.DateTime dateTime) => Word.ToByteArray(dateTime.GetDaysSinceIecDateStart()); + + /// + /// Converts an array of s to an array of bytes + /// + public static byte[] ToByteArray(System.DateTime[] value) + { + var arr = new ByteArray(); + foreach (var date in value) + arr.Add(ToByteArray(date)); + return arr.Array; + } + + /// + /// Converts an array of bytes to an array of s + /// + public static System.DateTime[] ToArray(byte[] bytes) + { + var values = new System.DateTime[bytes.Length / sizeof(ushort)]; + + for (int i = 0; i < values.Length; i++) + { + values[i] = FromByteArray( + new[] + { + bytes[i], bytes[i + 1] + }); + } + + return values; + } + } +} \ No newline at end of file