From 742addaa2527e78c246662fdf743db1535ddb5dc Mon Sep 17 00:00:00 2001 From: Rafael Schniedermann Date: Tue, 26 Jun 2018 23:57:36 +0200 Subject: [PATCH 1/3] weekly schedule read/write working --- BACnet.csproj | 2 ++ Serialize/ASN1.cs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/BACnet.csproj b/BACnet.csproj index a55cfe3..ed6de28 100644 --- a/BACnet.csproj +++ b/BACnet.csproj @@ -58,6 +58,7 @@ + @@ -100,6 +101,7 @@ + diff --git a/Serialize/ASN1.cs b/Serialize/ASN1.cs index 3e1cc03..9869099 100644 --- a/Serialize/ASN1.cs +++ b/Serialize/ASN1.cs @@ -483,6 +483,19 @@ public static void bacapp_encode_application_data(EncodeBuffer buffer, BacnetVal throw new ArgumentException($"Unsupported destination value '{value.Value}' (type {value.GetType()})"); } break; + case BacnetApplicationTags.BACNET_APPLICATION_TAG_WEEKLY_SCHEDULE: + if(value.Value is BacnetDailySchedule[] dayArr && dayArr.Length == 7) + { + for (int i = 0; i < 7; i++) + { + dayArr[i].Encode(buffer); + } + } + else + { + throw new ArgumentException("Value has to be array of 7 of daily schedule "); + } + break; default: //context specific if (value.Value is byte[] arr) @@ -2033,6 +2046,19 @@ public static int bacapp_decode_context_application_data(BacnetAddress address, return len; } + if(propertyId == BacnetPropertyIds.PROP_WEEKLY_SCHEDULE) + { + //has to be an array of 7 + var schedule = new BacnetDailySchedule[7]; + for (int i = 0; i < 7; i++) + { + schedule[i] = new BacnetDailySchedule(); + len += schedule[i].Decode(buffer, offset + len, (uint)maxOffset); + } + value.Value = schedule; + value.Tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_WEEKLY_SCHEDULE; + return len; + } value.Tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_CONTEXT_SPECIFIC_DECODED; var list = new List(); @@ -2418,6 +2444,7 @@ public static int decode_property_state(byte[] buffer, int offset, out BacnetPro return len + sectionLength; } + public static int decode_context_bitstring(byte[] buffer, int offset, byte tagNumber, out BacnetBitString value) { @@ -2466,5 +2493,8 @@ public static int decode_context_unsigned(byte[] buffer, int offset, byte tagNum var len = decode_tag_number_and_value(buffer, offset, out _, out var lenValue); return len + decode_unsigned(buffer, offset + len, lenValue, out value); } + + + } } From c9bb5e5bc7b18180d212d69b1346cc09b4eb0cb6 Mon Sep 17 00:00:00 2001 From: Rafael Schniedermann Date: Wed, 27 Jun 2018 00:00:47 +0200 Subject: [PATCH 2/3] added missing classes --- Base/BacnetDailySchedule.cs | 78 +++++++++++++++++++++++++++++++++++++ Base/BacnetTimeValue.cs | 24 ++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 Base/BacnetDailySchedule.cs create mode 100644 Base/BacnetTimeValue.cs diff --git a/Base/BacnetDailySchedule.cs b/Base/BacnetDailySchedule.cs new file mode 100644 index 0000000..be492a7 --- /dev/null +++ b/Base/BacnetDailySchedule.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.IO.BACnet.Serialize; +using System.Linq; +using System.Text; + +namespace System.IO.BACnet +{ + public struct BacnetDailySchedule : ASN1.IEncode, ASN1.IDecode + { + public List DaySchedule; + + + + public int Decode(byte[] buffer, int offset, uint count) + { + int len = 0; + DaySchedule = new List(); + //begin of daily sched + if (ASN1.IS_OPENING_TAG(buffer[offset + len])) + { + len++; + //end of daily sched + while (!ASN1.IS_CLOSING_TAG(buffer[offset + len]) ) + { + len++; //ignore apptag time ? + len += ASN1.decode_bacnet_time(buffer, offset + len, out DateTime time); + + + var tagLen = ASN1.decode_tag_number_and_value(buffer, offset + len, out BacnetApplicationTags tagNumber, out uint lenValueType); + BacnetValue value; + if (tagLen > 0) + { + len += tagLen; + var decodeLen = ASN1.bacapp_decode_data(buffer, offset + len, offset + len + 1, tagNumber, lenValueType, out value); + len += decodeLen; + } + else + { + value = new BacnetValue(BacnetApplicationTags.BACNET_APPLICATION_TAG_NULL, null); + } + + + DaySchedule.Add(new BacnetTimeValue(new BacnetGenericTime(time, BacnetTimestampTags.TIME_STAMP_TIME), value)); + + } + //closing tag + len++; + } + + return len; + } + + public void Encode(EncodeBuffer buffer) + { + ASN1.encode_opening_tag(buffer, 0); + + if (DaySchedule != null) + { + foreach (var dayItem in DaySchedule) + { + + ASN1.encode_tag(buffer, (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_TIME, false, 4); + ASN1.encode_bacnet_time(buffer, dayItem.Time.Time); + + ASN1.bacapp_encode_application_data(buffer, dayItem.Value); + } + } + ASN1.encode_closing_tag(buffer, 0); + } + + public override string ToString() + { + return $"DaySchedule Len: {DaySchedule?.Count()}"; + } + + } +} diff --git a/Base/BacnetTimeValue.cs b/Base/BacnetTimeValue.cs new file mode 100644 index 0000000..ecdf8b2 --- /dev/null +++ b/Base/BacnetTimeValue.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace System.IO.BACnet +{ + public struct BacnetTimeValue + { + public BacnetGenericTime Time; + public BacnetValue Value; + + public BacnetTimeValue(BacnetGenericTime time, BacnetValue value) + { + Time = time; + Value = value; + } + + public override string ToString() + { + return $"{Time} = {Value}"; + } + } +} From 9ac2b6518c77f944b94978a60b653462ce56621e Mon Sep 17 00:00:00 2001 From: Rafael Schniedermann Date: Wed, 27 Jun 2018 03:55:33 +0200 Subject: [PATCH 3/3] fixed bacnet value for schedule --- Base/BacnetValue.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Base/BacnetValue.cs b/Base/BacnetValue.cs index 1be34c2..962379f 100644 --- a/Base/BacnetValue.cs +++ b/Base/BacnetValue.cs @@ -45,6 +45,8 @@ public BacnetApplicationTags TagFromType(Type t) return BacnetApplicationTags.BACNET_APPLICATION_TAG_ERROR; if (t == typeof(BacnetDeviceObjectPropertyReference)) return BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_PROPERTY_REFERENCE; + if (t == typeof(BacnetDailySchedule[])) + return BacnetApplicationTags.BACNET_APPLICATION_TAG_WEEKLY_SCHEDULE; if (t.IsEnum) return BacnetApplicationTags.BACNET_APPLICATION_TAG_ENUMERATED;