From 9bdac289ec519485100e473eb392407307f1e490 Mon Sep 17 00:00:00 2001 From: jkpete <1031139173@qq.com> Date: Mon, 28 Oct 2024 14:43:10 +0800 Subject: [PATCH] delete global using and third code --- EGFramework.csproj | 3 +- Example/UsingTest/Script/EGSaveTest.cs | 2 + .../Module/SaveTools/EGByteSave.cs | 6 +- .../EGFramework/Module/SaveTools/EGCsvSave.cs | 4 +- .../Module/SaveTools/EGJsonSave.cs | 4 +- .../EGFramework/Module/SaveTools/EGSqlite.cs | 1 + .../BacNetPlugin/BACnetClient.cs | 2937 ----------------- .../BacNetPlugin/BacnetAsyncResult.cs | 158 - .../BacNetPlugin/Base/BaCnetCalendarEntry.cs | 69 - .../BacNetPlugin/Base/BacnetAbortReason.cs | 84 - .../BacNetPlugin/Base/BacnetAddress.cs | 196 -- .../BacNetPlugin/Base/BacnetAddressTypes.cs | 13 - .../Base/BacnetApplicationTags.cs | 65 - .../BacNetPlugin/Base/BacnetBinaryPv.cs | 10 - .../BacNetPlugin/Base/BacnetBitString.cs | 91 - .../BacNetPlugin/Base/BacnetBvlcFunctions.cs | 18 - .../BacNetPlugin/Base/BacnetBvlcResults.cs | 12 - .../Base/BacnetBvlcV6Functions.cs | 18 - .../BacNetPlugin/Base/BacnetBvlcV6Results.cs | 10 - .../Base/BacnetCOVSubscription.cs | 15 - .../Base/BacnetCharacterStringEncodings.cs | 13 - .../Base/BacnetConfirmedServices.cs | 47 - .../BacNetPlugin/Base/BacnetDate.cs | 125 - .../BacNetPlugin/Base/BacnetDateRange.cs | 53 - .../BacnetDeviceObjectPropertyReference.cs | 104 - .../BacNetPlugin/Base/BacnetDeviceStatus.cs | 11 - .../BacNetPlugin/Base/BacnetError.cs | 22 - .../BacNetPlugin/Base/BacnetErrorClasses.cs | 21 - .../BacNetPlugin/Base/BacnetErrorCodes.cs | 246 -- .../Base/BacnetEventNotificationData.cs | 140 - .../BacNetPlugin/Base/BacnetGenericTime.cs | 20 - .../Base/BacnetGetEventInformationData.cs | 12 - .../BacNetPlugin/Base/BacnetLogRecord.cs | 143 - .../BacNetPlugin/Base/BacnetMaxAdpu.cs | 11 - .../BacNetPlugin/Base/BacnetMaxSegments.cs | 13 - .../BacNetPlugin/Base/BacnetMstpFrameTypes.cs | 23 - .../Base/BacnetNetworkMessageTypes.cs | 31 - .../BacNetPlugin/Base/BacnetNodeTypes.cs | 17 - .../BacNetPlugin/Base/BacnetNpduControls.cs | 14 - .../Base/BacnetObjectDescription.cs | 7 - .../BacNetPlugin/Base/BacnetObjectId.cs | 82 - .../BacNetPlugin/Base/BacnetObjectTypes.cs | 82 - .../BacNetPlugin/Base/BacnetPduTypes.cs | 22 - .../BacNetPlugin/Base/BacnetPolarity.cs | 7 - .../BacNetPlugin/Base/BacnetProgramError.cs | 18 - .../BacNetPlugin/Base/BacnetProgramRequest.cs | 11 - .../BacNetPlugin/Base/BacnetProgramState.cs | 11 - .../BacNetPlugin/Base/BacnetPropertyIds.cs | 577 ---- .../Base/BacnetPropertyReference.cs | 23 - .../BacNetPlugin/Base/BacnetPropertyState.cs | 48 - .../BacNetPlugin/Base/BacnetPropertyValue.cs | 13 - .../Base/BacnetPtpDisconnectReasons.cs | 9 - .../BacNetPlugin/Base/BacnetPtpFrameTypes.cs | 24 - .../Base/BacnetReadAccessResult.cs | 13 - .../Base/BacnetReadAccessSpecification.cs | 40 - .../Base/BacnetReadRangeRequestTypes.cs | 9 - .../Base/BacnetReinitializedStates.cs | 14 - .../BacNetPlugin/Base/BacnetRejectReason.cs | 84 - .../BacNetPlugin/Base/BacnetReliability.cs | 27 - .../BacNetPlugin/Base/BacnetRestartReason.cs | 14 - .../BacNetPlugin/Base/BacnetResultFlags.cs | 10 - .../BacNetPlugin/Base/BacnetSegmentations.cs | 9 - .../Base/BacnetServicesSupported.cs | 62 - .../BacNetPlugin/Base/BacnetStatusFlags.cs | 10 - .../BacNetPlugin/Base/BacnetTimestampTags.cs | 9 - .../Base/BacnetTrendLogValueType.cs | 18 - .../Base/BacnetUnconfirmedServices.cs | 30 - .../BacNetPlugin/Base/BacnetUnitsId.cs | 311 -- .../BacNetPlugin/Base/BacnetValue.cs | 89 - .../BacNetPlugin/Base/BacnetWritePriority.cs | 22 - .../BacNetPlugin/Base/BacnetweekNDay.cs | 71 - .../Base/DeviceReportingRecipient.cs | 84 - .../Base/Enums/BacnetBackupState.cs | 10 - .../BacNetPlugin/Base/Enums/BacnetCOVTypes.cs | 7 - .../Base/Enums/BacnetEventEnable.cs | 8 - .../Base/Enums/BacnetEventStates.cs | 11 - .../Base/Enums/BacnetEventTypes.cs | 40 - .../Base/Enums/BacnetFileAccessMethod.cs | 7 - .../Base/Enums/BacnetLifeSafetyModes.cs | 30 - .../Base/Enums/BacnetLifeSafetyOperations.cs | 23 - .../Base/Enums/BacnetLifeSafetyStates.cs | 39 - .../Base/Enums/BacnetLimitEnable.cs | 7 - .../Base/Enums/BacnetNotifyTypes.cs | 8 - .../BacNetPlugin/GlobalUsings.cs | 21 - .../Helpers/BacnetValuesExtensions.cs | 64 - .../BacNetPlugin/Serialize/APDU.cs | 217 -- .../BacNetPlugin/Serialize/ASN1.cs | 2486 -------------- .../BacNetPlugin/Serialize/BVLC.cs | 416 --- .../BacNetPlugin/Serialize/EncodeBuffer.cs | 117 - .../BacNetPlugin/Serialize/EncodeResult.cs | 8 - .../BacNetPlugin/Serialize/MSTP.cs | 107 - .../BacNetPlugin/Serialize/NPDU.cs | 134 - .../BacNetPlugin/Serialize/PTP.cs | 67 - .../BacNetPlugin/Serialize/Services.cs | 2664 --------------- .../BacNetPlugin/Storage/DeviceStorage.cs | 459 --- .../BacNetPlugin/Storage/Object.cs | 18 - .../BacNetPlugin/Storage/Property.cs | 127 - .../BacNetPlugin/Transport/BVLCV6.cs | 351 -- .../Transport/BacnetIpUdpProtocolTransport.cs | 465 --- .../BacnetIpV6UdpProtocolTransport.cs | 362 -- .../Transport/BacnetMstpProtocolTransport.cs | 917 ----- .../Transport/BacnetPipeTransport.cs | 255 -- .../Transport/BacnetPtpProtocolTransport.cs | 607 ---- .../Transport/BacnetSerialPortTransport.cs | 72 - .../Transport/BacnetTransportBase.cs | 36 - .../Transport/BacnetTransportEthernet.cs | 224 -- .../Transport/IBacnetSerialTransport.cs | 11 - .../Transport/IBacnetTransport.cs | 17 - 108 files changed, 9 insertions(+), 17045 deletions(-) delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/BACnetClient.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/BacnetAsyncResult.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BaCnetCalendarEntry.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetAbortReason.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetAddress.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetAddressTypes.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetApplicationTags.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBinaryPv.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBitString.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBvlcFunctions.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBvlcResults.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBvlcV6Functions.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBvlcV6Results.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetCOVSubscription.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetCharacterStringEncodings.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetConfirmedServices.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetDate.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetDateRange.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetDeviceObjectPropertyReference.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetDeviceStatus.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetError.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetErrorClasses.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetErrorCodes.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetEventNotificationData.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetGenericTime.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetGetEventInformationData.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetLogRecord.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetMaxAdpu.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetMaxSegments.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetMstpFrameTypes.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetNetworkMessageTypes.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetNodeTypes.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetNpduControls.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetObjectDescription.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetObjectId.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetObjectTypes.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPduTypes.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPolarity.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetProgramError.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetProgramRequest.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetProgramState.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPropertyIds.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPropertyReference.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPropertyState.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPropertyValue.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPtpDisconnectReasons.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPtpFrameTypes.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetReadAccessResult.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetReadAccessSpecification.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetReadRangeRequestTypes.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetReinitializedStates.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetRejectReason.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetReliability.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetRestartReason.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetResultFlags.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetSegmentations.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetServicesSupported.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetStatusFlags.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetTimestampTags.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetTrendLogValueType.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetUnconfirmedServices.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetUnitsId.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetValue.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetWritePriority.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetweekNDay.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/DeviceReportingRecipient.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetBackupState.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetCOVTypes.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetEventEnable.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetEventStates.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetEventTypes.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetFileAccessMethod.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetLifeSafetyModes.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetLifeSafetyOperations.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetLifeSafetyStates.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetLimitEnable.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetNotifyTypes.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/GlobalUsings.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Helpers/BacnetValuesExtensions.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/APDU.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/ASN1.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/BVLC.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/EncodeBuffer.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/EncodeResult.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/MSTP.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/NPDU.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/PTP.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/Services.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Storage/DeviceStorage.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Storage/Object.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Storage/Property.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BVLCV6.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetIpUdpProtocolTransport.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetIpV6UdpProtocolTransport.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetMstpProtocolTransport.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetPipeTransport.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetPtpProtocolTransport.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetSerialPortTransport.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetTransportBase.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetTransportEthernet.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/IBacnetSerialTransport.cs delete mode 100644 addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/IBacnetTransport.cs diff --git a/EGFramework.csproj b/EGFramework.csproj index 2eb842e..70a91e5 100644 --- a/EGFramework.csproj +++ b/EGFramework.csproj @@ -13,9 +13,8 @@ - - + \ No newline at end of file diff --git a/Example/UsingTest/Script/EGSaveTest.cs b/Example/UsingTest/Script/EGSaveTest.cs index f6cbbce..6dab551 100644 --- a/Example/UsingTest/Script/EGSaveTest.cs +++ b/Example/UsingTest/Script/EGSaveTest.cs @@ -1,3 +1,5 @@ +using System.Collections.Generic; +using System.Linq; using Godot; using LiteDB; diff --git a/addons/EGFramework/Module/SaveTools/EGByteSave.cs b/addons/EGFramework/Module/SaveTools/EGByteSave.cs index 8d0d518..2da0141 100644 --- a/addons/EGFramework/Module/SaveTools/EGByteSave.cs +++ b/addons/EGFramework/Module/SaveTools/EGByteSave.cs @@ -1,9 +1,7 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using System.Runtime.Serialization.Formatters.Binary; using System.IO; +using System.Linq; +using System.Text; namespace EGFramework { diff --git a/addons/EGFramework/Module/SaveTools/EGCsvSave.cs b/addons/EGFramework/Module/SaveTools/EGCsvSave.cs index 7c45202..f5890c7 100644 --- a/addons/EGFramework/Module/SaveTools/EGCsvSave.cs +++ b/addons/EGFramework/Module/SaveTools/EGCsvSave.cs @@ -1,11 +1,11 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Data; using System.IO; using System.Linq; using System.Linq.Expressions; -using System.Threading.Tasks; +using System.Text; +using System.Reflection; namespace EGFramework { diff --git a/addons/EGFramework/Module/SaveTools/EGJsonSave.cs b/addons/EGFramework/Module/SaveTools/EGJsonSave.cs index f137aa5..65d5fed 100644 --- a/addons/EGFramework/Module/SaveTools/EGJsonSave.cs +++ b/addons/EGFramework/Module/SaveTools/EGJsonSave.cs @@ -1,8 +1,6 @@ using System; -using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Threading.Tasks; +using System.Text; using Newtonsoft.Json; using Newtonsoft.Json.Linq; diff --git a/addons/EGFramework/Module/SaveTools/EGSqlite.cs b/addons/EGFramework/Module/SaveTools/EGSqlite.cs index edb2a0a..747f47b 100644 --- a/addons/EGFramework/Module/SaveTools/EGSqlite.cs +++ b/addons/EGFramework/Module/SaveTools/EGSqlite.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using Microsoft.Data.Sqlite; using Newtonsoft.Json; diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/BACnetClient.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/BACnetClient.cs deleted file mode 100644 index 4d9a4de..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/BACnetClient.cs +++ /dev/null @@ -1,2937 +0,0 @@ -/************************************************************************** -* MIT License -* -* Copyright (C) 2014 Morten Kvistgaard -* -* Permission is hereby granted, free of charge, to any person obtaining -* a copy of this software and associated documentation files (the -* "Software"), to deal in the Software without restriction, including -* without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to -* permit persons to whom the Software is furnished to do so, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -* -*********************************************************************/ -using System.Collections.Concurrent; -using EGFramework; -using Godot; - -namespace System.IO.BACnet; - -public delegate void MessageRecievedHandler(IBacnetTransport sender, byte[] buffer, int offset, int msgLength, BacnetAddress remoteAddress); - -/// -/// BACnet network client or server -/// -public class BacnetClient : IDisposable -{ - private int _retries; - private int _invokeId; - - private readonly LastSegmentAck _lastSegmentAck = new(); - private uint _writepriority; - - /// - /// Dictionary of List of Tuples with sequence-number and byte[] per invoke-id - /// TODO: invoke-id should be PER (remote) DEVICE! - /// - private Dictionary>> _segmentsPerInvokeId = new(); - private ConcurrentDictionary _locksPerInvokeId = new(); - private Dictionary _expectedSegmentsPerInvokeId = new(); - - public const int DEFAULT_UDP_PORT = 0xBAC0; - public const int DEFAULT_TIMEOUT = 1000; - public const int DEFAULT_RETRIES = 3; - - public IBacnetTransport Transport { get; } - public ushort VendorId { get; set; } = 260; - public int Timeout { get; set; } - public int TransmitTimeout { get; set; } = 30000; - public BacnetMaxSegments MaxSegments { get; set; } = BacnetMaxSegments.MAX_SEG0; - public byte ProposedWindowSize { get; set; } = 10; - public bool ForceWindowSize { get; set; } - public bool DefaultSegmentationHandling { get; set; } = true; - public ILog Log { get; set; } = LogManager.GetLogger(); - - /// - /// Used as the number of tentatives - /// - public int Retries - { - get => _retries; - set => _retries = Math.Max(1, value); - } - - public uint WritePriority - { - get => _writepriority; - set { if (value < 17) _writepriority = value; } - } - - // These members allows to access undecoded buffer by the application - // layer, when the basic undecoding process is not really able to do the job - // in particular with application_specific_encoding values - public byte[] raw_buffer; - public int raw_offset, raw_length; - - public class Segmentation - { - // ReSharper disable InconsistentNaming - // was public before refactor so can't change this - public EncodeBuffer buffer; - public byte sequence_number; - public byte window_size; - public byte max_segments; - // ReSharper restore InconsistentNaming - } - - private class LastSegmentAck - { - private readonly ManualResetEvent _wait = new(false); - private readonly object _lockObject = new(); - private BacnetAddress _address; - private byte _invokeId; - - public byte SequenceNumber; - public byte WindowSize; - - public void Set(BacnetAddress adr, byte invokeId, byte sequenceNumber, byte windowSize) - { - lock (_lockObject) - { - _address = adr; - _invokeId = invokeId; - SequenceNumber = sequenceNumber; - WindowSize = windowSize; - _wait.Set(); - } - } - - public bool Wait(BacnetAddress adr, byte invokeId, int timeout) - { - Monitor.Enter(_lockObject); - while (!adr.Equals(this._address) || this._invokeId != invokeId) - { - _wait.Reset(); - Monitor.Exit(_lockObject); - if (!_wait.WaitOne(timeout)) return false; - Monitor.Enter(_lockObject); - } - Monitor.Exit(_lockObject); - _address = null; - return true; - } - } - - public BacnetClient(int port = DEFAULT_UDP_PORT, int timeout = DEFAULT_TIMEOUT, int retries = DEFAULT_RETRIES) - : this(new BacnetIpUdpProtocolTransport(port), timeout, retries) - { - } - - public BacnetClient(IBacnetTransport transport, int timeout = DEFAULT_TIMEOUT, int retries = DEFAULT_RETRIES) - { - Transport = transport; - Timeout = timeout; - Retries = retries; - } - - public override bool Equals(object obj) - { - return Transport.Equals((obj as BacnetClient)?.Transport); - } - - public override int GetHashCode() - { - return Transport.GetHashCode(); - } - - public override string ToString() - { - return Transport.ToString(); - } - - public EncodeBuffer GetEncodeBuffer(int startOffset) - { - return new EncodeBuffer(new byte[Transport.MaxBufferLength], startOffset); - } - - public void Start() - { - Transport.Start(); - Transport.MessageRecieved += OnRecieve; - Log.Info("Started communication"); - } - - public delegate void ConfirmedServiceRequestHandler(BacnetClient sender, BacnetAddress adr, BacnetPduTypes type, BacnetConfirmedServices service, BacnetMaxSegments maxSegments, BacnetMaxAdpu maxAdpu, byte invokeId, byte[] buffer, int offset, int length); - public event ConfirmedServiceRequestHandler OnConfirmedServiceRequest; - public delegate void ReadPropertyRequestHandler(BacnetClient sender, BacnetAddress adr, byte invokeId, BacnetObjectId objectId, BacnetPropertyReference property, BacnetMaxSegments maxSegments); - public event ReadPropertyRequestHandler OnReadPropertyRequest; - public delegate void ReadPropertyMultipleRequestHandler(BacnetClient sender, BacnetAddress adr, byte invokeId, IList properties, BacnetMaxSegments maxSegments); - public event ReadPropertyMultipleRequestHandler OnReadPropertyMultipleRequest; - public delegate void WritePropertyRequestHandler(BacnetClient sender, BacnetAddress adr, byte invokeId, BacnetObjectId objectId, BacnetPropertyValue value, BacnetMaxSegments maxSegments); - public event WritePropertyRequestHandler OnWritePropertyRequest; - public delegate void WritePropertyMultipleRequestHandler(BacnetClient sender, BacnetAddress adr, byte invokeId, BacnetObjectId objectId, ICollection values, BacnetMaxSegments maxSegments); - public event WritePropertyMultipleRequestHandler OnWritePropertyMultipleRequest; - public delegate void AtomicWriteFileRequestHandler(BacnetClient sender, BacnetAddress adr, byte invokeId, bool isStream, BacnetObjectId objectId, int position, uint blockCount, byte[][] blocks, int[] counts, BacnetMaxSegments maxSegments); - public event AtomicWriteFileRequestHandler OnAtomicWriteFileRequest; - public delegate void AtomicReadFileRequestHandler(BacnetClient sender, BacnetAddress adr, byte invokeId, bool isStream, BacnetObjectId objectId, int position, uint count, BacnetMaxSegments maxSegments); - public event AtomicReadFileRequestHandler OnAtomicReadFileRequest; - public delegate void SubscribeCOVRequestHandler(BacnetClient sender, BacnetAddress adr, byte invokeId, uint subscriberProcessIdentifier, BacnetObjectId monitoredObjectIdentifier, bool cancellationRequest, bool issueConfirmedNotifications, uint lifetime, BacnetMaxSegments maxSegments); - public event SubscribeCOVRequestHandler OnSubscribeCOV; - public delegate void EventNotificationCallbackHandler(BacnetClient sender, BacnetAddress adr, byte invokeId, BacnetEventNotificationData eventData, bool needConfirm); - public event EventNotificationCallbackHandler OnEventNotify; - public delegate void SubscribeCOVPropertyRequestHandler(BacnetClient sender, BacnetAddress adr, byte invokeId, uint subscriberProcessIdentifier, BacnetObjectId monitoredObjectIdentifier, BacnetPropertyReference monitoredProperty, bool cancellationRequest, bool issueConfirmedNotifications, uint lifetime, float covIncrement, BacnetMaxSegments maxSegments); - public event SubscribeCOVPropertyRequestHandler OnSubscribeCOVProperty; - public delegate void DeviceCommunicationControlRequestHandler(BacnetClient sender, BacnetAddress adr, byte invokeId, uint timeDuration, uint enableDisable, string password, BacnetMaxSegments maxSegments); - public event DeviceCommunicationControlRequestHandler OnDeviceCommunicationControl; - public delegate void ReinitializedRequestHandler(BacnetClient sender, BacnetAddress adr, byte invokeId, BacnetReinitializedStates state, string password, BacnetMaxSegments maxSegments); - public event ReinitializedRequestHandler OnReinitializedDevice; - public delegate void ReadRangeHandler(BacnetClient sender, BacnetAddress adr, byte invokeId, BacnetObjectId objectId, BacnetPropertyReference property, BacnetReadRangeRequestTypes requestType, uint position, DateTime time, int count, BacnetMaxSegments maxSegments); - public event ReadRangeHandler OnReadRange; - public delegate void CreateObjectRequestHandler(BacnetClient sender, BacnetAddress adr, byte invokeId, BacnetObjectId objectId, ICollection values, BacnetMaxSegments maxSegments); - public event CreateObjectRequestHandler OnCreateObjectRequest; - public delegate void DeleteObjectRequestHandler(BacnetClient sender, BacnetAddress adr, byte invokeId, BacnetObjectId objectId, BacnetMaxSegments maxSegments); - public event DeleteObjectRequestHandler OnDeleteObjectRequest; - public delegate void GetAlarmSummaryOrEventInformationRequestHandler(BacnetClient sender, BacnetAddress adr, byte invokeId, bool getEvent, BacnetObjectId objectId, BacnetMaxAdpu maxApdu, BacnetMaxSegments max_segments); - public event GetAlarmSummaryOrEventInformationRequestHandler OnGetAlarmSummaryOrEventInformation; - public delegate void AlarmAcknowledgeRequestHandler(BacnetClient sender, BacnetAddress adr, byte invokeId, uint ackProcessIdentifier, BacnetObjectId eventObjectIdentifier, uint eventStateAcked, string ackSource, BacnetGenericTime eventTimeStamp, BacnetGenericTime ackTimeStamp); - public event AlarmAcknowledgeRequestHandler OnAlarmAcknowledge; - - protected void ProcessConfirmedServiceRequest(BacnetAddress address, BacnetPduTypes type, BacnetConfirmedServices service, BacnetMaxSegments maxSegments, BacnetMaxAdpu maxAdpu, byte invokeId, byte[] buffer, int offset, int length) - { - try - { - Log.Debug($"ConfirmedServiceRequest {service}"); - - raw_buffer = buffer; - raw_length = length; - raw_offset = offset; - - OnConfirmedServiceRequest?.Invoke(this, address, type, service, maxSegments, maxAdpu, invokeId, buffer, offset, length); - - //don't send segmented messages, if client don't want it - if ((type & BacnetPduTypes.SEGMENTED_RESPONSE_ACCEPTED) == 0) - maxSegments = BacnetMaxSegments.MAX_SEG0; - - if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_READ_PROPERTY && OnReadPropertyRequest != null) - { - int thsRejectReason; - - if ((thsRejectReason = Services.DecodeReadProperty(buffer, offset, length, out var objectId, out var property)) >= 0) - { - OnReadPropertyRequest(this, address, invokeId, objectId, property, maxSegments); - } - else - { - switch (thsRejectReason) - { - case -1: - SendConfirmedServiceReject(address, invokeId, BacnetRejectReason.MISSING_REQUIRED_PARAMETER); - break; - case -2: - SendConfirmedServiceReject(address, invokeId, BacnetRejectReason.INVALID_TAG); - break; - case -3: - SendConfirmedServiceReject(address, invokeId, BacnetRejectReason.TOO_MANY_ARGUMENTS); - break; - } - Log.Warn("Couldn't decode DecodeReadProperty"); - } - } - else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_WRITE_PROPERTY && OnWritePropertyRequest != null) - { - if (Services.DecodeWriteProperty(address, buffer, offset, length, out var objectId, out var value) >= 0) - OnWritePropertyRequest(this, address, invokeId, objectId, value, maxSegments); - else - { - // DAL - SendAbort(address, invokeId, BacnetAbortReason.OTHER); - //ErrorResponse(address, service, invokeId, BacnetErrorClasses.ERROR_CLASS_SERVICES, BacnetErrorCodes.ERROR_CODE_ABORT_OTHER); - //SendConfirmedServiceReject(adr, invokeId, BacnetRejectReason.OTHER); - Log.Warn("Couldn't decode DecodeWriteProperty"); - } - } - else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_READ_PROP_MULTIPLE && OnReadPropertyMultipleRequest != null) - { - if (Services.DecodeReadPropertyMultiple(buffer, offset, length, out var properties) >= 0) - OnReadPropertyMultipleRequest(this, address, invokeId, properties, maxSegments); - else - { - // DAL - SendAbort(address, invokeId, BacnetAbortReason.OTHER); - //ErrorResponse(address, service, invokeId, BacnetErrorClasses.ERROR_CLASS_SERVICES, BacnetErrorCodes.ERROR_CODE_ABORT_OTHER); - Log.Warn("Couldn't decode DecodeReadPropertyMultiple"); - } - } - else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_WRITE_PROP_MULTIPLE && OnWritePropertyMultipleRequest != null) - { - if (Services.DecodeWritePropertyMultiple(address, buffer, offset, length, out var objectId, out var values) >= 0) - OnWritePropertyMultipleRequest(this, address, invokeId, objectId, values, maxSegments); - else - { - // DAL - SendAbort(address, invokeId, BacnetAbortReason.OTHER); - //ErrorResponse(address, service, invokeId, BacnetErrorClasses.ERROR_CLASS_SERVICES, BacnetErrorCodes.ERROR_CODE_ABORT_OTHER); - Log.Warn("Couldn't decode DecodeWritePropertyMultiple"); - } - } - else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_COV_NOTIFICATION && OnCOVNotification != null) - { - if (Services.DecodeCOVNotifyUnconfirmed(address, buffer, offset, length, out var subscriberProcessIdentifier, out var initiatingDeviceIdentifier, out var monitoredObjectIdentifier, out var timeRemaining, out var values) >= 0) - OnCOVNotification(this, address, invokeId, subscriberProcessIdentifier, initiatingDeviceIdentifier, monitoredObjectIdentifier, timeRemaining, true, values, maxSegments); - else - { - // DAL - SendAbort(address, invokeId, BacnetAbortReason.OTHER); - //ErrorResponse(address, service, invokeId, BacnetErrorClasses.ERROR_CLASS_SERVICES, BacnetErrorCodes.ERROR_CODE_ABORT_OTHER); - Log.Warn("Couldn't decode COVNotify"); - } - } - else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_ATOMIC_WRITE_FILE && OnAtomicWriteFileRequest != null) - { - if (Services.DecodeAtomicWriteFile(buffer, offset, length, out var isStream, out var objectId, out var position, out var blockCount, out var blocks, out var counts) >= 0) - OnAtomicWriteFileRequest(this, address, invokeId, isStream, objectId, position, blockCount, blocks, counts, maxSegments); - else - { - // DAL - SendAbort(address, invokeId, BacnetAbortReason.OTHER); - //ErrorResponse(address, service, invokeId, BacnetErrorClasses.ERROR_CLASS_SERVICES, BacnetErrorCodes.ERROR_CODE_ABORT_OTHER); - Log.Warn("Couldn't decode AtomicWriteFile"); - } - } - else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_ATOMIC_READ_FILE && OnAtomicReadFileRequest != null) - { - if (Services.DecodeAtomicReadFile(buffer, offset, length, out var isStream, out var objectId, out var position, out var count) >= 0) - OnAtomicReadFileRequest(this, address, invokeId, isStream, objectId, position, count, maxSegments); - else - { - // DAL - SendAbort(address, invokeId, BacnetAbortReason.OTHER); - //ErrorResponse(address, service, invokeId, BacnetErrorClasses.ERROR_CLASS_SERVICES, BacnetErrorCodes.ERROR_CODE_ABORT_OTHER); - Log.Warn("Couldn't decode AtomicReadFile"); - } - } - else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_SUBSCRIBE_COV && OnSubscribeCOV != null) - { - if (Services.DecodeSubscribeCOV(buffer, offset, length, out var subscriberProcessIdentifier, out var monitoredObjectIdentifier, out var cancellationRequest, out var issueConfirmedNotifications, out var lifetime) >= 0) - OnSubscribeCOV(this, address, invokeId, subscriberProcessIdentifier, monitoredObjectIdentifier, cancellationRequest, issueConfirmedNotifications, lifetime, maxSegments); - else - { - // DAL - SendAbort(address, invokeId, BacnetAbortReason.OTHER); - //ErrorResponse(address, service, invokeId, BacnetErrorClasses.ERROR_CLASS_SERVICES, BacnetErrorCodes.ERROR_CODE_ABORT_OTHER); - Log.Warn("Couldn't decode SubscribeCOV"); - } - } - else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_SUBSCRIBE_COV_PROPERTY && OnSubscribeCOVProperty != null) - { - if (Services.DecodeSubscribeProperty(buffer, offset, length, out var subscriberProcessIdentifier, out var monitoredObjectIdentifier, out var monitoredProperty, out var cancellationRequest, out var issueConfirmedNotifications, out var lifetime, out var covIncrement) >= 0) - OnSubscribeCOVProperty(this, address, invokeId, subscriberProcessIdentifier, monitoredObjectIdentifier, monitoredProperty, cancellationRequest, issueConfirmedNotifications, lifetime, covIncrement, maxSegments); - else - { - // DAL - SendAbort(address, invokeId, BacnetAbortReason.OTHER); - //ErrorResponse(address, service, invokeId, BacnetErrorClasses.ERROR_CLASS_SERVICES, BacnetErrorCodes.ERROR_CODE_ABORT_OTHER); - Log.Warn("Couldn't decode SubscribeCOVProperty"); - } - } - else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL && OnDeviceCommunicationControl != null) - { - // DAL - if (Services.DecodeDeviceCommunicationControl(buffer, offset, length, out var timeDuration, out var enableDisable, out var password) >= 0) - OnDeviceCommunicationControl(this, address, invokeId, timeDuration, enableDisable, password, maxSegments); - else - { - // DAL - SendAbort(address, invokeId, BacnetAbortReason.OTHER); - //ErrorResponse(address, service, invokeId, BacnetErrorClasses.ERROR_CLASS_SERVICES, BacnetErrorCodes.ERROR_CODE_ABORT_OTHER); - Log.Warn("Couldn't decode DeviceCommunicationControl"); - } - } - else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_REINITIALIZE_DEVICE && OnReinitializedDevice != null) - { - // DAL - if (Services.DecodeReinitializeDevice(buffer, offset, length, out var state, out var password) >= 0) - OnReinitializedDevice(this, address, invokeId, state, password, maxSegments); - else - { - // DAL - SendAbort(address, invokeId, BacnetAbortReason.OTHER); - //ErrorResponse(address, service, invokeId, BacnetErrorClasses.ERROR_CLASS_SERVICES, BacnetErrorCodes.ERROR_CODE_ABORT_OTHER); - Log.Warn("Couldn't decode ReinitializeDevice"); - } - } - else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_EVENT_NOTIFICATION && OnEventNotify != null) // F. Chaxel - { - if (Services.DecodeEventNotifyData(buffer, offset, length, out var eventData) >= 0) - { - OnEventNotify(this, address, invokeId, eventData, true); - } - else - { - // DAL - SendAbort(address, invokeId, BacnetAbortReason.OTHER); - //ErrorResponse(address, service, invokeId, BacnetErrorClasses.ERROR_CLASS_SERVICES, BacnetErrorCodes.ERROR_CODE_ABORT_OTHER); - Log.Warn("Couldn't decode confirmed Event/Alarm Notification"); - } - } - else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_READ_RANGE && OnReadRange != null) - { - if (Services.DecodeReadRange(buffer, offset, length, out var objectId, out var property, out var requestType, out var position, out var time, out var count) >= 0) - OnReadRange(this, address, invokeId, objectId, property, requestType, position, time, count, maxSegments); - else - { - // DAL - SendAbort(address, invokeId, BacnetAbortReason.OTHER); - //ErrorResponse(address, service, invokeId, BacnetErrorClasses.ERROR_CLASS_SERVICES, BacnetErrorCodes.ERROR_CODE_ABORT_OTHER); - Log.Warn("Couldn't decode ReadRange"); - } - } - else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_CREATE_OBJECT && OnCreateObjectRequest != null) - { - if (Services.DecodeCreateObject(address, buffer, offset, length, out var objectId, out var values) >= 0) - OnCreateObjectRequest(this, address, invokeId, objectId, values, maxSegments); - else - { - // DAL - SendAbort(address, invokeId, BacnetAbortReason.OTHER); - //ErrorResponse(address, service, invokeId, BacnetErrorClasses.ERROR_CLASS_SERVICES, BacnetErrorCodes.ERROR_CODE_ABORT_OTHER); - Log.Warn("Couldn't decode CreateObject"); - } - } - else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_DELETE_OBJECT && OnDeleteObjectRequest != null) - { - if (Services.DecodeDeleteObject(buffer, offset, length, out var objectId) >= 0) - OnDeleteObjectRequest(this, address, invokeId, objectId, maxSegments); - else - { - // DAL - SendAbort(address, invokeId, BacnetAbortReason.OTHER); - //ErrorResponse(address, service, invokeId, BacnetErrorClasses.ERROR_CLASS_SERVICES, BacnetErrorCodes.ERROR_CODE_ABORT_OTHER); - Log.Warn("Couldn't decode DecodeDeleteObject"); - } - } - else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_GET_ALARM_SUMMARY && OnGetAlarmSummaryOrEventInformation != null) - { - // DAL -- added the core code required but since I couldn't test it we just reject this service - // rejecting it shouldn't be too bad a thing since GetAlarmSummary has been retired anyway... - // if someone needs it they can uncomment the related code and test. -#if false - BacnetObjectId objectId = default(BacnetObjectId); - objectId.Type = BacnetObjectTypes.MAX_BACNET_OBJECT_TYPE; - if (Services.DecodeAlarmSummaryOrEventRequest(buffer, offset, length, false, ref objectId) >= 0) - { - OnGetAlarmSummaryOrEventInformation(this, address, invokeId, false, objectId, maxAdpu, maxSegments); - } - else - { - // DAL - SendAbort(address, invokeId, BacnetAbortReason.OTHER); - //ErrorResponse(address, service, invokeId, BacnetErrorClasses.ERROR_CLASS_SERVICES, BacnetErrorCodes.ERROR_CODE_ABORT_OTHER); - Log.Warn("Couldn't decode GetAlarmSummary"); - } -#else - SendConfirmedServiceReject(address, invokeId, BacnetRejectReason.RECOGNIZED_SERVICE); // should be unrecognized but this is the way it was spelled.. -#endif - } - else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_GET_EVENT_INFORMATION && OnGetAlarmSummaryOrEventInformation != null) - { - // DAL - BacnetObjectId objectId = default; - objectId.Type = BacnetObjectTypes.MAX_BACNET_OBJECT_TYPE; - if (Services.DecodeAlarmSummaryOrEventRequest(buffer, offset, length, true, ref objectId) >= 0) - { - OnGetAlarmSummaryOrEventInformation(this, address, invokeId, true, objectId, maxAdpu, maxSegments); - } - else - { - // DAL - SendAbort(address, invokeId, BacnetAbortReason.OTHER); - //ErrorResponse(address, service, invokeId, BacnetErrorClasses.ERROR_CLASS_SERVICES, BacnetErrorCodes.ERROR_CODE_ABORT_OTHER); - Log.Warn("Couldn't decode GetEventInformation"); - } - } - else if (service == BacnetConfirmedServices.SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM && OnAlarmAcknowledge != null) - { - // DAL - if (Services.DecodeAlarmAcknowledge(buffer, offset, length, out uint ackProcessIdentifier, out BacnetObjectId eventObjectIdentifier, out uint eventStateAcked, out string ackSource, out BacnetGenericTime eventTimeStamp, out BacnetGenericTime ackTimeStamp) >= 0) - { - OnAlarmAcknowledge(this, address, invokeId, ackProcessIdentifier, eventObjectIdentifier, eventStateAcked, ackSource, eventTimeStamp, ackTimeStamp); - } - else - { - // DAL - SendAbort(address, invokeId, BacnetAbortReason.OTHER); - //ErrorResponse(address, service, invokeId, BacnetErrorClasses.ERROR_CLASS_SERVICES, BacnetErrorCodes.ERROR_CODE_ABORT_OTHER); - Log.Warn("Couldn't decode AlarmAcknowledge"); - } - } - else - { - // DAL - SendConfirmedServiceReject(address, invokeId, BacnetRejectReason.RECOGNIZED_SERVICE); // should be unrecognized but this is the way it was spelled.. - Log.Debug($"Confirmed service not handled: {service}"); - } - } - catch (Exception ex) - { - // DAL - SendAbort(address, invokeId, BacnetAbortReason.OTHER); - //ErrorResponse(address, service, invokeId, BacnetErrorClasses.ERROR_CLASS_DEVICE, BacnetErrorCodes.ERROR_CODE_ABORT_OTHER); - Log.Error("Error in ProcessConfirmedServiceRequest", ex); - } - } - - public delegate void UnconfirmedServiceRequestHandler(BacnetClient sender, BacnetAddress adr, BacnetPduTypes type, BacnetUnconfirmedServices service, byte[] buffer, int offset, int length); - public event UnconfirmedServiceRequestHandler OnUnconfirmedServiceRequest; - public delegate void WhoHasHandler(BacnetClient sender, BacnetAddress adr, int lowLimit, int highLimit, BacnetObjectId? objId, string objName); - public event WhoHasHandler OnWhoHas; - public delegate void IamHandler(BacnetClient sender, BacnetAddress adr, uint deviceId, uint maxAPDU, BacnetSegmentations segmentation, ushort vendorId); - public event IamHandler OnIam; - public delegate void WhoIsHandler(BacnetClient sender, BacnetAddress adr, int lowLimit, int highLimit); - public event WhoIsHandler OnWhoIs; - public delegate void TimeSynchronizeHandler(BacnetClient sender, BacnetAddress adr, DateTime dateTime, bool utc); - public event TimeSynchronizeHandler OnTimeSynchronize; - - //used by both 'confirmed' and 'unconfirmed' notify - public delegate void COVNotificationHandler(BacnetClient sender, BacnetAddress adr, byte invokeId, uint subscriberProcessIdentifier, BacnetObjectId initiatingDeviceIdentifier, BacnetObjectId monitoredObjectIdentifier, uint timeRemaining, bool needConfirm, ICollection values, BacnetMaxSegments maxSegments); - public event COVNotificationHandler OnCOVNotification; - - protected void ProcessUnconfirmedServiceRequest(BacnetAddress address, BacnetPduTypes type, BacnetUnconfirmedServices service, byte[] buffer, int offset, int length) - { - try - { - Log.Debug("UnconfirmedServiceRequest"); - OnUnconfirmedServiceRequest?.Invoke(this, address, type, service, buffer, offset, length); - if (service == BacnetUnconfirmedServices.SERVICE_UNCONFIRMED_I_AM && OnIam != null) - { - if (Services.DecodeIamBroadcast(buffer, offset, out var deviceId, out var maxAdpu, out var segmentation, out var vendorId) >= 0) - OnIam(this, address, deviceId, maxAdpu, segmentation, vendorId); - else - Log.Warn("Couldn't decode IamBroadcast"); - } - else if (service == BacnetUnconfirmedServices.SERVICE_UNCONFIRMED_WHO_IS && OnWhoIs != null) - { - if (Services.DecodeWhoIsBroadcast(buffer, offset, length, out var lowLimit, out var highLimit) >= 0) - OnWhoIs(this, address, lowLimit, highLimit); - else - Log.Warn("Couldn't decode WhoIsBroadcast"); - } - // added by thamersalek - else if (service == BacnetUnconfirmedServices.SERVICE_UNCONFIRMED_WHO_HAS && OnWhoHas != null) - { - if (Services.DecodeWhoHasBroadcast(buffer, offset, length, out var lowLimit, out var highLimit, out var objId, out var objName) >= 0) - OnWhoHas(this, address, lowLimit, highLimit, objId, objName); - else - Log.Warn("Couldn't decode WhoHasBroadcast"); - } - else if (service == BacnetUnconfirmedServices.SERVICE_UNCONFIRMED_COV_NOTIFICATION && OnCOVNotification != null) - { - if (Services.DecodeCOVNotifyUnconfirmed(address, buffer, offset, length, out var subscriberProcessIdentifier, out var initiatingDeviceIdentifier, out var monitoredObjectIdentifier, out var timeRemaining, out var values) >= 0) - OnCOVNotification(this, address, 0, subscriberProcessIdentifier, initiatingDeviceIdentifier, monitoredObjectIdentifier, timeRemaining, false, values, BacnetMaxSegments.MAX_SEG0); - else - Log.Warn("Couldn't decode COVNotifyUnconfirmed"); - } - else if (service == BacnetUnconfirmedServices.SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION && OnTimeSynchronize != null) - { - if (Services.DecodeTimeSync(buffer, offset, length, out var dateTime) >= 0) - OnTimeSynchronize(this, address, dateTime, false); - else - Log.Warn("Couldn't decode TimeSynchronize"); - } - else if (service == BacnetUnconfirmedServices.SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION && OnTimeSynchronize != null) - { - if (Services.DecodeTimeSync(buffer, offset, length, out var dateTime) >= 0) - OnTimeSynchronize(this, address, dateTime, true); - else - Log.Warn("Couldn't decode TimeSynchronize"); - } - else if (service == BacnetUnconfirmedServices.SERVICE_UNCONFIRMED_EVENT_NOTIFICATION && OnEventNotify != null) // F. Chaxel - { - if (Services.DecodeEventNotifyData(buffer, offset, length, out var eventData) >= 0) - OnEventNotify(this, address, 0, eventData, false); - else - Log.Warn("Couldn't decode unconfirmed Event/Alarm Notification"); - } - else - { - Log.Debug($"Unconfirmed service not handled: {service}"); - // SendUnConfirmedServiceReject(adr); ? exists ? - } - } - catch (Exception ex) - { - Log.Error("Error in ProcessUnconfirmedServiceRequest", ex); - } - } - - public delegate void SimpleAckHandler(BacnetClient sender, BacnetAddress adr, BacnetPduTypes type, BacnetConfirmedServices service, byte invokeId, byte[] data, int dataOffset, int dataLength); - public event SimpleAckHandler OnSimpleAck; - - protected void ProcessSimpleAck(BacnetAddress adr, BacnetPduTypes type, BacnetConfirmedServices service, byte invokeId, byte[] buffer, int offset, int length) - { - try - { - Log.Debug($"Received SimpleAck for {service}"); - OnSimpleAck?.Invoke(this, adr, type, service, invokeId, buffer, offset, length); - } - catch (Exception ex) - { - Log.Error("Error in ProcessSimpleAck", ex); - } - } - - public delegate void ComplexAckHandler(BacnetClient sender, BacnetAddress adr, BacnetPduTypes type, BacnetConfirmedServices service, byte invokeId, byte[] buffer, int offset, int length); - public event ComplexAckHandler OnComplexAck; - - protected void ProcessComplexAck(BacnetAddress adr, BacnetPduTypes type, BacnetConfirmedServices service, byte invokeId, byte[] buffer, int offset, int length) - { - try - { - Log.Debug($"Received ComplexAck for {service}"); - OnComplexAck?.Invoke(this, adr, type, service, invokeId, buffer, offset, length); - } - catch (Exception ex) - { - Log.Error($"Error in {nameof(ProcessComplexAck)}", ex); - } - } - - public delegate void ErrorHandler(BacnetClient sender, BacnetAddress adr, BacnetPduTypes type, BacnetConfirmedServices service, byte invokeId, BacnetErrorClasses errorClass, BacnetErrorCodes errorCode, byte[] buffer, int offset, int length); - public event ErrorHandler OnError; - - protected void ProcessError(BacnetAddress adr, BacnetPduTypes type, BacnetConfirmedServices service, byte invokeId, byte[] buffer, int offset, int length) - { - try - { - if (Services.DecodeError(buffer, offset, length, out var errorClass, out var errorCode) < 0) - Log.Warn("Couldn't decode received Error"); - - Log.Debug($"Received Error {errorClass} {errorCode}"); - OnError?.Invoke(this, adr, type, service, invokeId, errorClass, errorCode, buffer, offset, length); - } - catch (Exception ex) - { - Log.Error($"Error in {nameof(ProcessError)}", ex); - } - } - - public delegate void AbortHandler(BacnetClient sender, BacnetAddress adr, BacnetPduTypes type, byte invokeId, BacnetAbortReason reason, byte[] buffer, int offset, int length); - public event AbortHandler OnAbort; - - protected void ProcessAbort(BacnetAddress adr, BacnetPduTypes type, byte invokeId, BacnetAbortReason reason, byte[] buffer, int offset, int length) - { - try - { - Log.Debug($"Received Abort, reason: {reason}"); - OnAbort?.Invoke(this, adr, type, invokeId, reason, buffer, offset, length); - } - catch (Exception ex) - { - Log.Error("Error in ProcessAbort", ex); - } - } - - public delegate void RejectHandler(BacnetClient sender, BacnetAddress adr, BacnetPduTypes type, byte invokeId, BacnetRejectReason reason, byte[] buffer, int offset, int length); - public event RejectHandler OnReject; - - protected void ProcessReject(BacnetAddress adr, BacnetPduTypes type, byte invokeId, BacnetRejectReason reason, byte[] buffer, int offset, int length) - { - try - { - Log.Debug($"Received Reject, reason: {reason}"); - OnReject?.Invoke(this, adr, type, invokeId, reason, buffer, offset, length); - } - catch (Exception ex) - { - Log.Error("Error in ProcessReject", ex); - } - } - - public delegate void SegmentAckHandler(BacnetClient sender, BacnetAddress adr, BacnetPduTypes type, byte originalInvokeId, byte sequenceNumber, byte actualWindowSize, byte[] buffer, int offset, int length); - public event SegmentAckHandler OnSegmentAck; - - protected void ProcessSegmentAck(BacnetAddress adr, BacnetPduTypes type, byte originalInvokeId, byte sequenceNumber, byte actualWindowSize, byte[] buffer, int offset, int length) - { - try - { - Log.Debug("Received SegmentAck"); - OnSegmentAck?.Invoke(this, adr, type, originalInvokeId, sequenceNumber, actualWindowSize, buffer, offset, length); - } - catch (Exception ex) - { - Log.Error("Error in ProcessSegmentAck", ex); - } - } - - public delegate void SegmentHandler(BacnetClient sender, BacnetAddress adr, BacnetPduTypes type, BacnetConfirmedServices service, byte invokeId, BacnetMaxSegments maxSegments, BacnetMaxAdpu maxAdpu, byte sequenceNumber, byte[] buffer, int offset, int length); - public event SegmentHandler OnSegment; - - private void ProcessSegment(BacnetAddress address, BacnetPduTypes type, BacnetConfirmedServices service, byte invokeId, BacnetMaxSegments maxSegments, BacnetMaxAdpu maxAdpu, bool server, byte sequenceNumber, byte proposedWindowNumber, byte[] buffer, int offset, int length) - { - lock (_locksPerInvokeId.GetOrAdd(invokeId, () => new object())) - { - ProcessSegmentLocked(address, type, service, invokeId, maxSegments, maxAdpu, server, sequenceNumber, - proposedWindowNumber, buffer, offset, length); - } - } - - private void ProcessSegmentLocked(BacnetAddress adr, BacnetPduTypes type, BacnetConfirmedServices service, - byte invokeId, BacnetMaxSegments maxSegments, BacnetMaxAdpu maxAdpu, bool server, byte sequenceNumber, - byte proposedWindowNumber, byte[] buffer, int offset, int length) - { - Log.Trace($@"Processing Segment #{sequenceNumber} of invoke-id #{invokeId}"); - - if (!_segmentsPerInvokeId.ContainsKey(invokeId)) - _segmentsPerInvokeId[invokeId] = new List>(); - - if (!_expectedSegmentsPerInvokeId.ContainsKey(invokeId)) - _expectedSegmentsPerInvokeId[invokeId] = byte.MaxValue; - - var moreFollows = (type & BacnetPduTypes.MORE_FOLLOWS) == BacnetPduTypes.MORE_FOLLOWS; - - if (!moreFollows) - _expectedSegmentsPerInvokeId[invokeId] = (byte)(sequenceNumber + 1); - - //send ACK - if (sequenceNumber % proposedWindowNumber == 0 || !moreFollows) - { - if (ForceWindowSize) - proposedWindowNumber = ProposedWindowSize; - - SegmentAckResponse(adr, false, server, invokeId, sequenceNumber, proposedWindowNumber); - } - - //Send on - OnSegment?.Invoke(this, adr, type, service, invokeId, maxSegments, maxAdpu, sequenceNumber, buffer, offset, length); - - //default segment assembly. We run this seperately from the above handler, to make sure that it comes after! - if (DefaultSegmentationHandling) - PerformDefaultSegmentHandling(adr, type, service, invokeId, maxSegments, maxAdpu, sequenceNumber, buffer, offset, length); - } - - /// - /// This is a simple handling that stores all segments in memory and assembles them when done - /// - private void PerformDefaultSegmentHandling(BacnetAddress adr, BacnetPduTypes type, BacnetConfirmedServices service, byte invokeId, BacnetMaxSegments maxSegments, BacnetMaxAdpu maxAdpu, byte sequenceNumber, byte[] buffer, int offset, int length) - { - var segments = _segmentsPerInvokeId[invokeId]; - - if (sequenceNumber == 0) - { - //copy buffer + encode new adpu header - type &= ~BacnetPduTypes.SEGMENTED_MESSAGE; - var confirmedServiceRequest = (type & BacnetPduTypes.PDU_TYPE_MASK) == BacnetPduTypes.PDU_TYPE_CONFIRMED_SERVICE_REQUEST; - var adpuHeaderLen = confirmedServiceRequest ? 4 : 3; - - var copy = new byte[length + adpuHeaderLen]; - Array.Copy(buffer, offset, copy, adpuHeaderLen, length); - var encodedBuffer = new EncodeBuffer(copy, 0); - - if (confirmedServiceRequest) - APDU.EncodeConfirmedServiceRequest(encodedBuffer, type, service, maxSegments, maxAdpu, invokeId); - else - APDU.EncodeComplexAck(encodedBuffer, type, service, invokeId); - - segments.Add(Tuple.Create(sequenceNumber, copy)); // doesn't include BVLC or NPDU - } - else - { - //copy only content part - segments.Add(Tuple.Create(sequenceNumber, buffer.Skip(offset).Take(length).ToArray())); - } - - //process when finished - if (segments.Count < _expectedSegmentsPerInvokeId[invokeId]) - return; - - //assemble whole part - var apduBuffer = segments.OrderBy(s => s.Item1).SelectMany(s => s.Item2).ToArray(); - segments.Clear(); - _expectedSegmentsPerInvokeId[invokeId] = byte.MaxValue; - - //process - ProcessApdu(adr, type, apduBuffer, 0, apduBuffer.Length); - } - - private void ProcessApdu(BacnetAddress adr, BacnetPduTypes type, byte[] buffer, int offset, int length) - { - switch (type & BacnetPduTypes.PDU_TYPE_MASK) - { - case BacnetPduTypes.PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST: - { - var apduHeaderLen = APDU.DecodeUnconfirmedServiceRequest(buffer, offset, out type, out var service); - offset += apduHeaderLen; - length -= apduHeaderLen; - ProcessUnconfirmedServiceRequest(adr, type, service, buffer, offset, length); - } - break; - - case BacnetPduTypes.PDU_TYPE_SIMPLE_ACK: - { - var apduHeaderLen = APDU.DecodeSimpleAck(buffer, offset, out type, out var service, out var invokeId); - offset += apduHeaderLen; - length -= apduHeaderLen; - ProcessSimpleAck(adr, type, service, invokeId, buffer, offset, length); - } - break; - - case BacnetPduTypes.PDU_TYPE_COMPLEX_ACK: - { - var apduHeaderLen = APDU.DecodeComplexAck(buffer, offset, out type, out var service, out var invokeId, - out var sequenceNumber, out var proposedWindowNumber); - - offset += apduHeaderLen; - length -= apduHeaderLen; - if ((type & BacnetPduTypes.SEGMENTED_MESSAGE) == 0) //don't process segmented messages here - { - ProcessComplexAck(adr, type, service, invokeId, buffer, offset, length); - } - else - { - ProcessSegment(adr, type, service, invokeId, BacnetMaxSegments.MAX_SEG0, BacnetMaxAdpu.MAX_APDU50, false, - sequenceNumber, proposedWindowNumber, buffer, offset, length); - } - } - break; - - case BacnetPduTypes.PDU_TYPE_SEGMENT_ACK: - { - var apduHeaderLen = APDU.DecodeSegmentAck(buffer, offset, out type, out var originalInvokeId, - out var sequenceNumber, out var actualWindowSize); - - offset += apduHeaderLen; - length -= apduHeaderLen; - _lastSegmentAck.Set(adr, originalInvokeId, sequenceNumber, actualWindowSize); - ProcessSegmentAck(adr, type, originalInvokeId, sequenceNumber, actualWindowSize, buffer, offset, length); - } - break; - - case BacnetPduTypes.PDU_TYPE_ERROR: - { - var apduHeaderLen = APDU.DecodeError(buffer, offset, out type, out var service, out var invokeId); - offset += apduHeaderLen; - length -= apduHeaderLen; - ProcessError(adr, type, service, invokeId, buffer, offset, length); - } - break; - - case BacnetPduTypes.PDU_TYPE_ABORT: - { - var apduHeaderLen = APDU.DecodeAbort(buffer, offset, out type, out var invokeId, out var reason); - offset += apduHeaderLen; - length -= apduHeaderLen; - ProcessAbort(adr, type, invokeId, reason, buffer, offset, length); - } - break; - - case BacnetPduTypes.PDU_TYPE_REJECT: - { - var apduHeaderLen = APDU.DecodeReject(buffer, offset, out type, out var invokeId, out var reason); - offset += apduHeaderLen; - length -= apduHeaderLen; - ProcessReject(adr, type, invokeId, reason, buffer, offset, length); - } - break; - - case BacnetPduTypes.PDU_TYPE_CONFIRMED_SERVICE_REQUEST: - { - var apduHeaderLen = APDU.DecodeConfirmedServiceRequest(buffer, offset, out type, out var service, - out var maxSegments, out var maxAdpu, out var invokeId, out var sequenceNumber, out var proposedWindowNumber); - - offset += apduHeaderLen; - length -= apduHeaderLen; - - if ((type & BacnetPduTypes.SEGMENTED_MESSAGE) == 0) //don't process segmented messages here - { - ProcessConfirmedServiceRequest(adr, type, service, maxSegments, maxAdpu, invokeId, buffer, offset, length); - } - else - { - ProcessSegment(adr, type, service, invokeId, maxSegments, maxAdpu, true, sequenceNumber, proposedWindowNumber, buffer, offset, length); - } - } - break; - - default: - Log.Warn($"Something else arrived: {type}"); - break; - } - } - - // DAL - public void SendNetworkMessage(BacnetAddress adr, byte[] buffer, int bufLen, BacnetNetworkMessageTypes messageType, ushort vendorId = 0) - { - if (adr == null) - { - adr = Transport.GetBroadcastAddress(); - } - var b = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(b, BacnetNpduControls.NetworkLayerMessage, adr, null, 255, messageType, vendorId); - b.Add(buffer, bufLen); - Transport.Send(b.buffer, Transport.HeaderLength, b.offset - Transport.HeaderLength, adr, false, 0); - } - public void SendIAmRouterToNetwork(ushort[] networks) - { - var b = GetEncodeBuffer(0); - for (int i = 0; i < networks.Length; i++) - { - ASN1.encode_unsigned16(b, networks[i]); - } - SendNetworkMessage(null, b.buffer, b.offset, BacnetNetworkMessageTypes.NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK); - } - - public void SendInitializeRoutingTableAck(BacnetAddress adr, ushort[] networks) - { - var b = GetEncodeBuffer(0); - if (networks != null) - { - for (int i = 0; i < networks.Length; i++) - { - ASN1.encode_unsigned16(b, networks[i]); - } - } - SendNetworkMessage(adr, b.buffer, b.offset, BacnetNetworkMessageTypes.NETWORK_MESSAGE_INIT_RT_TABLE_ACK); - } - public void SendRejectToNetwork(BacnetAddress adr, ushort[] networks) - { - var b = GetEncodeBuffer(0); - /* Sending our DNET doesn't make a lot of sense, does it? */ - for (int i = 0; i < networks.Length; i++) - { - ASN1.encode_unsigned16(b, networks[i]); - } - SendNetworkMessage(adr, b.buffer, b.offset, BacnetNetworkMessageTypes.NETWORK_MESSAGE_REJECT_MESSAGE_TO_NETWORK); - } - public delegate void NetworkMessageHandler(BacnetClient sender, BacnetAddress adr, BacnetNpduControls npduFunction, BacnetNetworkMessageTypes npduMessageType, byte[] buffer, int offset, int messageLength); - public event NetworkMessageHandler OnNetworkMessage; - public delegate void WhoIsRouterToNetworkHandler(BacnetClient sender, BacnetAddress adr, BacnetNpduControls npduFunction, byte[] buffer, int offset, int messageLength); - public event WhoIsRouterToNetworkHandler OnWhoIsRouterToNetworkMessage; - public delegate void IAmRouterToNetworkHandler(BacnetClient sender, BacnetAddress adr, BacnetNpduControls npduFunction, byte[] buffer, int offset, int messageLength); - public event IAmRouterToNetworkHandler OnIAmRouterToNetworkMessage; - public delegate void ICouldBeRouterToNetworkHandler(BacnetClient sender, BacnetAddress adr, BacnetNpduControls npduFunction, byte[] buffer, int offset, int messageLength); - public event ICouldBeRouterToNetworkHandler OnICouldBeRouterToNetworkMessage; - public delegate void RejectMessageToNetworkHandler(BacnetClient sender, BacnetAddress adr, BacnetNpduControls npduFunction, byte[] buffer, int offset, int messageLength); - public event RejectMessageToNetworkHandler OnRejectMessageToNetworkMessage; - public delegate void RouterBusyToNetworkHandler(BacnetClient sender, BacnetAddress adr, BacnetNpduControls npduFunction, byte[] buffer, int offset, int messageLength); - public event RouterBusyToNetworkHandler OnRouterBusyToNetworkMessage; - public delegate void RouterAvailableToNetworkHandler(BacnetClient sender, BacnetAddress adr, BacnetNpduControls npduFunction, byte[] buffer, int offset, int messageLength); - public event RouterAvailableToNetworkHandler OnRouterAvailableToNetworkMessage; - public delegate void InitRtTableToNetworkHandler(BacnetClient sender, BacnetAddress adr, BacnetNpduControls npduFunction, byte[] buffer, int offset, int messageLength); - public event InitRtTableToNetworkHandler OnInitRtTableToNetworkMessage; - public delegate void InitRtTableAckToNetworkHandler(BacnetClient sender, BacnetAddress adr, BacnetNpduControls npduFunction, byte[] buffer, int offset, int messageLength); - public event InitRtTableAckToNetworkHandler OnInitRtTableAckToNetworkMessage; - public delegate void EstablishConnectionToNetworkHandler(BacnetClient sender, BacnetAddress adr, BacnetNpduControls npduFunction, byte[] buffer, int offset, int messageLength); - public event EstablishConnectionToNetworkHandler OnEstablishConnectionToNetworkMessage; - public delegate void DisconnectConnectionToNetworkHandler(BacnetClient sender, BacnetAddress adr, BacnetNpduControls npduFunction, byte[] buffer, int offset, int messageLength); - public event DisconnectConnectionToNetworkHandler OnDisconnectConnectionToNetworkMessage; - public delegate void UnrecognizedNetworkHandler(BacnetClient sender, BacnetAddress adr, BacnetNpduControls npduFunction, byte[] buffer, int offset, int messageLength); - public event UnrecognizedNetworkHandler OnUnrecognizedNetworkMessage; - - private void ProcessNetworkMessage(BacnetAddress adr, BacnetNpduControls npduFunction, BacnetNetworkMessageTypes npduMessageType, byte[] buffer, int offset, int messageLength) - { - // DAL I don't want to make a generic router, but I do want to put in enough infrastructure - // that I can build on it to route multiple devices in the normal bacnet way. - OnNetworkMessage?.Invoke(this, adr, npduFunction, npduMessageType, buffer, offset, messageLength); - switch (npduMessageType) - { - case BacnetNetworkMessageTypes.NETWORK_MESSAGE_WHO_IS_ROUTER_TO_NETWORK: - OnWhoIsRouterToNetworkMessage?.Invoke(this, adr, npduFunction, buffer, offset, messageLength); - break; - case BacnetNetworkMessageTypes.NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK: - OnIAmRouterToNetworkMessage?.Invoke(this, adr, npduFunction, buffer, offset, messageLength); - break; - case BacnetNetworkMessageTypes.NETWORK_MESSAGE_I_COULD_BE_ROUTER_TO_NETWORK: - OnICouldBeRouterToNetworkMessage?.Invoke(this, adr, npduFunction, buffer, offset, messageLength); - break; - case BacnetNetworkMessageTypes.NETWORK_MESSAGE_REJECT_MESSAGE_TO_NETWORK: - OnRejectMessageToNetworkMessage?.Invoke(this, adr, npduFunction, buffer, offset, messageLength); - break; - case BacnetNetworkMessageTypes.NETWORK_MESSAGE_ROUTER_BUSY_TO_NETWORK: - OnRouterBusyToNetworkMessage?.Invoke(this, adr, npduFunction, buffer, offset, messageLength); - break; - case BacnetNetworkMessageTypes.NETWORK_MESSAGE_ROUTER_AVAILABLE_TO_NETWORK: - OnRouterAvailableToNetworkMessage?.Invoke(this, adr, npduFunction, buffer, offset, messageLength); - break; - case BacnetNetworkMessageTypes.NETWORK_MESSAGE_INIT_RT_TABLE: - OnInitRtTableToNetworkMessage?.Invoke(this, adr, npduFunction, buffer, offset, messageLength); - break; - case BacnetNetworkMessageTypes.NETWORK_MESSAGE_INIT_RT_TABLE_ACK: - OnInitRtTableAckToNetworkMessage?.Invoke(this, adr, npduFunction, buffer, offset, messageLength); - break; - case BacnetNetworkMessageTypes.NETWORK_MESSAGE_ESTABLISH_CONNECTION_TO_NETWORK: - OnEstablishConnectionToNetworkMessage?.Invoke(this, adr, npduFunction, buffer, offset, messageLength); - break; - case BacnetNetworkMessageTypes.NETWORK_MESSAGE_DISCONNECT_CONNECTION_TO_NETWORK: - OnDisconnectConnectionToNetworkMessage?.Invoke(this, adr, npduFunction, buffer, offset, messageLength); - break; - default: - /* An unrecognized message is bad; send an error response. */ - OnUnrecognizedNetworkMessage?.Invoke(this, adr, npduFunction, buffer, offset, messageLength); - break; - } - } - - private void OnRecieve(IBacnetTransport sender, byte[] buffer, int offset, int msgLength, BacnetAddress remoteAddress) - { - try - { - if (Transport == null) - return; //we're disposed - - if (msgLength <= 0) - return; - - // parse - var npduLen = NPDU.Decode(buffer, offset, out var npduFunction, out var destination, out var source, out _, out var npduMessageType, out _); - - // Modif FC - remoteAddress.RoutedSource = source; - - // DAL - remoteAddress.RoutedDestination = destination; - - if (npduLen <= 0) - return; - - offset += npduLen; - msgLength -= npduLen; - - if (msgLength < 0) // could be 0 for an already parsed - return; - - if (npduFunction.HasFlag(BacnetNpduControls.NetworkLayerMessage)) - { - Log.Info("Network Layer message received"); - // DAL - ProcessNetworkMessage(remoteAddress, npduFunction, npduMessageType, buffer, offset, msgLength); - return; - } - - if (msgLength <= 0) - return; - - var apduType = APDU.GetDecodedType(buffer, offset); - ProcessApdu(remoteAddress, apduType, buffer, offset, msgLength); - } - catch (Exception ex) - { - Log.Error("Error in OnRecieve", ex); - } - } - - // Modif FC - public void RegisterAsForeignDevice(string bbmdIp, short ttl, int port = DEFAULT_UDP_PORT) - { - try - { - var ep = new IPEndPoint(IPAddress.Parse(bbmdIp), port); - var sent = false; - - switch (Transport) - { - case BacnetIpUdpProtocolTransport t: - sent = t.SendRegisterAsForeignDevice(ep, ttl); - break; - - case BacnetIpV6UdpProtocolTransport t: - sent = t.SendRegisterAsForeignDevice(ep, ttl); - break; - } - - if (sent) - Log.Debug($"Sending Register as a Foreign Device to {bbmdIp}"); - else - Log.Warn("The given address do not match with the IP version"); - } - catch (Exception ex) - { - Log.Error("Error on RegisterAsForeignDevice (Wrong Transport, not IP ?)", ex); - } - } - - public void RemoteWhoIs(string bbmdIP, int port = DEFAULT_UDP_PORT, int lowLimit = -1, int highLimit = -1, BacnetAddress source = null) - { - try - { - var ep = new IPEndPoint(IPAddress.Parse(bbmdIP), port); - - var b = GetEncodeBuffer(Transport.HeaderLength); - var broadcast = Transport.GetBroadcastAddress(); - NPDU.Encode(b, BacnetNpduControls.PriorityNormalMessage, broadcast, source); - APDU.EncodeUnconfirmedServiceRequest(b, BacnetPduTypes.PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST, BacnetUnconfirmedServices.SERVICE_UNCONFIRMED_WHO_IS); - Services.EncodeWhoIsBroadcast(b, lowLimit, highLimit); - - var sent = false; - - switch (Transport) - { - case BacnetIpUdpProtocolTransport t: - sent = t.SendRemoteWhois(b.buffer, ep, b.offset); - break; - - case BacnetIpV6UdpProtocolTransport t: - sent = t.SendRemoteWhois(b.buffer, ep, b.offset); - break; - } - - if (sent) - Log.Debug($"Sending Remote Whois to {bbmdIP}"); - else - Log.Warn("The given address do not match with the IP version"); - } - catch (Exception ex) - { - Log.Error("Error on Sending Whois to remote BBMD (Wrong Transport, not IP ?)", ex); - } - - } - - public void WhoIs(int lowLimit = -1, int highLimit = -1, BacnetAddress receiver = null, BacnetAddress source = null) - { - if (receiver == null) - { - // _receiver could be an unicast @ : for direct acces - // usefull on BIP for a known IP:Port, unknown device Id - receiver = Transport.GetBroadcastAddress(); - Log.Debug("Broadcasting WhoIs"); - } - else - { - Log.Debug($"Sending WhoIs to {receiver}"); - } - - var b = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(b, BacnetNpduControls.PriorityNormalMessage, receiver, source); - APDU.EncodeUnconfirmedServiceRequest(b, BacnetPduTypes.PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST, BacnetUnconfirmedServices.SERVICE_UNCONFIRMED_WHO_IS); - Services.EncodeWhoIsBroadcast(b, lowLimit, highLimit); - - Transport.Send(b.buffer, Transport.HeaderLength, b.offset - Transport.HeaderLength, receiver, false, 0); - } - - public void Iam(uint deviceId, BacnetSegmentations segmentation = BacnetSegmentations.SEGMENTATION_BOTH, BacnetAddress receiver = null, BacnetAddress source = null) - { - if (receiver == null) - { - receiver = Transport.GetBroadcastAddress(); - Log.Debug($"Broadcasting Iam {deviceId}"); - } - else - { - Log.Debug($"Sending Iam {deviceId} to {receiver}"); - } - - var b = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(b, BacnetNpduControls.PriorityNormalMessage, receiver, source); - APDU.EncodeUnconfirmedServiceRequest(b, BacnetPduTypes.PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST, BacnetUnconfirmedServices.SERVICE_UNCONFIRMED_I_AM); - Services.EncodeIamBroadcast(b, deviceId, (uint)GetMaxApdu(), segmentation, VendorId); - - Transport.Send(b.buffer, Transport.HeaderLength, b.offset - Transport.HeaderLength, receiver, false, 0); - //GD.Print(b.buffer.ToStringByHex()); - } - - public void WhoHas(BacnetObjectId objId, int lowLimit = -1, int highLimit = -1, BacnetAddress receiver = null, BacnetAddress source = null) - { - WhoHasCore(objId, null, lowLimit, highLimit, receiver, source); - } - - public void WhoHas(string objName, int lowLimit = -1, int highLimit = -1, BacnetAddress receiver = null, BacnetAddress source = null) - { - WhoHasCore(null, objName, lowLimit, highLimit, receiver, source); - } - - private void WhoHasCore(BacnetObjectId? objId, string objName, int lowLimit, int highLimit, BacnetAddress receiver, BacnetAddress source) - { - if (receiver == null) - { - receiver = Transport.GetBroadcastAddress(); - Log.Debug($"Broadcasting WhoHas {objId?.ToString() ?? objName}"); - } - else - { - Log.Debug($"Sending WhoHas {objId?.ToString() ?? objName} to {receiver}"); - } - - var b = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(b, BacnetNpduControls.PriorityNormalMessage, receiver, source); - APDU.EncodeUnconfirmedServiceRequest(b, BacnetPduTypes.PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST, BacnetUnconfirmedServices.SERVICE_UNCONFIRMED_WHO_HAS); - Services.EncodeWhoHasBroadcast(b, lowLimit, highLimit, objId, objName); - - Transport.Send(b.buffer, Transport.HeaderLength, b.offset - Transport.HeaderLength, receiver, false, 0); - } - - // ReSharper disable once InconsistentNaming - public void IHave(BacnetObjectId deviceId, BacnetObjectId objId, string objName, BacnetAddress source = null) - { - Log.Debug($"Broadcasting IHave {objName} {objId}"); - - var b = GetEncodeBuffer(Transport.HeaderLength); - var broadcast = Transport.GetBroadcastAddress(); - NPDU.Encode(b, BacnetNpduControls.PriorityNormalMessage, broadcast, source); - APDU.EncodeUnconfirmedServiceRequest(b, BacnetPduTypes.PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST, BacnetUnconfirmedServices.SERVICE_UNCONFIRMED_I_HAVE); - Services.EncodeIhaveBroadcast(b, deviceId, objId, objName); - - Transport.Send(b.buffer, Transport.HeaderLength, b.offset - Transport.HeaderLength, broadcast, false, 0); - } - - public void SendUnconfirmedEventNotification(BacnetAddress adr, BacnetEventNotificationData eventData, BacnetAddress source = null) - { - Log.Debug($"Sending Event Notification {eventData.eventType} {eventData.eventObjectIdentifier}"); - - var b = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(b, BacnetNpduControls.PriorityNormalMessage, adr, source); - APDU.EncodeUnconfirmedServiceRequest(b, BacnetPduTypes.PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST, BacnetUnconfirmedServices.SERVICE_UNCONFIRMED_EVENT_NOTIFICATION); - Services.EncodeEventNotifyUnconfirmed(b, eventData); - Transport.Send(b.buffer, Transport.HeaderLength, b.offset - Transport.HeaderLength, adr, false, 0); - } - - public void SendConfirmedServiceReject(BacnetAddress adr, byte invokeId, BacnetRejectReason reason) - { - Log.Debug($"Sending Service reject: {reason}"); - - var b = GetEncodeBuffer(Transport.HeaderLength); - - NPDU.Encode(b, BacnetNpduControls.PriorityNormalMessage, adr.RoutedSource, adr.RoutedDestination); - APDU.EncodeError(b, BacnetPduTypes.PDU_TYPE_REJECT, (BacnetConfirmedServices)reason, invokeId); - Transport.Send(b.buffer, Transport.HeaderLength, b.offset - Transport.HeaderLength, adr, false, 0); - } - - public void SendAbort(BacnetAddress adr, byte invokeId, BacnetAbortReason reason) - { - // DAL - Log.Debug($"Sending Service reject: {reason}"); - - var b = GetEncodeBuffer(Transport.HeaderLength); - - NPDU.Encode(b, BacnetNpduControls.PriorityNormalMessage, adr.RoutedSource, adr.RoutedDestination); - APDU.EncodeError(b, BacnetPduTypes.PDU_TYPE_ABORT, (BacnetConfirmedServices)reason, invokeId); - Transport.Send(b.buffer, Transport.HeaderLength, b.offset - Transport.HeaderLength, adr, false, 0); - } - - public void SynchronizeTime(BacnetAddress adr, DateTime dateTime, BacnetAddress source = null) - { - Log.Debug($"Sending Time Synchronize: {dateTime} {dateTime.Kind.ToString().ToUpper()}"); - - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage, adr, source); - APDU.EncodeUnconfirmedServiceRequest(buffer, BacnetPduTypes.PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST, dateTime.Kind == DateTimeKind.Utc - ? BacnetUnconfirmedServices.SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION - : BacnetUnconfirmedServices.SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION); - Services.EncodeTimeSync(buffer, dateTime); - Transport.Send(buffer.buffer, Transport.HeaderLength, buffer.offset - Transport.HeaderLength, adr, false, 0); - } - - - public int GetMaxApdu() - { - return GetMaxApdu(Transport.MaxAdpuLength); - } - // DAL - public int GetMaxApdu(BacnetMaxAdpu apduLength) - { - int maxAPDU; - switch (apduLength) - { - case BacnetMaxAdpu.MAX_APDU1476: - maxAPDU = 1476; - break; - case BacnetMaxAdpu.MAX_APDU1024: - maxAPDU = 1024; - break; - case BacnetMaxAdpu.MAX_APDU480: - maxAPDU = 480; - break; - case BacnetMaxAdpu.MAX_APDU206: - maxAPDU = 206; - break; - case BacnetMaxAdpu.MAX_APDU128: - maxAPDU = 128; - break; - case BacnetMaxAdpu.MAX_APDU50: - maxAPDU = 50; - break; - default: - throw new NotImplementedException(); - } - - //max udp payload IRL seems to differ from the expectations in BACnet - //so we have to adjust it. (In order to fulfill the standard) - const int maxNPDUHeaderLength = 4; //usually it's '2', but it can also be more than '4'. Beware! - return Math.Min(maxAPDU, Transport.MaxBufferLength - Transport.HeaderLength - maxNPDUHeaderLength); - } - - public int GetFileBufferMaxSize() - { - //6 should be the max_apdu_header_length for Confirmed (with segmentation) - //12 should be the max_atomic_write_file - return GetMaxApdu() - 18; - } - - public bool WriteFileRequest(BacnetAddress adr, BacnetObjectId objectId, ref int position, int count, byte[] fileBuffer, byte invokeId = 0) - { - using (var result = (BacnetAsyncResult)BeginWriteFileRequest(adr, objectId, position, count, fileBuffer, true, invokeId)) - { - for (var r = 0; r < _retries; r++) - { - if (result.WaitForDone(Timeout)) - { - EndWriteFileRequest(result, out position, out var ex); - if (ex != null) - throw ex; - return true; - } - if (r < Retries - 1) - result.Resend(); - } - } - return false; - } - - public IAsyncResult BeginWriteFileRequest(BacnetAddress adr, BacnetObjectId objectId, int position, int count, byte[] fileBuffer, bool waitForTransmit, byte invokeId = 0) - { - Log.Debug("Sending AtomicWriteFileRequest"); - if (invokeId == 0) - invokeId = (byte)Interlocked.Increment(ref _invokeId); - - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply, adr.RoutedSource, adr.RoutedDestination); - APDU.EncodeConfirmedServiceRequest(buffer, PduConfirmedServiceRequest(), BacnetConfirmedServices.SERVICE_CONFIRMED_ATOMIC_WRITE_FILE, MaxSegments, Transport.MaxAdpuLength, invokeId); - Services.EncodeAtomicWriteFile(buffer, true, objectId, position, 1, new[] { fileBuffer }, new[] { count }); - - //send - var ret = new BacnetAsyncResult(this, adr, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - public void EndWriteFileRequest(IAsyncResult result, out int position, out Exception ex) - { - var res = (BacnetAsyncResult)result; - ex = res.Error; - if (ex == null && !res.WaitForDone(Timeout)) - ex = new Exception("Wait Timeout"); - - if (ex == null) - { - //decode - if (Services.DecodeAtomicWriteFileAcknowledge(res.Result, 0, res.Result.Length, out _, out position) < 0) - ex = new Exception("Decode"); - } - else - { - position = -1; - } - - res.Dispose(); - } - - public IAsyncResult BeginReadFileRequest(BacnetAddress adr, BacnetObjectId objectId, int position, uint count, bool waitForTransmit, byte invokeId = 0) - { - Log.Debug("Sending AtomicReadFileRequest"); - if (invokeId == 0) - invokeId = (byte)Interlocked.Increment(ref _invokeId); - - //encode - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply, adr.RoutedSource, adr.RoutedDestination); - APDU.EncodeConfirmedServiceRequest(buffer, PduConfirmedServiceRequest(), BacnetConfirmedServices.SERVICE_CONFIRMED_ATOMIC_READ_FILE, MaxSegments, Transport.MaxAdpuLength, invokeId); - Services.EncodeAtomicReadFile(buffer, true, objectId, position, count); - - //send - var ret = new BacnetAsyncResult(this, adr, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - public void EndReadFileRequest(IAsyncResult result, out uint count, out int position, out bool endOfFile, out byte[] fileBuffer, out int fileBufferOffset, out Exception ex) - { - var res = (BacnetAsyncResult)result; - ex = res.Error; - if (ex == null && !res.WaitForDone(Timeout)) - ex = new Exception("Wait Timeout"); - - if (ex == null) - { - //decode - if (Services.DecodeAtomicReadFileAcknowledge(res.Result, 0, res.Result.Length, out endOfFile, out _, out position, out count, out fileBuffer, out fileBufferOffset) < 0) - ex = new Exception("Decode"); - } - else - { - count = 0; - endOfFile = true; - position = -1; - fileBufferOffset = -1; - fileBuffer = new byte[0]; - } - - res.Dispose(); - } - - public bool ReadFileRequest(BacnetAddress adr, BacnetObjectId objectId, ref int position, ref uint count, out bool endOfFile, out byte[] fileBuffer, out int fileBufferOffset, byte invokeId = 0) - { - using (var result = (BacnetAsyncResult)BeginReadFileRequest(adr, objectId, position, count, true, invokeId)) - { - for (var r = 0; r < _retries; r++) - { - if (result.WaitForDone(Timeout)) - { - EndReadFileRequest(result, out count, out position, out endOfFile, out fileBuffer, out fileBufferOffset, out var ex); - if (ex != null) - throw ex; - return true; - } - if (r < Retries - 1) - result.Resend(); - } - } - position = -1; - count = 0; - fileBuffer = null; - endOfFile = true; - fileBufferOffset = -1; - return false; - } - - // Read range by postion - public IAsyncResult BeginReadRangeRequest(BacnetAddress adr, BacnetObjectId objectId, uint idxBegin, uint quantity, bool waitForTransmit, byte invokeId = 0) - { - return BeginReadRangeRequestCore(adr, objectId, BacnetReadRangeRequestTypes.RR_BY_POSITION, DateTime.Now, idxBegin, quantity, waitForTransmit, invokeId); - } - - // Read range by start time - public IAsyncResult BeginReadRangeRequest(BacnetAddress adr, BacnetObjectId objectId, DateTime readFrom, uint quantity, bool waitForTransmit, byte invokeId = 0) - { - return BeginReadRangeRequestCore(adr, objectId, BacnetReadRangeRequestTypes.RR_BY_TIME, readFrom, 1, quantity, waitForTransmit, invokeId); - } - - private IAsyncResult BeginReadRangeRequestCore(BacnetAddress adr, BacnetObjectId objectId, BacnetReadRangeRequestTypes bacnetReadRangeRequestTypes, DateTime readFrom, uint idxBegin, uint quantity, bool waitForTransmit, byte invokeId = 0) - { - Log.Debug("Sending ReadRangeRequest"); - if (invokeId == 0) - invokeId = (byte)Interlocked.Increment(ref _invokeId); - - //encode - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply, adr.RoutedSource, adr.RoutedDestination); - APDU.EncodeConfirmedServiceRequest(buffer, PduConfirmedServiceRequest(), BacnetConfirmedServices.SERVICE_CONFIRMED_READ_RANGE, MaxSegments, Transport.MaxAdpuLength, invokeId); - Services.EncodeReadRange(buffer, objectId, (uint)BacnetPropertyIds.PROP_LOG_BUFFER, ASN1.BACNET_ARRAY_ALL, bacnetReadRangeRequestTypes, idxBegin, readFrom, (int)quantity); - //send - var ret = new BacnetAsyncResult(this, adr, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - // Fc - public void EndReadRangeRequest(IAsyncResult result, out byte[] trendbuffer, out uint itemCount, out Exception ex) - { - var res = (BacnetAsyncResult)result; - itemCount = 0; - trendbuffer = null; - - ex = res.Error; - if (ex == null && !res.WaitForDone(40 * 1000)) - ex = new Exception("Wait Timeout"); - - if (ex == null) - { - itemCount = Services.DecodeReadRangeAcknowledge(res.Result, 0, res.Result.Length, out trendbuffer); - if (itemCount == 0) - ex = new Exception("Decode"); - } - - res.Dispose(); - } - - // Fc - public bool ReadRangeRequest(BacnetAddress adr, BacnetObjectId objectId, DateTime readFrom, ref uint quantity, out byte[] range, byte invokeId = 0) - { - return ReadRangeRequestCore(BacnetReadRangeRequestTypes.RR_BY_TIME, adr, objectId, 1, readFrom, ref quantity, out range, invokeId); - } - public bool ReadRangeRequest(BacnetAddress adr, BacnetObjectId objectId, uint idxBegin, ref uint quantity, out byte[] range, byte invokeId = 0) - { - return ReadRangeRequestCore(BacnetReadRangeRequestTypes.RR_BY_POSITION, adr, objectId, idxBegin, DateTime.Now, ref quantity, out range, invokeId); - } - - private bool ReadRangeRequestCore(BacnetReadRangeRequestTypes requestType, BacnetAddress adr, BacnetObjectId objectId, uint idxBegin, DateTime readFrom, ref uint quantity, out byte[] range, byte invokeId = 0) - { - Func getResult; - uint quantityCopy = quantity; - switch (requestType) - { - case BacnetReadRangeRequestTypes.RR_BY_TIME: - getResult = () => BeginReadRangeRequest(adr, objectId, readFrom, quantityCopy, true, invokeId); - break; - - case BacnetReadRangeRequestTypes.RR_BY_POSITION: - getResult = () => BeginReadRangeRequest(adr, objectId, idxBegin, quantityCopy, true, invokeId); - break; - - default: - throw new NotImplementedException($"BacnetReadRangeRequestTypes-Type {requestType} not supported in {nameof(ReadRangeRequestCore)}!"); - } - - range = null; - using (var result = getResult() as BacnetAsyncResult) - { - for (var r = 0; r < _retries; r++) - { - if (result.WaitForDone(Timeout)) - { - EndReadRangeRequest(result, out range, out quantity, out var ex); // quantity read could be less than demanded - if (ex != null) - throw ex; - return true; - } - if (r < Retries - 1) - result.Resend(); - } - } - return false; - } - - public bool SubscribeCOVRequest(BacnetAddress adr, BacnetObjectId objectId, uint subscribeId, bool cancel, bool issueConfirmedNotifications, uint lifetime, byte invokeId = 0) - { - using (var result = (BacnetAsyncResult)BeginSubscribeCOVRequest(adr, objectId, subscribeId, cancel, issueConfirmedNotifications, lifetime, true, invokeId)) - { - for (var r = 0; r < _retries; r++) - { - if (result.WaitForDone(Timeout)) - { - EndSubscribeCOVRequest(result, out var ex); - if (ex != null) - throw ex; - return true; - } - if (r < Retries - 1) - result.Resend(); - } - } - return false; - } - - public IAsyncResult BeginSubscribeCOVRequest(BacnetAddress adr, BacnetObjectId objectId, uint subscribeId, bool cancel, bool issueConfirmedNotifications, uint lifetime, bool waitForTransmit, byte invokeId = 0) - { - Log.Debug($"Sending SubscribeCOVRequest {objectId}"); - if (invokeId == 0) - invokeId = (byte)Interlocked.Increment(ref _invokeId); - - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply, adr.RoutedSource, adr.RoutedDestination); - APDU.EncodeConfirmedServiceRequest(buffer, PduConfirmedServiceRequest(), BacnetConfirmedServices.SERVICE_CONFIRMED_SUBSCRIBE_COV, MaxSegments, Transport.MaxAdpuLength, invokeId); - Services.EncodeSubscribeCOV(buffer, subscribeId, objectId, cancel, issueConfirmedNotifications, lifetime); - - //send - var ret = new BacnetAsyncResult(this, adr, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - public void EndSubscribeCOVRequest(IAsyncResult result, out Exception ex) - { - var res = (BacnetAsyncResult)result; - ex = res.Error; - if (ex == null && !res.WaitForDone(Timeout)) - ex = new Exception("Wait Timeout"); - - res.Dispose(); - } - - // DAL - public bool SendConfirmedEventNotificationRequest(BacnetAddress adr, BacnetEventNotificationData eventData, byte invokeId = 0, BacnetAddress source = null) - { - using (var result = (BacnetAsyncResult)BeginSendConfirmedEventNotificationRequest(adr, eventData, true, invokeId, source)) - { - for (var r = 0; r < _retries; r++) - { - if (result.WaitForDone(Timeout)) - { - EndSendConfirmedEventNotificationRequest(result, out var ex); - if (ex != null) - throw ex; - return true; - } - if (r < Retries - 1) - result.Resend(); - } - } - return false; - } - - // DAL - public IAsyncResult BeginSendConfirmedEventNotificationRequest(BacnetAddress adr, BacnetEventNotificationData eventData, bool waitForTransmit, byte invokeId = 0, BacnetAddress source = null) - { - Log.Debug($"Sending Confirmed Event Notification {eventData.eventType} {eventData.eventObjectIdentifier}"); - if (invokeId == 0) - invokeId = (byte)Interlocked.Increment(ref _invokeId); - - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply, adr, source); - APDU.EncodeConfirmedServiceRequest(buffer, PduConfirmedServiceRequest(), BacnetConfirmedServices.SERVICE_CONFIRMED_EVENT_NOTIFICATION, MaxSegments, Transport.MaxAdpuLength, invokeId); - Services.EncodeEventNotifyConfirmed(buffer, eventData); - - //send - var ret = new BacnetAsyncResult(this, adr, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - // DAL - public void EndSendConfirmedEventNotificationRequest(IAsyncResult result, out Exception ex) - { - var res = (BacnetAsyncResult)result; - ex = res.Error; - if (ex == null && !res.WaitForDone(Timeout)) - ex = new Exception("Wait Timeout"); - - res.Dispose(); - } - - public bool SubscribePropertyRequest(BacnetAddress adr, BacnetObjectId objectId, BacnetPropertyReference monitoredProperty, uint subscribeId, bool cancel, bool issueConfirmedNotifications, byte invokeId = 0) - { - using (var result = (BacnetAsyncResult)BeginSubscribePropertyRequest(adr, objectId, monitoredProperty, subscribeId, cancel, issueConfirmedNotifications, true, invokeId)) - { - for (var r = 0; r < _retries; r++) - { - if (result.WaitForDone(Timeout)) - { - EndSubscribePropertyRequest(result, out var ex); - if (ex != null) - throw ex; - return true; - } - if (r < Retries - 1) - result.Resend(); - } - } - return false; - } - - public IAsyncResult BeginSubscribePropertyRequest(BacnetAddress adr, BacnetObjectId objectId, BacnetPropertyReference monitoredProperty, uint subscribeId, bool cancel, bool issueConfirmedNotifications, bool waitForTransmit, byte invokeId = 0) - { - Log.Debug($"Sending SubscribePropertyRequest {objectId}.{monitoredProperty}"); - if (invokeId == 0) - invokeId = (byte)Interlocked.Increment(ref _invokeId); - - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply, adr.RoutedSource, adr.RoutedDestination); - APDU.EncodeConfirmedServiceRequest(buffer, PduConfirmedServiceRequest(), BacnetConfirmedServices.SERVICE_CONFIRMED_SUBSCRIBE_COV_PROPERTY, MaxSegments, Transport.MaxAdpuLength, invokeId); - Services.EncodeSubscribeProperty(buffer, subscribeId, objectId, cancel, issueConfirmedNotifications, 0, monitoredProperty, false, 0f); - - //send - var ret = new BacnetAsyncResult(this, adr, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - public void EndSubscribePropertyRequest(IAsyncResult result, out Exception ex) - { - var res = (BacnetAsyncResult)result; - ex = res.Error; - if (ex == null && !res.WaitForDone(Timeout)) - ex = new Exception("Wait Timeout"); - - res.Dispose(); - } - - public bool ReadPropertyRequest(BacnetAddress adr, BacnetObjectId objectId, BacnetPropertyIds propertyId, out IList valueList, byte invokeId = 0, uint arrayIndex = ASN1.BACNET_ARRAY_ALL) - { - using (var result = (BacnetAsyncResult)BeginReadPropertyRequest(adr, objectId, propertyId, true, invokeId, arrayIndex)) - { - for (var r = 0; r < _retries; r++) - { - if (result.WaitForDone(Timeout)) - { - EndReadPropertyRequest(result, out valueList, out var ex); - if (ex != null) - throw ex; - return true; - } - if (r < Retries - 1) - result.Resend(); - } - } - valueList = null; - return false; - } - - public Task> ReadPropertyAsync(BacnetAddress address, BacnetObjectTypes objType, uint objInstance, - BacnetPropertyIds propertyId, byte invokeId = 0, uint arrayIndex = ASN1.BACNET_ARRAY_ALL) - { - var objectId = new BacnetObjectId(objType, objInstance); - return ReadPropertyAsync(address, objectId, propertyId, invokeId, arrayIndex); - } - - public Task> ReadPropertyAsync(BacnetAddress address, BacnetObjectId objectId, - BacnetPropertyIds propertyId, byte invokeId = 0, uint arrayIndex = ASN1.BACNET_ARRAY_ALL) - { - return Task>.Factory.StartNew(() => - { - if (!ReadPropertyRequest(address, objectId, propertyId, out IList result, invokeId, arrayIndex)) - throw new Exception($"Failed to read property {propertyId} of {objectId} from {address}"); - - return result; - }); - } - - public IAsyncResult BeginReadPropertyRequest(BacnetAddress address, BacnetObjectId objectId, BacnetPropertyIds propertyId, bool waitForTransmit, byte invokeId = 0, uint arrayIndex = ASN1.BACNET_ARRAY_ALL) - { - Log.Debug($"Sending ReadPropertyRequest {objectId} {propertyId}"); - if (invokeId == 0) - invokeId = (byte)Interlocked.Increment(ref _invokeId); - - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply, address.RoutedSource, address.RoutedDestination); - APDU.EncodeConfirmedServiceRequest(buffer, PduConfirmedServiceRequest(), BacnetConfirmedServices.SERVICE_CONFIRMED_READ_PROPERTY, MaxSegments, Transport.MaxAdpuLength, invokeId); - Services.EncodeReadProperty(buffer, objectId, (uint)propertyId, arrayIndex); - - //send - var ret = new BacnetAsyncResult(this, address, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - public void EndReadPropertyRequest(IAsyncResult result, out IList valueList, out Exception ex) - { - var res = (BacnetAsyncResult)result; - ex = res.Error; - if (ex == null && !res.WaitForDone(Timeout)) - ex = new Exception("Wait Timeout"); - - if (ex == null) - { - //decode - if (Services.DecodeReadPropertyAcknowledge(res.Address, res.Result, 0, res.Result.Length, out _, out _, out valueList) < 0) - ex = new Exception("Decode"); - } - else - { - valueList = null; - } - - res.Dispose(); - } - - public bool WritePropertyRequest(BacnetAddress adr, BacnetObjectId objectId, BacnetPropertyIds propertyId, IEnumerable valueList, byte invokeId = 0) - { - using (var result = (BacnetAsyncResult)BeginWritePropertyRequest(adr, objectId, propertyId, valueList, true, invokeId)) - { - for (var r = 0; r < _retries; r++) - { - if (result.WaitForDone(Timeout)) - { - EndWritePropertyRequest(result, out var ex); - if (ex != null) - throw ex; - return true; - } - if (r < Retries - 1) - result.Resend(); - } - } - return false; - } - - public bool WritePropertyMultipleRequest(BacnetAddress adr, BacnetObjectId objectId, ICollection valueList, byte invokeId = 0) - { - using (var result = (BacnetAsyncResult)BeginWritePropertyMultipleRequest(adr, objectId, valueList, true, invokeId)) - { - for (var r = 0; r < _retries; r++) - { - if (result.WaitForDone(Timeout)) - { - EndWritePropertyRequest(result, out var ex); // Share the same with single write - if (ex != null) - throw ex; - return true; - } - if (r < Retries - 1) - result.Resend(); - } - } - return false; - } - - public IAsyncResult BeginWritePropertyRequest(BacnetAddress adr, BacnetObjectId objectId, BacnetPropertyIds propertyId, IEnumerable valueList, bool waitForTransmit, byte invokeId = 0) - { - Log.Debug($"Sending WritePropertyRequest {objectId} {propertyId}"); - if (invokeId == 0) - invokeId = (byte)Interlocked.Increment(ref _invokeId); - - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply, adr.RoutedSource, adr.RoutedDestination); - APDU.EncodeConfirmedServiceRequest(buffer, BacnetPduTypes.PDU_TYPE_CONFIRMED_SERVICE_REQUEST, BacnetConfirmedServices.SERVICE_CONFIRMED_WRITE_PROPERTY, MaxSegments, Transport.MaxAdpuLength, invokeId); - Services.EncodeWriteProperty(buffer, objectId, (uint)propertyId, ASN1.BACNET_ARRAY_ALL, _writepriority, valueList); - - //send - var ret = new BacnetAsyncResult(this, adr, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - public IAsyncResult BeginWritePropertyMultipleRequest(BacnetAddress adr, BacnetObjectId objectId, ICollection valueList, bool waitForTransmit, byte invokeId = 0) - { - Log.Debug($"Sending WritePropertyMultipleRequest {objectId}"); - if (invokeId == 0) invokeId = (byte)Interlocked.Increment(ref _invokeId); - - var buffer = GetEncodeBuffer(Transport.HeaderLength); - //BacnetNpduControls.PriorityNormalMessage - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply, adr.RoutedSource, adr.RoutedDestination); - - APDU.EncodeConfirmedServiceRequest(buffer, BacnetPduTypes.PDU_TYPE_CONFIRMED_SERVICE_REQUEST, BacnetConfirmedServices.SERVICE_CONFIRMED_WRITE_PROP_MULTIPLE, MaxSegments, Transport.MaxAdpuLength, invokeId); - Services.EncodeWritePropertyMultiple(buffer, objectId, valueList); - - //send - var ret = new BacnetAsyncResult(this, adr, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - public void EndWritePropertyRequest(IAsyncResult result, out Exception ex) - { - var res = (BacnetAsyncResult)result; - ex = res.Error; - if (ex == null && !res.WaitForDone(Timeout)) - ex = new Exception("Wait Timeout"); - - res.Dispose(); - } - - // By Chritopher Günter : Write multiple properties on multiple objects - public bool WritePropertyMultipleRequest(BacnetAddress adr, ICollection valueList, byte invokeId = 0) - { - using (var result = (BacnetAsyncResult)BeginWritePropertyMultipleRequest(adr, valueList, true, invokeId)) - { - for (var r = 0; r < _retries; r++) - { - if (result.WaitForDone(Timeout)) - { - EndWritePropertyRequest(result, out var ex); // Share the same with single write - if (ex != null) - throw ex; - return true; - } - if (r < Retries - 1) - result.Resend(); - } - } - return false; - } - - public IAsyncResult BeginWritePropertyMultipleRequest(BacnetAddress adr, ICollection valueList, bool waitForTransmit, byte invokeId = 0) - { - var objectIds = string.Join(", ", valueList.Select(v => v.objectIdentifier)); - Log.Debug($"Sending WritePropertyMultipleRequest {objectIds}"); - - if (invokeId == 0) - invokeId = (byte)Interlocked.Increment(ref _invokeId); - - var buffer = GetEncodeBuffer(Transport.HeaderLength); - //BacnetNpduControls.PriorityNormalMessage - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply, adr.RoutedSource, adr.RoutedDestination); - - APDU.EncodeConfirmedServiceRequest(buffer, BacnetPduTypes.PDU_TYPE_CONFIRMED_SERVICE_REQUEST, BacnetConfirmedServices.SERVICE_CONFIRMED_WRITE_PROP_MULTIPLE, MaxSegments, Transport.MaxAdpuLength, invokeId); - Services.EncodeWriteObjectMultiple(buffer, valueList); - - //send - var ret = new BacnetAsyncResult(this, adr, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - public bool ReadPropertyMultipleRequest(BacnetAddress address, BacnetObjectId objectId, IList propertyIdAndArrayIndex, out IList values, byte invokeId = 0) - { - using (var result = (BacnetAsyncResult)BeginReadPropertyMultipleRequest(address, objectId, propertyIdAndArrayIndex, true, invokeId)) - { - for (var r = 0; r < _retries; r++) - { - if (result.WaitForDone(Timeout)) - { - EndReadPropertyMultipleRequest(result, out values, out var ex); - if (ex != null) - throw ex; - return true; - } - if (r < Retries - 1) - result.Resend(); - } - } - values = null; - return false; - } - - public Task> ReadPropertyMultipleAsync(BacnetAddress address, - BacnetObjectTypes objType, uint objInstance, params BacnetPropertyIds[] propertyIds) - { - var objectId = new BacnetObjectId(objType, objInstance); - return ReadPropertyMultipleAsync(address, objectId, propertyIds); - } - - public Task> ReadPropertyMultipleAsync(BacnetAddress address, - BacnetObjectId objectId, params BacnetPropertyIds[] propertyIds) - { - var propertyReferences = propertyIds.Select(p => - new BacnetPropertyReference((uint)p, ASN1.BACNET_ARRAY_ALL)); - - return Task>.Factory.StartNew(() => - { - if (!ReadPropertyMultipleRequest(address, objectId, propertyReferences.ToList(), out var result)) - throw new Exception($"Failed to read multiple properties of {objectId} from {address}"); - - return result.Single().values; - }); - } - - public IAsyncResult BeginReadPropertyMultipleRequest(BacnetAddress adr, BacnetObjectId objectId, IList propertyIdAndArrayIndex, bool waitForTransmit, byte invokeId = 0) - { - var propertyIds = string.Join(", ", propertyIdAndArrayIndex.Select(v => (BacnetPropertyIds)v.propertyIdentifier)); - Log.Debug($"Sending ReadPropertyMultipleRequest {objectId} {propertyIds}"); - if (invokeId == 0) - invokeId = (byte)Interlocked.Increment(ref _invokeId); - - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply, adr.RoutedSource, adr.RoutedDestination); - APDU.EncodeConfirmedServiceRequest(buffer, PduConfirmedServiceRequest(), BacnetConfirmedServices.SERVICE_CONFIRMED_READ_PROP_MULTIPLE, MaxSegments, Transport.MaxAdpuLength, invokeId); - Services.EncodeReadPropertyMultiple(buffer, objectId, propertyIdAndArrayIndex); - - //send - var ret = new BacnetAsyncResult(this, adr, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - // Another way to read multiple properties on multiples objects, if supported by devices - public bool ReadPropertyMultipleRequest(BacnetAddress address, IList properties, out IList values, byte invokeId = 0) - { - using (var result = (BacnetAsyncResult)BeginReadPropertyMultipleRequest(address, properties, true, invokeId)) - { - for (var r = 0; r < _retries; r++) - { - if (result.WaitForDone(Timeout)) - { - EndReadPropertyMultipleRequest(result, out values, out var ex); - if (ex != null) - throw ex; - return true; - } - if (r < Retries - 1) - result.Resend(); - } - } - values = null; - return false; - } - - public IAsyncResult BeginReadPropertyMultipleRequest(BacnetAddress adr, IList properties, bool waitForTransmit, byte invokeId = 0) - { - var objectIds = string.Join(", ", properties.Select(v => v.objectIdentifier)); - Log.Debug($"Sending ReadPropertyMultipleRequest {objectIds}"); - if (invokeId == 0) - invokeId = (byte)Interlocked.Increment(ref _invokeId); - - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply, adr.RoutedSource, adr.RoutedDestination); - APDU.EncodeConfirmedServiceRequest(buffer, PduConfirmedServiceRequest(), BacnetConfirmedServices.SERVICE_CONFIRMED_READ_PROP_MULTIPLE, MaxSegments, Transport.MaxAdpuLength, invokeId); - Services.EncodeReadPropertyMultiple(buffer, properties); - - //send - var ret = new BacnetAsyncResult(this, adr, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - public void EndReadPropertyMultipleRequest(IAsyncResult result, out IList values, out Exception ex) - { - var res = (BacnetAsyncResult)result; - ex = res.Error; - if (ex == null && !res.WaitForDone(Timeout)) - ex = new Exception("Wait Timeout"); - - if (ex == null) - { - //decode - if (Services.DecodeReadPropertyMultipleAcknowledge(res.Address, res.Result, 0, res.Result.Length, out values) < 0) - ex = new Exception("Decode"); - } - else - { - values = null; - } - - res.Dispose(); - } - - private BacnetPduTypes PduConfirmedServiceRequest() - { - return MaxSegments != BacnetMaxSegments.MAX_SEG0 - ? BacnetPduTypes.PDU_TYPE_CONFIRMED_SERVICE_REQUEST | BacnetPduTypes.SEGMENTED_RESPONSE_ACCEPTED - : BacnetPduTypes.PDU_TYPE_CONFIRMED_SERVICE_REQUEST; - } - - // By Christopher Günter - public bool CreateObjectRequest(BacnetAddress adr, BacnetObjectId objectId, ICollection valueList = null, byte invokeId = 0) - { - using (var result = (BacnetAsyncResult)BeginCreateObjectRequest(adr, objectId, valueList, true, invokeId)) - { - for (var r = 0; r < _retries; r++) - { - if (result.WaitForDone(Timeout)) - { - EndCreateObjectRequest(result, out var ex); - if (ex != null) - throw ex; - return true; - } - if (r < Retries - 1) - result.Resend(); - } - } - return false; - } - - public IAsyncResult BeginCreateObjectRequest(BacnetAddress adr, BacnetObjectId objectId, ICollection valueList, bool waitForTransmit, byte invokeId = 0) - { - Log.Debug("Sending CreateObjectRequest"); - if (invokeId == 0) invokeId = (byte)Interlocked.Increment(ref _invokeId); - - var buffer = GetEncodeBuffer(Transport.HeaderLength); - - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply, adr.RoutedSource, adr.RoutedDestination); - APDU.EncodeConfirmedServiceRequest(buffer, PduConfirmedServiceRequest(), BacnetConfirmedServices.SERVICE_CONFIRMED_CREATE_OBJECT, MaxSegments, Transport.MaxAdpuLength, invokeId); - Services.EncodeCreateProperty(buffer, objectId, valueList); - - //send - var ret = new BacnetAsyncResult(this, adr, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - public void EndCreateObjectRequest(IAsyncResult result, out Exception ex) - { - var res = (BacnetAsyncResult)result; - ex = res.Error; - if (ex == null && !res.WaitForDone(Timeout)) - ex = new Exception("Wait Timeout"); - - res.Dispose(); - } - - public bool DeleteObjectRequest(BacnetAddress adr, BacnetObjectId objectId, byte invokeId = 0) - { - using (var result = (BacnetAsyncResult)BeginDeleteObjectRequest(adr, objectId, true, invokeId)) - { - for (var r = 0; r < _retries; r++) - { - if (result.WaitForDone(Timeout)) - { - EndDeleteObjectRequest(result, out var ex); - if (ex != null) - throw ex; - return true; - } - if (r < Retries - 1) - result.Resend(); - } - } - - return false; - } - - public IAsyncResult BeginDeleteObjectRequest(BacnetAddress adr, BacnetObjectId objectId, bool waitForTransmit, byte invokeId = 0) - { - Log.Debug("Sending DeleteObjectRequest"); - if (invokeId == 0) invokeId = (byte)Interlocked.Increment(ref _invokeId); - - var buffer = GetEncodeBuffer(Transport.HeaderLength); - - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply, adr.RoutedSource, adr.RoutedDestination); - //NPDU.Encode(b, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply , adr.RoutedSource); - - APDU.EncodeConfirmedServiceRequest(buffer, BacnetPduTypes.PDU_TYPE_CONFIRMED_SERVICE_REQUEST, BacnetConfirmedServices.SERVICE_CONFIRMED_DELETE_OBJECT, MaxSegments, Transport.MaxAdpuLength, invokeId); - ASN1.encode_application_object_id(buffer, objectId.type, objectId.instance); - - //send - var ret = new BacnetAsyncResult(this, adr, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - public void EndDeleteObjectRequest(IAsyncResult result, out Exception ex) - { - var res = (BacnetAsyncResult)result; - ex = res.Error; - if (ex == null && !res.WaitForDone(Timeout)) - ex = new Exception("Wait Timeout"); - - res.Dispose(); - } - - public bool AddListElementRequest(BacnetAddress adr, BacnetObjectId objectId, BacnetPropertyReference reference, IList valueList, byte invokeId = 0) - { - using (var result = (BacnetAsyncResult)BeginAddListElementRequest(adr, objectId, reference, valueList, true, invokeId)) - { - for (var r = 0; r < _retries; r++) - { - - if (result.WaitForDone(Timeout)) - { - EndAddListElementRequest(result, out var ex); - if (ex != null) - throw ex; - return true; - } - if (r < Retries - 1) - result.Resend(); - } - } - //values = null; - return false; - } - - public bool RemoveListElementRequest(BacnetAddress adr, BacnetObjectId objectId, BacnetPropertyReference reference, IList valueList, byte invokeId = 0) - { - using (var result = (BacnetAsyncResult)BeginRemoveListElementRequest(adr, objectId, reference, valueList, true, invokeId)) - { - for (var r = 0; r < _retries; r++) - { - if (result.WaitForDone(Timeout)) - { - EndAddListElementRequest(result, out var ex); - if (ex != null) - throw ex; - return true; - } - if (r < Retries - 1) - result.Resend(); - } - } - //values = null; - return false; - } - - public IAsyncResult BeginRemoveListElementRequest(BacnetAddress adr, BacnetObjectId objectId, BacnetPropertyReference reference, IList valueList, bool waitForTransmit, byte invokeId = 0) - { - Log.Debug("Sending RemoveListElementRequest"); - if (invokeId == 0) - invokeId = (byte)Interlocked.Increment(ref _invokeId); - - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply, adr.RoutedSource, adr.RoutedDestination); - APDU.EncodeConfirmedServiceRequest(buffer, BacnetPduTypes.PDU_TYPE_CONFIRMED_SERVICE_REQUEST, BacnetConfirmedServices.SERVICE_CONFIRMED_REMOVE_LIST_ELEMENT, MaxSegments, Transport.MaxAdpuLength, invokeId); - Services.EncodeAddListElement(buffer, objectId, reference.propertyIdentifier, reference.propertyArrayIndex, valueList); - - //send - var ret = new BacnetAsyncResult(this, adr, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - public IAsyncResult BeginAddListElementRequest(BacnetAddress adr, BacnetObjectId objectId, BacnetPropertyReference reference, IList valueList, bool waitForTransmit, byte invokeId = 0) - { - Log.Debug($"Sending AddListElementRequest {objectId} {(BacnetPropertyIds)reference.propertyIdentifier}"); - if (invokeId == 0) - invokeId = (byte)Interlocked.Increment(ref _invokeId); - - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply, adr.RoutedSource, adr.RoutedDestination); - APDU.EncodeConfirmedServiceRequest(buffer, BacnetPduTypes.PDU_TYPE_CONFIRMED_SERVICE_REQUEST, BacnetConfirmedServices.SERVICE_CONFIRMED_ADD_LIST_ELEMENT, MaxSegments, Transport.MaxAdpuLength, invokeId); - Services.EncodeAddListElement(buffer, objectId, reference.propertyIdentifier, reference.propertyArrayIndex, valueList); - - //send - var ret = new BacnetAsyncResult(this, adr, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - public void EndAddListElementRequest(IAsyncResult result, out Exception ex) - { - var res = (BacnetAsyncResult)result; - ex = res.Error; - if (ex == null && !res.WaitForDone(Timeout)) - ex = new Exception("Wait Timeout"); - - res.Dispose(); - } - - // Fc - // Read or Write without APDU Data encoding nor Decoding (just Request type, Object id and Property id) - // Data is given by the caller starting with the Tag 3 (or maybe another one), and ending with it - // return buffer start also with the Tag 3 - public bool RawEncodedDecodedPropertyConfirmedRequest(BacnetAddress adr, BacnetObjectId objectId, BacnetPropertyIds propertyId, BacnetConfirmedServices serviceId, ref byte[] inOutBuffer, byte invokeId = 0) - { - using (var result = (BacnetAsyncResult)BeginRawEncodedDecodedPropertyConfirmedRequest(adr, objectId, propertyId, serviceId, inOutBuffer, true, invokeId)) - { - for (var r = 0; r < _retries; r++) - { - if (result.WaitForDone(Timeout)) - { - EndRawEncodedDecodedPropertyConfirmedRequest(result, serviceId, out inOutBuffer, out var ex); - if (ex != null) - throw ex; - return true; - } - if (r < Retries - 1) - result.Resend(); - } - } - inOutBuffer = null; - return false; - } - - // Fc - public IAsyncResult BeginRawEncodedDecodedPropertyConfirmedRequest(BacnetAddress adr, BacnetObjectId objectId, BacnetPropertyIds propertyId, BacnetConfirmedServices serviceId, byte[] inOutBuffer, bool waitForTransmit, byte invokeId = 0) - { - Log.Debug("Sending RawEncodedRequest"); - if (invokeId == 0) - invokeId = (byte)Interlocked.Increment(ref _invokeId); - - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply, adr.RoutedSource, adr.RoutedDestination); - APDU.EncodeConfirmedServiceRequest(buffer, PduConfirmedServiceRequest(), serviceId, MaxSegments, Transport.MaxAdpuLength, invokeId); - - ASN1.encode_context_object_id(buffer, 0, objectId.type, objectId.instance); - ASN1.encode_context_enumerated(buffer, 1, (byte)propertyId); - - // No content encoding to do - if (inOutBuffer != null) - buffer.Add(inOutBuffer, inOutBuffer.Length); - - //send - var ret = new BacnetAsyncResult(this, adr, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - // Fc - public void EndRawEncodedDecodedPropertyConfirmedRequest(IAsyncResult result, BacnetConfirmedServices serviceId, out byte[] inOutBuffer, out Exception ex) - { - var res = (BacnetAsyncResult)result; - ex = res.Error; - if (ex == null && !res.WaitForDone(Timeout)) - ex = new Exception("Wait Timeout"); - - inOutBuffer = null; - - if (ex == null) - { - if (serviceId == BacnetConfirmedServices.SERVICE_CONFIRMED_READ_PROPERTY) - { - //decode - const int offset = 0; - var buffer = res.Result; - - ex = new Exception("Decode"); - - if (!ASN1.decode_is_context_tag(buffer, offset, 0)) - return; - var len = 1; - len += ASN1.decode_object_id(buffer, offset + len, out BacnetObjectTypes _, out _); - /* Tag 1: Property ID */ - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out var tagNumber, out var lenValueType); - if (tagNumber != 1) - return; - len += ASN1.decode_enumerated(buffer, offset + len, lenValueType, out _); - - inOutBuffer = new byte[buffer.Length - len]; - Array.Copy(buffer, len, inOutBuffer, 0, inOutBuffer.Length); - - ex = null; - } - } - - res.Dispose(); - } - - public bool DeviceCommunicationControlRequest(BacnetAddress adr, uint timeDuration, uint enableDisable, string password, byte invokeId = 0) - { - using (var result = (BacnetAsyncResult)BeginDeviceCommunicationControlRequest(adr, timeDuration, enableDisable, password, true, invokeId)) - { - for (var r = 0; r < _retries; r++) - { - if (result.WaitForDone(Timeout)) - { - EndDeviceCommunicationControlRequest(result, out var ex); - return ex == null; - } - if (r < Retries - 1) - result.Resend(); - } - } - return false; - } - - public IAsyncResult BeginDeviceCommunicationControlRequest(BacnetAddress adr, uint timeDuration, uint enableDisable, string password, bool waitForTransmit, byte invokeId = 0) - { - Log.Debug("Sending DeviceCommunicationControlRequest"); - if (invokeId == 0) - invokeId = (byte)Interlocked.Increment(ref _invokeId); - - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply, adr.RoutedSource, adr.RoutedDestination); - APDU.EncodeConfirmedServiceRequest(buffer, BacnetPduTypes.PDU_TYPE_CONFIRMED_SERVICE_REQUEST, BacnetConfirmedServices.SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL, MaxSegments, Transport.MaxAdpuLength, invokeId); - Services.EncodeDeviceCommunicationControl(buffer, timeDuration, enableDisable, password); - - //send - var ret = new BacnetAsyncResult(this, adr, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - public void EndDeviceCommunicationControlRequest(IAsyncResult result, out Exception ex) - { - var res = (BacnetAsyncResult)result; - ex = res.Error; - if (ex == null && !res.WaitForDone(Timeout)) - ex = new Exception("Wait Timeout"); - - res.Dispose(); - } - - // FChaxel - public bool GetAlarmSummaryOrEventRequest(BacnetAddress adr, bool getEvent, ref IList alarms, byte invokeId = 0) - { - using (var result = (BacnetAsyncResult)BeginGetAlarmSummaryOrEventRequest(adr, getEvent, alarms, true, invokeId)) - { - for (var r = 0; r < _retries; r++) - { - if (result.WaitForDone(Timeout)) - { - EndGetAlarmSummaryOrEventRequest(result, getEvent, ref alarms, out var moreEvent, out var ex); - if (ex != null) - return false; - return !moreEvent || GetAlarmSummaryOrEventRequest(adr, getEvent, ref alarms); - } - - if (r < Retries - 1) - result.Resend(); - } - } - return false; - } - - public Task> GetEventsAsync(BacnetAddress address, byte invokeId = 0) - { - IList result = new List(); - - return Task>.Factory.StartNew(() => - { - if (!GetAlarmSummaryOrEventRequest(address, true, ref result, invokeId)) - throw new Exception($"Failed to get events from {address}"); - - return result; - }); - } - - public IAsyncResult BeginGetAlarmSummaryOrEventRequest(BacnetAddress adr, bool getEvent, IList alarms, bool waitForTransmit, byte invokeId = 0) - { - Log.Debug("Sending Alarm summary request"); - if (invokeId == 0) - invokeId = (byte)Interlocked.Increment(ref _invokeId); - - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply, adr.RoutedSource, adr.RoutedDestination); - - var service = getEvent - ? BacnetConfirmedServices.SERVICE_CONFIRMED_GET_EVENT_INFORMATION - : BacnetConfirmedServices.SERVICE_CONFIRMED_GET_ALARM_SUMMARY; - - APDU.EncodeConfirmedServiceRequest(buffer, PduConfirmedServiceRequest(), service, MaxSegments, Transport.MaxAdpuLength, invokeId); - - // Get Next, never true if GetAlarmSummary is usee - if (alarms.Count != 0) - ASN1.encode_context_object_id(buffer, 0, alarms[alarms.Count - 1].objectIdentifier.type, alarms[alarms.Count - 1].objectIdentifier.instance); - - //send - var ret = new BacnetAsyncResult(this, adr, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - public void EndGetAlarmSummaryOrEventRequest(IAsyncResult result, bool getEvent, ref IList alarms, out bool moreEvent, out Exception ex) - { - moreEvent = false; - var res = (BacnetAsyncResult)result; - ex = res.Error; - if (ex == null && !res.WaitForDone(Timeout)) - ex = new Exception("Wait Timeout"); - - if (ex == null) - { - if (Services.DecodeAlarmSummaryOrEvent(res.Result, 0, res.Result.Length, getEvent, ref alarms, out moreEvent) < 0) - ex = new Exception("Decode"); - } - else - { - ex = new Exception("Service not available"); - } - - res.Dispose(); - } - // DAL - public void GetAlarmSummaryOrEventInformationResponse(BacnetAddress adr, bool getEvent, byte invoke_id, Segmentation segmentation, BacnetGetEventInformationData[] data, bool more_events) - { - // 'getEvent' is not currently used. Can be used if ever implementing GetAlarmSummary. - // response could be segmented - // but if you don't want it segmented (which would be normal usage) - // you have to compute the message data and the 'more' flag - // outside this function. - HandleSegmentationResponse(adr, invoke_id, segmentation, (o) => - { - SendComplexAck(adr, invoke_id, segmentation, BacnetConfirmedServices.SERVICE_CONFIRMED_GET_EVENT_INFORMATION, (b) => - { - Services.EncodeGetEventInformationAcknowledge(b, data, more_events); - }); - }); - } - - // FChaxel - public bool AlarmAcknowledgement(BacnetAddress adr, BacnetObjectId objId, BacnetEventStates eventState, string ackText, BacnetGenericTime evTimeStamp, BacnetGenericTime ackTimeStamp, byte invokeId = 0) - { - using (var result = (BacnetAsyncResult)BeginAlarmAcknowledgement(adr, objId, eventState, ackText, evTimeStamp, ackTimeStamp, true, invokeId)) - { - for (var r = 0; r < _retries; r++) - { - if (result.WaitForDone(Timeout)) - { - EndAlarmAcknowledgement(result, out var ex); - return ex == null; - } - if (r < Retries - 1) - result.Resend(); - } - } - return false; - } - - public IAsyncResult BeginAlarmAcknowledgement(BacnetAddress adr, BacnetObjectId objId, BacnetEventStates eventState, string ackText, BacnetGenericTime evTimeStamp, BacnetGenericTime ackTimeStamp, bool waitForTransmit, byte invokeId = 0) - { - Log.Debug("Sending AlarmAcknowledgement"); - if (invokeId == 0) - invokeId = (byte)Interlocked.Increment(ref _invokeId); - - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage, adr.RoutedSource, adr.RoutedDestination); - APDU.EncodeConfirmedServiceRequest(buffer, BacnetPduTypes.PDU_TYPE_CONFIRMED_SERVICE_REQUEST, BacnetConfirmedServices.SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM, MaxSegments, Transport.MaxAdpuLength, invokeId); - Services.EncodeAlarmAcknowledge(buffer, 57, objId, (uint)eventState, ackText, evTimeStamp, ackTimeStamp); - - //send - var ret = new BacnetAsyncResult(this, adr, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - public void EndAlarmAcknowledgement(IAsyncResult result, out Exception ex) - { - var res = (BacnetAsyncResult)result; - ex = res.Error; - if (!res.WaitForDone(Timeout)) - ex = new Exception("Wait Timeout"); - } - - public bool ReinitializeRequest(BacnetAddress adr, BacnetReinitializedStates state, string password, byte invokeId = 0) - { - using (var result = (BacnetAsyncResult)BeginReinitializeRequest(adr, state, password, true, invokeId)) - { - for (var r = 0; r < _retries; r++) - { - if (result.WaitForDone(Timeout)) - { - EndReinitializeRequest(result, out var ex); - return ex == null; - } - if (r < Retries - 1) - result.Resend(); - } - } - return false; - } - - public IAsyncResult BeginReinitializeRequest(BacnetAddress adr, BacnetReinitializedStates state, string password, bool waitForTransmit, byte invokeId = 0) - { - Log.Debug("Sending ReinitializeRequest"); - if (invokeId == 0) - invokeId = (byte)Interlocked.Increment(ref _invokeId); - - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply, adr.RoutedSource, adr.RoutedDestination); - APDU.EncodeConfirmedServiceRequest(buffer, BacnetPduTypes.PDU_TYPE_CONFIRMED_SERVICE_REQUEST, BacnetConfirmedServices.SERVICE_CONFIRMED_REINITIALIZE_DEVICE, MaxSegments, Transport.MaxAdpuLength, invokeId); - Services.EncodeReinitializeDevice(buffer, state, password); - - //send - var ret = new BacnetAsyncResult(this, adr, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - public void EndReinitializeRequest(IAsyncResult result, out Exception ex) - { - var res = (BacnetAsyncResult)result; - ex = res.Error; - if (ex == null && !res.WaitForDone(Timeout)) - ex = new Exception("Wait Timeout"); - - res.Dispose(); - } - - public IAsyncResult BeginConfirmedNotify(BacnetAddress adr, uint subscriberProcessIdentifier, uint initiatingDeviceIdentifier, BacnetObjectId monitoredObjectIdentifier, uint timeRemaining, IList values, bool waitForTransmit, byte invokeId = 0) - { - Log.Debug("Sending Notify (confirmed)"); - if (invokeId == 0) invokeId = (byte)Interlocked.Increment(ref _invokeId); - - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply, adr.RoutedSource, adr.RoutedDestination); - APDU.EncodeConfirmedServiceRequest(buffer, BacnetPduTypes.PDU_TYPE_CONFIRMED_SERVICE_REQUEST, BacnetConfirmedServices.SERVICE_CONFIRMED_COV_NOTIFICATION, MaxSegments, Transport.MaxAdpuLength, invokeId); - Services.EncodeCOVNotifyConfirmed(buffer, subscriberProcessIdentifier, initiatingDeviceIdentifier, monitoredObjectIdentifier, timeRemaining, values); - - //send - var ret = new BacnetAsyncResult(this, adr, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - public void EndConfirmedNotify(IAsyncResult result, out Exception ex) - { - var res = (BacnetAsyncResult)result; - ex = res.Error; - if (!res.WaitForDone(Timeout)) - ex = new Exception("Wait Timeout"); - } - - public bool Notify(BacnetAddress adr, uint subscriberProcessIdentifier, uint initiatingDeviceIdentifier, BacnetObjectId monitoredObjectIdentifier, uint timeRemaining, bool issueConfirmedNotifications, IList values) - { - if (!issueConfirmedNotifications) - { - Log.Debug("Sending Notify (unconfirmed)"); - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage, adr.RoutedSource, adr.RoutedDestination); - APDU.EncodeUnconfirmedServiceRequest(buffer, BacnetPduTypes.PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST, BacnetUnconfirmedServices.SERVICE_UNCONFIRMED_COV_NOTIFICATION); - Services.EncodeCOVNotifyUnconfirmed(buffer, subscriberProcessIdentifier, initiatingDeviceIdentifier, monitoredObjectIdentifier, timeRemaining, values); - // Modif F. Chaxel - - var sendbytes = Transport.Send(buffer.buffer, Transport.HeaderLength, buffer.offset - Transport.HeaderLength, adr, false, 0); - return sendbytes == buffer.offset; - } - - using (var result = (BacnetAsyncResult)BeginConfirmedNotify(adr, subscriberProcessIdentifier, initiatingDeviceIdentifier, monitoredObjectIdentifier, timeRemaining, values, true)) - { - for (var r = 0; r < _retries; r++) - { - if (result.WaitForDone(Timeout)) - { - EndConfirmedNotify(result, out var ex); - if (ex != null) - throw ex; - return true; - } - if (r < Retries - 1) - result.Resend(); - } - } - - return false; - } - - public bool LifeSafetyOperationRequest(BacnetAddress address, BacnetObjectId objectId, string requestingSrc, BacnetLifeSafetyOperations operation, byte invokeId = 0) - { - using (var result = (BacnetAsyncResult)BeginLifeSafetyOperationRequest(address, objectId, 0, requestingSrc, operation, true, invokeId)) - { - for (var r = 0; r < _retries; r++) - { - if (result.WaitForDone(Timeout)) - { - EndLifeSafetyOperationRequest(result, out var ex); - return ex == null; - } - if (r < Retries - 1) - result.Resend(); - } - } - return false; - } - - public IAsyncResult BeginLifeSafetyOperationRequest(BacnetAddress address, BacnetObjectId objectId, uint processId, string requestingSrc, BacnetLifeSafetyOperations operation, bool waitForTransmit, byte invokeId = 0) - { - Log.Debug($"Sending {ToTitleCase(operation)} {objectId}"); - if (invokeId == 0) - invokeId = (byte)Interlocked.Increment(ref _invokeId); - - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage | BacnetNpduControls.ExpectingReply, address.RoutedSource, address.RoutedDestination); - APDU.EncodeConfirmedServiceRequest(buffer, BacnetPduTypes.PDU_TYPE_CONFIRMED_SERVICE_REQUEST, BacnetConfirmedServices.SERVICE_CONFIRMED_LIFE_SAFETY_OPERATION, MaxSegments, Transport.MaxAdpuLength, invokeId); - Services.EncodeLifeSafetyOperation(buffer, processId, requestingSrc, (uint)operation, objectId); - - //send - var ret = new BacnetAsyncResult(this, address, invokeId, buffer.buffer, buffer.offset - Transport.HeaderLength, waitForTransmit, TransmitTimeout); - ret.Resend(); - - return ret; - } - - public void EndLifeSafetyOperationRequest(IAsyncResult result, out Exception ex) - { - var res = (BacnetAsyncResult)result; - ex = res.Error; - if (ex == null && !res.WaitForDone(Timeout)) - ex = new Exception("Wait Timeout"); - - res.Dispose(); - } - - public static byte GetSegmentsCount(BacnetMaxSegments maxSegments) - { - switch (maxSegments) - { - case BacnetMaxSegments.MAX_SEG0: - return 0; - case BacnetMaxSegments.MAX_SEG2: - return 2; - case BacnetMaxSegments.MAX_SEG4: - return 4; - case BacnetMaxSegments.MAX_SEG8: - return 8; - case BacnetMaxSegments.MAX_SEG16: - return 16; - case BacnetMaxSegments.MAX_SEG32: - return 32; - case BacnetMaxSegments.MAX_SEG64: - return 64; - case BacnetMaxSegments.MAX_SEG65: - return 0xFF; - default: - throw new Exception("Not an option"); - } - } - - public static BacnetMaxSegments GetSegmentsCount(byte maxSegments) - { - if (maxSegments == 0) - return BacnetMaxSegments.MAX_SEG0; - if (maxSegments <= 2) - return BacnetMaxSegments.MAX_SEG2; - if (maxSegments <= 4) - return BacnetMaxSegments.MAX_SEG4; - if (maxSegments <= 8) - return BacnetMaxSegments.MAX_SEG8; - if (maxSegments <= 16) - return BacnetMaxSegments.MAX_SEG16; - if (maxSegments <= 32) - return BacnetMaxSegments.MAX_SEG32; - if (maxSegments <= 64) - return BacnetMaxSegments.MAX_SEG64; - - return BacnetMaxSegments.MAX_SEG65; - } - - public Segmentation GetSegmentBuffer(BacnetMaxSegments maxSegments) - { - if (maxSegments == BacnetMaxSegments.MAX_SEG0) - return null; - - return new Segmentation - { - buffer = GetEncodeBuffer(Transport.HeaderLength), - max_segments = GetSegmentsCount(maxSegments), - window_size = ProposedWindowSize - }; - } - - private EncodeBuffer EncodeSegmentHeader(BacnetAddress adr, byte invokeId, Segmentation segmentation, BacnetConfirmedServices service, bool moreFollows) - { - EncodeBuffer buffer; - var isSegmented = false; - if (segmentation == null) - buffer = GetEncodeBuffer(Transport.HeaderLength); - else - { - buffer = segmentation.buffer; - isSegmented = segmentation.sequence_number > 0 | moreFollows; - } - buffer.Reset(Transport.HeaderLength); - - //encode - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage, adr.RoutedSource, adr.RoutedDestination); - - //set segments limits - buffer.max_offset = buffer.offset + GetMaxApdu(); - var apduHeader = APDU.EncodeComplexAck(buffer, BacnetPduTypes.PDU_TYPE_COMPLEX_ACK | (isSegmented ? BacnetPduTypes.SEGMENTED_MESSAGE | BacnetPduTypes.SERVER : 0) | (moreFollows ? BacnetPduTypes.MORE_FOLLOWS : 0), service, invokeId, segmentation?.sequence_number ?? 0, segmentation?.window_size ?? 0); - buffer.min_limit = (GetMaxApdu() - apduHeader) * (segmentation?.sequence_number ?? 0); - - return buffer; - } - - private bool EncodeSegment(BacnetAddress adr, byte invokeId, Segmentation segmentation, BacnetConfirmedServices service, out EncodeBuffer buffer, Action apduContentEncode) - { - //encode (regular) - buffer = EncodeSegmentHeader(adr, invokeId, segmentation, service, false); - apduContentEncode(buffer); - - var moreFollows = (buffer.result & EncodeResult.NotEnoughBuffer) > 0; - if (segmentation != null && moreFollows) - { - //reencode in segmented - EncodeSegmentHeader(adr, invokeId, segmentation, service, true); - apduContentEncode(buffer); - return true; - } - - if (moreFollows) - return true; - - return segmentation != null && segmentation.sequence_number > 0; - } - - /// - /// Handle the segmentation of several too hugh response (if it's accepted by the client) - /// used by ReadRange, ReadProperty, ReadPropertyMultiple & ReadFile responses - /// - private void HandleSegmentationResponse(BacnetAddress adr, byte invokeId, Segmentation segmentation, Action transmit) - { - // send first - transmit(segmentation); - - if (segmentation == null || segmentation.buffer.result == EncodeResult.Good) - return; - - // start new thread to handle the segment sequence (if required) - ThreadPool.QueueUserWorkItem(o => - { - var oldMaxInfoFrames = Transport.MaxInfoFrames; - Transport.MaxInfoFrames = segmentation.window_size; // increase max_info_frames, to increase throughput. This might be against 'standard' - - while (true) - { - var moreFollows = (segmentation.buffer.result & EncodeResult.NotEnoughBuffer) > 0; - - // wait for segmentACK - if ((segmentation.sequence_number - 1) % segmentation.window_size == 0 || !moreFollows) - { - if (!WaitForAllTransmits(TransmitTimeout)) - { - Log.Warn("Transmit timeout"); - break; - } - - var currentNumber = segmentation.sequence_number; - - if (!WaitForSegmentAck(adr, invokeId, segmentation, Timeout)) - { - Log.Warn("Didn't get segmentACK"); - break; - } - - if (segmentation.sequence_number != currentNumber) - { - Log.Debug("Oh, a retransmit"); - moreFollows = true; - } - } - else - { - // a negative segmentACK perhaps - var currentNumber = segmentation.sequence_number; - WaitForSegmentAck(adr, invokeId, segmentation, 0); // don't wait - - if (segmentation.sequence_number != currentNumber) - Log.Debug("Oh, a retransmit"); - } - - if (moreFollows) - // lock (m_lockObject) transmit(segmentation); - transmit(segmentation); - else - break; - } - - Transport.MaxInfoFrames = oldMaxInfoFrames; - }); - } - - private void SendComplexAck(BacnetAddress adr, byte invokeId, Segmentation segmentation, BacnetConfirmedServices service, Action apduContentEncode) - { - Log.Debug($"Sending {ToTitleCase(service)}"); - - //encode - if (EncodeSegment(adr, invokeId, segmentation, service, out var buffer, apduContentEncode)) - { - //client doesn't support segments - if (segmentation == null) - { - Log.Info("Segmentation denied"); - // DAL - SendAbort(adr, invokeId, BacnetAbortReason.SEGMENTATION_NOT_SUPPORTED); - //ErrorResponse(adr, service, invokeId, BacnetErrorClasses.ERROR_CLASS_SERVICES, BacnetErrorCodes.ERROR_CODE_ABORT_APDU_TOO_LONG); - buffer.result = EncodeResult.Good; //don't continue the segmentation - return; - } - - //first segment? validate max segments - if (segmentation.sequence_number == 0) //only validate first segment - { - if (segmentation.max_segments != 0xFF && segmentation.buffer.offset > segmentation.max_segments * (GetMaxApdu() - 5)) //5 is adpu header - { - Log.Info("Too much segmenation"); - // DAL - SendAbort(adr, invokeId, BacnetAbortReason.APDU_TOO_LONG); - //ErrorResponse(adr, service, invokeId, BacnetErrorClasses.ERROR_CLASS_SERVICES, BacnetErrorCodes.ERROR_CODE_ABORT_APDU_TOO_LONG); - buffer.result = EncodeResult.Good; //don't continue the segmentation - return; - } - Log.Debug("Segmentation required"); - } - - //increment before ack can do so (race condition) - unchecked { segmentation.sequence_number++; }; - } - - //send - Transport.Send(buffer.buffer, Transport.HeaderLength, buffer.GetLength() - Transport.HeaderLength, adr, false, 0); - } - - public void ReadPropertyResponse(BacnetAddress adr, byte invokeId, Segmentation segmentation, BacnetObjectId objectId, BacnetPropertyReference property, IEnumerable value) - { - HandleSegmentationResponse(adr, invokeId, segmentation, o => - { - SendComplexAck(adr, invokeId, segmentation, BacnetConfirmedServices.SERVICE_CONFIRMED_READ_PROPERTY, b => - { - Services.EncodeReadPropertyAcknowledge(b, objectId, property.propertyIdentifier, property.propertyArrayIndex, value); - }); - }); - } - - public void CreateObjectResponse(BacnetAddress adr, byte invokeId, Segmentation segmentation, BacnetObjectId objectId) - { - SendComplexAck(adr, invokeId, segmentation, BacnetConfirmedServices.SERVICE_CONFIRMED_CREATE_OBJECT, b => - { - Services.EncodeCreateObjectAcknowledge(b, objectId); - }); - } - - public void ReadPropertyMultipleResponse(BacnetAddress adr, byte invokeId, Segmentation segmentation, IList values) - { - HandleSegmentationResponse(adr, invokeId, segmentation, o => - { - SendComplexAck(adr, invokeId, segmentation, BacnetConfirmedServices.SERVICE_CONFIRMED_READ_PROP_MULTIPLE, b => - { - Services.EncodeReadPropertyMultipleAcknowledge(b, values); - }); - }); - } - - public void ReadRangeResponse(BacnetAddress adr, byte invokeId, Segmentation segmentation, BacnetObjectId objectId, BacnetPropertyReference property, BacnetResultFlags status, uint itemCount, byte[] applicationData, BacnetReadRangeRequestTypes requestType, uint firstSequenceNo) - { - HandleSegmentationResponse(adr, invokeId, segmentation, o => - { - SendComplexAck(adr, invokeId, segmentation, BacnetConfirmedServices.SERVICE_CONFIRMED_READ_RANGE, b => - { - Services.EncodeReadRangeAcknowledge(b, objectId, property.propertyIdentifier, property.propertyArrayIndex, BacnetBitString.ConvertFromInt((uint)status), itemCount, applicationData, requestType, firstSequenceNo); - }); - }); - } - - public void ReadFileResponse(BacnetAddress adr, byte invokeId, Segmentation segmentation, int position, uint count, bool endOfFile, byte[] fileBuffer) - { - HandleSegmentationResponse(adr, invokeId, segmentation, o => - { - SendComplexAck(adr, invokeId, segmentation, BacnetConfirmedServices.SERVICE_CONFIRMED_ATOMIC_READ_FILE, b => - { - Services.EncodeAtomicReadFileAcknowledge(b, true, endOfFile, position, 1, new[] { fileBuffer }, new[] { (int)count }); - }); - }); - } - - public void WriteFileResponse(BacnetAddress adr, byte invokeId, Segmentation segmentation, int position) - { - SendComplexAck(adr, invokeId, segmentation, BacnetConfirmedServices.SERVICE_CONFIRMED_ATOMIC_WRITE_FILE, b => - { - Services.EncodeAtomicWriteFileAcknowledge(b, true, position); - }); - } - - public void ErrorResponse(BacnetAddress adr, BacnetConfirmedServices service, byte invokeId, BacnetErrorClasses errorClass, BacnetErrorCodes errorCode) - { - Log.Debug($"Sending ErrorResponse for {service}: {errorCode}"); - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage, adr.RoutedSource, adr.RoutedDestination); - APDU.EncodeError(buffer, BacnetPduTypes.PDU_TYPE_ERROR, service, invokeId); - Services.EncodeError(buffer, errorClass, errorCode); - Transport.Send(buffer.buffer, Transport.HeaderLength, buffer.offset - Transport.HeaderLength, adr, false, 0); - } - - public void SimpleAckResponse(BacnetAddress adr, BacnetConfirmedServices service, byte invokeId) - { - Log.Debug($"Sending SimpleAckResponse for {service}"); - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage, adr.RoutedSource, adr.RoutedDestination); - APDU.EncodeSimpleAck(buffer, BacnetPduTypes.PDU_TYPE_SIMPLE_ACK, service, invokeId); - Transport.Send(buffer.buffer, Transport.HeaderLength, buffer.offset - Transport.HeaderLength, adr, false, 0); - // GD.Print(buffer.buffer.ToStringByHex()); - } - - public void SegmentAckResponse(BacnetAddress adr, bool negative, bool server, byte originalInvokeId, byte sequenceNumber, byte actualWindowSize) - { - Log.Debug("Sending SegmentAckResponse"); - var buffer = GetEncodeBuffer(Transport.HeaderLength); - NPDU.Encode(buffer, BacnetNpduControls.PriorityNormalMessage, adr.RoutedSource, adr.RoutedDestination); - APDU.EncodeSegmentAck(buffer, BacnetPduTypes.PDU_TYPE_SEGMENT_ACK | (negative ? BacnetPduTypes.NEGATIVE_ACK : 0) | (server ? BacnetPduTypes.SERVER : 0), originalInvokeId, sequenceNumber, actualWindowSize); - Transport.Send(buffer.buffer, Transport.HeaderLength, buffer.offset - Transport.HeaderLength, adr, false, 0); - } - - public bool WaitForAllTransmits(int timeout) - { - return Transport.WaitForAllTransmits(timeout); - } - - public bool WaitForSegmentAck(BacnetAddress adr, byte invokeId, Segmentation segmentation, int timeout) - { - if (!_lastSegmentAck.Wait(adr, invokeId, timeout)) - return false; - - segmentation.sequence_number = (byte)((_lastSegmentAck.SequenceNumber + 1) % 256); - segmentation.window_size = _lastSegmentAck.WindowSize; - return true; - } - - private static string ToTitleCase(object obj) - { - var cultureTextInfo = Thread.CurrentThread.CurrentCulture.TextInfo; - return cultureTextInfo.ToTitleCase($"{obj}".ToLower()); - } - - public void Dispose() - { - Transport.Dispose(); - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/BacnetAsyncResult.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/BacnetAsyncResult.cs deleted file mode 100644 index c68af53..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/BacnetAsyncResult.cs +++ /dev/null @@ -1,158 +0,0 @@ -namespace System.IO.BACnet; - -public class BacnetAsyncResult : IAsyncResult, IDisposable -{ - private BacnetClient _comm; - private readonly byte _waitInvokeId; - private Exception _error; - private readonly byte[] _transmitBuffer; - private readonly int _transmitLength; - private readonly bool _waitForTransmit; - private readonly int _transmitTimeout; - private ManualResetEvent _waitHandle; - private readonly BacnetAddress _address; - - public bool Segmented { get; private set; } - public byte[] Result { get; private set; } - public object AsyncState { get; set; } - public bool CompletedSynchronously { get; private set; } - public WaitHandle AsyncWaitHandle => _waitHandle; - public bool IsCompleted => _waitHandle.WaitOne(0); - public BacnetAddress Address => _address; - - public Exception Error - { - get => _error; - set - { - _error = value; - CompletedSynchronously = true; - _waitHandle.Set(); - } - } - - public BacnetAsyncResult(BacnetClient comm, BacnetAddress adr, byte invokeId, byte[] transmitBuffer, int transmitLength, bool waitForTransmit, int transmitTimeout) - { - _transmitTimeout = transmitTimeout; - _address = adr; - _waitForTransmit = waitForTransmit; - _transmitBuffer = transmitBuffer; - _transmitLength = transmitLength; - _comm = comm; - _waitInvokeId = invokeId; - _comm.OnComplexAck += OnComplexAck; - _comm.OnError += OnError; - _comm.OnAbort += OnAbort; - _comm.OnReject += OnReject; - _comm.OnSimpleAck += OnSimpleAck; - _comm.OnSegment += OnSegment; - _waitHandle = new ManualResetEvent(false); - } - - public void Resend() - { - try - { - if (_comm.Transport.Send(_transmitBuffer, _comm.Transport.HeaderLength, _transmitLength, _address, _waitForTransmit, _transmitTimeout) < 0) - { - Error = new IOException("Write Timeout"); - } - } - catch (Exception ex) - { - Error = new Exception($"Write Exception: {ex.Message}"); - } - } - - private void OnSegment(BacnetClient sender, BacnetAddress adr, BacnetPduTypes type, BacnetConfirmedServices service, byte invokeId, BacnetMaxSegments maxSegments, BacnetMaxAdpu maxAdpu, byte sequenceNumber, byte[] buffer, int offset, int length) - { - if (invokeId != _waitInvokeId || !adr.Equals(_address)) - return; - - Segmented = true; - _waitHandle.Set(); - } - - private void OnSimpleAck(BacnetClient sender, BacnetAddress adr, BacnetPduTypes type, BacnetConfirmedServices service, byte invokeId, byte[] data, int dataOffset, int dataLength) - { - if (invokeId != _waitInvokeId || !adr.Equals(_address)) - return; - - _waitHandle.Set(); - } - - private void OnAbort(BacnetClient sender, BacnetAddress adr, BacnetPduTypes type, byte invokeId, BacnetAbortReason reason, byte[] buffer, int offset, int length) - { - if (invokeId != _waitInvokeId || !adr.Equals(_address)) - return; - - Error = new Exception($"Abort from device, reason: {reason}"); - } - - private void OnReject(BacnetClient sender, BacnetAddress adr, BacnetPduTypes type, byte invokeId, BacnetRejectReason reason, byte[] buffer, int offset, int length) - { - if (invokeId != _waitInvokeId || !adr.Equals(_address)) - return; - - Error = new Exception($"Reject from device, reason: {reason}"); - } - - private void OnError(BacnetClient sender, BacnetAddress adr, BacnetPduTypes type, BacnetConfirmedServices service, byte invokeId, BacnetErrorClasses errorClass, BacnetErrorCodes errorCode, byte[] buffer, int offset, int length) - { - if (invokeId != _waitInvokeId || !adr.Equals(_address)) - return; - - Error = new Exception($"Error from device: {errorClass} - {errorCode}"); - } - - private void OnComplexAck(BacnetClient sender, BacnetAddress adr, BacnetPduTypes type, BacnetConfirmedServices service, byte invokeId, byte[] buffer, int offset, int length) - { - if (invokeId != _waitInvokeId || !adr.Equals(_address)) - return; - - Segmented = false; - Result = new byte[length]; - - if (length > 0) - Array.Copy(buffer, offset, Result, 0, length); - - //notify waiter even if segmented - _waitHandle.Set(); - } - - /// - /// Will continue waiting until all segments are recieved - /// - public bool WaitForDone(int timeout) - { - while (true) - { - if (!AsyncWaitHandle.WaitOne(timeout)) - return false; - if (Segmented) - _waitHandle.Reset(); - else - return true; - } - } - - public void Dispose() - { - if (_comm != null) - { - _comm.OnComplexAck -= OnComplexAck; - _comm.OnError -= OnError; - _comm.OnAbort -= OnAbort; - _comm.OnReject -= OnReject; - _comm.OnSimpleAck -= OnSimpleAck; - _comm.OnSegment -= OnSegment; - _comm = null; - } - - if (_waitHandle != null) - { - _waitHandle.Dispose(); - _waitHandle = null; - } - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BaCnetCalendarEntry.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BaCnetCalendarEntry.cs deleted file mode 100644 index 2005cb2..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BaCnetCalendarEntry.cs +++ /dev/null @@ -1,69 +0,0 @@ -namespace System.IO.BACnet; - -public struct BACnetCalendarEntry : ASN1.IEncode, ASN1.IDecode -{ - public List Entries; // BacnetDate or BacnetDateRange or BacnetweekNDay - - public void Encode(EncodeBuffer buffer) - { - if (Entries == null) - return; - - foreach (ASN1.IEncode entry in Entries) - { - if (entry is BacnetDate) - { - ASN1.encode_tag(buffer, 0, true, 4); - entry.Encode(buffer); - } - - if (entry is BacnetDateRange) - { - ASN1.encode_opening_tag(buffer, 1); - entry.Encode(buffer); - ASN1.encode_closing_tag(buffer, 1); - } - - if (entry is BacnetweekNDay) - { - ASN1.encode_tag(buffer, 2, true, 3); - entry.Encode(buffer); - } - } - } - - public int Decode(byte[] buffer, int offset, uint count) - { - var len = 0; - - Entries = new List(); - - while (true) - { - len += ASN1.decode_tag_number(buffer, offset + len, out byte tagNumber); - - switch (tagNumber) - { - case 0: - var bdt = new BacnetDate(); - len += bdt.Decode(buffer, offset + len, count); - Entries.Add(bdt); - break; - case 1: - var bdr = new BacnetDateRange(); - len += bdr.Decode(buffer, offset + len, count); - Entries.Add(bdr); - len++; // closing tag - break; - case 2: - var bwd = new BacnetweekNDay(); - len += bwd.Decode(buffer, offset + len, count); - Entries.Add(bwd); - break; - default: - return len - 1; // closing Tag - } - } - - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetAbortReason.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetAbortReason.cs deleted file mode 100644 index 3398b7e..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetAbortReason.cs +++ /dev/null @@ -1,84 +0,0 @@ -namespace System.IO.BACnet; - -/// -/// Reason the transaction with the indicated invoke ID is being aborted. -/// -/// -/// Enumerated values 0-63 are reserved for definition by ASHRAE. -/// Enumerated values 64-255 may be used by others. -/// -public enum BacnetAbortReason -{ - /// - /// This abort reason is returned for a reason other than any of those previously enumerated. - /// - OTHER = 0, - - /// - /// A buffer capacity has been exceeded. - /// - BUFFER_OVERFLOW = 1, - - /// - /// Generated in response to an APDU that is not expected in the present - /// state of the Transaction State Machine. - /// - INVALID_APDU_IN_THIS_STATE = 2, - - /// - /// The transaction shall be aborted to permit higher priority processing. - /// - PREEMPTED_BY_HIGHER_PRIORITY_TASK = 3, - - /// - /// Generated in response to an APDU that has its segmentation bit set to TRUE - /// when the receiving device does not support segmentation. It is also generated - /// when a BACnet-ComplexACKPDU is large enough to require segmentation but it - /// cannot be transmitted because either the transmitting device or the receiving - /// device does not support segmentation. - /// - SEGMENTATION_NOT_SUPPORTED = 4, - - /// - /// The Transaction is aborted due to receipt of a security error. - /// - SECURITY_ERROR = 5, - - /// - /// The transaction is aborted due to receipt of a PDU secured differently - /// than the original PDU of the transaction. - /// - INSUFFICIENT_SECURITY = 6, - - /// - /// A device receives a request that is segmented, or receives any segment of - /// a segmented request, where the Proposed Window Size field of the PDU header - /// is either zero or greater than 127. - /// - WINDOW_SIZE_OUT_OF_RANGE = 7, - - /// - /// A device receives a confirmed request but its application layer has - /// not responded within the published APDU Timeout period. - /// - APPLICATION_EXCEEDED_REPLY_TIME = 8, - - /// - /// A device receives a request but cannot start processing because it has run - /// out of some internal resource. - /// - OUT_OF_RESOURCES = 9, - - /// - /// A transaction state machine timer exceeded the timeout applicable for the - /// current state, causing the transaction machine to abort the transaction. - /// - TSM_TIMEOUT = 10, - - /// - /// An APDU was received from the local application program whose overall - /// size exceeds the maximum transmittable length or exceeds the maximum - /// number of segments accepted by the server. - /// - APDU_TOO_LONG = 11 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetAddress.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetAddress.cs deleted file mode 100644 index 5f39ce8..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetAddress.cs +++ /dev/null @@ -1,196 +0,0 @@ -namespace System.IO.BACnet; - -public class BacnetAddress : ASN1.IEncode -{ - public ushort net; - public byte[] adr; - public byte[] VMac = new byte[3]; // for IP V6, could be integrated also as 3 additional bytes in adr - public BacnetAddressTypes type; - - // Modif FC - public BacnetAddress RoutedSource = null; - - // DAL - public BacnetAddress RoutedDestination = null; - - public BacnetAddress(BacnetAddressTypes addressType, ushort network = 0, byte[] address = null) - { - type = addressType; - net = network; - adr = address; - } - - public BacnetAddress(BacnetAddressTypes addressType, string address = null, ushort network = 0) - : this(addressType, network) - { - if (address == null) - return; - - switch (type) - { - case BacnetAddressTypes.IP: - adr = new byte[6]; - var addressParts = address.Split(':'); - var addressBytes = IPAddress.Parse(addressParts[0]).GetAddressBytes(); - Array.Copy(addressBytes, adr, addressBytes.Length); - - var portBytes = BitConverter.GetBytes(addressParts.Length > 1 - ? ushort.Parse(addressParts[1]) - : (ushort)0xBAC0); - - if (BitConverter.IsLittleEndian) - portBytes = portBytes.Reverse().ToArray(); - - Array.Copy(portBytes, 0, adr, addressBytes.Length, portBytes.Length); - break; - - case BacnetAddressTypes.Ethernet: - adr = PhysicalAddress.Parse(address).GetAddressBytes(); - break; - - default: - throw new NotSupportedException("String format is not supported for address type " + type); - } - } - - public override int GetHashCode() - { - // DAL this was originally broken... - var str = Convert.ToBase64String(adr); - return str.GetHashCode(); - } - - public override string ToString() - { - return ToString(type); - } - - public string ToString(BacnetAddressTypes addressType) - { - while (true) - { - switch (addressType) - { - case BacnetAddressTypes.IP: - return adr != null && adr.Length >= 6 - ? $"{adr[0]}.{adr[1]}.{adr[2]}.{adr[3]}:{(adr[4] << 8) | adr[5]}" - : "0.0.0.0"; - - case BacnetAddressTypes.MSTP: - return adr != null && adr.Length >= 1 - ? $"{adr[0]}" - : "-1"; - - case BacnetAddressTypes.PTP: - return "x"; - - case BacnetAddressTypes.Ethernet: - return $"{new PhysicalAddress(adr)}"; - - case BacnetAddressTypes.IPV6: - return adr != null && adr.Length == 18 - ? $"{new IPAddress(adr.Take(16).ToArray())}:{(adr[16] << 8) | adr[17]}" - : "[::]"; - - default: // Routed @ are always like this, NPDU do not contains the MAC type, only the lenght - if (adr == null || adr.Length == 0) - return "?"; - - switch (adr.Length) - { - case 6: // certainly IP, but not sure (Newron System send it for internal usage with 4*0 bytes) - addressType = BacnetAddressTypes.IP; - continue; - - case 18: // Not sure it could appears, since NPDU may contains Vmac ? - addressType = BacnetAddressTypes.IPV6; - continue; - - case 3: - return $"IPv6 VMac : {adr[0] << 16 | (adr[1] << 8) | adr[2]}"; - - default: - return string.Join(" ", adr); - } - } - } - } - - public string ToString(bool sourceOnly) - { - if (RoutedSource == null) - return ToString(); - - return sourceOnly - ? RoutedSource.ToString() - : $"{RoutedSource} via {ToString()}"; - } - - public bool HasAddress(IPAddress ipAddress) - { - if (type != BacnetAddressTypes.IP || adr == null || ipAddress == null) - return false; - - return adr.Take(4).SequenceEqual(ipAddress.GetAddressBytes()); - } - - public override bool Equals(object obj) - { - if (obj is not BacnetAddress) return false; - var d = (BacnetAddress)obj; - if (adr == null && d.adr == null) return true; - if (adr == null || d.adr == null) return false; - if (adr.Length != d.adr.Length) return false; - if (adr.Where((t, i) => t != d.adr[i]).Any()) - return false; - - // Modif FC - if (RoutedSource == null && d.RoutedSource != null) - return false; - - // DAL - if (RoutedDestination == null && d.RoutedDestination != null) - return false; - - if (d.RoutedSource == null && RoutedSource == null && - d.RoutedDestination == null && RoutedDestination == null) - return true; - - bool rv = RoutedSource?.Equals(d.RoutedSource) ?? false; - rv |= RoutedDestination?.Equals(d.RoutedDestination) ?? false; - return rv; - } - - // checked if device is routed by curent equipement - public bool IsMyRouter(BacnetAddress device) - { - if (device.RoutedSource == null || RoutedSource != null) - return false; - - if (adr.Length != device.adr.Length) - return false; - - return !adr.Where((t, i) => t != device.adr[i]).Any(); - } - - public void Encode(EncodeBuffer buffer) - { - ASN1.encode_opening_tag(buffer, 1); - ASN1.encode_application_unsigned(buffer, net); - ASN1.encode_application_octet_string(buffer, adr, 0, adr.Length); - ASN1.encode_closing_tag(buffer, 1); - } - - public string FullHashString() - { - var hash = $"{(uint)type}.{net}.{string.Concat(adr.Select(a => a.ToString("X2")))}"; - - if (RoutedSource != null) - hash += $":{RoutedSource.FullHashString()}"; - - if (RoutedDestination != null) - hash += $":{RoutedDestination.FullHashString()}"; - - return hash; - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetAddressTypes.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetAddressTypes.cs deleted file mode 100644 index 7b67377..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetAddressTypes.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetAddressTypes -{ - None, - IP, - MSTP, - Ethernet, - ArcNet, - LonTalk, - PTP, - IPV6 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetApplicationTags.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetApplicationTags.cs deleted file mode 100644 index 4369ad5..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetApplicationTags.cs +++ /dev/null @@ -1,65 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetApplicationTags -{ - BACNET_APPLICATION_TAG_NULL = 0, - BACNET_APPLICATION_TAG_BOOLEAN = 1, - BACNET_APPLICATION_TAG_UNSIGNED_INT = 2, - BACNET_APPLICATION_TAG_SIGNED_INT = 3, - BACNET_APPLICATION_TAG_REAL = 4, - BACNET_APPLICATION_TAG_DOUBLE = 5, - BACNET_APPLICATION_TAG_OCTET_STRING = 6, - BACNET_APPLICATION_TAG_CHARACTER_STRING = 7, - BACNET_APPLICATION_TAG_BIT_STRING = 8, - BACNET_APPLICATION_TAG_ENUMERATED = 9, - BACNET_APPLICATION_TAG_DATE = 10, - BACNET_APPLICATION_TAG_TIME = 11, - BACNET_APPLICATION_TAG_OBJECT_ID = 12, - BACNET_APPLICATION_TAG_RESERVE1 = 13, - BACNET_APPLICATION_TAG_RESERVE2 = 14, - BACNET_APPLICATION_TAG_RESERVE3 = 15, - MAX_BACNET_APPLICATION_TAG = 16, - - /* Extra stuff - complex tagged data - not specifically enumerated */ - - /* Means : "nothing", an empty list, not even a null character */ - BACNET_APPLICATION_TAG_EMPTYLIST, - /* BACnetWeeknday */ - BACNET_APPLICATION_TAG_WEEKNDAY, - /* BACnetDateRange */ - BACNET_APPLICATION_TAG_DATERANGE, - /* BACnetDateTime */ - BACNET_APPLICATION_TAG_DATETIME, - /* BACnetTimeStamp */ - BACNET_APPLICATION_TAG_TIMESTAMP, - /* Error Class, Error Code */ - BACNET_APPLICATION_TAG_ERROR, - /* BACnetDeviceObjectPropertyReference */ - BACNET_APPLICATION_TAG_DEVICE_OBJECT_PROPERTY_REFERENCE, - /* BACnetDeviceObjectReference */ - BACNET_APPLICATION_TAG_DEVICE_OBJECT_REFERENCE, - /* BACnetObjectPropertyReference */ - BACNET_APPLICATION_TAG_OBJECT_PROPERTY_REFERENCE, - /* BACnetDestination (Recipient_List) */ - BACNET_APPLICATION_TAG_DESTINATION, - /* BACnetRecipient */ - BACNET_APPLICATION_TAG_RECIPIENT, - /* BACnetCOVSubscription */ - BACNET_APPLICATION_TAG_COV_SUBSCRIPTION, - /* BACnetCalendarEntry */ - BACNET_APPLICATION_TAG_CALENDAR_ENTRY, - /* BACnetWeeklySchedule */ - BACNET_APPLICATION_TAG_WEEKLY_SCHEDULE, - /* BACnetSpecialEvent */ - BACNET_APPLICATION_TAG_SPECIAL_EVENT, - /* BACnetReadAccessSpecification */ - BACNET_APPLICATION_TAG_READ_ACCESS_SPECIFICATION, - /* BACnetReadAccessResult */ - BACNET_APPLICATION_TAG_READ_ACCESS_RESULT, - /* BACnetLightingCommand */ - BACNET_APPLICATION_TAG_LIGHTING_COMMAND, - BACNET_APPLICATION_TAG_CONTEXT_SPECIFIC_DECODED, - BACNET_APPLICATION_TAG_CONTEXT_SPECIFIC_ENCODED, - /* BACnetLogRecord */ - BACNET_APPLICATION_TAG_LOG_RECORD -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBinaryPv.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBinaryPv.cs deleted file mode 100644 index 13553bd..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBinaryPv.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace System.IO.BACnet.Base; - -public enum BacnetBinaryPv : byte -{ - MIN_BINARY_PV = 0, /* for validating incoming values */ - BINARY_INACTIVE = 0, - BINARY_ACTIVE = 1, - MAX_BINARY_PV = 1, /* for validating incoming values */ - BINARY_NULL = 255 /* our homemade way of storing this info */ -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBitString.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBitString.cs deleted file mode 100644 index c2df69e..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBitString.cs +++ /dev/null @@ -1,91 +0,0 @@ -namespace System.IO.BACnet; - -public struct BacnetBitString -{ - public byte bits_used; - public byte[] value; - - public byte Length => bits_used; - public bool this[byte bitNumber] => GetBit(bitNumber); - - public override string ToString() - { - var ret = ""; - for (var i = 0; i < bits_used; i++) - { - ret += ((value[i / 8] & (1 << (i % 8))) > 0 ? "1" : "0"); - } - return ret; - } - - public void SetBit(byte bitNumber, bool v) - { - var byteNumber = (byte)(bitNumber / 8); - byte bitMask = 1; - - if (value == null) - value = new byte[ASN1.MAX_BITSTRING_BYTES]; - - if (byteNumber < ASN1.MAX_BITSTRING_BYTES) - { - /* set max bits used */ - if (bits_used < bitNumber + 1) - bits_used = (byte)(bitNumber + 1); - bitMask = (byte)(bitMask << (bitNumber - byteNumber * 8)); - if (v) - value[byteNumber] |= bitMask; - else - value[byteNumber] &= (byte)~bitMask; - } - } - - public bool GetBit(byte bitNumber) - { - var byteNumber = (byte)(bitNumber / 8); - - if (byteNumber >= ASN1.MAX_BITSTRING_BYTES || bitNumber >= bits_used) - throw new ArgumentOutOfRangeException(nameof(bitNumber)); - - if (value == null) - return false; - - var bitMask = (byte)(1 << (bitNumber - byteNumber * 8)); - return (value[byteNumber] & bitMask) > 0; - } - - public static BacnetBitString Parse(string str) - { - var ret = new BacnetBitString - { - value = new byte[ASN1.MAX_BITSTRING_BYTES] - }; - - if (string.IsNullOrEmpty(str)) - return ret; - - ret.bits_used = (byte)str.Length; - for (var i = 0; i < ret.bits_used; i++) - { - var isSet = str[i] == '1'; - if (isSet) ret.value[i / 8] |= (byte)(1 << (i % 8)); - } - - return ret; - } - - public uint ConvertToInt() - { - return value != null - ? BitConverter.ToUInt32(value, 0) - : 0; - } - - public static BacnetBitString ConvertFromInt(uint value) - { - return new BacnetBitString - { - value = BitConverter.GetBytes(value), - bits_used = (byte)Math.Ceiling(Math.Log(value, 2)) - }; - } -}; diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBvlcFunctions.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBvlcFunctions.cs deleted file mode 100644 index 7825d78..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBvlcFunctions.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetBvlcFunctions : byte -{ - BVLC_RESULT = 0, - BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE = 1, - BVLC_READ_BROADCAST_DIST_TABLE = 2, - BVLC_READ_BROADCAST_DIST_TABLE_ACK = 3, - BVLC_FORWARDED_NPDU = 4, - BVLC_REGISTER_FOREIGN_DEVICE = 5, - BVLC_READ_FOREIGN_DEVICE_TABLE = 6, - BVLC_READ_FOREIGN_DEVICE_TABLE_ACK = 7, - BVLC_DELETE_FOREIGN_DEVICE_TABLE_ENTRY = 8, - BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK = 9, - BVLC_ORIGINAL_UNICAST_NPDU = 10, - BVLC_ORIGINAL_BROADCAST_NPDU = 11, - MAX_BVLC_FUNCTION = 12 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBvlcResults.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBvlcResults.cs deleted file mode 100644 index 1c0ee01..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBvlcResults.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetBvlcResults : ushort -{ - BVLC_RESULT_SUCCESSFUL_COMPLETION = 0x0000, - BVLC_RESULT_WRITE_BROADCAST_DISTRIBUTION_TABLE_NAK = 0x0010, - BVLC_RESULT_READ_BROADCAST_DISTRIBUTION_TABLE_NAK = 0x0020, - BVLC_RESULT_REGISTER_FOREIGN_DEVICE_NAK = 0X0030, - BVLC_RESULT_READ_FOREIGN_DEVICE_TABLE_NAK = 0x0040, - BVLC_RESULT_DELETE_FOREIGN_DEVICE_TABLE_ENTRY_NAK = 0x0050, - BVLC_RESULT_DISTRIBUTE_BROADCAST_TO_NETWORK_NAK = 0x0060 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBvlcV6Functions.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBvlcV6Functions.cs deleted file mode 100644 index 9c51df5..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBvlcV6Functions.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetBvlcV6Functions : byte -{ - BVLC_RESULT = 0, - BVLC_ORIGINAL_UNICAST_NPDU = 1, - BVLC_ORIGINAL_BROADCAST_NPDU = 2, - BVLC_ADDRESS_RESOLUTION = 3, - BVLC_FORWARDED_ADDRESS_RESOLUTION = 4, - BVLC_ADDRESS_RESOLUTION_ACK = 5, - BVLC_VIRTUAL_ADDRESS_RESOLUTION = 6, - BVLC_VIRTUAL_ADDRESS_RESOLUTION_ACK = 7, - BVLC_FORWARDED_NPDU = 8, - BVLC_REGISTER_FOREIGN_DEVICE = 9, - BVLC_DELETE_FOREIGN_DEVICE_TABLE_ENTRY = 0xA, - BVLC_SECURE_BVLC = 0xB, - BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK = 0xC -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBvlcV6Results.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBvlcV6Results.cs deleted file mode 100644 index f8967d3..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetBvlcV6Results.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetBvlcV6Results : ushort -{ - SUCCESSFUL_COMPLETION = 0x0000, - ADDRESS_RESOLUTION_NAK = 0x0030, - VIRTUAL_ADDRESS_RESOLUTION_NAK = 0x0060, - REGISTER_FOREIGN_DEVICE_NAK = 0X0090, - DISTRIBUTE_BROADCAST_TO_NETWORK_NAK = 0x00B0 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetCOVSubscription.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetCOVSubscription.cs deleted file mode 100644 index abf0db9..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetCOVSubscription.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace System.IO.BACnet; - -public struct BacnetCOVSubscription -{ - /* BACnetRecipientProcess */ - public BacnetAddress Recipient; - public uint subscriptionProcessIdentifier; - /* BACnetObjectPropertyReference */ - public BacnetObjectId monitoredObjectIdentifier; - public BacnetPropertyReference monitoredProperty; - /* BACnetCOVSubscription */ - public bool IssueConfirmedNotifications; - public uint TimeRemaining; - public float COVIncrement; -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetCharacterStringEncodings.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetCharacterStringEncodings.cs deleted file mode 100644 index 928e48d..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetCharacterStringEncodings.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetCharacterStringEncodings -{ - CHARACTER_ANSI_X34 = 0, /* deprecated : Addendum 135-2008k */ - CHARACTER_UTF8 = 0, - CHARACTER_MS_DBCS = 1, - CHARACTER_JISC_6226 = 2, /* deprecated : Addendum 135-2008k */ - CHARACTER_JISX_0208 = 2, - CHARACTER_UCS4 = 3, - CHARACTER_UCS2 = 4, - CHARACTER_ISO8859 = 5 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetConfirmedServices.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetConfirmedServices.cs deleted file mode 100644 index a1aa49c..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetConfirmedServices.cs +++ /dev/null @@ -1,47 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetConfirmedServices : byte -{ - /* Alarm and Event Services */ - SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM = 0, - SERVICE_CONFIRMED_COV_NOTIFICATION = 1, - SERVICE_CONFIRMED_EVENT_NOTIFICATION = 2, - SERVICE_CONFIRMED_GET_ALARM_SUMMARY = 3, - SERVICE_CONFIRMED_GET_ENROLLMENT_SUMMARY = 4, - SERVICE_CONFIRMED_GET_EVENT_INFORMATION = 29, - SERVICE_CONFIRMED_SUBSCRIBE_COV = 5, - SERVICE_CONFIRMED_SUBSCRIBE_COV_PROPERTY = 28, - SERVICE_CONFIRMED_LIFE_SAFETY_OPERATION = 27, - /* File Access Services */ - SERVICE_CONFIRMED_ATOMIC_READ_FILE = 6, - SERVICE_CONFIRMED_ATOMIC_WRITE_FILE = 7, - /* Object Access Services */ - SERVICE_CONFIRMED_ADD_LIST_ELEMENT = 8, - SERVICE_CONFIRMED_REMOVE_LIST_ELEMENT = 9, - SERVICE_CONFIRMED_CREATE_OBJECT = 10, - SERVICE_CONFIRMED_DELETE_OBJECT = 11, - SERVICE_CONFIRMED_READ_PROPERTY = 12, - SERVICE_CONFIRMED_READ_PROP_CONDITIONAL = 13, - SERVICE_CONFIRMED_READ_PROP_MULTIPLE = 14, - SERVICE_CONFIRMED_READ_RANGE = 26, - SERVICE_CONFIRMED_WRITE_PROPERTY = 15, - SERVICE_CONFIRMED_WRITE_PROP_MULTIPLE = 16, - /* Remote Device Management Services */ - SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL = 17, - SERVICE_CONFIRMED_PRIVATE_TRANSFER = 18, - SERVICE_CONFIRMED_TEXT_MESSAGE = 19, - SERVICE_CONFIRMED_REINITIALIZE_DEVICE = 20, - /* Virtual Terminal Services */ - SERVICE_CONFIRMED_VT_OPEN = 21, - SERVICE_CONFIRMED_VT_CLOSE = 22, - SERVICE_CONFIRMED_VT_DATA = 23, - /* Security Services */ - SERVICE_CONFIRMED_AUTHENTICATE = 24, - SERVICE_CONFIRMED_REQUEST_KEY = 25, - /* Services added after 1995 */ - /* readRange (26) see Object Access Services */ - /* lifeSafetyOperation (27) see Alarm and Event Services */ - /* subscribeCOVProperty (28) see Alarm and Event Services */ - /* getEventInformation (29) see Alarm and Event Services */ - MAX_BACNET_CONFIRMED_SERVICE = 30 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetDate.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetDate.cs deleted file mode 100644 index 9298ab6..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetDate.cs +++ /dev/null @@ -1,125 +0,0 @@ -namespace System.IO.BACnet; - -public struct BacnetDate : ASN1.IEncode, ASN1.IDecode -{ - public byte year; /* 255 any */ - public byte month; /* 1=Jan; 255 any, 13 Odd, 14 Even */ - public byte day; /* 1..31; 32 last day of the month; 255 any */ - public byte wday; /* 1=Monday-7=Sunday, 255 any */ - - public BacnetDate(byte year, byte month, byte day, byte wday = 255) - { - this.year = year; - this.month = month; - this.day = day; - this.wday = wday; - } - - public void Encode(EncodeBuffer buffer) - { - buffer.Add(year); - buffer.Add(month); - buffer.Add(day); - buffer.Add(wday); - } - - public int Decode(byte[] buffer, int offset, uint count) - { - year = buffer[offset]; - month = buffer[offset + 1]; - day = buffer[offset + 2]; - wday = buffer[offset + 3]; - return 4; - } - - public bool IsPeriodic => year == 255 || month > 12 || day == 255; - - public bool IsAFittingDate(DateTime date) - { - if (date.Year != year + 1900 && year != 255) - return false; - - if (date.Month != month && month != 255 && month != 13 && month != 14) - return false; - if (month == 13 && (date.Month & 1) != 1) - return false; - if (month == 14 && (date.Month & 1) == 1) - return false; - - if (date.Day != day && day != 255) - return false; - // day 32 todo - - if (wday == 255) - return true; - - if (wday == 7 && date.DayOfWeek == 0) // Sunday 7 for Bacnet, 0 for .NET - return true; - - if (wday == (int)date.DayOfWeek) - return true; - - return false; - } - - public DateTime toDateTime() // Not every time possible, too much complex (any month, any year ...) - { - try - { - return IsPeriodic - ? new DateTime(1, 1, 1) - : new DateTime(year + 1900, month, day); - } - catch - { - return DateTime.Now; // or anything else why not ! - } - } - - private static string GetDayName(int day) - { - if (day == 7) - day = 0; - - return CultureInfo.CurrentCulture.DateTimeFormat.DayNames[day]; - } - - public override string ToString() - { - string ret; - - if (wday != 255) - ret = GetDayName(wday) + " "; - else - ret = ""; - - if (day != 255) - ret = ret + day + "/"; - else - ret += "**/"; - - switch (month) - { - case 13: - ret += "odd/"; - break; - case 14: - ret += "even/"; - break; - case 255: - ret += "**/"; - break; - default: - ret = ret + month + "/"; - break; - } - - - if (year != 255) - ret += year + 1900; - else - ret += "****"; - - return ret; - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetDateRange.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetDateRange.cs deleted file mode 100644 index 12238ed..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetDateRange.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace System.IO.BACnet; - -public struct BacnetDateRange : ASN1.IEncode, ASN1.IDecode -{ - public BacnetDate startDate; - public BacnetDate endDate; - - public BacnetDateRange(BacnetDate start, BacnetDate end) - { - startDate = start; - endDate = end; - } - - public void Encode(EncodeBuffer buffer) - { - ASN1.encode_tag(buffer, (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_DATE, false, 4); - startDate.Encode(buffer); - ASN1.encode_tag(buffer, (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_DATE, false, 4); - endDate.Encode(buffer); - } - - public int Decode(byte[] buffer, int offset, uint count) - { - var len = 1; // opening tag - len += startDate.Decode(buffer, offset + len, count); - len++; - len += endDate.Decode(buffer, offset + len, count); - return len; - } - - public bool IsAFittingDate(DateTime date) - { - date = new DateTime(date.Year, date.Month, date.Day); - return date >= startDate.toDateTime() && date <= endDate.toDateTime(); - } - - public override string ToString() - { - string ret; - - if (startDate.day != 255) - ret = "From " + startDate; - else - ret = "From **/**/**"; - - if (endDate.day != 255) - ret = ret + " to " + endDate; - else - ret += " to **/**/**"; - - return ret; - } -}; diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetDeviceObjectPropertyReference.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetDeviceObjectPropertyReference.cs deleted file mode 100644 index 3803d06..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetDeviceObjectPropertyReference.cs +++ /dev/null @@ -1,104 +0,0 @@ -namespace System.IO.BACnet; - -public struct BacnetDeviceObjectPropertyReference : ASN1.IEncode -{ - public BacnetObjectId objectIdentifier; - public BacnetPropertyIds propertyIdentifier; - public uint arrayIndex; - public BacnetObjectId deviceIndentifier; - - public BacnetDeviceObjectPropertyReference(BacnetObjectId objectIdentifier, BacnetPropertyIds propertyIdentifier, BacnetObjectId? deviceIndentifier = null, uint arrayIndex = ASN1.BACNET_ARRAY_ALL) - { - this.objectIdentifier = objectIdentifier; - this.propertyIdentifier = propertyIdentifier; - this.arrayIndex = arrayIndex; - this.deviceIndentifier = deviceIndentifier ?? new BacnetObjectId(BacnetObjectTypes.MAX_BACNET_OBJECT_TYPE, 0); - } - - public void Encode(EncodeBuffer buffer) - { - ASN1.bacapp_encode_device_obj_property_ref(buffer, this); - } - - public BacnetObjectId ObjectId - { - get => objectIdentifier; - set => objectIdentifier = value; - } - - public int ArrayIndex // shows -1 when it's ASN1.BACNET_ARRAY_ALL - { - get => arrayIndex != ASN1.BACNET_ARRAY_ALL - ? (int)arrayIndex - : -1; - set => arrayIndex = value < 0 - ? ASN1.BACNET_ARRAY_ALL - : (uint)value; - } - - public BacnetObjectId? DeviceId // shows null when it's not OBJECT_DEVICE - { - get - { - return deviceIndentifier.type == BacnetObjectTypes.OBJECT_DEVICE - ? (BacnetObjectId?)deviceIndentifier - : null; - } - set - { - deviceIndentifier = value ?? new BacnetObjectId(); - } - } - - public BacnetPropertyIds PropertyId - { - get => propertyIdentifier; - set => propertyIdentifier = value; - } - - public static object Parse(string value) - { - var parts = value.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries); - - BacnetObjectId? deviceId = null; - BacnetObjectId objectId; - - switch (parts.Length) - { - case 2: - objectId = BacnetObjectId.Parse(parts[0]); - break; - - case 3: - deviceId = BacnetObjectId.Parse(parts[0]); - objectId = BacnetObjectId.Parse(parts[1]); - break; - - default: - throw new ArgumentException("Invalid format", nameof(value)); - } - - if (!Enum.TryParse(parts.Last(), out BacnetPropertyIds propertyId)) - { - if (!uint.TryParse(parts.Last(), out var vendorSpecificPropertyId)) - throw new ArgumentException("Invalid format of property id", nameof(value)); - - propertyId = (BacnetPropertyIds)vendorSpecificPropertyId; - } - - return new BacnetDeviceObjectPropertyReference - { - DeviceId = deviceId, - ObjectId = objectId, - PropertyId = propertyId, - ArrayIndex = -1 - }; - } - - public override string ToString() - { - return DeviceId != null - ? $"{DeviceId}.{ObjectId}.{PropertyId}" - : $"{ObjectId}.{PropertyId}"; - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetDeviceStatus.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetDeviceStatus.cs deleted file mode 100644 index 60f4627..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetDeviceStatus.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetDeviceStatus : byte -{ - OPERATIONAL = 0, - OPERATIONAL_READONLY = 1, - DOWNLOAD_REQUIRED = 2, - DOWNLOAD_IN_PROGRESS = 3, - NON_OPERATIONAL = 4, - BACKUP_IN_PROGRESS = 5 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetError.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetError.cs deleted file mode 100644 index ef6d697..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetError.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace System.IO.BACnet; - -public struct BacnetError -{ - public BacnetErrorClasses error_class; - public BacnetErrorCodes error_code; - - public BacnetError(BacnetErrorClasses errorClass, BacnetErrorCodes errorCode) - { - error_class = errorClass; - error_code = errorCode; - } - public BacnetError(uint errorClass, uint errorCode) - { - error_class = (BacnetErrorClasses)errorClass; - error_code = (BacnetErrorCodes)errorCode; - } - public override string ToString() - { - return $"{error_class}: {error_code}"; - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetErrorClasses.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetErrorClasses.cs deleted file mode 100644 index b5f08b2..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetErrorClasses.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetErrorClasses -{ - ERROR_CLASS_DEVICE = 0, - ERROR_CLASS_OBJECT = 1, - ERROR_CLASS_PROPERTY = 2, - ERROR_CLASS_RESOURCES = 3, - ERROR_CLASS_SECURITY = 4, - ERROR_CLASS_SERVICES = 5, - ERROR_CLASS_VT = 6, - ERROR_CLASS_COMMUNICATION = 7, - /* Enumerated values 0-63 are reserved for definition by ASHRAE. */ - /* Enumerated values 64-65535 may be used by others subject to */ - /* the procedures and constraints described in Clause 23. */ - MAX_BACNET_ERROR_CLASS = 8, - /* do the MAX here instead of outside of enum so that - compilers will allocate adequate sized datatype for enum */ - ERROR_CLASS_PROPRIETARY_FIRST = 64, - ERROR_CLASS_PROPRIETARY_LAST = 65535 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetErrorCodes.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetErrorCodes.cs deleted file mode 100644 index b99286c..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetErrorCodes.cs +++ /dev/null @@ -1,246 +0,0 @@ -namespace System.IO.BACnet; - -// These are sorted in the order given in Clause 18. -// ERROR, REJECT AND ABORT CODES The Class and Code pairings -// are required to be used in accordance with Clause 18. -public enum BacnetErrorCodes -{ - /* valid for all classes */ - ERROR_CODE_OTHER = 0, - - /* Error Class - Device */ - ERROR_CODE_DEVICE_BUSY = 3, - ERROR_CODE_CONFIGURATION_IN_PROGRESS = 2, - ERROR_CODE_OPERATIONAL_PROBLEM = 25, - - /* Error Class - Object */ - ERROR_CODE_DYNAMIC_CREATION_NOT_SUPPORTED = 4, - ERROR_CODE_NO_OBJECTS_OF_SPECIFIED_TYPE = 17, - ERROR_CODE_OBJECT_DELETION_NOT_PERMITTED = 23, - ERROR_CODE_OBJECT_IDENTIFIER_ALREADY_EXISTS = 24, - ERROR_CODE_READ_ACCESS_DENIED = 27, - ERROR_CODE_UNKNOWN_OBJECT = 31, - ERROR_CODE_UNSUPPORTED_OBJECT_TYPE = 36, - - /* Error Class - Property */ - ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED = 41, - ERROR_CODE_DATATYPE_NOT_SUPPORTED = 47, - ERROR_CODE_INCONSISTENT_SELECTION_CRITERION = 8, - ERROR_CODE_INVALID_ARRAY_INDEX = 42, - ERROR_CODE_INVALID_DATA_TYPE = 9, - ERROR_CODE_NOT_COV_PROPERTY = 44, - ERROR_CODE_OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED = 45, - ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY = 50, - /* ERROR_CODE_READ_ACCESS_DENIED = 27, */ - ERROR_CODE_UNKNOWN_PROPERTY = 32, - ERROR_CODE_VALUE_OUT_OF_RANGE = 37, - ERROR_CODE_WRITE_ACCESS_DENIED = 40, - - /* Error Class - Resources */ - ERROR_CODE_NO_SPACE_FOR_OBJECT = 18, - ERROR_CODE_NO_SPACE_TO_ADD_LIST_ELEMENT = 19, - ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY = 20, - - /* Error Class - Security */ - ERROR_CODE_AUTHENTICATION_FAILED = 1, - /* ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED = 41, */ - ERROR_CODE_INCOMPATIBLE_SECURITY_LEVELS = 6, - ERROR_CODE_INVALID_OPERATOR_NAME = 12, - ERROR_CODE_KEY_GENERATION_ERROR = 15, - ERROR_CODE_PASSWORD_FAILURE = 26, - ERROR_CODE_SECURITY_NOT_SUPPORTED = 28, - ERROR_CODE_TIMEOUT = 30, - - /* Error Class - Services */ - /* ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED = 41, */ - ERROR_CODE_COV_SUBSCRIPTION_FAILED = 43, - ERROR_CODE_DUPLICATE_NAME = 48, - ERROR_CODE_DUPLICATE_OBJECT_ID = 49, - ERROR_CODE_FILE_ACCESS_DENIED = 5, - ERROR_CODE_INCONSISTENT_PARAMETERS = 7, - ERROR_CODE_INVALID_CONFIGURATION_DATA = 46, - ERROR_CODE_INVALID_FILE_ACCESS_METHOD = 10, - ERROR_CODE_INVALID_FILE_START_POSITION = 11, - ERROR_CODE_INVALID_PARAMETER_DATA_TYPE = 13, - ERROR_CODE_INVALID_TIME_STAMP = 14, - ERROR_CODE_MISSING_REQUIRED_PARAMETER = 16, - /* ERROR_CODE_OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED = 45, */ - ERROR_CODE_PROPERTY_IS_NOT_A_LIST = 22, - ERROR_CODE_SERVICE_REQUEST_DENIED = 29, - - /* Error Class - VT */ - ERROR_CODE_UNKNOWN_VT_CLASS = 34, - ERROR_CODE_UNKNOWN_VT_SESSION = 35, - ERROR_CODE_NO_VT_SESSIONS_AVAILABLE = 21, - ERROR_CODE_VT_SESSION_ALREADY_CLOSED = 38, - ERROR_CODE_VT_SESSION_TERMINATION_FAILURE = 39, - - /* unused */ - ERROR_CODE_RESERVED1 = 33, - /* new error codes from new addenda */ - ERROR_CODE_ABORT_BUFFER_OVERFLOW = 51, - ERROR_CODE_ABORT_INVALID_APDU_IN_THIS_STATE = 52, - ERROR_CODE_ABORT_PREEMPTED_BY_HIGHER_PRIORITY_TASK = 53, - ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED = 54, - ERROR_CODE_ABORT_PROPRIETARY = 55, - ERROR_CODE_ABORT_OTHER = 56, - ERROR_CODE_INVALID_TAG = 57, - ERROR_CODE_NETWORK_DOWN = 58, - ERROR_CODE_REJECT_BUFFER_OVERFLOW = 59, - ERROR_CODE_REJECT_INCONSISTENT_PARAMETERS = 60, - ERROR_CODE_REJECT_INVALID_PARAMETER_DATA_TYPE = 61, - ERROR_CODE_REJECT_INVALID_TAG = 62, - ERROR_CODE_REJECT_MISSING_REQUIRED_PARAMETER = 63, - ERROR_CODE_REJECT_PARAMETER_OUT_OF_RANGE = 64, - ERROR_CODE_REJECT_TOO_MANY_ARGUMENTS = 65, - ERROR_CODE_REJECT_UNDEFINED_ENUMERATION = 66, - ERROR_CODE_REJECT_UNRECOGNIZED_SERVICE = 67, - ERROR_CODE_REJECT_PROPRIETARY = 68, - ERROR_CODE_REJECT_OTHER = 69, - ERROR_CODE_UNKNOWN_DEVICE = 70, - ERROR_CODE_UNKNOWN_ROUTE = 71, - ERROR_CODE_VALUE_NOT_INITIALIZED = 72, - ERROR_CODE_INVALID_EVENT_STATE = 73, - ERROR_CODE_NO_ALARM_CONFIGURED = 74, - ERROR_CODE_LOG_BUFFER_FULL = 75, - ERROR_CODE_LOGGED_VALUE_PURGED = 76, - ERROR_CODE_NO_PROPERTY_SPECIFIED = 77, - ERROR_CODE_NOT_CONFIGURED_FOR_TRIGGERED_LOGGING = 78, - ERROR_CODE_UNKNOWN_SUBSCRIPTION = 79, - ERROR_CODE_PARAMETER_OUT_OF_RANGE = 80, - ERROR_CODE_LIST_ELEMENT_NOT_FOUND = 81, - ERROR_CODE_BUSY = 82, - ERROR_CODE_COMMUNICATION_DISABLED = 83, - ERROR_CODE_SUCCESS = 84, - ERROR_CODE_ACCESS_DENIED = 85, - ERROR_CODE_BAD_DESTINATION_ADDRESS = 86, - ERROR_CODE_BAD_DESTINATION_DEVICE_ID = 87, - ERROR_CODE_BAD_SIGNATURE = 88, - ERROR_CODE_BAD_SOURCE_ADDRESS = 89, - ERROR_CODE_BAD_TIMESTAMP = 90, - ERROR_CODE_CANNOT_USE_KEY = 91, - ERROR_CODE_CANNOT_VERIFY_MESSAGE_ID = 92, - ERROR_CODE_CORRECT_KEY_REVISION = 93, - ERROR_CODE_DESTINATION_DEVICE_ID_REQUIRED = 94, - ERROR_CODE_DUPLICATE_MESSAGE = 95, - ERROR_CODE_ENCRYPTION_NOT_CONFIGURED = 96, - ERROR_CODE_ENCRYPTION_REQUIRED = 97, - ERROR_CODE_INCORRECT_KEY = 98, - ERROR_CODE_INVALID_KEY_DATA = 99, - ERROR_CODE_KEY_UPDATE_IN_PROGRESS = 100, - ERROR_CODE_MALFORMED_MESSAGE = 101, - ERROR_CODE_NOT_KEY_SERVER = 102, - ERROR_CODE_SECURITY_NOT_CONFIGURED = 103, - ERROR_CODE_SOURCE_SECURITY_REQUIRED = 104, - ERROR_CODE_TOO_MANY_KEYS = 105, - ERROR_CODE_UNKNOWN_AUTHENTICATION_TYPE = 106, - ERROR_CODE_UNKNOWN_KEY = 107, - ERROR_CODE_UNKNOWN_KEY_REVISION = 108, - ERROR_CODE_UNKNOWN_SOURCE_MESSAGE = 109, - ERROR_CODE_NOT_ROUTER_TO_DNET = 110, - ERROR_CODE_ROUTER_BUSY = 111, - ERROR_CODE_UNKNOWN_NETWORK_MESSAGE = 112, - ERROR_CODE_MESSAGE_TOO_LONG = 113, - ERROR_CODE_SECURITY_ERROR = 114, - ERROR_CODE_ADDRESSING_ERROR = 115, - ERROR_CODE_WRITE_BDT_FAILED = 116, - ERROR_CODE_READ_BDT_FAILED = 117, - ERROR_CODE_REGISTER_FOREIGN_DEVICE_FAILED = 118, - ERROR_CODE_READ_FDT_FAILED = 119, - ERROR_CODE_DELETE_FDT_ENTRY_FAILED = 120, - ERROR_CODE_DISTRIBUTE_BROADCAST_FAILED = 121, - ERROR_CODE_UNKNOWN_FILE_SIZE = 122, - ERROR_CODE_ABORT_APDU_TOO_LONG = 123, - ERROR_CODE_ABORT_APPLICATION_EXCEEDED_REPLY_TIME = 124, - ERROR_CODE_ABORT_OUT_OF_RESOURCES = 125, - ERROR_CODE_ABORT_TSM_TIMEOUT = 126, - ERROR_CODE_ABORT_WINDOW_SIZE_OUT_OF_RANGE = 127, - ERROR_CODE_FILE_FULL = 128, - ERROR_CODE_INCONSISTENT_CONFIGURATION = 129, - ERROR_CODE_INCONSISTENT_OBJECT_TYPE = 130, - ERROR_CODE_INTERNAL_ERROR = 131, - ERROR_CODE_NOT_CONFIGURED = 132, - ERROR_CODE_OUT_OF_MEMORY = 133, - ERROR_CODE_VALUE_TOO_LONG = 134, - ERROR_CODE_ABORT_INSUFFICIENT_SECURITY = 135, - ERROR_CODE_ABORT_SECURITY_ERROR = 136, - ERROR_CODE_DUPLICATE_ENTRY = 137, - ERROR_CODE_INVALID_VALUE_IN_THIS_STATE = 138, - ERROR_CODE_INVALID_OPERATION_IN_THIS_STATE = 139, - ERROR_CODE_LIST_ITEM_NOT_NUMBERED = 140, - ERROR_CODE_LIST_ITEM_NOT_TIMESTAMPED = 141, - ERROR_CODE_INVALID_DATA_ENCODING = 142, - ERROR_CODE_BVLC_FUNCTION_UNKNOWN = 143, - ERROR_CODE_BVLC_PROPRIETARY_FUNCTION_UNKNOWN = 144, - ERROR_CODE_HEADER_ENCODING_ERROR = 145, - ERROR_CODE_HEADER_NOT_UNDERSTOOD = 146, - ERROR_CODE_MESSAGE_INCOMPLETE = 147, - ERROR_CODE_NOT_A_BACNET_SC_HUB = 148, - ERROR_CODE_PAYLOAD_EXPECTED = 149, - ERROR_CODE_UNEXPECTED_DATA = 150, - ERROR_CODE_NODE_DUPLICATE_VMAC = 151, - ERROR_CODE_HTTP_UNEXPECTED_RESPONSE_CODE = 152, - ERROR_CODE_HTTP_NO_UPGRADE = 153, - ERROR_CODE_HTTP_RESOURCE_NOT_LOCAL = 154, - ERROR_CODE_HTTP_PROXY_AUTHENTICATION_FAILED = 155, - ERROR_CODE_HTTP_RESPONSE_TIMEOUT = 156, - ERROR_CODE_HTTP_RESPONSE_SYNTAX_ERROR = 157, - ERROR_CODE_HTTP_RESPONSE_VALUE_ERROR = 158, - ERROR_CODE_HTTP_RESPONSE_MISSING_HEADER = 159, - ERROR_CODE_HTTP_WEBSOCKET_HEADER_ERROR = 160, - ERROR_CODE_HTTP_UPGRADE_REQUIRED = 161, - ERROR_CODE_HTTP_UPGRADE_ERROR = 162, - ERROR_CODE_HTTP_TEMPORARY_UNAVAILABLE = 163, - ERROR_CODE_HTTP_NOT_A_SERVER = 164, - ERROR_CODE_HTTP_ERROR = 165, - ERROR_CODE_WEBSOCKET_SCHEME_NOT_SUPPORTED = 166, - ERROR_CODE_WEBSOCKET_UNKNOWN_CONTROL_MESSAGE = 167, - ERROR_CODE_WEBSOCKET_CLOSE_ERROR = 168, - ERROR_CODE_WEBSOCKET_CLOSED_BY_PEER = 169, - ERROR_CODE_WEBSOCKET_ENDPOINT_LEAVES = 170, - ERROR_CODE_WEBSOCKET_PROTOCOL_ERROR = 171, - ERROR_CODE_WEBSOCKET_DATA_NOT_ACCEPTED = 172, - ERROR_CODE_WEBSOCKET_CLOSED_ABNORMALLY = 173, - ERROR_CODE_WEBSOCKET_DATA_INCONSISTENT = 174, - ERROR_CODE_WEBSOCKET_DATA_AGAINST_POLICY = 175, - ERROR_CODE_WEBSOCKET_FRAME_TOO_LONG = 176, - ERROR_CODE_WEBSOCKET_EXTENSION_MISSING = 177, - ERROR_CODE_WEBSOCKET_REQUEST_UNAVAILABLE = 178, - ERROR_CODE_WEBSOCKET_ERROR = 179, - ERROR_CODE_TLS_CLIENT_CERTIFICATE_ERROR = 180, - ERROR_CODE_TLS_SERVER_CERTIFICATE_ERROR = 181, - ERROR_CODE_TLS_CLIENT_AUTHENTICATION_FAILED = 182, - ERROR_CODE_TLS_SERVER_AUTHENTICATION_FAILED = 183, - ERROR_CODE_TLS_CLIENT_CERTIFICATE_EXPIRED = 184, - ERROR_CODE_TLS_SERVER_CERTIFICATE_EXPIRED = 185, - ERROR_CODE_TLS_CLIENT_CERTIFICATE_REVOKED = 186, - ERROR_CODE_TLS_SERVER_CERTIFICATE_REVOKED = 187, - ERROR_CODE_TLS_ERROR = 188, - ERROR_CODE_DNS_UNAVAILABLE = 189, - ERROR_CODE_DNS_NAME_RESOLUTION_FAILED = 190, - ERROR_CODE_DNS_RESOLVER_FAILURE = 191, - ERROR_CODE_DNS_ERROR = 192, - ERROR_CODE_TCP_CONNECT_TIMEOUT = 193, - ERROR_CODE_TCP_CONNECTION_REFUSED = 194, - ERROR_CODE_TCP_CLOSED_BY_LOCAL = 195, - ERROR_CODE_TCP_CLOSED_OTHER = 196, - ERROR_CODE_TCP_ERROR = 197, - ERROR_CODE_IP_ADDRESS_NOT_REACHABLE = 198, - ERROR_CODE_IP_ERROR = 199, - ERROR_CODE_CERTIFICATE_EXPIRED = 200, - ERROR_CODE_CERTIFICATE_INVALID = 201, - ERROR_CODE_CERTIFICATE_MALFORMED = 202, - ERROR_CODE_CERTIFICATE_REVOKED = 203, - ERROR_CODE_UNKNOWN_SECURITY_KEY = 204, - ERROR_CODE_REFERENCED_PORT_IN_ERROR = 205, - MAX_BACNET_ERROR_CODE = 206, - ERROR_CODE_RESERVED_MAX = 255, - /* Enumerated values 0-255 are reserved for definition by ASHRAE. */ - /* Enumerated values 256-65535 may be used by others subject to */ - /* the procedures and constraints described in Clause 23. */ - /* do the max range inside of enum so that - compilers will allocate adequate sized datatype for enum - which is used to store decoding */ - ERROR_CODE_PROPRIETARY_FIRST = 256, - ERROR_CODE_PROPRIETARY_LAST = 65535 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetEventNotificationData.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetEventNotificationData.cs deleted file mode 100644 index abda801..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetEventNotificationData.cs +++ /dev/null @@ -1,140 +0,0 @@ -namespace System.IO.BACnet; - -public struct BacnetEventNotificationData -{ - public uint processIdentifier; - public BacnetObjectId initiatingObjectIdentifier; - public BacnetObjectId eventObjectIdentifier; - public BacnetGenericTime timeStamp; - public uint notificationClass; - public byte priority; - public BacnetEventTypes eventType; - public string messageText; /* OPTIONAL - Set to NULL if not being used */ - public BacnetNotifyTypes notifyType; - public bool ackRequired; - public BacnetEventStates fromState; - public BacnetEventStates toState; - - /* - ** Each of these structures in the union maps to a particular eventtype - ** Based on BACnetNotificationParameters - */ - - /* - ** EVENT_CHANGE_OF_BITSTRING - */ - public BacnetBitString changeOfBitstring_referencedBitString; - public BacnetBitString changeOfBitstring_statusFlags; - /* - ** EVENT_CHANGE_OF_STATE - */ - public BacnetPropertyState changeOfState_newState; - public BacnetBitString changeOfState_statusFlags; - /* - ** EVENT_CHANGE_OF_VALUE - */ - public BacnetBitString changeOfValue_changedBits; - public float changeOfValue_changeValue; - public BacnetCOVTypes? changeOfValue_tag; - public BacnetBitString changeOfValue_statusFlags; - /* - ** EVENT_COMMAND_FAILURE - */ - public uint commandFailure_commandValue; - public BacnetBitString commandFailure_statusFlags; - public uint commandFailure_feedbackValue; - /* - ** EVENT_FLOATING_LIMIT - */ - public float floatingLimit_referenceValue; - public BacnetBitString floatingLimit_statusFlags; - public float floatingLimit_setPointValue; - public float floatingLimit_errorLimit; - /* - ** EVENT_OUT_OF_RANGE - */ - public float outOfRange_exceedingValue; - public BacnetBitString outOfRange_statusFlags; - public float outOfRange_deadband; - public float outOfRange_exceededLimit; - /* - ** EVENT_CHANGE_OF_LIFE_SAFETY - */ - public BacnetLifeSafetyStates? changeOfLifeSafety_newState; - public BacnetLifeSafetyModes? changeOfLifeSafety_newMode; - public BacnetBitString changeOfLifeSafety_statusFlags; - public BacnetLifeSafetyOperations? changeOfLifeSafety_operationExpected; - /* - ** EVENT_EXTENDED - ** - ** Not Supported! - */ - /* - ** EVENT_BUFFER_READY - */ - public BacnetDeviceObjectPropertyReference bufferReady_bufferProperty; - public uint bufferReady_previousNotification; - public uint bufferReady_currentNotification; - /* - ** EVENT_UNSIGNED_RANGE - */ - public uint unsignedRange_exceedingValue; - public BacnetBitString unsignedRange_statusFlags; - public uint unsignedRange_exceededLimit; - /* - ** EVENT_EXTENDED - */ - public uint extended_vendorId; - public uint extended_eventType; - public object[] extended_parameters; - - public override string ToString() - { - return $"initiatingObject: {initiatingObjectIdentifier}, eventObject: {eventObjectIdentifier}, " - + $"eventType: {eventType}, notifyType: {notifyType}, timeStamp: {timeStamp}, " - + $"fromState: {fromState}, toState: {toState}, {GetEventDetails() ?? "no details"}"; - } - - private string GetEventDetails() - { - switch (eventType) - { - case BacnetEventTypes.EVENT_CHANGE_OF_BITSTRING: - return $"referencedBitString: {changeOfBitstring_referencedBitString}, statusFlags: {changeOfBitstring_statusFlags}"; - - case BacnetEventTypes.EVENT_CHANGE_OF_STATE: - return $"newState: {changeOfState_newState}, statusFlags: {changeOfState_statusFlags}"; - - case BacnetEventTypes.EVENT_CHANGE_OF_VALUE: - return $"changedBits: {changeOfValue_changedBits}, changeValue: {changeOfValue_changeValue}, " - + $"tag: {changeOfValue_tag}, statusFlags: {changeOfValue_statusFlags}"; - - case BacnetEventTypes.EVENT_FLOATING_LIMIT: - return $"referenceValue: {floatingLimit_referenceValue}, statusFlags: {floatingLimit_statusFlags}, " - + $"setPointValue: {floatingLimit_setPointValue}, errorLimit: {floatingLimit_errorLimit}"; - - case BacnetEventTypes.EVENT_OUT_OF_RANGE: - return $"exceedingValue: {outOfRange_exceedingValue}, statusFlags: {outOfRange_statusFlags}, " - + $"deadband: {outOfRange_deadband}, exceededLimit: {outOfRange_exceededLimit}"; - - case BacnetEventTypes.EVENT_CHANGE_OF_LIFE_SAFETY: - return $"newState: {changeOfLifeSafety_newState}, newMode: {changeOfLifeSafety_newMode}, " - + - $"statusFlags: {changeOfLifeSafety_statusFlags}, operationExpected: {changeOfLifeSafety_operationExpected}"; - - case BacnetEventTypes.EVENT_BUFFER_READY: - return $"bufferProperty: {bufferReady_bufferProperty}, previousNotification: {bufferReady_previousNotification}, " - + $"currentNotification: {bufferReady_currentNotification}"; - - case BacnetEventTypes.EVENT_UNSIGNED_RANGE: - return $"exceedingValue: {unsignedRange_exceedingValue}, statusFlags: {unsignedRange_statusFlags}, " - + $"exceededLimit: {unsignedRange_exceededLimit}"; - - case BacnetEventTypes.EVENT_EXTENDED: - return $"vendorId: {extended_vendorId}, extendedEventType: {extended_eventType}, parameters: [{extended_parameters?.Length ?? 0}]"; - - default: - return null; - } - } -}; diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetGenericTime.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetGenericTime.cs deleted file mode 100644 index 1214a1a..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetGenericTime.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace System.IO.BACnet; - -public struct BacnetGenericTime -{ - public BacnetTimestampTags Tag; - public DateTime Time; - public ushort Sequence; - - public BacnetGenericTime(DateTime time, BacnetTimestampTags tag, ushort sequence = 0) - { - Time = time; - Tag = tag; - Sequence = sequence; - } - - public override string ToString() - { - return $"{Time}"; - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetGetEventInformationData.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetGetEventInformationData.cs deleted file mode 100644 index 7b01a63..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetGetEventInformationData.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace System.IO.BACnet; - -public struct BacnetGetEventInformationData -{ - public BacnetObjectId objectIdentifier; - public BacnetEventStates eventState; - public BacnetBitString acknowledgedTransitions; - public BacnetGenericTime[] eventTimeStamps; //3 - public BacnetNotifyTypes notifyType; - public BacnetBitString eventEnable; - public uint[] eventPriorities; //3 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetLogRecord.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetLogRecord.cs deleted file mode 100644 index 2750977..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetLogRecord.cs +++ /dev/null @@ -1,143 +0,0 @@ -namespace System.IO.BACnet; - -public struct BacnetLogRecord -{ - public DateTime timestamp; - - /* logDatum: CHOICE { */ - public BacnetTrendLogValueType type; - //private BacnetBitString log_status; - //private bool boolean_value; - //private float real_value; - //private uint enum_value; - //private uint unsigned_value; - //private int signed_value; - //private BacnetBitString bitstring_value; - //private bool null_value; - //private BacnetError failure; - //private float time_change; - private object any_value; - /* } */ - - public BacnetBitString statusFlags; - - public BacnetLogRecord(BacnetTrendLogValueType type, object value, DateTime stamp, uint status) - { - this.type = type; - timestamp = stamp; - statusFlags = BacnetBitString.ConvertFromInt(status); - any_value = null; - Value = value; - } - - public object Value - { - get - { - switch (type) - { - case BacnetTrendLogValueType.TL_TYPE_ANY: - return any_value; - case BacnetTrendLogValueType.TL_TYPE_BITS: - return (BacnetBitString)Convert.ChangeType(any_value, typeof(BacnetBitString)); - case BacnetTrendLogValueType.TL_TYPE_BOOL: - return (bool)Convert.ChangeType(any_value, typeof(bool)); - case BacnetTrendLogValueType.TL_TYPE_DELTA: - return (float)Convert.ChangeType(any_value, typeof(float)); - case BacnetTrendLogValueType.TL_TYPE_ENUM: - return (uint)Convert.ChangeType(any_value, typeof(uint)); - case BacnetTrendLogValueType.TL_TYPE_ERROR: - if (any_value != null) - return (BacnetError)Convert.ChangeType(any_value, typeof(BacnetError)); - else - return new BacnetError(BacnetErrorClasses.ERROR_CLASS_DEVICE, BacnetErrorCodes.ERROR_CODE_ABORT_OTHER); - case BacnetTrendLogValueType.TL_TYPE_NULL: - return null; - case BacnetTrendLogValueType.TL_TYPE_REAL: - return (float)Convert.ChangeType(any_value, typeof(float)); - case BacnetTrendLogValueType.TL_TYPE_SIGN: - return (int)Convert.ChangeType(any_value, typeof(int)); - case BacnetTrendLogValueType.TL_TYPE_STATUS: - return (BacnetBitString)Convert.ChangeType(any_value, typeof(BacnetBitString)); - case BacnetTrendLogValueType.TL_TYPE_UNSIGN: - return (uint)Convert.ChangeType(any_value, typeof(uint)); - default: - throw new NotSupportedException(); - } - } - set - { - switch (type) - { - case BacnetTrendLogValueType.TL_TYPE_ANY: - any_value = value; - break; - case BacnetTrendLogValueType.TL_TYPE_BITS: - if (value == null) value = new BacnetBitString(); - if (value.GetType() != typeof(BacnetBitString)) - value = BacnetBitString.ConvertFromInt((uint)Convert.ChangeType(value, typeof(uint))); - any_value = (BacnetBitString)value; - break; - case BacnetTrendLogValueType.TL_TYPE_BOOL: - if (value == null) value = false; - if (value.GetType() != typeof(bool)) - value = (bool)Convert.ChangeType(value, typeof(bool)); - any_value = (bool)value; - break; - case BacnetTrendLogValueType.TL_TYPE_DELTA: - if (value == null) value = (float)0; - if (value.GetType() != typeof(float)) - value = (float)Convert.ChangeType(value, typeof(float)); - any_value = (float)value; - break; - case BacnetTrendLogValueType.TL_TYPE_ENUM: - if (value == null) value = (uint)0; - if (value.GetType() != typeof(uint)) - value = (uint)Convert.ChangeType(value, typeof(uint)); - any_value = (uint)value; - break; - case BacnetTrendLogValueType.TL_TYPE_ERROR: - if (value == null) value = new BacnetError(); - if (value.GetType() != typeof(BacnetError)) - throw new ArgumentException(); - any_value = (BacnetError)value; - break; - case BacnetTrendLogValueType.TL_TYPE_NULL: - if (value != null) throw new ArgumentException(); - any_value = value; - break; - case BacnetTrendLogValueType.TL_TYPE_REAL: - if (value == null) value = (float)0; - if (value.GetType() != typeof(float)) - value = (float)Convert.ChangeType(value, typeof(float)); - any_value = (float)value; - break; - case BacnetTrendLogValueType.TL_TYPE_SIGN: - if (value == null) value = 0; - if (value.GetType() != typeof(int)) - value = (int)Convert.ChangeType(value, typeof(int)); - any_value = (int)value; - break; - case BacnetTrendLogValueType.TL_TYPE_STATUS: - if (value == null) value = new BacnetBitString(); - if (value.GetType() != typeof(BacnetBitString)) - value = BacnetBitString.ConvertFromInt((uint)Convert.ChangeType(value, typeof(uint))); - any_value = (BacnetBitString)value; - break; - case BacnetTrendLogValueType.TL_TYPE_UNSIGN: - if (value == null) value = (uint)0; - if (value.GetType() != typeof(uint)) - value = (uint)Convert.ChangeType(value, typeof(uint)); - any_value = (uint)value; - break; - default: - throw new NotSupportedException(); - } - } - } - - public T GetValue() - { - return (T)Convert.ChangeType(Value, typeof(T)); - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetMaxAdpu.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetMaxAdpu.cs deleted file mode 100644 index 21a1cd0..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetMaxAdpu.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetMaxAdpu : byte -{ - MAX_APDU50 = 0, - MAX_APDU128 = 1, - MAX_APDU206 = 2, - MAX_APDU480 = 3, - MAX_APDU1024 = 4, - MAX_APDU1476 = 5 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetMaxSegments.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetMaxSegments.cs deleted file mode 100644 index f00f72b..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetMaxSegments.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetMaxSegments : byte -{ - MAX_SEG0 = 0, - MAX_SEG2 = 0x10, - MAX_SEG4 = 0x20, - MAX_SEG8 = 0x30, - MAX_SEG16 = 0x40, - MAX_SEG32 = 0x50, - MAX_SEG64 = 0x60, - MAX_SEG65 = 0x70 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetMstpFrameTypes.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetMstpFrameTypes.cs deleted file mode 100644 index be5b24f..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetMstpFrameTypes.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace System.IO.BACnet; - -/* MS/TP Frame Type */ -public enum BacnetMstpFrameTypes : byte -{ - /* Frame Types 8 through 127 are reserved by ASHRAE. */ - FRAME_TYPE_TOKEN = 0, - FRAME_TYPE_POLL_FOR_MASTER = 1, - FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER = 2, - FRAME_TYPE_TEST_REQUEST = 3, - FRAME_TYPE_TEST_RESPONSE = 4, - FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY = 5, - FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY = 6, - FRAME_TYPE_REPLY_POSTPONED = 7, - /* Frame Types 128 through 255: Proprietary Frames */ - /* These frames are available to vendors as proprietary (non-BACnet) frames. */ - /* The first two octets of the Data field shall specify the unique vendor */ - /* identification code, most significant octet first, for the type of */ - /* vendor-proprietary frame to be conveyed. The length of the data portion */ - /* of a Proprietary frame shall be in the range of 2 to 501 octets. */ - FRAME_TYPE_PROPRIETARY_MIN = 128, - FRAME_TYPE_PROPRIETARY_MAX = 255 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetNetworkMessageTypes.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetNetworkMessageTypes.cs deleted file mode 100644 index 8577ebe..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetNetworkMessageTypes.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace System.IO.BACnet; - -/*Network Layer Message Type */ -/*If Bit 7 of the control octet described in 6.2.2 is 1, */ -/* a message type octet shall be present as shown in Figure 6-1. */ -/* The following message types are indicated: */ -public enum BacnetNetworkMessageTypes : byte -{ - NETWORK_MESSAGE_WHO_IS_ROUTER_TO_NETWORK = 0, - NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK = 1, - NETWORK_MESSAGE_I_COULD_BE_ROUTER_TO_NETWORK = 2, - NETWORK_MESSAGE_REJECT_MESSAGE_TO_NETWORK = 3, - NETWORK_MESSAGE_ROUTER_BUSY_TO_NETWORK = 4, - NETWORK_MESSAGE_ROUTER_AVAILABLE_TO_NETWORK = 5, - NETWORK_MESSAGE_INIT_RT_TABLE = 6, - NETWORK_MESSAGE_INIT_RT_TABLE_ACK = 7, - NETWORK_MESSAGE_ESTABLISH_CONNECTION_TO_NETWORK = 8, - NETWORK_MESSAGE_DISCONNECT_CONNECTION_TO_NETWORK = 9, - NETWORK_MESSAGE_CHALLENGE_REQUEST = 10, - NETWORK_MESSAGE_SECURITY_PAYLOAD = 11, - NETWORK_MESSAGE_SECURITY_RESPONSE = 12, - NETWORK_MESSAGE_REQUEST_KEY_UPDATE = 13, - NETWORK_MESSAGE_UPDATE_KEY_SET = 14, - NETWORK_MESSAGE_UPDATE_DISTRIBUTION_KEY = 15, - NETWORK_MESSAGE_REQUEST_MASTER_KEY = 16, - NETWORK_MESSAGE_SET_MASTER_KEY = 17, - NETWORK_MESSAGE_WHAT_IS_NETWORK_NUMBER = 18, - NETWORK_MESSAGE_NETWORK_NUMBER_IS = 19 - /* X'0A' to X'7F': Reserved for use by ASHRAE, */ - /* X'80' to X'FF': Available for vendor proprietary messages */ -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetNodeTypes.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetNodeTypes.cs deleted file mode 100644 index a6c493f..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetNodeTypes.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetNodeTypes -{ - NT_UNKNOWN, - NT_SYSTEM, - NT_NETWORK, - NT_DEVICE, - NT_ORGANIZATIONAL, - NT_AREA, - NT_EQUIPMENT, - NT_POINT, - NT_COLLECTION, - NT_PROPERTY, - NT_FUNCTIONAL, - NT_OTHER, -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetNpduControls.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetNpduControls.cs deleted file mode 100644 index 0fda2ff..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetNpduControls.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace System.IO.BACnet; - -[Flags] -public enum BacnetNpduControls : byte -{ - PriorityNormalMessage = 0, - PriorityUrgentMessage = 1, - PriorityCriticalMessage = 2, - PriorityLifeSafetyMessage = 3, - ExpectingReply = 4, - SourceSpecified = 8, - DestinationSpecified = 32, - NetworkLayerMessage = 128 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetObjectDescription.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetObjectDescription.cs deleted file mode 100644 index 688070f..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetObjectDescription.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace System.IO.BACnet; - -public struct BacnetObjectDescription -{ - public BacnetObjectTypes typeId; - public List propsId; -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetObjectId.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetObjectId.cs deleted file mode 100644 index 830ed00..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetObjectId.cs +++ /dev/null @@ -1,82 +0,0 @@ -namespace System.IO.BACnet; - -[Serializable] -public struct BacnetObjectId : IComparable -{ - public BacnetObjectTypes type; - public uint instance; - - public BacnetObjectTypes Type - { - get => type; - set => type = value; - } - - public uint Instance - { - get => instance; - set => instance = value; - } - - public BacnetObjectId(BacnetObjectTypes type, uint instance) - { - this.type = type; - this.instance = instance; - } - - public override string ToString() - { - return $"{Type}:{Instance}"; - } - - public override int GetHashCode() - { - return ToString().GetHashCode(); - } - - public override bool Equals(object obj) - { - return obj != null && obj.ToString().Equals(ToString()); - } - - public int CompareTo(BacnetObjectId other) - { - if (Type == other.Type) - return Instance.CompareTo(other.Instance); - - if (Type == BacnetObjectTypes.OBJECT_DEVICE) - return -1; - - if (other.Type == BacnetObjectTypes.OBJECT_DEVICE) - return 1; - - // cast to int for comparison otherwise unpredictable behaviour with outbound enum (proprietary type) - return ((int)Type).CompareTo((int)other.Type); - } - - public static bool operator ==(BacnetObjectId a, BacnetObjectId b) - { - return a.Equals(b); - } - - public static bool operator !=(BacnetObjectId a, BacnetObjectId b) - { - return !(a == b); - } - - public static BacnetObjectId Parse(string value) - { - var pattern = new Regex($"(?<{nameof(Type)}>.+):(?<{nameof(Instance)}>.+)"); - - if (string.IsNullOrEmpty(value) || !pattern.IsMatch(value)) - return new BacnetObjectId(); - - var objectType = (BacnetObjectTypes)Enum.Parse(typeof(BacnetObjectTypes), - pattern.Match(value).Groups[nameof(Type)].Value); - - var objectInstance = uint.Parse(pattern.Match(value).Groups[nameof(Instance)].Value); - - return new BacnetObjectId(objectType, objectInstance); - } - -}; diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetObjectTypes.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetObjectTypes.cs deleted file mode 100644 index 1cbb8bb..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetObjectTypes.cs +++ /dev/null @@ -1,82 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetObjectTypes : uint -{ - OBJECT_ANALOG_INPUT = 0, - OBJECT_ANALOG_OUTPUT = 1, - OBJECT_ANALOG_VALUE = 2, - OBJECT_BINARY_INPUT = 3, - OBJECT_BINARY_OUTPUT = 4, - OBJECT_BINARY_VALUE = 5, - OBJECT_CALENDAR = 6, - OBJECT_COMMAND = 7, - OBJECT_DEVICE = 8, - OBJECT_EVENT_ENROLLMENT = 9, - OBJECT_FILE = 10, - OBJECT_GROUP = 11, - OBJECT_LOOP = 12, - OBJECT_MULTI_STATE_INPUT = 13, - OBJECT_MULTI_STATE_OUTPUT = 14, - OBJECT_NOTIFICATION_CLASS = 15, - OBJECT_PROGRAM = 16, - OBJECT_SCHEDULE = 17, - OBJECT_AVERAGING = 18, - OBJECT_MULTI_STATE_VALUE = 19, - OBJECT_TRENDLOG = 20, - OBJECT_LIFE_SAFETY_POINT = 21, - OBJECT_LIFE_SAFETY_ZONE = 22, - OBJECT_ACCUMULATOR = 23, - OBJECT_PULSE_CONVERTER = 24, - OBJECT_EVENT_LOG = 25, - OBJECT_GLOBAL_GROUP = 26, - OBJECT_TREND_LOG_MULTIPLE = 27, - OBJECT_LOAD_CONTROL = 28, - OBJECT_STRUCTURED_VIEW = 29, - OBJECT_ACCESS_DOOR = 30, - OBJECT_TIMER = 31, /* Addendum 135-2012ay */ - OBJECT_ACCESS_CREDENTIAL = 32, /* Addendum 2008-j */ - OBJECT_ACCESS_POINT = 33, - OBJECT_ACCESS_RIGHTS = 34, - OBJECT_ACCESS_USER = 35, - OBJECT_ACCESS_ZONE = 36, - OBJECT_CREDENTIAL_DATA_INPUT = 37, /* authentication-factor-input */ - OBJECT_NETWORK_SECURITY = 38, /* Addendum 2008-g */ - OBJECT_BITSTRING_VALUE = 39, /* Addendum 2008-w */ - OBJECT_CHARACTERSTRING_VALUE = 40, /* Addendum 2008-w */ - OBJECT_DATE_PATTERN_VALUE = 41, /* Addendum 2008-w */ - OBJECT_DATE_VALUE = 42, /* Addendum 2008-w */ - OBJECT_DATETIME_PATTERN_VALUE = 43, /* Addendum 2008-w */ - OBJECT_DATETIME_VALUE = 44, /* Addendum 2008-w */ - OBJECT_INTEGER_VALUE = 45, /* Addendum 2008-w */ - OBJECT_LARGE_ANALOG_VALUE = 46, /* Addendum 2008-w */ - OBJECT_OCTETSTRING_VALUE = 47, /* Addendum 2008-w */ - OBJECT_POSITIVE_INTEGER_VALUE = 48, /* Addendum 2008-w */ - OBJECT_TIME_PATTERN_VALUE = 49, /* Addendum 2008-w */ - OBJECT_TIME_VALUE = 50, /* Addendum 2008-w */ - OBJECT_NOTIFICATION_FORWARDER = 51, /* Addendum 2010-af */ - OBJECT_ALERT_ENROLLMENT = 52, /* Addendum 2010-af */ - OBJECT_CHANNEL = 53, /* Addendum 2010-aa */ - OBJECT_LIGHTING_OUTPUT = 54, /* Addendum 2010-i */ - OBJECT_BINARY_LIGHTING_OUTPUT = 55, /* Addendum 135-2012az */ - OBJECT_NETWORK_PORT = 56, /* Addendum 135-2012az */ - OBJECT_ELEVATOR_GROUP = 57, /* Addendum 135-2012aq */ - OBJECT_ESCALATOR = 58, /* Addendum 135-2012aq */ - OBJECT_LIFT = 59, /* Addendum 135-2012aq */ - OBJECT_STAGING = 60, /* Addendum 135-2016bd */ - OBJECT_AUDIT_LOG = 61, /* Addendum 135-2016bi */ - OBJECT_AUDIT_REPORTER = 62, /* Addendum 135-2016bi */ - OBJECT_COLOR = 63, /* Addendum 135-2020ca */ - OBJECT_COLOR_TEMPERATURE = 64, /* Addendum 135-2020ca */ - - /* Enumerated values 0-127 are reserved for definition by ASHRAE. */ - /* Enumerated values 128-1023 may be used by others subject to */ - /* the procedures and constraints described in Clause 23. */ - /* do the max range inside of enum so that - compilers will allocate adequate sized datatype for enum - which is used to store decoding */ - - OBJECT_PROPRIETARY_MIN = 128, - OBJECT_PROPRIETARY_MAX = 1023, - MAX_BACNET_OBJECT_TYPE = 1024, - MAX_ASHRAE_OBJECT_TYPE = 65 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPduTypes.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPduTypes.cs deleted file mode 100644 index 85a8b01..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPduTypes.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace System.IO.BACnet; - -[Flags] -/* note: these are not the real values, */ -/* but are shifted left for easy encoding */ -public enum BacnetPduTypes : byte -{ - PDU_TYPE_CONFIRMED_SERVICE_REQUEST = 0, - SERVER = 1, - NEGATIVE_ACK = 2, - SEGMENTED_RESPONSE_ACCEPTED = 2, - MORE_FOLLOWS = 4, - SEGMENTED_MESSAGE = 8, - PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST = 0x10, - PDU_TYPE_SIMPLE_ACK = 0x20, - PDU_TYPE_COMPLEX_ACK = 0x30, - PDU_TYPE_SEGMENT_ACK = 0x40, - PDU_TYPE_ERROR = 0x50, - PDU_TYPE_REJECT = 0x60, - PDU_TYPE_ABORT = 0x70, - PDU_TYPE_MASK = 0xF0, -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPolarity.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPolarity.cs deleted file mode 100644 index 375b7ee..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPolarity.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetPolarity : byte -{ - POLARITY_NORMAL = 0, - POLARITY_REVERSE = 1 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetProgramError.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetProgramError.cs deleted file mode 100644 index 6034c07..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetProgramError.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace System.IO.BACnet.Base; - -public enum BacnetProgramError : ushort -{ - PROGRAM_ERROR_NORMAL = 0, - PROGRAM_ERROR_LOAD_FAILED = 1, - PROGRAM_ERROR_INTERNAL = 2, - PROGRAM_ERROR_PROGRAM = 3, - PROGRAM_ERROR_OTHER = 4, - /* Enumerated values 0-63 are reserved for definition by ASHRAE. */ - /* Enumerated values 64-65535 may be used by others subject to */ - /* the procedures and constraints described in Clause 23. */ - /* do the max range inside of enum so that - compilers will allocate adequate sized datatype for enum - which is used to store decoding */ - PROGRAM_ERROR_PROPRIETARY_MIN = 64, - PROGRAM_ERROR_PROPRIETARY_MAX = 65535 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetProgramRequest.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetProgramRequest.cs deleted file mode 100644 index 83a5815..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetProgramRequest.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace System.IO.BACnet.Base; - -public enum BacnetProgramRequest -{ - PROGRAM_REQUEST_READY = 0, - PROGRAM_REQUEST_LOAD = 1, - PROGRAM_REQUEST_RUN = 2, - PROGRAM_REQUEST_HALT = 3, - PROGRAM_REQUEST_RESTART = 4, - PROGRAM_REQUEST_UNLOAD = 5 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetProgramState.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetProgramState.cs deleted file mode 100644 index 541b6be..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetProgramState.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace System.IO.BACnet.Base; - -public enum BacnetProgramState -{ - PROGRAM_STATE_IDLE = 0, - PROGRAM_STATE_LOADING = 1, - PROGRAM_STATE_RUNNING = 2, - PROGRAM_STATE_WAITING = 3, - PROGRAM_STATE_HALTED = 4, - PROGRAM_STATE_UNLOADING = 5 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPropertyIds.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPropertyIds.cs deleted file mode 100644 index eb21605..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPropertyIds.cs +++ /dev/null @@ -1,577 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetPropertyIds -{ - PROP_ACKED_TRANSITIONS = 0, - PROP_ACK_REQUIRED = 1, - PROP_ACTION = 2, - PROP_ACTION_TEXT = 3, - PROP_ACTIVE_TEXT = 4, - PROP_ACTIVE_VT_SESSIONS = 5, - PROP_ALARM_VALUE = 6, - PROP_ALARM_VALUES = 7, - PROP_ALL = 8, - PROP_ALL_WRITES_SUCCESSFUL = 9, - PROP_APDU_SEGMENT_TIMEOUT = 10, - PROP_APDU_TIMEOUT = 11, - PROP_APPLICATION_SOFTWARE_VERSION = 12, - PROP_ARCHIVE = 13, - PROP_BIAS = 14, - PROP_CHANGE_OF_STATE_COUNT = 15, - PROP_CHANGE_OF_STATE_TIME = 16, - PROP_NOTIFICATION_CLASS = 17, - PROP_BLANK_1 = 18, - PROP_CONTROLLED_VARIABLE_REFERENCE = 19, - PROP_CONTROLLED_VARIABLE_UNITS = 20, - PROP_CONTROLLED_VARIABLE_VALUE = 21, - PROP_COV_INCREMENT = 22, - PROP_DATE_LIST = 23, - PROP_DAYLIGHT_SAVINGS_STATUS = 24, - PROP_DEADBAND = 25, - PROP_DERIVATIVE_CONSTANT = 26, - PROP_DERIVATIVE_CONSTANT_UNITS = 27, - PROP_DESCRIPTION = 28, - PROP_DESCRIPTION_OF_HALT = 29, - PROP_DEVICE_ADDRESS_BINDING = 30, - PROP_DEVICE_TYPE = 31, - PROP_EFFECTIVE_PERIOD = 32, - PROP_ELAPSED_ACTIVE_TIME = 33, - PROP_ERROR_LIMIT = 34, - PROP_EVENT_ENABLE = 35, - PROP_EVENT_STATE = 36, - PROP_EVENT_TYPE = 37, - PROP_EXCEPTION_SCHEDULE = 38, - PROP_FAULT_VALUES = 39, - PROP_FEEDBACK_VALUE = 40, - PROP_FILE_ACCESS_METHOD = 41, - PROP_FILE_SIZE = 42, - PROP_FILE_TYPE = 43, - PROP_FIRMWARE_REVISION = 44, - PROP_HIGH_LIMIT = 45, - PROP_INACTIVE_TEXT = 46, - PROP_IN_PROCESS = 47, - PROP_INSTANCE_OF = 48, - PROP_INTEGRAL_CONSTANT = 49, - PROP_INTEGRAL_CONSTANT_UNITS = 50, - PROP_ISSUE_CONFIRMED_NOTIFICATIONS = 51, - PROP_LIMIT_ENABLE = 52, - PROP_LIST_OF_GROUP_MEMBERS = 53, - PROP_LIST_OF_OBJECT_PROPERTY_REFERENCES = 54, - PROP_LIST_OF_SESSION_KEYS = 55, - PROP_LOCAL_DATE = 56, - PROP_LOCAL_TIME = 57, - PROP_LOCATION = 58, - PROP_LOW_LIMIT = 59, - PROP_MANIPULATED_VARIABLE_REFERENCE = 60, - PROP_MAXIMUM_OUTPUT = 61, - PROP_MAX_APDU_LENGTH_ACCEPTED = 62, - PROP_MAX_INFO_FRAMES = 63, - PROP_MAX_MASTER = 64, - PROP_MAX_PRES_VALUE = 65, - PROP_MINIMUM_OFF_TIME = 66, - PROP_MINIMUM_ON_TIME = 67, - PROP_MINIMUM_OUTPUT = 68, - PROP_MIN_PRES_VALUE = 69, - PROP_MODEL_NAME = 70, - PROP_MODIFICATION_DATE = 71, - PROP_NOTIFY_TYPE = 72, - PROP_NUMBER_OF_APDU_RETRIES = 73, - PROP_NUMBER_OF_STATES = 74, - PROP_OBJECT_IDENTIFIER = 75, - PROP_OBJECT_LIST = 76, - PROP_OBJECT_NAME = 77, - PROP_OBJECT_PROPERTY_REFERENCE = 78, - PROP_OBJECT_TYPE = 79, - PROP_OPTIONAL = 80, - PROP_OUT_OF_SERVICE = 81, - PROP_OUTPUT_UNITS = 82, - PROP_EVENT_PARAMETERS = 83, - PROP_POLARITY = 84, - PROP_PRESENT_VALUE = 85, - PROP_PRIORITY = 86, - PROP_PRIORITY_ARRAY = 87, - PROP_PRIORITY_FOR_WRITING = 88, - PROP_PROCESS_IDENTIFIER = 89, - PROP_PROGRAM_CHANGE = 90, - PROP_PROGRAM_LOCATION = 91, - PROP_PROGRAM_STATE = 92, - PROP_PROPORTIONAL_CONSTANT = 93, - PROP_PROPORTIONAL_CONSTANT_UNITS = 94, - PROP_PROTOCOL_CONFORMANCE_CLASS = 95, /* deleted in version 1 revision 2 */ - PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED = 96, - PROP_PROTOCOL_SERVICES_SUPPORTED = 97, - PROP_PROTOCOL_VERSION = 98, - PROP_READ_ONLY = 99, - PROP_REASON_FOR_HALT = 100, - PROP_RECIPIENT = 101, - PROP_RECIPIENT_LIST = 102, - PROP_RELIABILITY = 103, - PROP_RELINQUISH_DEFAULT = 104, - PROP_REQUIRED = 105, - PROP_RESOLUTION = 106, - PROP_SEGMENTATION_SUPPORTED = 107, - PROP_SETPOINT = 108, - PROP_SETPOINT_REFERENCE = 109, - PROP_STATE_TEXT = 110, - PROP_STATUS_FLAGS = 111, - PROP_SYSTEM_STATUS = 112, - PROP_TIME_DELAY = 113, - PROP_TIME_OF_ACTIVE_TIME_RESET = 114, - PROP_TIME_OF_STATE_COUNT_RESET = 115, - PROP_TIME_SYNCHRONIZATION_RECIPIENTS = 116, - PROP_UNITS = 117, - PROP_UPDATE_INTERVAL = 118, - PROP_UTC_OFFSET = 119, - PROP_VENDOR_IDENTIFIER = 120, - PROP_VENDOR_NAME = 121, - PROP_VT_CLASSES_SUPPORTED = 122, - PROP_WEEKLY_SCHEDULE = 123, - PROP_ATTEMPTED_SAMPLES = 124, - PROP_AVERAGE_VALUE = 125, - PROP_BUFFER_SIZE = 126, - PROP_CLIENT_COV_INCREMENT = 127, - PROP_COV_RESUBSCRIPTION_INTERVAL = 128, - PROP_CURRENT_NOTIFY_TIME = 129, - PROP_EVENT_TIME_STAMPS = 130, - PROP_LOG_BUFFER = 131, - PROP_LOG_DEVICE_OBJECT_PROPERTY = 132, - /* The enable property is renamed from log-enable in - Addendum b to ANSI/ASHRAE 135-2004(135b-2) */ - PROP_ENABLE = 133, - PROP_LOG_INTERVAL = 134, - PROP_MAXIMUM_VALUE = 135, - PROP_MINIMUM_VALUE = 136, - PROP_NOTIFICATION_THRESHOLD = 137, - PROP_PREVIOUS_NOTIFY_TIME = 138, - PROP_PROTOCOL_REVISION = 139, - PROP_RECORDS_SINCE_NOTIFICATION = 140, - PROP_RECORD_COUNT = 141, - PROP_START_TIME = 142, - PROP_STOP_TIME = 143, - PROP_STOP_WHEN_FULL = 144, - PROP_TOTAL_RECORD_COUNT = 145, - PROP_VALID_SAMPLES = 146, - PROP_WINDOW_INTERVAL = 147, - PROP_WINDOW_SAMPLES = 148, - PROP_MAXIMUM_VALUE_TIMESTAMP = 149, - PROP_MINIMUM_VALUE_TIMESTAMP = 150, - PROP_VARIANCE_VALUE = 151, - PROP_ACTIVE_COV_SUBSCRIPTIONS = 152, - PROP_BACKUP_FAILURE_TIMEOUT = 153, - PROP_CONFIGURATION_FILES = 154, - PROP_DATABASE_REVISION = 155, - PROP_DIRECT_READING = 156, - PROP_LAST_RESTORE_TIME = 157, - PROP_MAINTENANCE_REQUIRED = 158, - PROP_MEMBER_OF = 159, - PROP_MODE = 160, - PROP_OPERATION_EXPECTED = 161, - PROP_SETTING = 162, - PROP_SILENCED = 163, - PROP_TRACKING_VALUE = 164, - PROP_ZONE_MEMBERS = 165, - PROP_LIFE_SAFETY_ALARM_VALUES = 166, - PROP_MAX_SEGMENTS_ACCEPTED = 167, - PROP_PROFILE_NAME = 168, - PROP_AUTO_SLAVE_DISCOVERY = 169, - PROP_MANUAL_SLAVE_ADDRESS_BINDING = 170, - PROP_SLAVE_ADDRESS_BINDING = 171, - PROP_SLAVE_PROXY_ENABLE = 172, - PROP_LAST_NOTIFY_RECORD = 173, - PROP_SCHEDULE_DEFAULT = 174, - PROP_ACCEPTED_MODES = 175, - PROP_ADJUST_VALUE = 176, - PROP_COUNT = 177, - PROP_COUNT_BEFORE_CHANGE = 178, - PROP_COUNT_CHANGE_TIME = 179, - PROP_COV_PERIOD = 180, - PROP_INPUT_REFERENCE = 181, - PROP_LIMIT_MONITORING_INTERVAL = 182, - PROP_LOGGING_OBJECT = 183, - PROP_LOGGING_RECORD = 184, - PROP_PRESCALE = 185, - PROP_PULSE_RATE = 186, - PROP_SCALE = 187, - PROP_SCALE_FACTOR = 188, - PROP_UPDATE_TIME = 189, - PROP_VALUE_BEFORE_CHANGE = 190, - PROP_VALUE_SET = 191, - PROP_VALUE_CHANGE_TIME = 192, - /* enumerations 193-206 are new */ - PROP_ALIGN_INTERVALS = 193, - /* enumeration 194 is unassigned */ - PROP_INTERVAL_OFFSET = 195, - PROP_LAST_RESTART_REASON = 196, - PROP_LOGGING_TYPE = 197, - /* enumeration 198-201 is unassigned */ - PROP_RESTART_NOTIFICATION_RECIPIENTS = 202, - PROP_TIME_OF_DEVICE_RESTART = 203, - PROP_TIME_SYNCHRONIZATION_INTERVAL = 204, - PROP_TRIGGER = 205, - PROP_UTC_TIME_SYNCHRONIZATION_RECIPIENTS = 206, - /* enumerations 207-211 are used in Addendum d to ANSI/ASHRAE 135-2004 */ - PROP_NODE_SUBTYPE = 207, - PROP_NODE_TYPE = 208, - PROP_STRUCTURED_OBJECT_LIST = 209, - PROP_SUBORDINATE_ANNOTATIONS = 210, - PROP_SUBORDINATE_LIST = 211, - /* enumerations 212-225 are used in Addendum e to ANSI/ASHRAE 135-2004 */ - PROP_ACTUAL_SHED_LEVEL = 212, - PROP_DUTY_WINDOW = 213, - PROP_EXPECTED_SHED_LEVEL = 214, - PROP_FULL_DUTY_BASELINE = 215, - /* enumerations 216-217 are unassigned */ - /* enumerations 212-225 are used in Addendum e to ANSI/ASHRAE 135-2004 */ - PROP_REQUESTED_SHED_LEVEL = 218, - PROP_SHED_DURATION = 219, - PROP_SHED_LEVEL_DESCRIPTIONS = 220, - PROP_SHED_LEVELS = 221, - PROP_STATE_DESCRIPTION = 222, - /* enumerations 223-225 are unassigned */ - /* enumerations 226-235 are used in Addendum f to ANSI/ASHRAE 135-2004 */ - PROP_DOOR_ALARM_STATE = 226, - PROP_DOOR_EXTENDED_PULSE_TIME = 227, - PROP_DOOR_MEMBERS = 228, - PROP_DOOR_OPEN_TOO_LONG_TIME = 229, - PROP_DOOR_PULSE_TIME = 230, - PROP_DOOR_STATUS = 231, - PROP_DOOR_UNLOCK_DELAY_TIME = 232, - PROP_LOCK_STATUS = 233, - PROP_MASKED_ALARM_VALUES = 234, - PROP_SECURED_STATUS = 235, - /* enumerations 236-243 are unassigned */ - /* enumerations 244-311 are used in Addendum j to ANSI/ASHRAE 135-2004 */ - PROP_ABSENTEE_LIMIT = 244, - PROP_ACCESS_ALARM_EVENTS = 245, - PROP_ACCESS_DOORS = 246, - PROP_ACCESS_EVENT = 247, - PROP_ACCESS_EVENT_AUTHENTICATION_FACTOR = 248, - PROP_ACCESS_EVENT_CREDENTIAL = 249, - PROP_ACCESS_EVENT_TIME = 250, - PROP_ACCESS_TRANSACTION_EVENTS = 251, - PROP_ACCOMPANIMENT = 252, - PROP_ACCOMPANIMENT_TIME = 253, - PROP_ACTIVATION_TIME = 254, - PROP_ACTIVE_AUTHENTICATION_POLICY = 255, - PROP_ASSIGNED_ACCESS_RIGHTS = 256, - PROP_AUTHENTICATION_FACTORS = 257, - PROP_AUTHENTICATION_POLICY_LIST = 258, - PROP_AUTHENTICATION_POLICY_NAMES = 259, - PROP_AUTHENTICATION_STATUS = 260, - PROP_AUTHORIZATION_MODE = 261, - PROP_BELONGS_TO = 262, - PROP_CREDENTIAL_DISABLE = 263, - PROP_CREDENTIAL_STATUS = 264, - PROP_CREDENTIALS = 265, - PROP_CREDENTIALS_IN_ZONE = 266, - PROP_DAYS_REMAINING = 267, - PROP_ENTRY_POINTS = 268, - PROP_EXIT_POINTS = 269, - PROP_EXPIRY_TIME = 270, - PROP_EXTENDED_TIME_ENABLE = 271, - PROP_FAILED_ATTEMPT_EVENTS = 272, - PROP_FAILED_ATTEMPTS = 273, - PROP_FAILED_ATTEMPTS_TIME = 274, - PROP_LAST_ACCESS_EVENT = 275, - PROP_LAST_ACCESS_POINT = 276, - PROP_LAST_CREDENTIAL_ADDED = 277, - PROP_LAST_CREDENTIAL_ADDED_TIME = 278, - PROP_LAST_CREDENTIAL_REMOVED = 279, - PROP_LAST_CREDENTIAL_REMOVED_TIME = 280, - PROP_LAST_USE_TIME = 281, - PROP_LOCKOUT = 282, - PROP_LOCKOUT_RELINQUISH_TIME = 283, - PROP_MASTER_EXEMPTION = 284, - PROP_MAX_FAILED_ATTEMPTS = 285, - PROP_MEMBERS = 286, - PROP_MUSTER_POINT = 287, - PROP_NEGATIVE_ACCESS_RULES = 288, - PROP_NUMBER_OF_AUTHENTICATION_POLICIES = 289, - PROP_OCCUPANCY_COUNT = 290, - PROP_OCCUPANCY_COUNT_ADJUST = 291, - PROP_OCCUPANCY_COUNT_ENABLE = 292, - PROP_OCCUPANCY_EXEMPTION = 293, - PROP_OCCUPANCY_LOWER_LIMIT = 294, - PROP_OCCUPANCY_LOWER_LIMIT_ENFORCED = 295, - PROP_OCCUPANCY_STATE = 296, - PROP_OCCUPANCY_UPPER_LIMIT = 297, - PROP_OCCUPANCY_UPPER_LIMIT_ENFORCED = 298, - PROP_PASSBACK_EXEMPTION = 299, - PROP_PASSBACK_MODE = 300, - PROP_PASSBACK_TIMEOUT = 301, - PROP_POSITIVE_ACCESS_RULES = 302, - PROP_REASON_FOR_DISABLE = 303, - PROP_SUPPORTED_FORMATS = 304, - PROP_SUPPORTED_FORMAT_CLASSES = 305, - PROP_THREAT_AUTHORITY = 306, - PROP_THREAT_LEVEL = 307, - PROP_TRACE_FLAG = 308, - PROP_TRANSACTION_NOTIFICATION_CLASS = 309, - PROP_USER_EXTERNAL_IDENTIFIER = 310, - PROP_USER_INFORMATION_REFERENCE = 311, - /* enumerations 312-316 are unassigned */ - PROP_USER_NAME = 317, - PROP_USER_TYPE = 318, - PROP_USES_REMAINING = 319, - PROP_ZONE_FROM = 320, - PROP_ZONE_TO = 321, - PROP_ACCESS_EVENT_TAG = 322, - PROP_GLOBAL_IDENTIFIER = 323, - /* enumerations 324-325 are unassigned */ - PROP_VERIFICATION_TIME = 326, - PROP_BASE_DEVICE_SECURITY_POLICY = 327, - PROP_DISTRIBUTION_KEY_REVISION = 328, - PROP_DO_NOT_HIDE = 329, - PROP_KEY_SETS = 330, - PROP_LAST_KEY_SERVER = 331, - PROP_NETWORK_ACCESS_SECURITY_POLICIES = 332, - PROP_PACKET_REORDER_TIME = 333, - PROP_SECURITY_PDU_TIMEOUT = 334, - PROP_SECURITY_TIME_WINDOW = 335, - PROP_SUPPORTED_SECURITY_ALGORITHM = 336, - PROP_UPDATE_KEY_SET_TIMEOUT = 337, - PROP_BACKUP_AND_RESTORE_STATE = 338, - PROP_BACKUP_PREPARATION_TIME = 339, - PROP_RESTORE_COMPLETION_TIME = 340, - PROP_RESTORE_PREPARATION_TIME = 341, - /* enumerations 342-344 are defined in Addendum 2008-w */ - PROP_BIT_MASK = 342, - PROP_BIT_TEXT = 343, - PROP_IS_UTC = 344, - PROP_GROUP_MEMBERS = 345, - PROP_GROUP_MEMBER_NAMES = 346, - PROP_MEMBER_STATUS_FLAGS = 347, - PROP_REQUESTED_UPDATE_INTERVAL = 348, - PROP_COVU_PERIOD = 349, - PROP_COVU_RECIPIENTS = 350, - PROP_EVENT_MESSAGE_TEXTS = 351, - /* enumerations 352-363 are defined in Addendum 2010-af */ - PROP_EVENT_MESSAGE_TEXTS_CONFIG = 352, - PROP_EVENT_DETECTION_ENABLE = 353, - PROP_EVENT_ALGORITHM_INHIBIT = 354, - PROP_EVENT_ALGORITHM_INHIBIT_REF = 355, - PROP_TIME_DELAY_NORMAL = 356, - PROP_RELIABILITY_EVALUATION_INHIBIT = 357, - PROP_FAULT_PARAMETERS = 358, - PROP_FAULT_TYPE = 359, - PROP_LOCAL_FORWARDING_ONLY = 360, - PROP_PROCESS_IDENTIFIER_FILTER = 361, - PROP_SUBSCRIBED_RECIPIENTS = 362, - PROP_PORT_FILTER = 363, - /* enumeration 364 is defined in Addendum 2010-ae */ - PROP_AUTHORIZATION_EXEMPTIONS = 364, - /* enumerations 365-370 are defined in Addendum 2010-aa */ - PROP_ALLOW_GROUP_DELAY_INHIBIT = 365, - PROP_CHANNEL_NUMBER = 366, - PROP_CONTROL_GROUPS = 367, - PROP_EXECUTION_DELAY = 368, - PROP_LAST_PRIORITY = 369, - PROP_WRITE_STATUS = 370, - /* enumeration 371 is defined in Addendum 2010-ao */ - PROP_PROPERTY_LIST = 371, - /* enumeration 372 is defined in Addendum 2010-ak */ - PROP_SERIAL_NUMBER = 372, - /* enumerations 373-386 are defined in Addendum 2010-i */ - PROP_BLINK_WARN_ENABLE = 373, - PROP_DEFAULT_FADE_TIME = 374, - PROP_DEFAULT_RAMP_RATE = 375, - PROP_DEFAULT_STEP_INCREMENT = 376, - PROP_EGRESS_TIME = 377, - PROP_IN_PROGRESS = 378, - PROP_INSTANTANEOUS_POWER = 379, - PROP_LIGHTING_COMMAND = 380, - PROP_LIGHTING_COMMAND_DEFAULT_PRIORITY = 381, - PROP_MAX_ACTUAL_VALUE = 382, - PROP_MIN_ACTUAL_VALUE = 383, - PROP_POWER = 384, - PROP_TRANSITION = 385, - PROP_EGRESS_ACTIVE = 386, - PROP_INTERFACE_VALUE = 387, - PROP_FAULT_HIGH_LIMIT = 388, - PROP_FAULT_LOW_LIMIT = 389, - PROP_LOW_DIFF_LIMIT = 390, - /* enumerations 391-392 are defined in Addendum 135-2012az */ - PROP_STRIKE_COUNT = 391, - PROP_TIME_OF_STRIKE_COUNT_RESET = 392, - /* enumerations 393-398 are defined in Addendum 135-2012ay */ - PROP_DEFAULT_TIMEOUT = 393, - PROP_INITIAL_TIMEOUT = 394, - PROP_LAST_STATE_CHANGE = 395, - PROP_STATE_CHANGE_VALUES = 396, - PROP_TIMER_RUNNING = 397, - PROP_TIMER_STATE = 398, - /* enumerations 399-427 are defined in Addendum 2012-ai */ - PROP_APDU_LENGTH = 399, - PROP_IP_ADDRESS = 400, - PROP_IP_DEFAULT_GATEWAY = 401, - PROP_IP_DHCP_ENABLE = 402, - PROP_IP_DHCP_LEASE_TIME = 403, - PROP_IP_DHCP_LEASE_TIME_REMAINING = 404, - PROP_IP_DHCP_SERVER = 405, - PROP_IP_DNS_SERVER = 406, - PROP_BACNET_IP_GLOBAL_ADDRESS = 407, - PROP_BACNET_IP_MODE = 408, - PROP_BACNET_IP_MULTICAST_ADDRESS = 409, - PROP_BACNET_IP_NAT_TRAVERSAL = 410, - PROP_IP_SUBNET_MASK = 411, - PROP_BACNET_IP_UDP_PORT = 412, - PROP_BBMD_ACCEPT_FD_REGISTRATIONS = 413, - PROP_BBMD_BROADCAST_DISTRIBUTION_TABLE = 414, - PROP_BBMD_FOREIGN_DEVICE_TABLE = 415, - PROP_CHANGES_PENDING = 416, - PROP_COMMAND = 417, - PROP_FD_BBMD_ADDRESS = 418, - PROP_FD_SUBSCRIPTION_LIFETIME = 419, - PROP_LINK_SPEED = 420, - PROP_LINK_SPEEDS = 421, - PROP_LINK_SPEED_AUTONEGOTIATE = 422, - PROP_MAC_ADDRESS = 423, - PROP_NETWORK_INTERFACE_NAME = 424, - PROP_NETWORK_NUMBER = 425, - PROP_NETWORK_NUMBER_QUALITY = 426, - PROP_NETWORK_TYPE = 427, - PROP_ROUTING_TABLE = 428, - PROP_VIRTUAL_MAC_ADDRESS_TABLE = 429, - - // Addendum-135-2012as - PROP_COMMAND_TIME_ARRAY = 430, - PROP_CURRENT_COMMAND_PRIORITY = 431, - PROP_LAST_COMMAND_TIME = 432, - PROP_VALUE_SOURCE = 433, - PROP_VALUE_SOURCE_ARRAY = 434, - PROP_BACNET_IPV6_MODE = 435, - PROP_IPV6_ADDRESS = 436, - PROP_IPV6_PREFIX_LENGTH = 437, - PROP_BACNET_IPV6_UDP_PORT = 438, - PROP_IPV6_DEFAULT_GATEWAY = 439, - PROP_BACNET_IPV6_MULTICAST_ADDRESS = 440, - PROP_IPV6_DNS_SERVER = 441, - PROP_IPV6_AUTO_ADDRESSING_ENABLE = 442, - PROP_IPV6_DHCP_LEASE_TIME = 443, - PROP_IPV6_DHCP_LEASE_TIME_REMAINING = 444, - PROP_IPV6_DHCP_SERVER = 445, - PROP_IPV6_ZONE_INDEX = 446, - PROP_ASSIGNED_LANDING_CALLS = 447, - PROP_CAR_ASSIGNED_DIRECTION = 448, - PROP_CAR_DOOR_COMMAND = 449, - PROP_CAR_DOOR_STATUS = 450, - PROP_CAR_DOOR_TEXT = 451, - PROP_CAR_DOOR_ZONE = 452, - PROP_CAR_DRIVE_STATUS = 453, - PROP_CAR_LOAD = 454, - PROP_CAR_LOAD_UNITS = 455, - PROP_CAR_MODE = 456, - PROP_CAR_MOVING_DIRECTION = 457, - PROP_CAR_POSITION = 458, - PROP_ELEVATOR_GROUP = 459, - PROP_ENERGY_METER = 460, - PROP_ENERGY_METER_REF = 461, - PROP_ESCALATOR_MODE = 462, - PROP_FAULT_SIGNALS = 463, - PROP_FLOOR_TEXT = 464, - PROP_GROUP_ID = 465, - /* value 466 is unassigned */ - PROP_GROUP_MODE = 467, - PROP_HIGHER_DECK = 468, - PROP_INSTALLATION_ID = 469, - PROP_LANDING_CALLS = 470, - PROP_LANDING_CALL_CONTROL = 471, - PROP_LANDING_DOOR_STATUS = 472, - PROP_LOWER_DECK = 473, - PROP_MACHINE_ROOM_ID = 474, - PROP_MAKING_CAR_CALL = 475, - PROP_NEXT_STOPPING_FLOOR = 476, - PROP_OPERATION_DIRECTION = 477, - PROP_PASSENGER_ALARM = 478, - PROP_POWER_MODE = 479, - PROP_REGISTERED_CAR_CALL = 480, - PROP_ACTIVE_COV_MULTIPLE_SUBSCRIPTIONS = 481, - PROP_PROTOCOL_LEVEL = 482, - PROP_REFERENCE_PORT = 483, - PROP_DEPLOYED_PROFILE_LOCATION = 484, - PROP_PROFILE_LOCATION = 485, - PROP_TAGS = 486, - PROP_SUBORDINATE_NODE_TYPES = 487, - PROP_SUBORDINATE_TAGS = 488, - PROP_SUBORDINATE_RELATIONSHIPS = 489, - PROP_DEFAULT_SUBORDINATE_RELATIONSHIP = 490, - PROP_REPRESENTS = 491, - PROP_DEFAULT_PRESENT_VALUE = 492, - PROP_PRESENT_STAGE = 493, - PROP_STAGES = 494, - PROP_STAGE_NAMES = 495, - PROP_TARGET_REFERENCES = 496, - PROP_AUDIT_SOURCE_LEVEL = 497, - PROP_AUDIT_LEVEL = 498, - PROP_AUDIT_NOTIFICATION_RECIPIENT = 499, - PROP_AUDIT_PRIORITY_FILTER = 500, - PROP_AUDITABLE_OPERATIONS = 501, - PROP_DELETE_ON_FORWARD = 502, - PROP_MAXIMUM_SEND_DELAY = 503, - PROP_MONITORED_OBJECTS = 504, - PROP_SEND_NOW = 505, - PROP_FLOOR_NUMBER = 506, - PROP_DEVICE_UUID = 507, - /* enumerations 508-511 are defined in Addendum 2020cc */ - PROP_ADDITIONAL_REFERENCE_PORTS = 508, - PROP_CERTIFICATE_SIGNING_REQUEST_FILE = 509, - PROP_COMMAND_VALIDATION_RESULT = 510, - PROP_ISSUER_CERTIFICATE_FILES = 511, - /* The special property identifiers all, optional, and required */ - /* are reserved for use in the ReadPropertyConditional and */ - /* ReadPropertyMultiple services or services not defined in this standard. - */ - /* Enumerated values 0-511 are reserved for definition by ASHRAE. */ - /* Enumerated values 512-4194303 may be used by others subject to the */ - /* procedures and constraints described in Clause 23. */ - PROP_PROPRIETARY_RANGE_MIN = 512, - PROP_PROPRIETARY_RANGE_MAX = 4194303, - /* enumerations 4194304-4194327 are defined in Addendum 2020cc */ - PROP_MAX_BVLC_LENGTH_ACCEPTED = 4194304, - PROP_MAX_NPDU_LENGTH_ACCEPTED = 4194305, - PROP_OPERATIONAL_CERTIFICATE_FILE = 4194305, - PROP_CURRENT_HEALTH = 4194307, - PROP_SC_CONNECT_WAIT_TIMEOUT = 4194308, - PROP_SC_DIRECT_CONNECT_ACCEPT_ENABLE = 4194309, - PROP_SC_DIRECT_CONNECT_ACCEPT_URIS = 4194310, - PROP_SC_DIRECT_CONNECT_BINDING = 4194311, - PROP_SC_DIRECT_CONNECT_CONNECTION_STATUS = 4194312, - PROP_SC_DIRECT_CONNECT_INITIATE_ENABLE = 4194313, - PROP_SC_DISCONNECT_WAIT_TIMEOUT = 4194314, - PROP_SC_FAILED_CONNECTION_REQUESTS = 4194315, - PROP_SC_FAILOVER_HUB_CONNECTION_STATUS = 4194316, - PROP_SC_FAILOVER_HUB_URI = 4194317, - PROP_SC_HUB_CONNECTOR_STATE = 4194318, - PROP_SC_HUB_FUNCTION_ACCEPT_URIS = 4194319, - PROP_SC_HUB_FUNCTION_BINDING = 4194320, - PROP_SC_HUB_FUNCTION_CONNECTION_STATUS = 4194321, - PROP_SC_HUB_FUNCTION_ENABLE = 4194322, - PROP_SC_HEARTBEAT_TIMEOUT = 4194323, - PROP_SC_PRIMARY_HUB_CONNECTION_STATUS = 4194324, - PROP_SC_PRIMARY_HUB_URI = 4194325, - PROP_SC_MAXIMUM_RECONNECT_TIME = 4194326, - PROP_SC_MINIMUM_RECONNECT_TIME = 4194327, - /* enumerations 4194328-4194332 are defined in Addendum 2020ca */ - PROP_COLOR_OVERRIDE = 4194328, - PROP_COLOR_REFERENCE = 4194329, - PROP_DEFAULT_COLOR = 4194330, - PROP_DEFAULT_COLOR_TEMPERATURE = 4194331, - PROP_OVERRIDE_COLOR_REFERENCE = 4194332, - PROP_COLOR_COMMAND = 4194334, - PROP_HIGH_END_TRIM = 4194335, - PROP_LOW_END_TRIM = 4194336, - PROP_TRIM_FADE_TIME = 4194337, - - /* The special property identifiers all, optional, and required */ - /* are reserved for use in the ReadPropertyConditional and */ - /* ReadPropertyMultiple services or services not defined in this standard. */ - /* Enumerated values 0-511 are reserved for definition by ASHRAE. */ - /* Enumerated values 512-4194303 may be used by others subject to the */ - /* procedures and constraints described in Clause 23. */ - /* Enumerated values 4194303-16777215 are reserved - for definition by ASHRAE. */ - /* do the max range inside of enum so that - compilers will allocate adequate sized datatype for enum - which is used to store decoding */ - MAX_BACNET_PROPERTY_ID = 16777215 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPropertyReference.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPropertyReference.cs deleted file mode 100644 index 3f463fd..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPropertyReference.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace System.IO.BACnet; - -public struct BacnetPropertyReference -{ - public uint propertyIdentifier; - public uint propertyArrayIndex; /* optional */ - - public BacnetPropertyReference(uint id, uint arrayIndex) - { - propertyIdentifier = id; - propertyArrayIndex = arrayIndex; - } - - public BacnetPropertyIds GetPropertyId() - { - return (BacnetPropertyIds)propertyIdentifier; - } - - public override string ToString() - { - return $"{GetPropertyId()}"; - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPropertyState.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPropertyState.cs deleted file mode 100644 index 76dce11..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPropertyState.cs +++ /dev/null @@ -1,48 +0,0 @@ -namespace System.IO.BACnet; - -public struct BacnetPropertyState -{ - public enum BacnetPropertyStateTypes - { - BOOLEAN_VALUE, - BINARY_VALUE, - EVENT_TYPE, - POLARITY, - PROGRAM_CHANGE, - PROGRAM_STATE, - REASON_FOR_HALT, - RELIABILITY, - STATE, - SYSTEM_STATUS, - UNITS, - UNSIGNED_VALUE, - LIFE_SAFETY_MODE, - LIFE_SAFETY_STATE - } - - public struct State - { - public bool boolean_value; - public BacnetBinaryPv binaryValue; - public BacnetEventTypes eventType; - public BacnetPolarity polarity; - public BacnetProgramRequest programChange; - public BacnetProgramState programState; - public BacnetProgramError programError; - public BacnetReliability reliability; - public BacnetEventStates state; - public BacnetDeviceStatus systemStatus; - public BacnetUnitsId units; - public uint unsignedValue; - public BacnetLifeSafetyModes lifeSafetyMode; - public BacnetLifeSafetyStates lifeSafetyState; - } - - public BacnetPropertyStateTypes tag; - public State state; - - public override string ToString() - { - return $"{tag}:{state}"; - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPropertyValue.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPropertyValue.cs deleted file mode 100644 index 6b046cd..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPropertyValue.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace System.IO.BACnet; - -public struct BacnetPropertyValue -{ - public BacnetPropertyReference property; - public IList value; - public byte priority; - - public override string ToString() - { - return property.ToString(); - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPtpDisconnectReasons.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPtpDisconnectReasons.cs deleted file mode 100644 index 068f3df..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPtpDisconnectReasons.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetPtpDisconnectReasons : byte -{ - PTP_DISCONNECT_NO_MORE_DATA = 0, - PTP_DISCONNECT_PREEMPTED = 1, - PTP_DISCONNECT_INVALID_PASSWORD = 2, - PTP_DISCONNECT_OTHER = 3, -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPtpFrameTypes.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPtpFrameTypes.cs deleted file mode 100644 index c4158d4..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetPtpFrameTypes.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetPtpFrameTypes : byte -{ - FRAME_TYPE_HEARTBEAT_XOFF = 0, - FRAME_TYPE_HEARTBEAT_XON = 1, - FRAME_TYPE_DATA0 = 2, - FRAME_TYPE_DATA1 = 3, - FRAME_TYPE_DATA_ACK0_XOFF = 4, - FRAME_TYPE_DATA_ACK1_XOFF = 5, - FRAME_TYPE_DATA_ACK0_XON = 6, - FRAME_TYPE_DATA_ACK1_XON = 7, - FRAME_TYPE_DATA_NAK0_XOFF = 8, - FRAME_TYPE_DATA_NAK1_XOFF = 9, - FRAME_TYPE_DATA_NAK0_XON = 0x0A, - FRAME_TYPE_DATA_NAK1_XON = 0x0B, - FRAME_TYPE_CONNECT_REQUEST = 0x0C, - FRAME_TYPE_CONNECT_RESPONSE = 0x0D, - FRAME_TYPE_DISCONNECT_REQUEST = 0x0E, - FRAME_TYPE_DISCONNECT_RESPONSE = 0x0F, - FRAME_TYPE_TEST_REQUEST = 0x14, - FRAME_TYPE_TEST_RESPONSE = 0x15, - FRAME_TYPE_GREETING = 0xFF //special invention -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetReadAccessResult.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetReadAccessResult.cs deleted file mode 100644 index d55b009..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetReadAccessResult.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace System.IO.BACnet; - -public struct BacnetReadAccessResult -{ - public BacnetObjectId objectIdentifier; - public IList values; - - public BacnetReadAccessResult(BacnetObjectId objectIdentifier, IList values) - { - this.objectIdentifier = objectIdentifier; - this.values = values; - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetReadAccessSpecification.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetReadAccessSpecification.cs deleted file mode 100644 index 06cc690..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetReadAccessSpecification.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace System.IO.BACnet; - -public struct BacnetReadAccessSpecification -{ - public BacnetObjectId objectIdentifier; - public IList propertyReferences; - - public BacnetReadAccessSpecification(BacnetObjectId objectIdentifier, IList propertyReferences) - { - this.objectIdentifier = objectIdentifier; - this.propertyReferences = propertyReferences; - } - - public static object Parse(string value) - { - var ret = new BacnetReadAccessSpecification(); - if (string.IsNullOrEmpty(value)) return ret; - var tmp = value.Split(':'); - if (tmp.Length < 2) return ret; - ret.objectIdentifier.type = (BacnetObjectTypes)Enum.Parse(typeof(BacnetObjectTypes), tmp[0]); - ret.objectIdentifier.instance = uint.Parse(tmp[1]); - var refs = new List(); - for (var i = 2; i < tmp.Length; i++) - { - refs.Add(new BacnetPropertyReference - { - propertyArrayIndex = ASN1.BACNET_ARRAY_ALL, - propertyIdentifier = (uint)(BacnetPropertyIds)Enum.Parse(typeof(BacnetPropertyIds), tmp[i]) - }); - } - ret.propertyReferences = refs; - return ret; - } - - public override string ToString() - { - return propertyReferences.Aggregate(objectIdentifier.ToString(), (current, r) => - $"{current}:{(BacnetPropertyIds)r.propertyIdentifier}"); - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetReadRangeRequestTypes.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetReadRangeRequestTypes.cs deleted file mode 100644 index 1d9ced2..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetReadRangeRequestTypes.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace System.IO.BACnet.Serialize; - -public enum BacnetReadRangeRequestTypes -{ - RR_BY_POSITION = 1, - RR_BY_SEQUENCE = 2, - RR_BY_TIME = 4, - RR_READ_ALL = 8 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetReinitializedStates.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetReinitializedStates.cs deleted file mode 100644 index e146109..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetReinitializedStates.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetReinitializedStates -{ - BACNET_REINIT_COLDSTART = 0, - BACNET_REINIT_WARMSTART = 1, - BACNET_REINIT_STARTBACKUP = 2, - BACNET_REINIT_ENDBACKUP = 3, - BACNET_REINIT_STARTRESTORE = 4, - BACNET_REINIT_ENDRESTORE = 5, - BACNET_REINIT_ABORTRESTORE = 6, - BACNET_REINIT_ACTIVATE_CHANGES = 7, - BACNET_REINIT_IDLE = 255 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetRejectReason.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetRejectReason.cs deleted file mode 100644 index bb2a9e6..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetRejectReason.cs +++ /dev/null @@ -1,84 +0,0 @@ -namespace System.IO.BACnet; - -/// -/// Possible reason for rejecting the PDU. -/// -/// -/// Enumerated values 0-63 are reserved for definition by ASHRAE. -/// Enumerated values 64-255 may be used by others. -/// -public enum BacnetRejectReason : byte -{ - /// - /// Generated in response to a confirmed request APDU that contains a syntax error - /// for which an error code has not been explicitly defined. - /// - OTHER = 0, - - /// - /// A buffer capacity has been exceeded. - /// - BUFFER_OVERFLOW = 1, - - /// - /// Generated in response to a confirmed request APDU that omits a conditional - /// service argument that should be present or contains a conditional service - /// argument that should not be present. This condition could also elicit - /// a Reject PDU with a Reject Reason of . - /// - INCONSISTENT_PARAMETERS = 2, - - /// - /// Generated in response to a confirmed request APDU in which the encoding - /// of one or more of the service parameters does not follow the correct - /// type specification. This condition could also elicit a Reject PDU - /// with a Reject Reason of . - /// - INVALID_PARAMETER_DATA_TYPE = 3, - - /// - /// While parsing a message, an invalid tag was encountered. Since an invalid tag - /// could confuse the parsing logic, any of the following Reject Reasons may also - /// be generated in response to a confirmed request containing an invalid tag: - /// - /// - /// - /// - /// - /// - /// - INVALID_TAG = 4, - - /// - /// Generated in response to a confirmed request APDU that is missing at least one - /// mandatory service argument. This condition could also elicit a Reject PDU with - /// a Reject Reason of . - /// - MISSING_REQUIRED_PARAMETER = 5, - - /// - /// Generated in response to a confirmed request APDU that conveys a parameter - /// whose value is outside the range defined for this service. - /// - PARAMETER_OUT_OF_RANGE = 6, - - /// - /// Generated in response to a confirmed request APDU in which the total number - /// of service arguments is greater than specified for the service. This condition - /// could also elicit a Reject PDU with a Reject Reason of . - /// - TOO_MANY_ARGUMENTS = 7, - - /// - /// Generated in response to a confirmed request APDU in which one or more of - /// the service parameters is decoded as an enumeration that is not defined by - /// the type specification of this parameter. - /// - UNDEFINED_ENUMERATION = 8, - - /// - /// Generated in response to a confirmed request APDU in which the Service Choice - /// field specifies an unknown or unsupported service - /// - RECOGNIZED_SERVICE = 9 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetReliability.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetReliability.cs deleted file mode 100644 index 6a4ae1b..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetReliability.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetReliability : uint -{ - RELIABILITY_NO_FAULT_DETECTED = 0, - RELIABILITY_NO_SENSOR = 1, - RELIABILITY_OVER_RANGE = 2, - RELIABILITY_UNDER_RANGE = 3, - RELIABILITY_OPEN_LOOP = 4, - RELIABILITY_SHORTED_LOOP = 5, - RELIABILITY_NO_OUTPUT = 6, - RELIABILITY_UNRELIABLE_OTHER = 7, - RELIABILITY_PROCESS_ERROR = 8, - RELIABILITY_MULTI_STATE_FAULT = 9, - RELIABILITY_CONFIGURATION_ERROR = 10, - RELIABILITY_MEMBER_FAULT = 11, - RELIABILITY_COMMUNICATION_FAILURE = 12, - RELIABILITY_TRIPPED = 13, - /* Enumerated values 0-63 are reserved for definition by ASHRAE. */ - /* Enumerated values 64-65535 may be used by others subject to */ - /* the procedures and constraints described in Clause 23. */ - /* do the max range inside of enum so that - compilers will allocate adequate sized datatype for enum - which is used to store decoding */ - RELIABILITY_PROPRIETARY_MIN = 64, - RELIABILITY_PROPRIETARY_MAX = 65535 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetRestartReason.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetRestartReason.cs deleted file mode 100644 index c2f7950..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetRestartReason.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace System.IO.BACnet; - -// From Loren Van Spronsen csharp-bacnet -public enum BacnetRestartReason -{ - UNKNOWN = 0, - COLD_START = 1, - WARM_START = 2, - DETECTED_POWER_LOST = 3, - DETECTED_POWER_OFF = 4, - HARDWARE_WATCHDOG = 5, - SOFTWARE_WATCHDOG = 6, - SUSPENDED = 7 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetResultFlags.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetResultFlags.cs deleted file mode 100644 index 31fd278..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetResultFlags.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace System.IO.BACnet; - -[Flags] -public enum BacnetResultFlags -{ - NONE = 0, - FIRST_ITEM = 1, - LAST_ITEM = 2, - MORE_ITEMS = 4, -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetSegmentations.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetSegmentations.cs deleted file mode 100644 index 9562c1e..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetSegmentations.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetSegmentations -{ - SEGMENTATION_BOTH = 0, - SEGMENTATION_TRANSMIT = 1, - SEGMENTATION_RECEIVE = 2, - SEGMENTATION_NONE = 3, -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetServicesSupported.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetServicesSupported.cs deleted file mode 100644 index b7d1e94..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetServicesSupported.cs +++ /dev/null @@ -1,62 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetServicesSupported -{ - /* Alarm and Event Services */ - SERVICE_SUPPORTED_ACKNOWLEDGE_ALARM = 0, - SERVICE_SUPPORTED_CONFIRMED_COV_NOTIFICATION = 1, - SERVICE_SUPPORTED_CONFIRMED_EVENT_NOTIFICATION = 2, - SERVICE_SUPPORTED_GET_ALARM_SUMMARY = 3, - SERVICE_SUPPORTED_GET_ENROLLMENT_SUMMARY = 4, - SERVICE_SUPPORTED_GET_EVENT_INFORMATION = 39, - SERVICE_SUPPORTED_SUBSCRIBE_COV = 5, - SERVICE_SUPPORTED_SUBSCRIBE_COV_PROPERTY = 38, - SERVICE_SUPPORTED_LIFE_SAFETY_OPERATION = 37, - SERVICE_SUPPORTED_CONFIRMED_AUDIT_NOTIFICATION = 44, - SERVICE_SUPPORTED_AUDIT_LOG_QUERY = 45, - /* File Access Services */ - SERVICE_SUPPORTED_ATOMIC_READ_FILE = 6, - SERVICE_SUPPORTED_ATOMIC_WRITE_FILE = 7, - /* Object Access Services */ - SERVICE_SUPPORTED_ADD_LIST_ELEMENT = 8, - SERVICE_SUPPORTED_REMOVE_LIST_ELEMENT = 9, - SERVICE_SUPPORTED_CREATE_OBJECT = 10, - SERVICE_SUPPORTED_DELETE_OBJECT = 11, - SERVICE_SUPPORTED_READ_PROPERTY = 12, - SERVICE_SUPPORTED_READ_PROP_CONDITIONAL = 13, - SERVICE_SUPPORTED_READ_PROP_MULTIPLE = 14, - SERVICE_SUPPORTED_READ_RANGE = 35, - SERVICE_SUPPORTED_WRITE_PROPERTY = 15, - SERVICE_SUPPORTED_WRITE_PROP_MULTIPLE = 16, - SERVICE_SUPPORTED_WRITE_GROUP = 40, - /* Remote Device Management Services */ - SERVICE_SUPPORTED_DEVICE_COMMUNICATION_CONTROL = 17, - SERVICE_SUPPORTED_PRIVATE_TRANSFER = 18, - SERVICE_SUPPORTED_TEXT_MESSAGE = 19, - SERVICE_SUPPORTED_REINITIALIZE_DEVICE = 20, - SERVICE_SUPPORTED_WHO_AM_I = 47, - SERVICE_SUPPORTED_YOU_ARE = 48, - /* Virtual Terminal Services */ - SERVICE_SUPPORTED_VT_OPEN = 21, - SERVICE_SUPPORTED_VT_CLOSE = 22, - SERVICE_SUPPORTED_VT_DATA = 23, - /* Security Services */ - SERVICE_SUPPORTED_AUTHENTICATE = 24, - SERVICE_SUPPORTED_REQUEST_KEY = 25, - /* Unconfirmed Services */ - SERVICE_SUPPORTED_I_AM = 26, - SERVICE_SUPPORTED_I_HAVE = 27, - SERVICE_SUPPORTED_UNCONFIRMED_COV_NOTIFICATION = 28, - SERVICE_SUPPORTED_UNCONFIRMED_EVENT_NOTIFICATION = 29, - SERVICE_SUPPORTED_UNCONFIRMED_PRIVATE_TRANSFER = 30, - SERVICE_SUPPORTED_UNCONFIRMED_TEXT_MESSAGE = 31, - SERVICE_SUPPORTED_TIME_SYNCHRONIZATION = 32, - SERVICE_SUPPORTED_UTC_TIME_SYNCHRONIZATION = 36, - SERVICE_SUPPORTED_WHO_HAS = 33, - SERVICE_SUPPORTED_WHO_IS = 34, - SERVICE_SUPPORTED_UNCONFIRMED_AUDIT_NOTIFICATION = 46, - /* Other services to be added as they are defined. */ - /* All values in this production are reserved */ - /* for definition by ASHRAE. */ - MAX_BACNET_SERVICES_SUPPORTED = 47 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetStatusFlags.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetStatusFlags.cs deleted file mode 100644 index 412e2b7..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetStatusFlags.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace System.IO.BACnet; - -[Flags] -public enum BacnetStatusFlags -{ - STATUS_FLAG_IN_ALARM = 1, - STATUS_FLAG_FAULT = 2, - STATUS_FLAG_OVERRIDDEN = 4, - STATUS_FLAG_OUT_OF_SERVICE = 8 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetTimestampTags.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetTimestampTags.cs deleted file mode 100644 index dcc886f..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetTimestampTags.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetTimestampTags -{ - TIME_STAMP_NONE = -1, - TIME_STAMP_TIME = 0, - TIME_STAMP_SEQUENCE = 1, - TIME_STAMP_DATETIME = 2 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetTrendLogValueType.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetTrendLogValueType.cs deleted file mode 100644 index c26fabe..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetTrendLogValueType.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetTrendLogValueType : byte -{ - // Copyright (C) 2009 Peter Mc Shane in Steve Karg Stack, trendlog.h - // Thank's to it's encoding sample, very usefull for this decoding work - TL_TYPE_STATUS = 0, - TL_TYPE_BOOL = 1, - TL_TYPE_REAL = 2, - TL_TYPE_ENUM = 3, - TL_TYPE_UNSIGN = 4, - TL_TYPE_SIGN = 5, - TL_TYPE_BITS = 6, - TL_TYPE_NULL = 7, - TL_TYPE_ERROR = 8, - TL_TYPE_DELTA = 9, - TL_TYPE_ANY = 10 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetUnconfirmedServices.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetUnconfirmedServices.cs deleted file mode 100644 index cf75c13..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetUnconfirmedServices.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetUnconfirmedServices : byte -{ - SERVICE_UNCONFIRMED_I_AM = 0, - SERVICE_UNCONFIRMED_I_HAVE = 1, - SERVICE_UNCONFIRMED_COV_NOTIFICATION = 2, - SERVICE_UNCONFIRMED_EVENT_NOTIFICATION = 3, - SERVICE_UNCONFIRMED_PRIVATE_TRANSFER = 4, - SERVICE_UNCONFIRMED_TEXT_MESSAGE = 5, - SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION = 6, - SERVICE_UNCONFIRMED_WHO_HAS = 7, - SERVICE_UNCONFIRMED_WHO_IS = 8, - SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION = 9, - /* addendum 2010-aa */ - SERVICE_UNCONFIRMED_WRITE_GROUP = 10, - /* addendum 2012-aq */ - SERVICE_UNCONFIRMED_COV_NOTIFICATION_MULTIPLE = 11, - /* addendum 2016-bi */ - SERVICE_UNCONFIRMED_AUDIT_NOTIFICATION = 12, - /* addendum 2016-bz */ - SERVICE_UNCONFIRMED_WHO_AM_I = 13, - SERVICE_UNCONFIRMED_YOU_ARE = 14, - /* Other services to be added as they are defined. */ - /* All choice values in this production are reserved */ - /* for definition by ASHRAE. */ - /* Proprietary extensions are made by using the */ - /* UnconfirmedPrivateTransfer service. See Clause 23. */ - MAX_BACNET_UNCONFIRMED_SERVICE = 15 -}; diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetUnitsId.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetUnitsId.cs deleted file mode 100644 index a7857bf..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetUnitsId.cs +++ /dev/null @@ -1,311 +0,0 @@ -namespace System.IO.BACnet; - -// Add FC : from Karg's Stack -public enum BacnetUnitsId -{ - UNITS_METERS_PER_SECOND_PER_SECOND = 166, - /* Area */ - UNITS_SQUARE_METERS = 0, - UNITS_SQUARE_CENTIMETERS = 116, - UNITS_SQUARE_FEET = 1, - UNITS_SQUARE_INCHES = 115, - /* Currency */ - UNITS_CURRENCY1 = 105, - UNITS_CURRENCY2 = 106, - UNITS_CURRENCY3 = 107, - UNITS_CURRENCY4 = 108, - UNITS_CURRENCY5 = 109, - UNITS_CURRENCY6 = 110, - UNITS_CURRENCY7 = 111, - UNITS_CURRENCY8 = 112, - UNITS_CURRENCY9 = 113, - UNITS_CURRENCY10 = 114, - /* Electrical */ - UNITS_MILLIAMPERES = 2, - UNITS_AMPERES = 3, - UNITS_AMPERES_PER_METER = 167, - UNITS_AMPERES_PER_SQUARE_METER = 168, - UNITS_AMPERE_SQUARE_METERS = 169, - UNITS_DECIBELS = 199, - UNITS_DECIBELS_MILLIVOLT = 200, - UNITS_DECIBELS_VOLT = 201, - UNITS_FARADS = 170, - UNITS_HENRYS = 171, - UNITS_OHMS = 4, - UNITS_OHM_METERS = 172, - UNITS_MILLIOHMS = 145, - UNITS_KILOHMS = 122, - UNITS_MEGOHMS = 123, - UNITS_MICROSIEMENS = 190, - UNITS_MILLISIEMENS = 202, - UNITS_SIEMENS = 173, /* 1 mho equals 1 siemens */ - UNITS_SIEMENS_PER_METER = 174, - UNITS_TESLAS = 175, - UNITS_VOLTS = 5, - UNITS_MILLIVOLTS = 124, - UNITS_KILOVOLTS = 6, - UNITS_MEGAVOLTS = 7, - UNITS_VOLT_AMPERES = 8, - UNITS_KILOVOLT_AMPERES = 9, - UNITS_MEGAVOLT_AMPERES = 10, - UNITS_VOLT_AMPERES_REACTIVE = 11, - UNITS_KILOVOLT_AMPERES_REACTIVE = 12, - UNITS_MEGAVOLT_AMPERES_REACTIVE = 13, - UNITS_VOLTS_PER_DEGREE_KELVIN = 176, - UNITS_VOLTS_PER_METER = 177, - UNITS_DEGREES_PHASE = 14, - UNITS_POWER_FACTOR = 15, - UNITS_WEBERS = 178, - /* Energy */ - UNITS_JOULES = 16, - UNITS_KILOJOULES = 17, - UNITS_KILOJOULES_PER_KILOGRAM = 125, - UNITS_MEGAJOULES = 126, - UNITS_WATT_HOURS = 18, - UNITS_KILOWATT_HOURS = 19, - UNITS_MEGAWATT_HOURS = 146, - UNITS_WATT_HOURS_REACTIVE = 203, - UNITS_KILOWATT_HOURS_REACTIVE = 204, - UNITS_MEGAWATT_HOURS_REACTIVE = 205, - UNITS_BTUS = 20, - UNITS_KILO_BTUS = 147, - UNITS_MEGA_BTUS = 148, - UNITS_THERMS = 21, - UNITS_TON_HOURS = 22, - /* Enthalpy */ - UNITS_JOULES_PER_KILOGRAM_DRY_AIR = 23, - UNITS_KILOJOULES_PER_KILOGRAM_DRY_AIR = 149, - UNITS_MEGAJOULES_PER_KILOGRAM_DRY_AIR = 150, - UNITS_BTUS_PER_POUND_DRY_AIR = 24, - UNITS_BTUS_PER_POUND = 117, - /* Entropy */ - UNITS_JOULES_PER_DEGREE_KELVIN = 127, - UNITS_KILOJOULES_PER_DEGREE_KELVIN = 151, - UNITS_MEGAJOULES_PER_DEGREE_KELVIN = 152, - UNITS_JOULES_PER_KILOGRAM_DEGREE_KELVIN = 128, - /* Force */ - UNITS_NEWTON = 153, - /* Frequency */ - UNITS_CYCLES_PER_HOUR = 25, - UNITS_CYCLES_PER_MINUTE = 26, - UNITS_HERTZ = 27, - UNITS_KILOHERTZ = 129, - UNITS_MEGAHERTZ = 130, - UNITS_PER_HOUR = 131, - /* Humidity */ - UNITS_GRAMS_OF_WATER_PER_KILOGRAM_DRY_AIR = 28, - UNITS_PERCENT_RELATIVE_HUMIDITY = 29, - /* Length */ - UNITS_MICROMETERS = 194, - UNITS_MILLIMETERS = 30, - UNITS_CENTIMETERS = 118, - UNITS_KILOMETERS = 193, - UNITS_METERS = 31, - UNITS_INCHES = 32, - UNITS_FEET = 33, - /* Light */ - UNITS_CANDELAS = 179, - UNITS_CANDELAS_PER_SQUARE_METER = 180, - UNITS_WATTS_PER_SQUARE_FOOT = 34, - UNITS_WATTS_PER_SQUARE_METER = 35, - UNITS_LUMENS = 36, - UNITS_LUXES = 37, - UNITS_FOOT_CANDLES = 38, - /* Mass */ - UNITS_MILLIGRAMS = 196, - UNITS_GRAMS = 195, - UNITS_KILOGRAMS = 39, - UNITS_POUNDS_MASS = 40, - UNITS_TONS = 41, - /* Mass Flow */ - UNITS_GRAMS_PER_SECOND = 154, - UNITS_GRAMS_PER_MINUTE = 155, - UNITS_KILOGRAMS_PER_SECOND = 42, - UNITS_KILOGRAMS_PER_MINUTE = 43, - UNITS_KILOGRAMS_PER_HOUR = 44, - UNITS_POUNDS_MASS_PER_SECOND = 119, - UNITS_POUNDS_MASS_PER_MINUTE = 45, - UNITS_POUNDS_MASS_PER_HOUR = 46, - UNITS_TONS_PER_HOUR = 156, - /* Power */ - UNITS_MILLIWATTS = 132, - UNITS_WATTS = 47, - UNITS_KILOWATTS = 48, - UNITS_MEGAWATTS = 49, - UNITS_BTUS_PER_HOUR = 50, - UNITS_KILO_BTUS_PER_HOUR = 157, - UNITS_HORSEPOWER = 51, - UNITS_TONS_REFRIGERATION = 52, - /* Pressure */ - UNITS_PASCALS = 53, - UNITS_HECTOPASCALS = 133, - UNITS_KILOPASCALS = 54, - UNITS_MILLIBARS = 134, - UNITS_BARS = 55, - UNITS_POUNDS_FORCE_PER_SQUARE_INCH = 56, - UNITS_MILLIMETERS_OF_WATER = 206, - UNITS_CENTIMETERS_OF_WATER = 57, - UNITS_INCHES_OF_WATER = 58, - UNITS_MILLIMETERS_OF_MERCURY = 59, - UNITS_CENTIMETERS_OF_MERCURY = 60, - UNITS_INCHES_OF_MERCURY = 61, - /* Temperature */ - UNITS_DEGREES_CELSIUS = 62, - UNITS_DEGREES_KELVIN = 63, - UNITS_DEGREES_KELVIN_PER_HOUR = 181, - UNITS_DEGREES_KELVIN_PER_MINUTE = 182, - UNITS_DEGREES_FAHRENHEIT = 64, - UNITS_DEGREE_DAYS_CELSIUS = 65, - UNITS_DEGREE_DAYS_FAHRENHEIT = 66, - UNITS_DELTA_DEGREES_FAHRENHEIT = 120, - UNITS_DELTA_DEGREES_KELVIN = 121, - /* Time */ - UNITS_YEARS = 67, - UNITS_MONTHS = 68, - UNITS_WEEKS = 69, - UNITS_DAYS = 70, - UNITS_HOURS = 71, - UNITS_MINUTES = 72, - UNITS_SECONDS = 73, - UNITS_HUNDREDTHS_SECONDS = 158, - UNITS_MILLISECONDS = 159, - /* Torque */ - UNITS_NEWTON_METERS = 160, - /* Velocity */ - UNITS_MILLIMETERS_PER_SECOND = 161, - UNITS_MILLIMETERS_PER_MINUTE = 162, - UNITS_METERS_PER_SECOND = 74, - UNITS_METERS_PER_MINUTE = 163, - UNITS_METERS_PER_HOUR = 164, - UNITS_KILOMETERS_PER_HOUR = 75, - UNITS_FEET_PER_SECOND = 76, - UNITS_FEET_PER_MINUTE = 77, - UNITS_MILES_PER_HOUR = 78, - /* Volume */ - UNITS_CUBIC_FEET = 79, - UNITS_CUBIC_METERS = 80, - UNITS_IMPERIAL_GALLONS = 81, - UNITS_MILLILITERS = 197, - UNITS_LITERS = 82, - UNITS_US_GALLONS = 83, - /* Volumetric Flow */ - UNITS_CUBIC_FEET_PER_SECOND = 142, - UNITS_CUBIC_FEET_PER_MINUTE = 84, - // One unit in Addendum 135-2012bg - UNITS_MILLION_CUBIC_FEET_PER_MINUTE = 254, - UNITS_CUBIC_FEET_PER_HOUR = 191, - // five units in Addendum 135-2012bg - UNITS_STANDARD_CUBIC_FEET_PER_DAY = 47808, - UNITS_MILLION_STANDARD_CUBIC_FEET_PER_DAY = 47809, - UNITS_THOUSAND_CUBIC_FEET_PER_DAY = 47810, - UNITS_THOUSAND_STANDARD_CUBIC_FEET_PER_DAY = 47811, - UINITS_POUNDS_MASS_PER_DAY = 47812, - UNITS_CUBIC_METERS_PER_SECOND = 85, - UNITS_CUBIC_METERS_PER_MINUTE = 165, - UNITS_CUBIC_METERS_PER_HOUR = 135, - UNITS_IMPERIAL_GALLONS_PER_MINUTE = 86, - UNITS_MILLILITERS_PER_SECOND = 198, - UNITS_LITERS_PER_SECOND = 87, - UNITS_LITERS_PER_MINUTE = 88, - UNITS_LITERS_PER_HOUR = 136, - UNITS_US_GALLONS_PER_MINUTE = 89, - UNITS_US_GALLONS_PER_HOUR = 192, - /* Other */ - UNITS_DEGREES_ANGULAR = 90, - UNITS_DEGREES_CELSIUS_PER_HOUR = 91, - UNITS_DEGREES_CELSIUS_PER_MINUTE = 92, - UNITS_DEGREES_FAHRENHEIT_PER_HOUR = 93, - UNITS_DEGREES_FAHRENHEIT_PER_MINUTE = 94, - UNITS_JOULE_SECONDS = 183, - UNITS_KILOGRAMS_PER_CUBIC_METER = 186, - UNITS_KW_HOURS_PER_SQUARE_METER = 137, - UNITS_KW_HOURS_PER_SQUARE_FOOT = 138, - UNITS_MEGAJOULES_PER_SQUARE_METER = 139, - UNITS_MEGAJOULES_PER_SQUARE_FOOT = 140, - UNITS_NO_UNITS = 95, - UNITS_NEWTON_SECONDS = 187, - UNITS_NEWTONS_PER_METER = 188, - UNITS_PARTS_PER_MILLION = 96, - UNITS_PARTS_PER_BILLION = 97, - UNITS_PERCENT = 98, - UNITS_PERCENT_OBSCURATION_PER_FOOT = 143, - UNITS_PERCENT_OBSCURATION_PER_METER = 144, - UNITS_PERCENT_PER_SECOND = 99, - UNITS_PER_MINUTE = 100, - UNITS_PER_SECOND = 101, - UNITS_PSI_PER_DEGREE_FAHRENHEIT = 102, - UNITS_RADIANS = 103, - UNITS_RADIANS_PER_SECOND = 184, - UNITS_REVOLUTIONS_PER_MINUTE = 104, - UNITS_SQUARE_METERS_PER_NEWTON = 185, - UNITS_WATTS_PER_METER_PER_DEGREE_KELVIN = 189, - UNITS_WATTS_PER_SQUARE_METER_DEGREE_KELVIN = 141, - UNITS_PER_MILLE = 207, - UNITS_GRAMS_PER_GRAM = 208, - UNITS_KILOGRAMS_PER_KILOGRAM = 209, - UNITS_GRAMS_PER_KILOGRAM = 210, - UNITS_MILLIGRAMS_PER_GRAM = 211, - UNITS_MILLIGRAMS_PER_KILOGRAM = 212, - UNITS_GRAMS_PER_MILLILITER = 213, - UNITS_GRAMS_PER_LITER = 214, - UNITS_MILLIGRAMS_PER_LITER = 215, - UNITS_MICROGRAMS_PER_LITER = 216, - UNITS_GRAMS_PER_CUBIC_METER = 217, - UNITS_MILLIGRAMS_PER_CUBIC_METER = 218, - UNITS_MICROGRAMS_PER_CUBIC_METER = 219, - UNITS_NANOGRAMS_PER_CUBIC_METER = 220, - UNITS_GRAMS_PER_CUBIC_CENTIMETER = 221, - UNITS_BECQUERELS = 222, - UNITS_KILOBECQUERELS = 223, - UNITS_MEGABECQUERELS = 224, - UNITS_GRAY = 225, - UNITS_MILLIGRAY = 226, - UNITS_MICROGRAY = 227, - UNITS_SIEVERTS = 228, - UNITS_MILLISIEVERTS = 229, - UNITS_MICROSIEVERTS = 230, - UNITS_MICROSIEVERTS_PER_HOUR = 231, - UNITS_DECIBELS_A = 232, - UNITS_NEPHELOMETRIC_TURBIDITY_UNIT = 233, - UNITS_PH = 234, - UNITS_GRAMS_PER_SQUARE_METER = 235, - // Since Addendum 135-2012ar - UNITS_MINUTES_PER_DEGREE_KELVIN = 236, - UNITS_METER_SQUARED_PER_METER = 237, - UNITS_AMPERE_SECONDS = 238, - UNITS_VOLT_AMPERE_HOURS = 239, - UNITS_KILOVOLT_AMPERE_HOURS = 240, - UNITS_MEGAVOLT_AMPERE_HOURS = 241, - UNITS_VOLT_AMPERE_HOURS_REACTIVE = 242, - UNITS_KILOVOLT_AMPERE_HOURS_REACTIVE = 243, - UNITS_MEGAVOLT_AMPERE_HOURS_REACTIVE = 244, - UNITS_VOLT_SQUARE_HOURS = 245, - UNITS_AMPERE_SQUARE_HOURS = 246, - UNITS_JOULE_PER_HOURS = 247, - UNITS_CUBIC_FEET_PER_DAY = 248, - UNITS_CUBIC_METERS_PER_DAY = 249, - UNITS_WATT_HOURS_PER_CUBIC_METER = 250, - UNITS_JOULES_PER_CUBIC_METER = 251, - UNITS_MOLE_PERCENT = 252, - UNITS_PASCAL_SECONDS = 253, - UNITS_MILLION_STANDARD_CUBIC_FEET_PER_MINUTE = 254, - UNITS_RESERVED_RANGE_MAX = 255, - /* Enumerated values 256-47807 may be used by others - subject to the procedures and constraints described in Clause 23. */ - UNITS_PROPRIETARY_RANGE_MIN = 256, - UNITS_PROPRIETARY_RANGE_MAX = 47807, - /* Enumerated values 47808-49999 are reserved for definition by ASHRAE. */ - UNITS_RESERVED_RANGE_MIN2 = 47808, - UNITS_POUNDS_MASS_PER_DAY = 47812, - /* 47813 - NOT USED */ - UNITS_MILLIREMS = 47814, - UNITS_MILLIREMS_PER_HOUR = 47815, - UNITS_RESERVED_RANGE_MAX2 = 49999, - UNITS_PROPRIETARY_RANGE_MIN2 = 50000, - /* Enumerated values 50000-65535 may be used by others - subject to the procedures and constraints described in Clause 23. */ - /* do the proprietary range inside of enum so that - compilers will allocate adequate sized datatype for enum - which is used to store decoding */ - UNITS_PROPRIETARY_RANGE_MAX2 = 65535 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetValue.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetValue.cs deleted file mode 100644 index be98d82..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetValue.cs +++ /dev/null @@ -1,89 +0,0 @@ -namespace System.IO.BACnet; - -public struct BacnetValue -{ - public BacnetApplicationTags Tag; - public object Value; - - public BacnetValue(BacnetApplicationTags tag, object value) - { - Tag = tag; - Value = value; - } - - public BacnetValue(object value) - { - Value = value; - Tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_NULL; - - //guess at the tag - if (value != null) - Tag = TagFromType(value.GetType()); - } - - public BacnetApplicationTags TagFromType(Type t) - { - if (t == typeof(string)) - return BacnetApplicationTags.BACNET_APPLICATION_TAG_CHARACTER_STRING; - if (t == typeof(int) || t == typeof(short) || t == typeof(sbyte)) - return BacnetApplicationTags.BACNET_APPLICATION_TAG_SIGNED_INT; - if (t == typeof(uint) || t == typeof(ushort) || t == typeof(byte)) - return BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT; - if (t == typeof(bool)) - return BacnetApplicationTags.BACNET_APPLICATION_TAG_BOOLEAN; - if (t == typeof(float)) - return BacnetApplicationTags.BACNET_APPLICATION_TAG_REAL; - if (t == typeof(double)) - return BacnetApplicationTags.BACNET_APPLICATION_TAG_DOUBLE; - if (t == typeof(BacnetBitString)) - return BacnetApplicationTags.BACNET_APPLICATION_TAG_BIT_STRING; - if (t == typeof(BacnetObjectId)) - return BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID; - if (t == typeof(BacnetError)) - return BacnetApplicationTags.BACNET_APPLICATION_TAG_ERROR; - if (t == typeof(BacnetDeviceObjectPropertyReference)) - return BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_PROPERTY_REFERENCE; - if (t.IsEnum) - return BacnetApplicationTags.BACNET_APPLICATION_TAG_ENUMERATED; - - return BacnetApplicationTags.BACNET_APPLICATION_TAG_CONTEXT_SPECIFIC_ENCODED; - } - - public T As() - { - if (typeof(T) == typeof(DateTime)) - { - switch (Tag) - { - case BacnetApplicationTags.BACNET_APPLICATION_TAG_DATE: - case BacnetApplicationTags.BACNET_APPLICATION_TAG_DATETIME: - case BacnetApplicationTags.BACNET_APPLICATION_TAG_TIME: - case BacnetApplicationTags.BACNET_APPLICATION_TAG_TIMESTAMP: - return (T)Value; - } - } - - if (typeof(T) == typeof(TimeSpan) && Tag == BacnetApplicationTags.BACNET_APPLICATION_TAG_TIME) - return (T)(dynamic)((DateTime)Value).TimeOfDay; - - if (typeof(T) != typeof(object) && TagFromType(typeof(T)) != Tag) - throw new ArgumentException($"Value with tag {Tag} can't be converted to {typeof(T).Name}"); - - // ReSharper disable once RedundantCast - // This is needed for casting to enums - return (T)(dynamic)Value; - } - - public override string ToString() - { - if (Value == null) - return string.Empty; - - if (Value.GetType() != typeof(byte[])) - return Value.ToString(); - - var tmp = (byte[])Value; - return tmp.Aggregate(string.Empty, (current, b) => - current + b.ToString("X2")); - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetWritePriority.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetWritePriority.cs deleted file mode 100644 index 29d6c86..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetWritePriority.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetWritePriority -{ - NO_PRIORITY = 0, - MANUAL_LIFE_SAFETY = 1, - AUTOMATIC_LIFE_SAFETY = 2, - UNSPECIFIED_LEVEL_3 = 3, - UNSPECIFIED_LEVEL_4 = 4, - CRITICAL_EQUIPMENT_CONTROL = 5, - MINIMUM_ON_OFF = 6, - UNSPECIFIED_LEVEL_7 = 7, - MANUAL_OPERATOR = 8, - UNSPECIFIED_LEVEL_9 = 9, - UNSPECIFIED_LEVEL_10 = 10, - UNSPECIFIED_LEVEL_11 = 11, - UNSPECIFIED_LEVEL_12 = 12, - UNSPECIFIED_LEVEL_13 = 13, - UNSPECIFIED_LEVEL_14 = 14, - UNSPECIFIED_LEVEL_15 = 15, - LOWEST_AND_DEFAULT = 16 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetweekNDay.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetweekNDay.cs deleted file mode 100644 index c7a92ec..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/BacnetweekNDay.cs +++ /dev/null @@ -1,71 +0,0 @@ -namespace System.IO.BACnet; - -public struct BacnetweekNDay : ASN1.IEncode, ASN1.IDecode -{ - public byte month; /* 1 January, 13 Odd, 14 Even, 255 Any */ - public byte week; /* Don't realy understand ??? 1 for day 1 to 7, 2 for ... what's the objective ? boycott it*/ - public byte wday; /* 1=Monday-7=Sunday, 255 any */ - - public BacnetweekNDay(byte day, byte month, byte week = 255) - { - wday = day; - this.month = month; - this.week = week; - } - - public void Encode(EncodeBuffer buffer) - { - buffer.Add(month); - buffer.Add(week); - buffer.Add(wday); - } - - public int Decode(byte[] buffer, int offset, uint count) - { - month = buffer[offset++]; - week = buffer[offset++]; - wday = buffer[offset]; - return 3; - } - - private static string GetDayName(int day) - { - if (day == 7) - day = 0; - - return CultureInfo.CurrentCulture.DateTimeFormat.DayNames[day]; - } - - public override string ToString() - { - string ret = wday != 255 ? GetDayName(wday) : "Every days"; - - if (month != 255) - ret += " on " + CultureInfo.CurrentCulture.DateTimeFormat.MonthNames[month - 1]; - else - ret += " on every month"; - - return ret; - } - - public bool IsAFittingDate(DateTime date) - { - if (date.Month != month && month != 255 && month != 13 && month != 14) - return false; - if (month == 13 && (date.Month & 1) != 1) - return false; - if (month == 14 && (date.Month & 1) == 1) - return false; - - // What about week, too much stupid : boycott it ! - - if (wday == 255) - return true; - if (wday == 7 && date.DayOfWeek == 0) // Sunday 7 for Bacnet, 0 for .NET - return true; - if (wday == (int)date.DayOfWeek) - return true; - - return false; - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/DeviceReportingRecipient.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/DeviceReportingRecipient.cs deleted file mode 100644 index 4ca99d4..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/DeviceReportingRecipient.cs +++ /dev/null @@ -1,84 +0,0 @@ -namespace System.IO.BACnet; - -public struct DeviceReportingRecipient : ASN1.IEncode -{ - public BacnetBitString WeekofDay; - public DateTime toTime, fromTime; - - public BacnetObjectId Id; - public BacnetAddress adr; - - public uint processIdentifier; - public bool Ack_Required; - public BacnetBitString evenType; - - public DeviceReportingRecipient(BacnetValue v0, BacnetValue v1, BacnetValue v2, BacnetValue v3, BacnetValue v4, BacnetValue v5, BacnetValue v6) - { - Id = new BacnetObjectId(); - adr = null; - - WeekofDay = (BacnetBitString)v0.Value; - fromTime = (DateTime)v1.Value; - toTime = (DateTime)v2.Value; - if (v3.Value is BacnetObjectId id) - { - Id = id; - } - else - { - var netdescr = (BacnetValue[])v3.Value; - var s = (ushort)(uint)netdescr[0].Value; - var b = (byte[])netdescr[1].Value; - adr = new BacnetAddress(BacnetAddressTypes.IP, s, b); - } - processIdentifier = (uint)v4.Value; - Ack_Required = (bool)v5.Value; - evenType = (BacnetBitString)v6.Value; - } - - public DeviceReportingRecipient(BacnetBitString weekofDay, DateTime fromTime, DateTime toTime, BacnetObjectId id, uint processIdentifier, bool ackRequired, BacnetBitString evenType) - { - adr = null; - - WeekofDay = weekofDay; - this.toTime = toTime; - this.fromTime = fromTime; - Id = id; - this.processIdentifier = processIdentifier; - Ack_Required = ackRequired; - this.evenType = evenType; - } - - public DeviceReportingRecipient(BacnetBitString weekofDay, DateTime fromTime, DateTime toTime, BacnetAddress adr, uint processIdentifier, bool ackRequired, BacnetBitString evenType) - { - Id = new BacnetObjectId(); - WeekofDay = weekofDay; - this.toTime = toTime; - this.fromTime = fromTime; - this.adr = adr; - this.processIdentifier = processIdentifier; - Ack_Required = ackRequired; - this.evenType = evenType; - } - - public void Encode(EncodeBuffer buffer) - { - ASN1.bacapp_encode_application_data(buffer, new BacnetValue(WeekofDay)); - ASN1.bacapp_encode_application_data(buffer, new BacnetValue(BacnetApplicationTags.BACNET_APPLICATION_TAG_TIME, fromTime)); - ASN1.bacapp_encode_application_data(buffer, new BacnetValue(BacnetApplicationTags.BACNET_APPLICATION_TAG_TIME, toTime)); - - if (adr != null) - { - adr.Encode(buffer); - } - else - { - // BacnetObjectId is context specific encoded - ASN1.encode_context_object_id(buffer, 0, Id.type, Id.instance); - } - - ASN1.bacapp_encode_application_data(buffer, new BacnetValue(processIdentifier)); - ASN1.bacapp_encode_application_data(buffer, new BacnetValue(Ack_Required)); - ASN1.bacapp_encode_application_data(buffer, new BacnetValue(evenType)); - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetBackupState.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetBackupState.cs deleted file mode 100644 index 9377ab3..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetBackupState.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetBackupState -{ - IDLE = 0, - PREPARING_FOR_BACKUP = 1, - PREPARING_FOR_RESTORE = 2, - PERFORMING_A_BACKUP = 3, - PERFORMING_A_RESTORE = 4 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetCOVTypes.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetCOVTypes.cs deleted file mode 100644 index 39d27fe..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetCOVTypes.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetCOVTypes -{ - CHANGE_OF_VALUE_BITS, - CHANGE_OF_VALUE_REAL -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetEventEnable.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetEventEnable.cs deleted file mode 100644 index fc02ce7..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetEventEnable.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetEventEnable -{ - EVENT_ENABLE_TO_OFFNORMAL = 1, - EVENT_ENABLE_TO_FAULT = 2, - EVENT_ENABLE_TO_NORMAL = 4 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetEventStates.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetEventStates.cs deleted file mode 100644 index 3630637..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetEventStates.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetEventStates -{ - EVENT_STATE_NORMAL = 0, - EVENT_STATE_FAULT = 1, - EVENT_STATE_OFFNORMAL = 2, - EVENT_STATE_HIGH_LIMIT = 3, - EVENT_STATE_LOW_LIMIT = 4, - EVENT_STATE_LIFE_SAFETY_ALARM = 5 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetEventTypes.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetEventTypes.cs deleted file mode 100644 index 9719c2b..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetEventTypes.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetEventTypes -{ - EVENT_CHANGE_OF_BITSTRING = 0, - EVENT_CHANGE_OF_STATE = 1, - EVENT_CHANGE_OF_VALUE = 2, - EVENT_COMMAND_FAILURE = 3, - EVENT_FLOATING_LIMIT = 4, - EVENT_OUT_OF_RANGE = 5, - /* complex-event-type (6), -- see comment below */ - /* event-buffer-ready (7), -- context tag 7 is deprecated */ - EVENT_CHANGE_OF_LIFE_SAFETY = 8, - EVENT_EXTENDED = 9, - EVENT_BUFFER_READY = 10, - EVENT_UNSIGNED_RANGE = 11, - /* -- enumeration value 12 is reserved for future addenda */ - EVENT_ACCESS_EVENT = 13, - EVENT_DOUBLE_OUT_OF_RANGE = 14, - EVENT_SIGNED_OUT_OF_RANGE = 15, - EVENT_UNSIGNED_OUT_OF_RANGE = 16, - EVENT_CHANGE_OF_CHARACTERSTRING = 17, - EVENT_CHANGE_OF_STATUS_FLAGS = 18, - EVENT_CHANGE_OF_RELIABILITY = 19, - EVENT_NONE = 20, - EVENT_CHANGE_OF_DISCRETE_VALUE = 21, - EVENT_CHANGE_OF_TIMER = 22, - /* Enumerated values 0-63 are reserved for definition by ASHRAE. */ - /* Enumerated values 64-65535 may be used by others subject to */ - /* the procedures and constraints described in Clause 23. */ - /* It is expected that these enumerated values will correspond to */ - /* the use of the complex-event-type CHOICE [6] of the */ - /* BACnetNotificationParameters production. */ - /* The last enumeration used in this version is 11. */ - /* do the max range inside of enum so that - compilers will allocate adequate sized datatype for enum - which is used to store decoding */ - EVENT_PROPRIETARY_MIN = 64, - EVENT_PROPRIETARY_MAX = 65535 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetFileAccessMethod.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetFileAccessMethod.cs deleted file mode 100644 index da4ea15..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetFileAccessMethod.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetFileAccessMethod -{ - RECORD_ACCESS = 0, - STREAM_ACCESS = 1 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetLifeSafetyModes.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetLifeSafetyModes.cs deleted file mode 100644 index e2ff5d4..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetLifeSafetyModes.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetLifeSafetyModes -{ - MIN_LIFE_SAFETY_MODE = 0, - LIFE_SAFETY_MODE_OFF = 0, - LIFE_SAFETY_MODE_ON = 1, - LIFE_SAFETY_MODE_TEST = 2, - LIFE_SAFETY_MODE_MANNED = 3, - LIFE_SAFETY_MODE_UNMANNED = 4, - LIFE_SAFETY_MODE_ARMED = 5, - LIFE_SAFETY_MODE_DISARMED = 6, - LIFE_SAFETY_MODE_PREARMED = 7, - LIFE_SAFETY_MODE_SLOW = 8, - LIFE_SAFETY_MODE_FAST = 9, - LIFE_SAFETY_MODE_DISCONNECTED = 10, - LIFE_SAFETY_MODE_ENABLED = 11, - LIFE_SAFETY_MODE_DISABLED = 12, - LIFE_SAFETY_MODE_AUTOMATIC_RELEASE_DISABLED = 13, - LIFE_SAFETY_MODE_DEFAULT = 14, - MAX_LIFE_SAFETY_MODE = 15, - /* Enumerated values 0-255 are reserved for definition by ASHRAE. */ - /* Enumerated values 256-65535 may be used by others subject to */ - /* procedures and constraints described in Clause 23. */ - /* do the max range inside of enum so that - compilers will allocate adequate sized datatype for enum - which is used to store decoding */ - LIFE_SAFETY_MODE_PROPRIETARY_MIN = 256, - LIFE_SAFETY_MODE_PROPRIETARY_MAX = 65535 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetLifeSafetyOperations.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetLifeSafetyOperations.cs deleted file mode 100644 index 9e968bb..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetLifeSafetyOperations.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetLifeSafetyOperations -{ - LIFE_SAFETY_OP_NONE = 0, - LIFE_SAFETY_OP_SILENCE = 1, - LIFE_SAFETY_OP_SILENCE_AUDIBLE = 2, - LIFE_SAFETY_OP_SILENCE_VISUAL = 3, - LIFE_SAFETY_OP_RESET = 4, - LIFE_SAFETY_OP_RESET_ALARM = 5, - LIFE_SAFETY_OP_RESET_FAULT = 6, - LIFE_SAFETY_OP_UNSILENCE = 7, - LIFE_SAFETY_OP_UNSILENCE_AUDIBLE = 8, - LIFE_SAFETY_OP_UNSILENCE_VISUAL = 9, - /* Enumerated values 0-63 are reserved for definition by ASHRAE. */ - /* Enumerated values 64-65535 may be used by others subject to */ - /* procedures and constraints described in Clause 23. */ - /* do the max range inside of enum so that - compilers will allocate adequate sized datatype for enum - which is used to store decoding */ - LIFE_SAFETY_OP_PROPRIETARY_MIN = 64, - LIFE_SAFETY_OP_PROPRIETARY_MAX = 65535 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetLifeSafetyStates.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetLifeSafetyStates.cs deleted file mode 100644 index 78c73ac..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetLifeSafetyStates.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetLifeSafetyStates -{ - MIN_LIFE_SAFETY_STATE = 0, - LIFE_SAFETY_STATE_QUIET = 0, - LIFE_SAFETY_STATE_PRE_ALARM = 1, - LIFE_SAFETY_STATE_ALARM = 2, - LIFE_SAFETY_STATE_FAULT = 3, - LIFE_SAFETY_STATE_FAULT_PRE_ALARM = 4, - LIFE_SAFETY_STATE_FAULT_ALARM = 5, - LIFE_SAFETY_STATE_NOT_READY = 6, - LIFE_SAFETY_STATE_ACTIVE = 7, - LIFE_SAFETY_STATE_TAMPER = 8, - LIFE_SAFETY_STATE_TEST_ALARM = 9, - LIFE_SAFETY_STATE_TEST_ACTIVE = 10, - LIFE_SAFETY_STATE_TEST_FAULT = 11, - LIFE_SAFETY_STATE_TEST_FAULT_ALARM = 12, - LIFE_SAFETY_STATE_HOLDUP = 13, - LIFE_SAFETY_STATE_DURESS = 14, - LIFE_SAFETY_STATE_TAMPER_ALARM = 15, - LIFE_SAFETY_STATE_ABNORMAL = 16, - LIFE_SAFETY_STATE_EMERGENCY_POWER = 17, - LIFE_SAFETY_STATE_DELAYED = 18, - LIFE_SAFETY_STATE_BLOCKED = 19, - LIFE_SAFETY_STATE_LOCAL_ALARM = 20, - LIFE_SAFETY_STATE_GENERAL_ALARM = 21, - LIFE_SAFETY_STATE_SUPERVISORY = 22, - LIFE_SAFETY_STATE_TEST_SUPERVISORY = 23, - MAX_LIFE_SAFETY_STATE = 24, - /* Enumerated values 0-255 are reserved for definition by ASHRAE. */ - /* Enumerated values 256-65535 may be used by others subject to */ - /* procedures and constraints described in Clause 23. */ - /* do the max range inside of enum so that - compilers will allocate adequate sized datatype for enum - which is used to store decoding */ - LIFE_SAFETY_STATE_PROPRIETARY_MIN = 256, - LIFE_SAFETY_STATE_PROPRIETARY_MAX = 65535 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetLimitEnable.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetLimitEnable.cs deleted file mode 100644 index 21cc118..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetLimitEnable.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetLimitEnable -{ - EVENT_LOW_LIMIT_ENABLE = 1, - EVENT_HIGH_LIMIT_ENABLE = 2 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetNotifyTypes.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetNotifyTypes.cs deleted file mode 100644 index b1eda1f..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Base/Enums/BacnetNotifyTypes.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace System.IO.BACnet; - -public enum BacnetNotifyTypes -{ - NOTIFY_ALARM = 0, - NOTIFY_EVENT = 1, - NOTIFY_ACK_NOTIFICATION = 2 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/GlobalUsings.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/GlobalUsings.cs deleted file mode 100644 index ad05b8e..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/GlobalUsings.cs +++ /dev/null @@ -1,21 +0,0 @@ -global using Common.Logging; -global using PacketDotNet; -global using SharpPcap; -global using SharpPcap.LibPcap; -global using System.Collections.Generic; -global using System.Globalization; -global using System.IO.BACnet.Base; -global using System.IO.BACnet.Serialize; -global using System.IO.Pipes; -global using System.IO.Ports; -global using System.Linq; -global using System.Net; -global using System.Net.NetworkInformation; -global using System.Net.Sockets; -global using System.Reflection; -global using System.Runtime.InteropServices; -global using System.Text; -global using System.Text.RegularExpressions; -global using System.Threading; -global using System.Threading.Tasks; -global using System.Xml.Serialization; diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Helpers/BacnetValuesExtensions.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Helpers/BacnetValuesExtensions.cs deleted file mode 100644 index ddefad0..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Helpers/BacnetValuesExtensions.cs +++ /dev/null @@ -1,64 +0,0 @@ -namespace System.IO.BACnet.Helpers; - -public static class BacnetValuesExtensions -{ - public static bool Has(this IList propertyValues, BacnetPropertyIds propertyId) - { - if (propertyValues.All(v => v.property.GetPropertyId() != propertyId)) - return false; - - return propertyValues - .Where(v => v.property.GetPropertyId() == propertyId) - .Any(v => !v.value.HasError()); - } - - public static bool HasError(this IList propertyValues, BacnetErrorCodes error) - { - return propertyValues - .SelectMany(p => p.value) - .Where(v => v.Tag == BacnetApplicationTags.BACNET_APPLICATION_TAG_ERROR) - .Any(v => v.As().error_code == error); - } - - public static bool HasError(this IList propertyValues) - { - return propertyValues.Any(p => p.value.HasError()); - } - - public static bool HasError(this IList values) - { - return values.Any(v => v.Tag == BacnetApplicationTags.BACNET_APPLICATION_TAG_ERROR); - } - - public static object Get(this IList propertyValues, BacnetPropertyIds propertyId) - { - return Get(propertyValues, propertyId); - } - - public static T Get(this IList propertyValues, BacnetPropertyIds propertyId) - { - return GetMany(propertyValues, propertyId).FirstOrDefault(); - } - - public static T[] GetMany(this IList propertyValues, BacnetPropertyIds propertyId) - { - if (!propertyValues.Has(propertyId)) - return new T[0]; - - var property = propertyValues.First(v => v.property.GetPropertyId() == propertyId); - - return property.property.propertyArrayIndex == ASN1.BACNET_ARRAY_ALL - ? property.value.GetMany() - : new[] { property.value[(int)property.property.propertyArrayIndex].As() }; - } - - public static T[] GetMany(this IList values) - { - return values.Select(v => v.As()).ToArray(); - } - - public static T Get(this IList values) - { - return GetMany(values).FirstOrDefault(); - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/APDU.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/APDU.cs deleted file mode 100644 index 7c8546e..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/APDU.cs +++ /dev/null @@ -1,217 +0,0 @@ -namespace System.IO.BACnet.Serialize; - -public class APDU -{ - public static BacnetPduTypes GetDecodedType(byte[] buffer, int offset) - { - return (BacnetPduTypes)buffer[offset]; - } - - public static void SetDecodedType(byte[] buffer, int offset, BacnetPduTypes type) - { - buffer[offset] = (byte)type; - } - - public static int GetDecodedInvokeId(byte[] buffer, int offset) - { - var type = GetDecodedType(buffer, offset); - switch (type & BacnetPduTypes.PDU_TYPE_MASK) - { - case BacnetPduTypes.PDU_TYPE_SIMPLE_ACK: - case BacnetPduTypes.PDU_TYPE_COMPLEX_ACK: - case BacnetPduTypes.PDU_TYPE_ERROR: - case BacnetPduTypes.PDU_TYPE_REJECT: - case BacnetPduTypes.PDU_TYPE_ABORT: - return buffer[offset + 1]; - case BacnetPduTypes.PDU_TYPE_CONFIRMED_SERVICE_REQUEST: - return buffer[offset + 2]; - default: - return -1; - } - } - - public static void EncodeConfirmedServiceRequest(EncodeBuffer buffer, BacnetPduTypes type, BacnetConfirmedServices service, BacnetMaxSegments maxSegments, - BacnetMaxAdpu maxAdpu, byte invokeId, byte sequenceNumber = 0, byte proposedWindowSize = 0) - { - buffer.buffer[buffer.offset++] = (byte)type; - buffer.buffer[buffer.offset++] = (byte)((byte)maxSegments | (byte)maxAdpu); - buffer.buffer[buffer.offset++] = invokeId; - - if ((type & BacnetPduTypes.SEGMENTED_MESSAGE) > 0) - { - buffer.buffer[buffer.offset++] = sequenceNumber; - buffer.buffer[buffer.offset++] = proposedWindowSize; - } - buffer.buffer[buffer.offset++] = (byte)service; - } - - public static int DecodeConfirmedServiceRequest(byte[] buffer, int offset, out BacnetPduTypes type, out BacnetConfirmedServices service, - out BacnetMaxSegments maxSegments, out BacnetMaxAdpu maxAdpu, out byte invokeId, out byte sequenceNumber, out byte proposedWindowNumber) - { - var orgOffset = offset; - - type = (BacnetPduTypes)buffer[offset++]; - maxSegments = (BacnetMaxSegments)(buffer[offset] & 0xF0); - maxAdpu = (BacnetMaxAdpu)(buffer[offset++] & 0x0F); - invokeId = buffer[offset++]; - - sequenceNumber = 0; - proposedWindowNumber = 0; - if ((type & BacnetPduTypes.SEGMENTED_MESSAGE) > 0) - { - sequenceNumber = buffer[offset++]; - proposedWindowNumber = buffer[offset++]; - } - service = (BacnetConfirmedServices)buffer[offset++]; - - return offset - orgOffset; - } - - public static void EncodeUnconfirmedServiceRequest(EncodeBuffer buffer, BacnetPduTypes type, BacnetUnconfirmedServices service) - { - buffer.buffer[buffer.offset++] = (byte)type; - buffer.buffer[buffer.offset++] = (byte)service; - } - - public static int DecodeUnconfirmedServiceRequest(byte[] buffer, int offset, out BacnetPduTypes type, out BacnetUnconfirmedServices service) - { - var orgOffset = offset; - - type = (BacnetPduTypes)buffer[offset++]; - service = (BacnetUnconfirmedServices)buffer[offset++]; - - return offset - orgOffset; - } - - public static void EncodeSimpleAck(EncodeBuffer buffer, BacnetPduTypes type, BacnetConfirmedServices service, byte invokeId) - { - buffer.buffer[buffer.offset++] = (byte)type; - buffer.buffer[buffer.offset++] = invokeId; - buffer.buffer[buffer.offset++] = (byte)service; - } - - public static int DecodeSimpleAck(byte[] buffer, int offset, out BacnetPduTypes type, out BacnetConfirmedServices service, out byte invokeId) - { - var orgOffset = offset; - - type = (BacnetPduTypes)buffer[offset++]; - invokeId = buffer[offset++]; - service = (BacnetConfirmedServices)buffer[offset++]; - - return offset - orgOffset; - } - - public static int EncodeComplexAck(EncodeBuffer buffer, BacnetPduTypes type, BacnetConfirmedServices service, byte invokeId, byte sequenceNumber = 0, byte proposedWindowNumber = 0) - { - var len = 3; - buffer.buffer[buffer.offset++] = (byte)type; - buffer.buffer[buffer.offset++] = invokeId; - if ((type & BacnetPduTypes.SEGMENTED_MESSAGE) > 0) - { - buffer.buffer[buffer.offset++] = sequenceNumber; - buffer.buffer[buffer.offset++] = proposedWindowNumber; - len += 2; - } - buffer.buffer[buffer.offset++] = (byte)service; - return len; - } - - public static int DecodeComplexAck(byte[] buffer, int offset, out BacnetPduTypes type, out BacnetConfirmedServices service, out byte invokeId, - out byte sequenceNumber, out byte proposedWindowNumber) - { - var orgOffset = offset; - - type = (BacnetPduTypes)buffer[offset++]; - invokeId = buffer[offset++]; - - sequenceNumber = 0; - proposedWindowNumber = 0; - if ((type & BacnetPduTypes.SEGMENTED_MESSAGE) > 0) - { - sequenceNumber = buffer[offset++]; - proposedWindowNumber = buffer[offset++]; - } - service = (BacnetConfirmedServices)buffer[offset++]; - - return offset - orgOffset; - } - - public static void EncodeSegmentAck(EncodeBuffer buffer, BacnetPduTypes type, byte originalInvokeId, byte sequenceNumber, byte actualWindowSize) - { - buffer.buffer[buffer.offset++] = (byte)type; - buffer.buffer[buffer.offset++] = originalInvokeId; - buffer.buffer[buffer.offset++] = sequenceNumber; - buffer.buffer[buffer.offset++] = actualWindowSize; - } - - public static int DecodeSegmentAck(byte[] buffer, int offset, out BacnetPduTypes type, out byte originalInvokeId, out byte sequenceNumber, out byte actualWindowSize) - { - var orgOffset = offset; - - type = (BacnetPduTypes)buffer[offset++]; - originalInvokeId = buffer[offset++]; - sequenceNumber = buffer[offset++]; - actualWindowSize = buffer[offset++]; - - return offset - orgOffset; - } - - public static void EncodeError(EncodeBuffer buffer, BacnetPduTypes type, BacnetConfirmedServices service, byte invokeId) - { - buffer.buffer[buffer.offset++] = (byte)type; - buffer.buffer[buffer.offset++] = invokeId; - buffer.buffer[buffer.offset++] = (byte)service; - } - - public static int DecodeError(byte[] buffer, int offset, out BacnetPduTypes type, out BacnetConfirmedServices service, out byte invokeId) - { - var orgOffset = offset; - - type = (BacnetPduTypes)buffer[offset++]; - invokeId = buffer[offset++]; - service = (BacnetConfirmedServices)buffer[offset++]; - - return offset - orgOffset; - } - - public static void EncodeAbort(EncodeBuffer buffer, BacnetPduTypes type, byte invokeId, BacnetAbortReason reason) - { - EncodeAbortOrReject(buffer, type, invokeId, reason); - } - - public static void EncodeReject(EncodeBuffer buffer, BacnetPduTypes type, byte invokeId, BacnetRejectReason reason) - { - EncodeAbortOrReject(buffer, type, invokeId, reason); - } - - private static void EncodeAbortOrReject(EncodeBuffer buffer, BacnetPduTypes type, byte invokeId, dynamic reason) - { - buffer.buffer[buffer.offset++] = (byte)type; - buffer.buffer[buffer.offset++] = invokeId; - buffer.buffer[buffer.offset++] = (byte)reason; - } - - public static int DecodeAbort(byte[] buffer, int offset, out BacnetPduTypes type, - out byte invokeId, out BacnetAbortReason reason) - { - return DecodeAbortOrReject(buffer, offset, out type, out invokeId, out reason); - } - - public static int DecodeReject(byte[] buffer, int offset, out BacnetPduTypes type, - out byte invokeId, out BacnetRejectReason reason) - { - return DecodeAbortOrReject(buffer, offset, out type, out invokeId, out reason); - } - - private static int DecodeAbortOrReject(byte[] buffer, int offset, - out BacnetPduTypes type, out byte invokeId, out TReason reason) - { - var orgOffset = offset; - - type = (BacnetPduTypes)buffer[offset++]; - invokeId = buffer[offset++]; - reason = (TReason)(dynamic)buffer[offset++]; - - return offset - orgOffset; - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/ASN1.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/ASN1.cs deleted file mode 100644 index 5177796..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/ASN1.cs +++ /dev/null @@ -1,2486 +0,0 @@ -namespace System.IO.BACnet.Serialize; - -public class ASN1 -{ - public const int BACNET_MAX_OBJECT = 0x3FF; - public const int BACNET_INSTANCE_BITS = 22; - public const int BACNET_MAX_INSTANCE = 0x3FFFFF; - public const int MAX_BITSTRING_BYTES = 15; - public const uint BACNET_ARRAY_ALL = 0xFFFFFFFFU; - public const uint BACNET_NO_PRIORITY = 0; - public const uint BACNET_MIN_PRIORITY = 1; - public const uint BACNET_MAX_PRIORITY = 16; - - /// - /// You can provide a function to resolve a given tag within a property to a different tag (e.g. for custom properties) - /// The address of the remote device is provided so that you can support devices from multiple vendors - /// (the same custom property# has different meaning for each vendor) - /// - public static Func CustomTagResolver; - - public interface IEncode - { - void Encode(EncodeBuffer buffer); - } - - public interface IDecode - { - int Decode(byte[] buffer, int offset, uint count); - } - - public static void encode_bacnet_object_id(EncodeBuffer buffer, BacnetObjectTypes objectType, uint instance) - { - var type = (uint)objectType; - var value = ((type & BACNET_MAX_OBJECT) << BACNET_INSTANCE_BITS) | (instance & BACNET_MAX_INSTANCE); - encode_unsigned32(buffer, value); - } - - public static void encode_tag(EncodeBuffer buffer, byte tagNumber, bool contextSpecific, uint lenValueType) - { - var len = 1; - var tmp = new byte[3]; - - tmp[0] = 0; - if (contextSpecific) tmp[0] |= 0x8; - - /* additional tag byte after this byte */ - /* for extended tag byte */ - if (tagNumber <= 14) - { - tmp[0] |= (byte)(tagNumber << 4); - } - else - { - tmp[0] |= 0xF0; - tmp[1] = tagNumber; - len++; - } - - /* NOTE: additional len byte(s) after extended tag byte */ - /* if larger than 4 */ - if (lenValueType <= 4) - { - tmp[0] |= (byte)lenValueType; - buffer.Add(tmp, len); - } - else - { - tmp[0] |= 5; - if (lenValueType <= 253) - { - tmp[len++] = (byte)lenValueType; - buffer.Add(tmp, len); - } - else if (lenValueType <= 65535) - { - tmp[len++] = 254; - buffer.Add(tmp, len); - encode_unsigned16(buffer, (ushort)lenValueType); - } - else - { - tmp[len++] = 255; - buffer.Add(tmp, len); - encode_unsigned32(buffer, lenValueType); - } - } - } - - public static void encode_bacnet_enumerated(EncodeBuffer buffer, uint value) - { - encode_bacnet_unsigned(buffer, value); - } - - public static void encode_application_object_id(EncodeBuffer buffer, BacnetObjectTypes objectType, uint instance) - { - var tmp1 = new EncodeBuffer(); - encode_bacnet_object_id(tmp1, objectType, instance); - encode_tag(buffer, (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID, false, (uint)tmp1.offset); - buffer.Add(tmp1.buffer, tmp1.offset); - } - - public static void encode_application_unsigned(EncodeBuffer buffer, uint value) - { - var tmp1 = new EncodeBuffer(); - encode_bacnet_unsigned(tmp1, value); - encode_tag(buffer, (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT, false, (uint)tmp1.offset); - buffer.Add(tmp1.buffer, tmp1.offset); - } - - public static void encode_application_enumerated(EncodeBuffer buffer, uint value) - { - var tmp1 = new EncodeBuffer(); - encode_bacnet_enumerated(tmp1, value); - encode_tag(buffer, (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_ENUMERATED, false, (uint)tmp1.offset); - buffer.Add(tmp1.buffer, tmp1.offset); - } - - public static void encode_application_signed(EncodeBuffer buffer, int value) - { - var tmp1 = new EncodeBuffer(); - encode_bacnet_signed(tmp1, value); - encode_tag(buffer, (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_SIGNED_INT, false, (uint)tmp1.offset); - buffer.Add(tmp1.buffer, tmp1.offset); - } - - public static void encode_bacnet_unsigned(EncodeBuffer buffer, uint value) - { - if (value < 0x100) - { - buffer.Add((byte)value); - } - else if (value < 0x10000) - { - encode_unsigned16(buffer, (ushort)value); - } - else if (value < 0x1000000) - { - encode_unsigned24(buffer, value); - } - else - { - encode_unsigned32(buffer, value); - } - } - - public static void encode_context_boolean(EncodeBuffer buffer, byte tagNumber, bool boolean_value) - { - encode_tag(buffer, tagNumber, true, 1); - buffer.Add(boolean_value ? (byte)1 : (byte)0); - } - - public static void encode_context_real(EncodeBuffer buffer, byte tagNumber, float value) - { - encode_tag(buffer, tagNumber, true, 4); - encode_bacnet_real(buffer, value); - } - - public static void encode_context_unsigned(EncodeBuffer buffer, byte tagNumber, uint value) - { - int len; - - /* length of unsigned is variable, as per 20.2.4 */ - if (value < 0x100) - len = 1; - else if (value < 0x10000) - len = 2; - else if (value < 0x1000000) - len = 3; - else - len = 4; - - encode_tag(buffer, tagNumber, true, (uint)len); - encode_bacnet_unsigned(buffer, value); - } - - public static void encode_context_character_string(EncodeBuffer buffer, byte tagNumber, string value) - { - var tmp = new EncodeBuffer(); - encode_bacnet_character_string(tmp, value); - - encode_tag(buffer, tagNumber, true, (uint)tmp.offset); - buffer.Add(tmp.buffer, tmp.offset); - } - - public static void encode_context_enumerated(EncodeBuffer buffer, byte tagNumber, uint value) - { - int len; /* return value */ - - if (value < 0x100) - len = 1; - else if (value < 0x10000) - len = 2; - else if (value < 0x1000000) - len = 3; - else - len = 4; - - encode_tag(buffer, tagNumber, true, (uint)len); - encode_bacnet_enumerated(buffer, value); - } - - public static void encode_bacnet_signed(EncodeBuffer buffer, long value) - { - /* don't encode the leading X'FF' or X'00' of the two's compliment. - That is, the first octet of any multi-octet encoded value shall - not be X'00' if the most significant bit (bit 7) of the second - octet is 0, and the first octet shall not be X'FF' if the most - significant bit of the second octet is 1. */ - if (value >= -128 && value < 128) - buffer.Add((byte)(sbyte)value); - else if (value >= -32768 && value < 32768) - encode_signed16(buffer, (short)value); - else if (value > -8388607 && value < 8388608) - encode_signed24(buffer, (int)value); - else if (value > -2147483648 && value < 2147483648) - encode_signed32(buffer, (int)value); - else - encode_signed64(buffer, value); - } - - public static void encode_octetString(EncodeBuffer buffer, byte[] octetString, int octetOffset, int octetCount) - { - if (octetString != null) - { - for (var i = octetOffset; i < octetOffset + octetCount; i++) - buffer.Add(octetString[i]); - } - } - - public static void encode_application_octet_string(EncodeBuffer buffer, byte[] octetString, int octetOffset, int octetCount) - { - encode_tag(buffer, (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_OCTET_STRING, false, (uint)octetCount); - encode_octetString(buffer, octetString, octetOffset, octetCount); - } - - public static void encode_application_boolean(EncodeBuffer buffer, bool booleanValue) - { - encode_tag(buffer, (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_BOOLEAN, false, - booleanValue ? 1 : (uint)0); - } - - public static void encode_bacnet_real(EncodeBuffer buffer, float value) - { - var data = BitConverter.GetBytes(value); - buffer.Add(data[3]); - buffer.Add(data[2]); - buffer.Add(data[1]); - buffer.Add(data[0]); - } - - public static void encode_bacnet_double(EncodeBuffer buffer, double value) - { - var data = BitConverter.GetBytes(value); - buffer.Add(data[7]); - buffer.Add(data[6]); - buffer.Add(data[5]); - buffer.Add(data[4]); - buffer.Add(data[3]); - buffer.Add(data[2]); - buffer.Add(data[1]); - buffer.Add(data[0]); - } - - public static void encode_application_real(EncodeBuffer buffer, float value) - { - encode_tag(buffer, (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_REAL, false, 4); - encode_bacnet_real(buffer, value); - } - - public static void encode_application_double(EncodeBuffer buffer, double value) - { - encode_tag(buffer, (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_DOUBLE, false, 8); - encode_bacnet_double(buffer, value); - } - - private static byte bitstring_bytesUsed(BacnetBitString bitString) - { - byte len = 0; /* return value */ - - if (bitString.bits_used <= 0) - return len; - - var lastBit = (byte)(bitString.bits_used - 1); - var usedBytes = (byte)(lastBit / 8); - /* add one for the first byte */ - usedBytes++; - len = usedBytes; - - return len; - } - - private static byte byte_reverse_bits(byte inByte) - { - byte outByte = 0; - - if ((inByte & 1) > 0) - { - outByte |= 0x80; - } - if ((inByte & 2) > 0) - { - outByte |= 0x40; - } - if ((inByte & 4) > 0) - { - outByte |= 0x20; - } - if ((inByte & 8) > 0) - { - outByte |= 0x10; - } - if ((inByte & 16) > 0) - { - outByte |= 0x8; - } - if ((inByte & 32) > 0) - { - outByte |= 0x4; - } - if ((inByte & 64) > 0) - { - outByte |= 0x2; - } - if ((inByte & 128) > 0) - { - outByte |= 1; - } - - return outByte; - } - - private static byte bitstring_octet(BacnetBitString bitString, byte octetIndex) - { - byte octet = 0; - - if (bitString.value == null) - return octet; - - if (octetIndex < MAX_BITSTRING_BYTES) - octet = bitString.value[octetIndex]; - - return octet; - } - - public static void encode_bitstring(EncodeBuffer buffer, BacnetBitString bitString) - { - /* if the bit string is empty, then the first octet shall be zero */ - if (bitString.bits_used == 0) - { - buffer.Add(0); - } - else - { - var usedBytes = bitstring_bytesUsed(bitString); - var remainingUsedBits = (byte)(bitString.bits_used - (usedBytes - 1) * 8); - /* number of unused bits in the subsequent final octet */ - buffer.Add((byte)(8 - remainingUsedBits)); - for (byte i = 0; i < usedBytes; i++) - buffer.Add(byte_reverse_bits(bitstring_octet(bitString, i))); - } - } - - public static void encode_application_bitstring(EncodeBuffer buffer, BacnetBitString bitString) - { - uint bitStringEncodedLength = 1; /* 1 for the bits remaining octet */ - - /* bit string may use more than 1 octet for the tag, so find out how many */ - bitStringEncodedLength += bitstring_bytesUsed(bitString); - encode_tag(buffer, (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_BIT_STRING, false, bitStringEncodedLength); - encode_bitstring(buffer, bitString); - } - - public static void EncodeApplicationDestination(EncodeBuffer buffer, BacnetObjectTypes objectType, uint instance) - { - var tempBuffer = new EncodeBuffer(); - encode_bacnet_object_id(tempBuffer, objectType, instance); - buffer.Add(0x0C); - buffer.Add(tempBuffer.buffer, tempBuffer.offset); - } - - public static void EncodeApplicationDestination(EncodeBuffer buffer, BacnetAddress address) - { - address.Encode(buffer); - } - - public static void bacapp_encode_application_data(EncodeBuffer buffer, BacnetValue value) - { - if (value.Value == null) - { - // Modif FC - buffer.Add((byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_NULL); - return; - } - - switch (value.Tag) - { - case BacnetApplicationTags.BACNET_APPLICATION_TAG_NULL: - /* don't encode anything */ - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_BOOLEAN: - encode_application_boolean(buffer, (bool)value.Value); - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT: - encode_application_unsigned(buffer, (uint)value.Value); - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_SIGNED_INT: - encode_application_signed(buffer, (int)value.Value); - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_REAL: - encode_application_real(buffer, (float)value.Value); - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_DOUBLE: - encode_application_double(buffer, (double)value.Value); - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_OCTET_STRING: - encode_application_octet_string(buffer, (byte[])value.Value, 0, ((byte[])value.Value).Length); - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_CHARACTER_STRING: - encode_application_character_string(buffer, (string)value.Value); - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_BIT_STRING: - encode_application_bitstring(buffer, (BacnetBitString)value.Value); - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_ENUMERATED: - encode_application_enumerated(buffer, (uint)(dynamic)value.Value); - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_DATE: - encode_application_date(buffer, (DateTime)value.Value); - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_TIME: - encode_application_time(buffer, (DateTime)value.Value); - break; - // Added for EventTimeStamp - case BacnetApplicationTags.BACNET_APPLICATION_TAG_TIMESTAMP: - bacapp_encode_timestamp(buffer, (BacnetGenericTime)value.Value); - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_DATETIME: - bacapp_encode_datetime(buffer, (DateTime)value.Value); - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID: - encode_application_object_id(buffer, ((BacnetObjectId)value.Value).type, - ((BacnetObjectId)value.Value).instance); - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_COV_SUBSCRIPTION: - encode_cov_subscription(buffer, (BacnetCOVSubscription)value.Value); - //is this the right way to do it, I wonder? - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_READ_ACCESS_RESULT: - encode_read_access_result(buffer, (BacnetReadAccessResult)value.Value); - //is this the right way to do it, I wonder? - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_READ_ACCESS_SPECIFICATION: - encode_read_access_specification(buffer, (BacnetReadAccessSpecification)value.Value); - //is this the right way to do it, I wonder? - break; - case BacnetApplicationTags.BACNET_APPLICATION_TAG_DESTINATION: - switch (value.Value) - { - case BacnetObjectId oid: - EncodeApplicationDestination(buffer, oid.type, oid.instance); - break; - case BacnetAddress address: - EncodeApplicationDestination(buffer, address); - break; - default: - throw new ArgumentException($"Unsupported destination value '{value.Value}' (type {value.GetType()})"); - } - break; - default: - //context specific - if (value.Value is byte[] arr) - { - buffer?.Add(arr, arr.Length); - } - else - { - try - { - var oType = value.Value.GetType(); - if (oType.IsGenericType && oType.GetGenericTypeDefinition() == typeof(List<>)) - { - // last chance to encode a List - var t = (List)value.Value; - foreach (var o in t) - ((IEncode)o).Encode(buffer); - } - else - { - // last chance to encode a value - ((IEncode)value.Value).Encode(buffer); - } - } - catch - { - throw new Exception("I cannot encode this"); - } - } - break; - } - } - - public static void bacapp_encode_device_obj_property_ref(EncodeBuffer buffer, BacnetDeviceObjectPropertyReference value) - { - encode_context_object_id(buffer, 0, value.objectIdentifier.type, value.objectIdentifier.instance); - encode_context_enumerated(buffer, 1, (uint)value.propertyIdentifier); - - /* Array index is optional so check if needed before inserting */ - if (value.arrayIndex != BACNET_ARRAY_ALL) - encode_context_unsigned(buffer, 2, value.arrayIndex); - - /* Likewise, device id is optional so see if needed - * (set type to non device to omit */ - if (value.deviceIndentifier.type == BacnetObjectTypes.OBJECT_DEVICE) - encode_context_object_id(buffer, 3, value.deviceIndentifier.type, value.deviceIndentifier.instance); - } - - public static void bacapp_encode_context_device_obj_property_ref(EncodeBuffer buffer, byte tagNumber, BacnetDeviceObjectPropertyReference value) - { - encode_opening_tag(buffer, tagNumber); - bacapp_encode_device_obj_property_ref(buffer, value); - encode_closing_tag(buffer, tagNumber); - } - - public static void bacapp_encode_property_state(EncodeBuffer buffer, BacnetPropertyState value) - { - switch (value.tag) - { - case BacnetPropertyState.BacnetPropertyStateTypes.BOOLEAN_VALUE: - encode_context_boolean(buffer, 0, value.state.boolean_value); - break; - - case BacnetPropertyState.BacnetPropertyStateTypes.BINARY_VALUE: - encode_context_enumerated(buffer, 1, (uint)value.state.binaryValue); - break; - - case BacnetPropertyState.BacnetPropertyStateTypes.EVENT_TYPE: - encode_context_enumerated(buffer, 2, (uint)value.state.eventType); - break; - - case BacnetPropertyState.BacnetPropertyStateTypes.POLARITY: - encode_context_enumerated(buffer, 3, (uint)value.state.polarity); - break; - - case BacnetPropertyState.BacnetPropertyStateTypes.PROGRAM_CHANGE: - encode_context_enumerated(buffer, 4, (uint)value.state.programChange); - break; - - case BacnetPropertyState.BacnetPropertyStateTypes.PROGRAM_STATE: - encode_context_enumerated(buffer, 5, (uint)value.state.programState); - break; - - case BacnetPropertyState.BacnetPropertyStateTypes.REASON_FOR_HALT: - encode_context_enumerated(buffer, 6, (uint)value.state.programError); - break; - - case BacnetPropertyState.BacnetPropertyStateTypes.RELIABILITY: - encode_context_enumerated(buffer, 7, (uint)value.state.reliability); - break; - - case BacnetPropertyState.BacnetPropertyStateTypes.STATE: - encode_context_enumerated(buffer, 8, (uint)value.state.state); - break; - - case BacnetPropertyState.BacnetPropertyStateTypes.SYSTEM_STATUS: - encode_context_enumerated(buffer, 9, (uint)value.state.systemStatus); - break; - - case BacnetPropertyState.BacnetPropertyStateTypes.UNITS: - encode_context_enumerated(buffer, 10, (uint)value.state.units); - break; - - case BacnetPropertyState.BacnetPropertyStateTypes.UNSIGNED_VALUE: - encode_context_unsigned(buffer, 11, value.state.unsignedValue); - break; - - case BacnetPropertyState.BacnetPropertyStateTypes.LIFE_SAFETY_MODE: - encode_context_enumerated(buffer, 12, (uint)value.state.lifeSafetyMode); - break; - - case BacnetPropertyState.BacnetPropertyStateTypes.LIFE_SAFETY_STATE: - encode_context_enumerated(buffer, 13, (uint)value.state.lifeSafetyState); - break; - - default: - /* FIXME: assert(0); - return a negative len? */ - break; - } - } - - public static void encode_context_bitstring(EncodeBuffer buffer, byte tagNumber, BacnetBitString bitString) - { - uint bitStringEncodedLength = 1; /* 1 for the bits remaining octet */ - - /* bit string may use more than 1 octet for the tag, so find out how many */ - bitStringEncodedLength += bitstring_bytesUsed(bitString); - encode_tag(buffer, tagNumber, true, bitStringEncodedLength); - encode_bitstring(buffer, bitString); - } - - public static void encode_opening_tag(EncodeBuffer buffer, byte tagNumber) - { - var len = 1; - var tmp = new byte[2]; - - /* set class field to context specific */ - tmp[0] = 0x8; - /* additional tag byte after this byte for extended tag byte */ - if (tagNumber <= 14) - { - tmp[0] |= (byte)(tagNumber << 4); - } - else - { - tmp[0] |= 0xF0; - tmp[1] = tagNumber; - len++; - } - /* set type field to opening tag */ - tmp[0] |= 6; - - buffer.Add(tmp, len); - } - - public static void encode_context_signed(EncodeBuffer buffer, byte tagNumber, int value) - { - int len; /* return value */ - - /* length of signed int is variable, as per 20.2.11 */ - if (value >= -128 && value < 128) - len = 1; - else if (value >= -32768 && value < 32768) - len = 2; - else if (value > -8388608 && value < 8388608) - len = 3; - else - len = 4; - - encode_tag(buffer, tagNumber, true, (uint)len); - encode_bacnet_signed(buffer, value); - } - - public static void encode_context_object_id(EncodeBuffer buffer, byte tagNumber, BacnetObjectTypes objectType, uint instance) - { - encode_tag(buffer, tagNumber, true, 4); - encode_bacnet_object_id(buffer, objectType, instance); - } - - public static void encode_closing_tag(EncodeBuffer buffer, byte tagNumber) - { - var len = 1; - var tmp = new byte[2]; - - /* set class field to context specific */ - tmp[0] = 0x8; - /* additional tag byte after this byte for extended tag byte */ - if (tagNumber <= 14) - { - tmp[0] |= (byte)(tagNumber << 4); - } - else - { - tmp[0] |= 0xF0; - tmp[1] = tagNumber; - len++; - } - /* set type field to closing tag */ - tmp[0] |= 7; - - buffer.Add(tmp, len); - } - - public static void encode_bacnet_time(EncodeBuffer buffer, DateTime value) - { - buffer.Add((byte)value.Hour); - buffer.Add((byte)value.Minute); - buffer.Add((byte)value.Second); - buffer.Add((byte)(value.Millisecond / 10)); - } - - public static void encode_context_time(EncodeBuffer buffer, byte tagNumber, DateTime value) - { - encode_tag(buffer, tagNumber, true, 4); - encode_bacnet_time(buffer, value); - } - - public static void encode_bacnet_date(EncodeBuffer buffer, DateTime value) - { - if (value == new DateTime(1, 1, 1)) // this is the way decode do for 'Date any' = DateTime(0) - { - buffer.Add(0xFF); - buffer.Add(0xFF); - buffer.Add(0xFF); - buffer.Add(0xFF); - return; - } - - /* allow 2 digit years */ - if (value.Year >= 1900) - buffer.Add((byte)(value.Year - 1900)); - else if (value.Year < 0x100) - buffer.Add((byte)value.Year); - else - throw new Exception("Date is rubbish"); - - buffer.Add((byte)value.Month); - buffer.Add((byte)value.Day); - buffer.Add(value.DayOfWeek != DayOfWeek.Sunday - ? (byte)value.DayOfWeek - : (byte)7); - } - - public static void encode_application_date(EncodeBuffer buffer, DateTime value) - { - encode_tag(buffer, (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_DATE, false, 4); - encode_bacnet_date(buffer, value); - } - - public static void encode_application_time(EncodeBuffer buffer, DateTime value) - { - encode_tag(buffer, (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_TIME, false, 4); - encode_bacnet_time(buffer, value); - } - - public static void bacapp_encode_datetime(EncodeBuffer buffer, DateTime value) - { - if (value != new DateTime(1, 1, 1)) - { - encode_application_date(buffer, value); - encode_application_time(buffer, value); - } - } - - public static void bacapp_encode_context_datetime(EncodeBuffer buffer, byte tagNumber, DateTime value) - { - if (value != new DateTime(1, 1, 1)) - { - encode_opening_tag(buffer, tagNumber); - bacapp_encode_datetime(buffer, value); - encode_closing_tag(buffer, tagNumber); - } - } - - public static void bacapp_encode_timestamp(EncodeBuffer buffer, BacnetGenericTime value) - { - switch (value.Tag) - { - case BacnetTimestampTags.TIME_STAMP_TIME: - encode_context_time(buffer, 0, value.Time); - break; - - case BacnetTimestampTags.TIME_STAMP_SEQUENCE: - encode_context_unsigned(buffer, 1, value.Sequence); - break; - - case BacnetTimestampTags.TIME_STAMP_DATETIME: - bacapp_encode_context_datetime(buffer, 2, value.Time); - break; - - case BacnetTimestampTags.TIME_STAMP_NONE: - break; - - default: - throw new NotImplementedException(); - } - } - - public static void bacapp_encode_context_timestamp(EncodeBuffer buffer, byte tagNumber, BacnetGenericTime value) - { - if (value.Tag != BacnetTimestampTags.TIME_STAMP_NONE) - { - encode_opening_tag(buffer, tagNumber); - bacapp_encode_timestamp(buffer, value); - encode_closing_tag(buffer, tagNumber); - } - } - - public static void encode_application_character_string(EncodeBuffer buffer, string value) - { - var tmp = new EncodeBuffer(); - encode_bacnet_character_string(tmp, value); - - encode_tag(buffer, (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_CHARACTER_STRING, false, - (uint)tmp.offset); - buffer.Add(tmp.buffer, tmp.offset); - } - - public static void encode_bacnet_character_string(EncodeBuffer buffer, string value) - { - buffer.Add((byte)BacnetCharacterStringEncodings.CHARACTER_UTF8); - var bufUtf8 = Encoding.UTF8.GetBytes(value); // Encoding.ASCII depreciated : Addendum 135-2008k - buffer.Add(bufUtf8, bufUtf8.Length); - } - - public static void encode_unsigned16(EncodeBuffer buffer, ushort value) - { - buffer.Add((byte)((value & 0xff00) >> 8)); - buffer.Add((byte)((value & 0x00ff) >> 0)); - } - - public static void encode_unsigned24(EncodeBuffer buffer, uint value) - { - buffer.Add((byte)((value & 0xff0000) >> 16)); - buffer.Add((byte)((value & 0x00ff00) >> 8)); - buffer.Add((byte)((value & 0x0000ff) >> 0)); - } - - public static void encode_unsigned32(EncodeBuffer buffer, uint value) - { - buffer.Add((byte)((value & 0xff000000) >> 24)); - buffer.Add((byte)((value & 0x00ff0000) >> 16)); - buffer.Add((byte)((value & 0x0000ff00) >> 8)); - buffer.Add((byte)((value & 0x000000ff) >> 0)); - } - - public static void encode_signed16(EncodeBuffer buffer, short value) - { - buffer.Add((byte)((value & 0xff00) >> 8)); - buffer.Add((byte)((value & 0x00ff) >> 0)); - } - - public static void encode_signed24(EncodeBuffer buffer, int value) - { - buffer.Add((byte)((value & 0xff0000) >> 16)); - buffer.Add((byte)((value & 0x00ff00) >> 8)); - buffer.Add((byte)((value & 0x0000ff) >> 0)); - } - - public static void encode_signed32(EncodeBuffer buffer, int value) - { - buffer.Add((byte)((value & 0xff000000) >> 24)); - buffer.Add((byte)((value & 0x00ff0000) >> 16)); - buffer.Add((byte)((value & 0x0000ff00) >> 8)); - buffer.Add((byte)((value & 0x000000ff) >> 0)); - } - - public static void encode_signed64(EncodeBuffer buffer, long value) - { - buffer.Add((byte)(value >> 56)); - buffer.Add((byte)((value & 0xff000000000000) >> 48)); - buffer.Add((byte)((value & 0xff0000000000) >> 40)); - buffer.Add((byte)((value & 0xff00000000) >> 32)); - - buffer.Add((byte)((value & 0xff000000) >> 24)); - buffer.Add((byte)((value & 0x00ff0000) >> 16)); - buffer.Add((byte)((value & 0x0000ff00) >> 8)); - buffer.Add((byte)((value & 0x000000ff) >> 0)); - } - - public static void encode_read_access_specification(EncodeBuffer buffer, BacnetReadAccessSpecification value) - { - /* Tag 0: BACnetObjectIdentifier */ - encode_context_object_id(buffer, 0, value.objectIdentifier.type, value.objectIdentifier.instance); - - /* Tag 1: sequence of BACnetPropertyReference */ - encode_opening_tag(buffer, 1); - foreach (var p in value.propertyReferences) - { - encode_context_enumerated(buffer, 0, p.propertyIdentifier); - - /* optional array index */ - if (p.propertyArrayIndex != BACNET_ARRAY_ALL) - encode_context_unsigned(buffer, 1, p.propertyArrayIndex); - } - encode_closing_tag(buffer, 1); - } - - public static void encode_read_access_result(EncodeBuffer buffer, BacnetReadAccessResult value) - { - /* Tag 0: BACnetObjectIdentifier */ - encode_context_object_id(buffer, 0, value.objectIdentifier.type, value.objectIdentifier.instance); - - /* Tag 1: listOfResults */ - encode_opening_tag(buffer, 1); - foreach (var pValue in value.values) - { - /* Tag 2: propertyIdentifier */ - encode_context_enumerated(buffer, 2, pValue.property.propertyIdentifier); - /* Tag 3: optional propertyArrayIndex */ - if (pValue.property.propertyArrayIndex != BACNET_ARRAY_ALL) - encode_context_unsigned(buffer, 3, pValue.property.propertyArrayIndex); - - if (pValue.value != null && pValue.value[0].Value is BacnetError) - { - /* Tag 5: Error */ - encode_opening_tag(buffer, 5); - encode_application_enumerated(buffer, (uint)((BacnetError)pValue.value[0].Value).error_class); - encode_application_enumerated(buffer, (uint)((BacnetError)pValue.value[0].Value).error_code); - encode_closing_tag(buffer, 5); - } - else - { - /* Tag 4: Value */ - encode_opening_tag(buffer, 4); - foreach (var v in pValue.value) - { - bacapp_encode_application_data(buffer, v); - } - encode_closing_tag(buffer, 4); - } - } - encode_closing_tag(buffer, 1); - } - - public static int decode_read_access_result(BacnetAddress address, byte[] buffer, int offset, int apdu_len, out BacnetReadAccessResult value) - { - var len = 0; - - value = new BacnetReadAccessResult(); - - if (!decode_is_context_tag(buffer, offset + len, 0)) - return -1; - len = 1; - len += decode_object_id(buffer, offset + len, out value.objectIdentifier.type, - out value.objectIdentifier.instance); - - /* Tag 1: listOfResults */ - if (!decode_is_opening_tag_number(buffer, offset + len, 1)) - return -1; - len++; - - var valueList = new List(); - while (apdu_len - len > 0) - { - var new_entry = new BacnetPropertyValue(); - - /* end */ - if (decode_is_closing_tag_number(buffer, offset + len, 1)) - { - len++; - break; - } - - /* Tag 2: propertyIdentifier */ - len += decode_tag_number_and_value(buffer, offset + len, out var tagNumber, out var lenValueType); - if (tagNumber != 2) - return -1; - len += decode_enumerated(buffer, offset + len, lenValueType, out new_entry.property.propertyIdentifier); - /* Tag 3: Optional Array Index */ - var tagLen = decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - if (tagNumber == 3) - { - len += tagLen; - len += decode_unsigned(buffer, offset + len, lenValueType, - out new_entry.property.propertyArrayIndex); - } - else - new_entry.property.propertyArrayIndex = BACNET_ARRAY_ALL; - - /* Tag 4: Value */ - tagLen = decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - len += tagLen; - if (tagNumber == 4) - { - var localValueList = new List(); - while (!decode_is_closing_tag_number(buffer, offset + len, 4)) - { - tagLen = bacapp_decode_application_data(address, buffer, offset + len, apdu_len + offset - 1, - value.objectIdentifier.type, (BacnetPropertyIds)new_entry.property.propertyIdentifier, out var v); - if (tagLen < 0) return -1; - len += tagLen; - localValueList.Add(v); - } - // FC : two values one Date & one Time => change to one datetime - if (localValueList.Count == 2 && localValueList[0].Tag == BacnetApplicationTags.BACNET_APPLICATION_TAG_DATE && localValueList[1].Tag == BacnetApplicationTags.BACNET_APPLICATION_TAG_TIME) - { - var date = (DateTime)localValueList[0].Value; - var time = (DateTime)localValueList[1].Value; - var bdatetime = new DateTime(date.Year, date.Month, date.Day, time.Hour, time.Minute, time.Second, time.Millisecond); - localValueList.Clear(); - localValueList.Add(new BacnetValue(BacnetApplicationTags.BACNET_APPLICATION_TAG_DATETIME, bdatetime)); - new_entry.value = localValueList; - } - else - new_entry.value = localValueList; - len++; - } - else if (tagNumber == 5) - { - /* Tag 5: Error */ - var err = new BacnetError(); - len += decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - len += decode_enumerated(buffer, offset + len, lenValueType, out err.error_class); - len += decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - len += decode_enumerated(buffer, offset + len, lenValueType, out err.error_code); - if (!decode_is_closing_tag_number(buffer, offset + len, 5)) - return -1; - len++; - - new_entry.value = new[] { new BacnetValue(BacnetApplicationTags.BACNET_APPLICATION_TAG_ERROR, err) }; - } - - valueList.Add(new_entry); - } - value.values = valueList; - - return len; - } - - public static int decode_read_access_specification(byte[] buffer, int offset, int apdu_len, out BacnetReadAccessSpecification value) - { - var len = 0; - - value = new BacnetReadAccessSpecification(); - - /* Tag 0: Object ID */ - if (!decode_is_context_tag(buffer, offset + len, 0)) - return -1; - len++; - len += decode_object_id(buffer, offset + len, out value.objectIdentifier.type, - out value.objectIdentifier.instance); - - /* Tag 1: sequence of ReadAccessSpecification */ - if (!decode_is_opening_tag_number(buffer, offset + len, 1)) - return -1; - len++; /* opening tag is only one octet */ - - /* properties */ - var propertyIdAndArrayIndex = new List(); - while (apdu_len - len > 1 && !decode_is_closing_tag_number(buffer, offset + len, 1)) - { - var p_ref = new BacnetPropertyReference(); - - /* Tag 0: propertyIdentifier */ - if (!IS_CONTEXT_SPECIFIC(buffer[offset + len])) - return -1; - - len += decode_tag_number_and_value(buffer, offset + len, out var tagNumber, out var lenValue_type); - if (tagNumber != 0) - return -1; - - /* Should be at least the unsigned value + 1 tag left */ - if (len + lenValue_type >= apdu_len) - return -1; - len += decode_enumerated(buffer, offset + len, lenValue_type, out p_ref.propertyIdentifier); - /* Assume most probable outcome */ - p_ref.propertyArrayIndex = BACNET_ARRAY_ALL; - /* Tag 1: Optional propertyArrayIndex */ - if (IS_CONTEXT_SPECIFIC(buffer[offset + len]) && !IS_CLOSING_TAG(buffer[offset + len])) - { - var tmp = decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValue_type); - if (tagNumber == 1) - { - len += tmp; - /* Should be at least the unsigned array index + 1 tag left */ - if (len + lenValue_type >= apdu_len) - return -1; - len += decode_unsigned(buffer, offset + len, lenValue_type, out p_ref.propertyArrayIndex); - } - } - propertyIdAndArrayIndex.Add(p_ref); - } - - /* closing tag */ - if (!decode_is_closing_tag_number(buffer, offset + len, 1)) - return -1; - len++; - - value.propertyReferences = propertyIdAndArrayIndex; - return len; - } - - public static int decode_device_obj_property_ref(byte[] buffer, int offset, int apdu_len, out BacnetDeviceObjectPropertyReference value) - { - var len = 0; - - value = new BacnetDeviceObjectPropertyReference { arrayIndex = BACNET_ARRAY_ALL }; - - /* Tag 0: Object ID */ - if (!decode_is_context_tag(buffer, offset + len, 0)) - return -1; - - len++; - len += decode_object_id(buffer, offset + len, out value.objectIdentifier.type, - out value.objectIdentifier.instance); - - /* Tag 1 : Property identifier */ - len += decode_tag_number_and_value(buffer, offset + len, out var tagNumber, out var lenValueType); - if (tagNumber != 1) - return -1; - - len += decode_enumerated(buffer, offset + len, lenValueType, out value.propertyIdentifier); - - /* Tag 2: Optional Array Index */ - var tagLen = decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - if (tagNumber == 2) - { - len += tagLen; - len += decode_unsigned(buffer, offset + len, lenValueType, out value.arrayIndex); - } - - /* Tag 3 : Optional Device Identifier */ - if (!decode_is_context_tag(buffer, offset + len, 3)) - return len; - if (IS_CLOSING_TAG(buffer[offset + len])) return len; - - len++; - - len += decode_object_id(buffer, offset + len, out value.deviceIndentifier.type, - out value.deviceIndentifier.instance); - - return len; - } - - public static int decode_unsigned(byte[] buffer, int offset, uint lenValue, out uint value) - { - switch (lenValue) - { - case 1: - value = buffer[offset]; - break; - - case 2: - decode_unsigned16(buffer, offset, out var unsigned16Value); - value = unsigned16Value; - break; - - case 3: - decode_unsigned24(buffer, offset, out value); - break; - - case 4: - decode_unsigned32(buffer, offset, out value); - break; - - default: - value = 0; - break; - } - - return (int)lenValue; - } - - public static int decode_unsigned32(byte[] buffer, int offset, out uint value) - { - value = ((uint)buffer[offset + 0] << 24) & 0xff000000; - value |= ((uint)buffer[offset + 1] << 16) & 0x00ff0000; - value |= ((uint)buffer[offset + 2] << 8) & 0x0000ff00; - value |= (uint)buffer[offset + 3] & 0x000000ff; - return 4; - } - - public static int decode_unsigned24(byte[] buffer, int offset, out uint value) - { - value = ((uint)buffer[offset + 0] << 16) & 0x00ff0000; - value |= ((uint)buffer[offset + 1] << 8) & 0x0000ff00; - value |= (uint)buffer[offset + 2] & 0x000000ff; - return 3; - } - - public static int decode_unsigned16(byte[] buffer, int offset, out ushort value) - { - value = (ushort)(((uint)buffer[offset + 0] << 8) & 0x0000ff00); - value |= (ushort)((uint)buffer[offset + 1] & 0x000000ff); - return 2; - } - - public static int decode_unsigned8(byte[] buffer, int offset, out byte value) - { - value = buffer[offset + 0]; - return 1; - } - - public static int decode_signed32(byte[] buffer, int offset, out int value) - { - value = (int)((buffer[offset + 0] << 24) & 0xff000000); - value |= (buffer[offset + 1] << 16) & 0x00ff0000; - value |= (buffer[offset + 2] << 8) & 0x0000ff00; - value |= buffer[offset + 3] & 0x000000ff; - return 4; - } - - public static int decode_signed24(byte[] buffer, int offset, out int value) - { - value = (buffer[offset + 0] << 16) & 0x00ff0000; - value |= (buffer[offset + 1] << 8) & 0x0000ff00; - value |= buffer[offset + 2] & 0x000000ff; - if ((value & 0x800000) != 0) value |= 0xff << 24; // set sign - return 3; - } - - public static int decode_signed16(byte[] buffer, int offset, out short value) - { - value = (short)((buffer[offset + 0] << 8) & 0x0000ff00); - value |= (short)(buffer[offset + 1] & 0x000000ff); - return 2; - } - - public static int decode_signed8(byte[] buffer, int offset, out sbyte value) - { - value = (sbyte)buffer[offset + 0]; - return 1; - } - - public static bool IS_EXTENDED_TAG_NUMBER(byte x) - { - return (x & 0xF0) == 0xF0; - } - - public static bool IS_EXTENDED_VALUE(byte x) - { - return (x & 0x07) == 5; - } - - public static bool IS_CONTEXT_SPECIFIC(byte x) - { - return (x & 0x8) == 0x8; - } - - public static bool IS_OPENING_TAG(byte x) - { - return (x & 0x07) == 6; - } - - public static bool IS_CLOSING_TAG(byte x) - { - return (x & 0x07) == 7; - } - - public static int decode_tag_number(byte[] buffer, int offset, out byte tagNumber) - { - var len = 1; /* return value */ - - /* decode the tag number first */ - if (IS_EXTENDED_TAG_NUMBER(buffer[offset])) - { - /* extended tag */ - tagNumber = buffer[offset + 1]; - len++; - } - else - { - tagNumber = (byte)(buffer[offset] >> 4); - } - - return len; - } - - public static int decode_signed(byte[] buffer, int offset, uint lenValue, out int value) - { - switch (lenValue) - { - case 1: - decode_signed8(buffer, offset, out var sbyteValue); - value = sbyteValue; - break; - - case 2: - decode_signed16(buffer, offset, out var shortValue); - value = shortValue; - break; - - case 3: - decode_signed24(buffer, offset, out value); - break; - - case 4: - decode_signed32(buffer, offset, out value); - break; - - default: - value = 0; - break; - } - - return (int)lenValue; - } - - public static int decode_real(byte[] buffer, int offset, out float value) - { - byte[] tmp = { buffer[offset + 3], buffer[offset + 2], buffer[offset + 1], buffer[offset + 0] }; - value = BitConverter.ToSingle(tmp, 0); - return 4; - } - - public static int decode_real_safe(byte[] buffer, int offset, uint lenValue, out float value) - { - if (lenValue == 4) - return decode_real(buffer, offset, out value); - - value = 0.0f; - return (int)lenValue; - } - - public static int decode_double(byte[] buffer, int offset, out double value) - { - byte[] tmp = - { - buffer[offset + 7], buffer[offset + 6], buffer[offset + 5], buffer[offset + 4], - buffer[offset + 3], buffer[offset + 2], buffer[offset + 1], buffer[offset + 0] - }; - value = BitConverter.ToDouble(tmp, 0); - return 8; - } - - public static int decode_double_safe(byte[] buffer, int offset, uint lenValue, out double value) - { - if (lenValue == 8) - return decode_double(buffer, offset, out value); - - value = 0.0f; - return (int)lenValue; - } - - private static bool octetstring_copy(byte[] buffer, int offset, int maxOffset, byte[] octetString, int octetStringOffset, uint octetStringLength) - { - var status = false; /* return value */ - - if (octetStringLength <= maxOffset + offset) - { - if (octetString != null) - Array.Copy(buffer, offset, octetString, octetStringOffset, - Math.Min(octetString.Length, buffer.Length - offset)); - status = true; - } - - return status; - } - - public static int decode_octet_string(byte[] buffer, int offset, int maxLength, byte[] octetString, int octetStringOffset, uint octetStringLength) - { - octetstring_copy(buffer, offset, maxLength, octetString, octetStringOffset, octetStringLength); - var len = (int)octetStringLength; - - return len; - } - - public static int decode_context_octet_string(byte[] buffer, int offset, int maxLength, byte tagNumber, byte[] octetString, int octetStringOffset) - { - var len = 0; /* return value */ - - if (decode_is_context_tag(buffer, offset, tagNumber)) - { - len += decode_tag_number_and_value(buffer, offset + len, out tagNumber, out var lenValue); - - if (octetstring_copy(buffer, offset + len, maxLength, octetString, octetStringOffset, lenValue)) - { - len += (int)lenValue; - } - } - else - len = -1; - - return len; - } - - private static bool multi_charset_characterstring_decode(byte[] buffer, int offset, byte encoding, uint length, out string charString) - { - try - { - Encoding e; - - switch ((BacnetCharacterStringEncodings)encoding) - { - // 'normal' encoding, backward compatible ANSI_X34 (for decoding only) - case BacnetCharacterStringEncodings.CHARACTER_UTF8: - e = Encoding.UTF8; - break; - - // UCS2 is backward compatible UTF16 (for decoding only) - // http://hackipedia.org/Character%20sets/Unicode,%20UTF%20and%20UCS%20encodings/UCS-2.htm - // https://en.wikipedia.org/wiki/Byte_order_mark - case BacnetCharacterStringEncodings.CHARACTER_UCS2: - if (buffer[offset] == 0xFF && buffer[offset + 1] == 0xFE) // Byte Order Mark - e = Encoding.Unicode; // little endian encoding - else - e = Encoding.BigEndianUnicode; // big endian encoding if BOM is not set, or 0xFE-0xFF - break; - - // eq. UTF32. In usage somewhere for transmission ? A bad idea ! - case BacnetCharacterStringEncodings.CHARACTER_UCS4: - if (buffer[offset] == 0xFF && buffer[offset + 1] == 0xFE && buffer[offset + 2] == 0 && - buffer[offset + 3] == 0) - e = Encoding.UTF32; // UTF32 little endian encoding - else - e = Encoding.GetEncoding(12001); - // UTF32 big endian encoding if BOM is not set, or 0-0-0xFE-0xFF - break; - - case BacnetCharacterStringEncodings.CHARACTER_ISO8859: - e = Encoding.GetEncoding(28591); // "iso-8859-1" - break; - - // FIXME: somebody in Japan (or elsewhere) could help,test&validate if such devices exist ? - // http://cgproducts.johnsoncontrols.com/met_pdf/1201531.pdf?ref=binfind.com/web page 18 - case BacnetCharacterStringEncodings.CHARACTER_MS_DBCS: - e = Encoding.GetEncoding("shift_jis"); - break; - - // FIXME: somebody in Japan (or elsewhere) could help,test&validate if such devices exist ? - // http://www.sljfaq.org/afaq/encodings.html - case BacnetCharacterStringEncodings.CHARACTER_JISX_0208: - e = Encoding.GetEncoding("shift_jis"); // maybe "iso-2022-jp" ? - break; - - // unknown code (wrong code, experimental, ...) - // decoded as ISO-8859-1 (removing controls) : displays certainly a strange content ! - default: - var sb = new StringBuilder(); - for (var i = 0; i < length; i++) - { - var oneChar = (char)buffer[offset + i]; // byte to char on .NET : ISO-8859-1 - if (char.IsSymbol(oneChar)) sb.Append(oneChar); - } - charString = sb.ToString(); - return true; - } - - charString = e.GetString(buffer, offset, (int)length); - } - catch - { - charString = "string decoding error !"; - } - - return true; // always OK - } - - public static int decode_character_string(byte[] buffer, int offset, int maxLength, uint lenValue, out string charString) - { - var len = 0; /* return value */ - - var status = multi_charset_characterstring_decode(buffer, offset + 1, buffer[offset], lenValue - 1, out charString); - if (status) - { - len = (int)lenValue; - } - - return len; - } - - private static void bitstring_set_octet(ref BacnetBitString bitString, byte index, byte octet) - { - if (index < MAX_BITSTRING_BYTES) - bitString.value[index] = octet; - } - - private static void bitstring_set_bits_used(ref BacnetBitString bitString, byte bytesUsed, byte unusedBits) - { - /* FIXME: check that bytesUsed is at least one? */ - bitString.bits_used = (byte)(bytesUsed * 8); - bitString.bits_used -= unusedBits; - } - - public static int decode_bitstring(byte[] buffer, int offset, uint lenValue, out BacnetBitString bitString) - { - var len = 0; - - bitString = new BacnetBitString { value = new byte[MAX_BITSTRING_BYTES] }; - if (lenValue > 0) - { - /* the first octet contains the unused bits */ - var bytesUsed = lenValue - 1; - if (bytesUsed <= MAX_BITSTRING_BYTES) - { - len = 1; - for (uint i = 0; i < bytesUsed; i++) - { - bitstring_set_octet(ref bitString, (byte)i, byte_reverse_bits(buffer[offset + len++])); - } - var unusedBits = (byte)(buffer[offset] & 0x07); - bitstring_set_bits_used(ref bitString, (byte)bytesUsed, unusedBits); - } - } - - return len; - } - - public static int decode_context_character_string(byte[] buffer, int offset, int maxLength, byte tagNumber, out string charString) - { - var len = 0; /* return value */ - - charString = null; - if (decode_is_context_tag(buffer, offset + len, tagNumber)) - { - len += decode_tag_number_and_value(buffer, offset + len, out tagNumber, out var lenValue); - - var status = multi_charset_characterstring_decode(buffer, offset + 1 + len, buffer[offset + len], lenValue - 1, out charString); - - if (status) - len += (int)lenValue; - } - else - len = -1; - - return len; - } - - public static int decode_date(byte[] buffer, int offset, out DateTime bdate) - { - int year = (ushort)(buffer[offset] + 1900); - int month = buffer[offset + 1]; - int day = buffer[offset + 2]; - int wday = buffer[offset + 3]; - - if (month == 0xFF && day == 0xFF && wday == 0xFF && year - 1900 == 0xFF) - bdate = new DateTime(1, 1, 1); - else - bdate = new DateTime(year, month, day); - - return 4; - } - - public static int decode_date_safe(byte[] buffer, int offset, uint lenValue, out DateTime bdate) - { - if (lenValue == 4) - return decode_date(buffer, offset, out bdate); - - bdate = new DateTime(1, 1, 1); - return (int)lenValue; - } - - public static int decode_bacnet_time(byte[] buffer, int offset, out DateTime btime) - { - int hour = buffer[offset + 0]; - int min = buffer[offset + 1]; - int sec = buffer[offset + 2]; - int hundredths = buffer[offset + 3]; - if (hour == 0xFF && min == 0xFF && sec == 0xFF && hundredths == 0xFF) - { - btime = new DateTime(1, 1, 1); - } - else - { - if (hundredths > 100) hundredths = 0; // sometimes set to 255 - btime = new DateTime(1, 1, 1, hour, min, sec, hundredths * 10); - } - return 4; - } - - public static int decode_bacnet_time_safe(byte[] buffer, int offset, uint lenValue, out DateTime btime) - { - if (lenValue == 4) - return decode_bacnet_time(buffer, offset, out btime); - - btime = new DateTime(1, 1, 1); - return (int)lenValue; - } - - public static int decode_bacnet_datetime(byte[] buffer, int offset, out DateTime bdatetime) - { - var len = 0; - len += decode_application_date(buffer, offset + len, out var date); // Date - len += decode_application_time(buffer, offset + len, out var time); // Time - bdatetime = new DateTime(date.Year, date.Month, date.Day, time.Hour, time.Minute, time.Second, time.Millisecond); - return len; - } - - public static int decode_object_id(byte[] buffer, int offset, out ushort objectType, out uint instance) - { - var len = decode_unsigned32(buffer, offset, out var value); - objectType = (ushort)((value >> BACNET_INSTANCE_BITS) & BACNET_MAX_OBJECT); - instance = value & BACNET_MAX_INSTANCE; - - return len; - } - - public static int decode_object_id_safe(byte[] buffer, int offset, uint lenValue, out ushort objectType, out uint instance) - { - if (lenValue == 4) - return decode_object_id(buffer, offset, out objectType, out instance); - - objectType = 0; - instance = 0; - return 0; - } - - public static int decode_context_object_id(byte[] buffer, int offset, byte tagNumber, out ushort objectType, out uint instance) - { - var len = 0; - - if (decode_is_context_tag_with_length(buffer, offset + len, tagNumber, out len)) - { - len += decode_object_id(buffer, offset + len, out objectType, out instance); - } - else - { - objectType = 0; - instance = 0; - len = -1; - } - return len; - } - - public static int decode_application_time(byte[] buffer, int offset, out DateTime btime) - { - var len = 0; - decode_tag_number(buffer, offset + len, out var tagNumber); - - if (tagNumber == (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_TIME) - { - len++; - len += decode_bacnet_time(buffer, offset + len, out btime); - } - else - { - btime = new DateTime(1, 1, 1); - len = -1; - } - return len; - } - - public static int decode_context_bacnet_time(byte[] buffer, int offset, byte tagNumber, out DateTime btime) - { - var len = 0; - - if (decode_is_context_tag_with_length(buffer, offset + len, tagNumber, out len)) - { - len += decode_bacnet_time(buffer, offset + len, out btime); - } - else - { - btime = new DateTime(1, 1, 1); - len = -1; - } - return len; - } - - public static int decode_application_date(byte[] buffer, int offset, out DateTime bdate) - { - var len = 0; - decode_tag_number(buffer, offset + len, out var tagNumber); - - if (tagNumber == (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_DATE) - { - len++; - len += decode_date(buffer, offset + len, out bdate); - } - else - { - bdate = new DateTime(1, 1, 1); - len = -1; - } - return len; - } - - public static bool decode_is_context_tag_with_length(byte[] buffer, int offset, byte tagNumber, out int tagLength) - { - tagLength = decode_tag_number(buffer, offset, out var myTagNumber); - return IS_CONTEXT_SPECIFIC(buffer[offset]) && myTagNumber == tagNumber; - } - - public static int decode_context_date(byte[] buffer, int offset, byte tagNumber, out DateTime bdate) - { - var len = 0; - - if (decode_is_context_tag_with_length(buffer, offset + len, tagNumber, out len)) - { - len += decode_date(buffer, offset + len, out bdate); - } - else - { - bdate = new DateTime(1, 1, 1); - len = -1; - } - return len; - } - - public static int bacapp_decode_data(byte[] buffer, int offset, int maxLength, BacnetApplicationTags tagDataType, uint lenValueType, out BacnetValue value) - { - var len = 0; - uint uintValue; - - value = new BacnetValue { Tag = tagDataType }; - - switch (tagDataType) - { - case BacnetApplicationTags.BACNET_APPLICATION_TAG_NULL: - /* nothing else to do */ - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_BOOLEAN: - value.Value = lenValueType > 0; - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT: - len = decode_unsigned(buffer, offset, lenValueType, out uintValue); - value.Value = uintValue; - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_SIGNED_INT: - len = decode_signed(buffer, offset, lenValueType, out var intValue); - value.Value = intValue; - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_REAL: - len = decode_real_safe(buffer, offset, lenValueType, out var floatValue); - value.Value = floatValue; - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_DOUBLE: - len = decode_double_safe(buffer, offset, lenValueType, out var doubleValue); - value.Value = doubleValue; - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_OCTET_STRING: - var octetString = new byte[lenValueType]; - len = decode_octet_string(buffer, offset, maxLength, octetString, 0, lenValueType); - value.Value = octetString; - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_CHARACTER_STRING: - len = decode_character_string(buffer, offset, maxLength, lenValueType, out var stringValue); - value.Value = stringValue; - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_BIT_STRING: - len = decode_bitstring(buffer, offset, lenValueType, out var bitValue); - value.Value = bitValue; - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_ENUMERATED: - len = decode_enumerated(buffer, offset, lenValueType, out value.Value); - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_DATE: - len = decode_date_safe(buffer, offset, lenValueType, out var dateValue); - value.Value = dateValue; - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_TIME: - len = decode_bacnet_time_safe(buffer, offset, lenValueType, out var timeValue); - value.Value = timeValue; - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID: - len = decode_object_id_safe(buffer, offset, lenValueType, out var objectType, out var instance); - value.Value = new BacnetObjectId((BacnetObjectTypes)objectType, instance); - break; - } - - return len; - } - - /* returns the fixed tag type for certain context tagged properties */ - - private static BacnetApplicationTags bacapp_context_tag_type(BacnetAddress address, BacnetPropertyIds property, byte tagNumber) - { - var tag = BacnetApplicationTags.MAX_BACNET_APPLICATION_TAG; - - switch (property) - { - case BacnetPropertyIds.PROP_ACTUAL_SHED_LEVEL: - case BacnetPropertyIds.PROP_REQUESTED_SHED_LEVEL: - case BacnetPropertyIds.PROP_EXPECTED_SHED_LEVEL: - switch (tagNumber) - { - case 0: - case 1: - tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT; - break; - - case 2: - tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_REAL; - break; - } - break; - - case BacnetPropertyIds.PROP_ACTION: - switch (tagNumber) - { - case 0: - case 1: - tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID; - break; - - case 2: - tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_ENUMERATED; - break; - - case 3: - case 5: - case 6: - tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT; - break; - - case 7: - case 8: - tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_BOOLEAN; - break; - - case 4: /* propertyValue: abstract syntax */ - break; - } - break; - - case BacnetPropertyIds.PROP_LIST_OF_GROUP_MEMBERS: - /* Sequence of ReadAccessSpecification */ - switch (tagNumber) - { - case 0: - tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID; - break; - } - break; - - case BacnetPropertyIds.PROP_EXCEPTION_SCHEDULE: - switch (tagNumber) - { - case 1: - tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID; - break; - - case 3: - tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT; - break; - - case 0: /* calendarEntry: abstract syntax + context */ - case 2: /* list of BACnetTimeValue: abstract syntax */ - break; - } - break; - - case BacnetPropertyIds.PROP_LOG_DEVICE_OBJECT_PROPERTY: - switch (tagNumber) - { - case 0: /* Object ID */ - case 3: /* Device ID */ - tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID; - break; - - case 1: /* Property ID */ - tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_ENUMERATED; - break; - - case 2: /* Array index */ - tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT; - break; - } - break; - - case BacnetPropertyIds.PROP_SUBORDINATE_LIST: - case BacnetPropertyIds.PROP_ZONE_MEMBERS: - /* BACnetARRAY[N] of BACnetDeviceObjectReference */ - switch (tagNumber) - { - case 0: /* Optional Device ID */ - case 1: /* Object ID */ - tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID; - break; - } - break; - - case BacnetPropertyIds.PROP_RECIPIENT_LIST: - /* List of BACnetDestination */ - switch (tagNumber) - { - case 0: /* Device Object ID */ - tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID; - break; - } - break; - - case BacnetPropertyIds.PROP_ACTIVE_COV_SUBSCRIPTIONS: - /* BACnetCOVSubscription */ - switch (tagNumber) - { - case 0: /* BACnetRecipientProcess */ - case 1: /* BACnetObjectPropertyReference */ - break; - - case 2: /* issueConfirmedNotifications */ - tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_BOOLEAN; - break; - - case 3: /* timeRemaining */ - tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT; - break; - - case 4: /* covIncrement */ - tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_REAL; - break; - } - break; - default: - tag = CustomTagResolver?.Invoke(address, property, tagNumber) ?? tag; - break; - } - - return tag; - } - - public static int bacapp_decode_context_data(byte[] buffer, int offset, uint maxAPDULen, BacnetApplicationTags propertyTag, out BacnetValue value) - { - int apduLen = 0, len = 0; - - value = new BacnetValue(); - - if (IS_CONTEXT_SPECIFIC(buffer[offset])) - { - //value->context_specific = true; - var tagLen = decode_tag_number_and_value(buffer, offset + len, out var tagNumber, out var lenValueType); - apduLen = tagLen; - /* Empty construct : (closing tag) => returns NULL value */ - if (tagLen > 0 && tagLen <= maxAPDULen && - !decode_is_closing_tag_number(buffer, offset + len, tagNumber)) - { - //value->context_tag = tagNumber; - if (propertyTag < BacnetApplicationTags.MAX_BACNET_APPLICATION_TAG) - { - len = bacapp_decode_data(buffer, offset + apduLen, (int)maxAPDULen, propertyTag, - lenValueType, out value); - apduLen += len; - } - else if (lenValueType > 0) - { - /* Unknown value : non null size (elementary type) */ - apduLen += (int)lenValueType; - /* SHOULD NOT HAPPEN, EXCEPTED WHEN READING UNKNOWN CONTEXTUAL PROPERTY */ - } - else - apduLen = -1; - } - else if (tagLen == 1) /* and is a Closing tag */ - apduLen = 0; /* Don't advance over that closing tag. */ - } - - return apduLen; - } - - public static int bacapp_decode_application_data(BacnetAddress address, byte[] buffer, int offset, int maxOffset, BacnetObjectTypes objectType, BacnetPropertyIds propertyId, out BacnetValue value) - { - var len = 0; - - value = new BacnetValue(); - - /* FIXME: use max_apdu_len! */ - if (!IS_CONTEXT_SPECIFIC(buffer[offset])) - { - var tagLen = decode_tag_number_and_value(buffer, offset, out BacnetApplicationTags tagNumber, out uint lenValueType); - if (tagLen > 0) - { - len += tagLen; - var decodeLen = bacapp_decode_data(buffer, offset + len, maxOffset, tagNumber, lenValueType, out value); - if (decodeLen < 0) return decodeLen; - len += decodeLen; - } - } - else - { - return bacapp_decode_context_application_data(address, buffer, offset, maxOffset, objectType, propertyId, - out value); - } - - return len; - } - - public static int bacapp_decode_context_application_data(BacnetAddress address, byte[] buffer, int offset, int maxOffset, BacnetObjectTypes objectType, BacnetPropertyIds propertyId, out BacnetValue value) - { - var len = 0; - - value = new BacnetValue(); - - if (IS_CONTEXT_SPECIFIC(buffer[offset])) - { - int tagLen; - uint lenValueType; - byte tagNumber; - - //this seems to be a strange way to determine object encodings - if (propertyId == BacnetPropertyIds.PROP_LIST_OF_GROUP_MEMBERS) - { - tagLen = decode_read_access_specification(buffer, offset, maxOffset, out var v); - if (tagLen < 0) return -1; - value.Tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_READ_ACCESS_SPECIFICATION; - value.Value = v; - return tagLen; - } - if (propertyId == BacnetPropertyIds.PROP_ACTIVE_COV_SUBSCRIPTIONS) - { - tagLen = decode_cov_subscription(buffer, offset, maxOffset, out var v); - if (tagLen < 0) return -1; - value.Tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_COV_SUBSCRIPTION; - value.Value = v; - return tagLen; - } - if (objectType == BacnetObjectTypes.OBJECT_GROUP && propertyId == BacnetPropertyIds.PROP_PRESENT_VALUE) - { - tagLen = decode_read_access_result(address, buffer, offset, maxOffset, out BacnetReadAccessResult v); - if (tagLen < 0) return -1; - value.Tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_READ_ACCESS_RESULT; - value.Value = v; - return tagLen; - } - if (propertyId == BacnetPropertyIds.PROP_LIST_OF_OBJECT_PROPERTY_REFERENCES || - propertyId == BacnetPropertyIds.PROP_LOG_DEVICE_OBJECT_PROPERTY || - propertyId == BacnetPropertyIds.PROP_OBJECT_PROPERTY_REFERENCE) - { - tagLen = decode_device_obj_property_ref(buffer, offset, maxOffset, out var v); - if (tagLen < 0) return -1; - value.Tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_PROPERTY_REFERENCE; - value.Value = v; - return tagLen; - } - if (propertyId == BacnetPropertyIds.PROP_DATE_LIST) - { - var v = new BACnetCalendarEntry(); - tagLen = v.Decode(buffer, offset, (uint)maxOffset); - if (tagLen < 0) return -1; - value.Tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_CONTEXT_SPECIFIC_DECODED; - value.Value = v; - return tagLen; - } - if (propertyId == BacnetPropertyIds.PROP_EVENT_TIME_STAMPS) - { - decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - len++; // skip Tag - - if (tagNumber == 0) // Time without date - { - len += decode_bacnet_time(buffer, offset + len, out var dt); - value.Tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_TIMESTAMP; - value.Value = dt; - } - else if (tagNumber == 1) // sequence number - { - len += decode_unsigned(buffer, offset + len, lenValueType, out var val); - value.Tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT; - value.Value = val; - } - else if (tagNumber == 2) // date + time - { - len += decode_bacnet_datetime(buffer, offset + len, out var dt); - value.Tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_TIMESTAMP; - len++; // closing Tag - value.Value = dt; - } - else - return -1; - - return len; - } - - value.Tag = BacnetApplicationTags.BACNET_APPLICATION_TAG_CONTEXT_SPECIFIC_DECODED; - var list = new List(); - - decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - // If an opening tag is not present, no loop to get the values - var multiplValue = IS_OPENING_TAG(buffer[offset + len]); - - while (len + offset <= maxOffset && !IS_CLOSING_TAG(buffer[offset + len])) - { - tagLen = decode_tag_number_and_value(buffer, offset + len, out var subTagNumber, out lenValueType); - if (tagLen < 0) return -1; - - // DAL need to check explicitly for an opening tag, because, - // lenValueType could also be zero for example if we are parsing - // an empty octect string, or an integer value of zero - // The former happens when parsing the BACnetAddress within a RecipientList - // if the BACnetAddress has a broadcast MAC address - if (IS_OPENING_TAG(buffer[offset + len])) - { - len += tagLen; - tagLen = bacapp_decode_application_data(address, buffer, offset + len, maxOffset, - BacnetObjectTypes.MAX_BACNET_OBJECT_TYPE, BacnetPropertyIds.MAX_BACNET_PROPERTY_ID, - out var subValue); - if (tagLen < 0) return -1; - list.Add(subValue); - len += tagLen; - } - else - { - //override tagNumber - var overrideTagNumber = bacapp_context_tag_type(address, propertyId, subTagNumber); - if (overrideTagNumber != BacnetApplicationTags.MAX_BACNET_APPLICATION_TAG) - subTagNumber = (byte)overrideTagNumber; - - //try app decode - var subTagLen = bacapp_decode_data(buffer, offset + len + tagLen, maxOffset, - (BacnetApplicationTags)subTagNumber, lenValueType, out var subValue); - if (subTagLen == (int)lenValueType) - { - list.Add(subValue); - len += tagLen + (int)lenValueType; - } - else - { - //fallback to copy byte array - var contextSpecific = new byte[(int)lenValueType]; - Array.Copy(buffer, offset + len + tagLen, contextSpecific, 0, (int)lenValueType); - subValue = - new BacnetValue(BacnetApplicationTags.BACNET_APPLICATION_TAG_CONTEXT_SPECIFIC_ENCODED, - contextSpecific); - - list.Add(subValue); - len += tagLen + (int)lenValueType; - } - } - - if (multiplValue == false) - { - value = list[0]; - return len; - } - } - if (len + offset > maxOffset) return -1; - - //end tag - if (decode_is_closing_tag_number(buffer, offset + len, tagNumber)) - len++; - - //context specifique is array of BACNET_VALUE - value.Value = list.ToArray(); - } - else - { - return -1; - } - - return len; - } - - public static int decode_object_id(byte[] buffer, int offset, out BacnetObjectTypes objectType, out uint instance) - { - var len = decode_unsigned32(buffer, offset, out var value); - objectType = (BacnetObjectTypes)((value >> BACNET_INSTANCE_BITS) & BACNET_MAX_OBJECT); - instance = value & BACNET_MAX_INSTANCE; - - return len; - } - - public static int decode_enumerated(byte[] buffer, int offset, uint lenValue, out uint value) - { - var len = decode_unsigned(buffer, offset, lenValue, out value); - return len; - } - - public static int decode_enumerated(byte[] buffer, int offset, uint lenValue, out TEnum value) - { - var len = decode_enumerated(buffer, offset, lenValue, out var rawValue); - value = (TEnum)(dynamic)rawValue; - return len; - } - - public static bool decode_is_context_tag(byte[] buffer, int offset, byte tagNumber) - { - decode_tag_number(buffer, offset, out var myTagNumber); - return IS_CONTEXT_SPECIFIC(buffer[offset]) && myTagNumber == tagNumber; - } - - public static bool decode_is_opening_tag_number(byte[] buffer, int offset, byte tagNumber) - { - decode_tag_number(buffer, offset, out var myTagNumber); - return IS_OPENING_TAG(buffer[offset]) && myTagNumber == tagNumber; - } - - public static bool decode_is_closing_tag_number(byte[] buffer, int offset, byte tagNumber) - { - decode_tag_number(buffer, offset, out var myTagNumber); - return IS_CLOSING_TAG(buffer[offset]) && myTagNumber == tagNumber; - } - - public static bool decode_is_closing_tag(byte[] buffer, int offset) - { - return (buffer[offset] & 0x07) == 7; - } - - public static bool decode_is_opening_tag(byte[] buffer, int offset) - { - return (buffer[offset] & 0x07) == 6; - } - - public static int decode_tag_number_and_value(byte[] buffer, int offset, out byte tagNumber, out uint value) - { - var len = decode_tag_number(buffer, offset, out tagNumber); - if (IS_EXTENDED_VALUE(buffer[offset])) - { - /* tagged as uint32_t */ - if (buffer[offset + len] == 255) - { - len++; - len += decode_unsigned32(buffer, offset + len, out var value32); - value = value32; - } - /* tagged as uint16_t */ - else if (buffer[offset + len] == 254) - { - len++; - len += decode_unsigned16(buffer, offset + len, out var value16); - value = value16; - } - /* no tag - must be uint8_t */ - else - { - value = buffer[offset + len]; - len++; - } - } - else if (IS_OPENING_TAG(buffer[offset])) - { - value = 0; - } - else if (IS_CLOSING_TAG(buffer[offset])) - { - /* closing tag */ - value = 0; - } - else - { - /* small value */ - value = (uint)(buffer[offset] & 0x07); - } - - return len; - } - - public static int decode_tag_number_and_value(byte[] buffer, int offset, out TTag tag, out TValue value) - { - var len = decode_tag_number_and_value(buffer, offset, out var rawByte, out var rawValue); - tag = (TTag)(dynamic)rawByte; - value = (TValue)(dynamic)rawValue; - return len; - } - - /// - /// This is used by the Active_COV_Subscriptions property in DEVICE - /// - public static void encode_cov_subscription(EncodeBuffer buffer, BacnetCOVSubscription value) - { - /* Recipient [0] BACnetRecipientProcess - opening */ - encode_opening_tag(buffer, 0); - - /* recipient [0] BACnetRecipient - opening */ - encode_opening_tag(buffer, 0); - /* CHOICE - device [0] BACnetObjectIdentifier - opening */ - /* CHOICE - address [1] BACnetAddress - opening */ - encode_opening_tag(buffer, 1); - /* network-number Unsigned16, */ - /* -- A value of 0 indicates the local network */ - encode_application_unsigned(buffer, value.Recipient.net); - /* mac-address OCTET STRING */ - /* -- A string of length 0 indicates a broadcast */ - if (value.Recipient.net == 0xFFFF) - encode_application_octet_string(buffer, new byte[0], 0, 0); - else - encode_application_octet_string(buffer, value.Recipient.adr, 0, value.Recipient.adr.Length); - /* CHOICE - address [1] BACnetAddress - closing */ - encode_closing_tag(buffer, 1); - /* recipient [0] BACnetRecipient - closing */ - encode_closing_tag(buffer, 0); - - /* processIdentifier [1] Unsigned32 */ - encode_context_unsigned(buffer, 1, value.subscriptionProcessIdentifier); - /* Recipient [0] BACnetRecipientProcess - closing */ - encode_closing_tag(buffer, 0); - - /* MonitoredPropertyReference [1] BACnetObjectPropertyReference, */ - encode_opening_tag(buffer, 1); - /* objectIdentifier [0] */ - encode_context_object_id(buffer, 0, value.monitoredObjectIdentifier.type, - value.monitoredObjectIdentifier.instance); - /* propertyIdentifier [1] */ - /* FIXME: we are monitoring 2 properties! How to encode? */ - encode_context_enumerated(buffer, 1, value.monitoredProperty.propertyIdentifier); - if (value.monitoredProperty.propertyArrayIndex != BACNET_ARRAY_ALL) - encode_context_unsigned(buffer, 2, value.monitoredProperty.propertyArrayIndex); - /* MonitoredPropertyReference [1] - closing */ - encode_closing_tag(buffer, 1); - - /* IssueConfirmedNotifications [2] BOOLEAN, */ - encode_context_boolean(buffer, 2, value.IssueConfirmedNotifications); - /* TimeRemaining [3] Unsigned, */ - encode_context_unsigned(buffer, 3, value.TimeRemaining); - /* COVIncrement [4] REAL OPTIONAL, */ - if (value.COVIncrement > 0) - encode_context_real(buffer, 4, value.COVIncrement); - } - - public static int decode_cov_subscription(byte[] buffer, int offset, int apduLen, out BacnetCOVSubscription value) - { - var len = 0; - - value = new BacnetCOVSubscription { Recipient = new BacnetAddress(BacnetAddressTypes.None, 0, null) }; - - if (!decode_is_opening_tag_number(buffer, offset + len, 0)) - return -1; - len++; - if (!decode_is_opening_tag_number(buffer, offset + len, 0)) - return -1; - len++; - if (!decode_is_opening_tag_number(buffer, offset + len, 1)) - return -1; - len++; - len += decode_tag_number_and_value(buffer, offset + len, out var tagNumber, out var lenValueType); - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT) - return -1; - len += decode_unsigned(buffer, offset + len, lenValueType, out var tmp); - value.Recipient.net = (ushort)tmp; - len += decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_OCTET_STRING) - return -1; - value.Recipient.adr = new byte[lenValueType]; - len += decode_octet_string(buffer, offset + len, apduLen, value.Recipient.adr, 0, lenValueType); - if (!decode_is_closing_tag_number(buffer, offset + len, 1)) - return -1; - len++; - if (!decode_is_closing_tag_number(buffer, offset + len, 0)) - return -1; - len++; - - len += decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - if (tagNumber != 1) - return -1; - len += decode_unsigned(buffer, offset + len, lenValueType, out value.subscriptionProcessIdentifier); - if (!decode_is_closing_tag_number(buffer, offset + len, 0)) - return -1; - len++; - - if (!decode_is_opening_tag_number(buffer, offset + len, 1)) - return -1; - len++; - len += decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - if (tagNumber != 0) - return -1; - len += decode_object_id(buffer, offset + len, out value.monitoredObjectIdentifier.type, - out value.monitoredObjectIdentifier.instance); - len += decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - if (tagNumber != 1) - return -1; - len += decode_enumerated(buffer, offset + len, lenValueType, - out value.monitoredProperty.propertyIdentifier); - var tagLen = decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - if (tagNumber == 2) - { - len += tagLen; - len += decode_unsigned(buffer, offset + len, lenValueType, - out value.monitoredProperty.propertyArrayIndex); - } - else - value.monitoredProperty.propertyArrayIndex = BACNET_ARRAY_ALL; - if (!decode_is_closing_tag_number(buffer, offset + len, 1)) - return -1; - len++; - - len += decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - if (tagNumber != 2) - return -1; - value.IssueConfirmedNotifications = buffer[offset + len] > 0; - len++; - - len += decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - if (tagNumber != 3) - return -1; - len += decode_unsigned(buffer, offset + len, lenValueType, out value.TimeRemaining); - - if (len < apduLen && !IS_CLOSING_TAG(buffer[offset + len])) - { - decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - if (tagNumber != 4) - return len; - len++; - len += decode_real(buffer, offset + len, out value.COVIncrement); - } - - return len; - } - - public static int decode_context_property_state(byte[] buffer, int offset, byte tagNumber, out BacnetPropertyState value) - { - if (!decode_is_opening_tag_number(buffer, offset, tagNumber)) - { - value = default; - return -1; - } - - var len = 1; - var sectionLength = decode_property_state(buffer, offset + len, out value); - if (sectionLength == -1) - return -1; - - len += sectionLength; - if (!decode_is_closing_tag_number(buffer, offset + len, tagNumber)) - return -1; - - return len + 1; - } - - public static int decode_property_state(byte[] buffer, int offset, out BacnetPropertyState value) - { - value = default; - - var len = decode_tag_number_and_value(buffer, offset, out value.tag, out uint lenValueType); - if (len == -1) - return -1; - - var sectionLength = 0; - switch (value.tag) - { - case BacnetPropertyState.BacnetPropertyStateTypes.BOOLEAN_VALUE: - value.state.boolean_value = lenValueType == 1; - break; - - case BacnetPropertyState.BacnetPropertyStateTypes.BINARY_VALUE: - sectionLength = decode_enumerated(buffer, offset + len, lenValueType, out value.state.binaryValue); - if (sectionLength == -1) - return -1; - break; - - case BacnetPropertyState.BacnetPropertyStateTypes.EVENT_TYPE: - sectionLength = decode_enumerated(buffer, offset + len, lenValueType, out value.state.eventType); - if (sectionLength == -1) - return -1; - break; - - case BacnetPropertyState.BacnetPropertyStateTypes.STATE: - sectionLength = decode_enumerated(buffer, offset + len, lenValueType, out value.state.state); - if (sectionLength == -1) - return -1; - break; - - case BacnetPropertyState.BacnetPropertyStateTypes.UNSIGNED_VALUE: - sectionLength = decode_unsigned(buffer, offset + len, lenValueType, out value.state.unsignedValue); - if (sectionLength == -1) - return -1; - break; - - default: - return -1; - } - - return len + sectionLength; - } - - public static int decode_context_bitstring(byte[] buffer, int offset, byte tagNumber, out BacnetBitString value) - { - if (!decode_is_context_tag(buffer, offset, tagNumber) || decode_is_closing_tag(buffer, offset)) - { - value = new BacnetBitString(); - return -1; // BACNET_STATUS_ERROR - } - - var len = decode_tag_number_and_value(buffer, offset, out _, out var lenValue); - return len + decode_bitstring(buffer, offset + len, lenValue, out value); - } - - public static int decode_context_real(byte[] buffer, int offset, byte tagNumber, out float value) - { - if (!decode_is_context_tag(buffer, offset, tagNumber)) - { - value = 0; - return -1; - } - - var len = decode_tag_number_and_value(buffer, offset, out _, out _); - return len + decode_real(buffer, offset + len, out value); - } - - public static int decode_context_enumerated(byte[] buffer, int offset, byte tagNumber, out TEnum value) - { - if (!decode_is_context_tag(buffer, offset, tagNumber) || decode_is_closing_tag(buffer, offset)) - { - value = default; - return -1; - } - - var len = decode_tag_number_and_value(buffer, offset, out _, out var lenValue); - return len + decode_enumerated(buffer, offset + len, lenValue, out value); - } - - public static int decode_context_unsigned(byte[] buffer, int offset, byte tagNumber, out uint value) - { - if (!decode_is_context_tag(buffer, offset, tagNumber) || decode_is_closing_tag(buffer, offset)) - { - value = 0; - return -1; - } - - var len = decode_tag_number_and_value(buffer, offset, out _, out var lenValue); - return len + decode_unsigned(buffer, offset + len, lenValue, out value); - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/BVLC.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/BVLC.cs deleted file mode 100644 index ca62f0e..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/BVLC.cs +++ /dev/null @@ -1,416 +0,0 @@ -namespace System.IO.BACnet.Serialize; - -// Special thanks to VTS tool (BBMD services not activated but programmed !) and Steve Karg stack -public class BVLC -{ - public delegate void BVLCMessageReceiveHandler(IPEndPoint sender, BacnetBvlcFunctions function, BacnetBvlcResults result, object data); - public event BVLCMessageReceiveHandler MessageReceived; - - private readonly BacnetIpUdpProtocolTransport _myBbmdTransport; - readonly string _broadcastAdd; - private bool _bbmdFdServiceActivated; - - public const byte BVLL_TYPE_BACNET_IP = 0x81; - public const byte BVLC_HEADER_LENGTH = 4; - public const BacnetMaxAdpu BVLC_MAX_APDU = BacnetMaxAdpu.MAX_APDU1476; - - // Two lists for optional BBMD activity - readonly List> _foreignDevices = new(); - private readonly List> _bbmds = new(); - - // Contains the rules to accept FRD based on the IP adress - // If empty it's equal to *.*.*.*, everyone allows - private readonly List _autorizedFdr = new(); - - public ILog Log { get; set; } = LogManager.GetLogger(); - - public BVLC(BacnetIpUdpProtocolTransport transport) - { - _myBbmdTransport = transport; - _broadcastAdd = _myBbmdTransport.GetBroadcastAddress().ToString().Split(':')[0]; - } - - public string FDList() - { - var sb = new StringBuilder(); - lock (_foreignDevices) - { - // remove oldest Device entries (Time expiration > TTL + 30s delay) - _foreignDevices.Remove(_foreignDevices.Find(item => DateTime.Now > item.Value)); - - foreach (var client in _foreignDevices) - sb.Append($"{client.Key.Address}:{client.Key.Port};"); - } - return sb.ToString(); - } - - public void AddFDRAutorisationRule(Regex ipRule) - { - _autorizedFdr.Add(ipRule); - } - - // Used to initiate the BBMD & FD behaviour, if BBMD is null it start the FD activity only - public void AddBBMDPeer(IPEndPoint bbmd, IPAddress mask) - { - _bbmdFdServiceActivated = true; - - if (bbmd == null) - return; - - lock (_bbmds) - _bbmds.Add(new KeyValuePair(bbmd, mask)); - } - - // Add a FD to the table or renew it - private void RegisterForeignDevice(IPEndPoint sender, int ttl) - { - lock (_foreignDevices) - { - // remove it, if any - _foreignDevices.Remove(_foreignDevices.Find(item => item.Key.Equals(sender))); - // TTL + 30s grace period - var expiration = DateTime.Now.AddSeconds(ttl + 30); - // add it - if (_autorizedFdr.Count == 0) // No rules, accept all - { - _foreignDevices.Add(new KeyValuePair(sender, expiration)); - return; - } - foreach (var r in _autorizedFdr) - { - if (r.Match(sender.Address.ToString()).Success) - { - _foreignDevices.Add(new KeyValuePair(sender, expiration)); - return; - } - } - Log.Info($"Rejected FDR registration, IP : {sender.Address}"); - } - } - - // Send a Frame to each registered foreign devices, except the original sender - private void SendToFDs(byte[] buffer, int msgLength, IPEndPoint ePsender = null) - { - lock (_foreignDevices) - { - // remove oldest Device entries (Time expiration > TTL + 30s delay) - _foreignDevices.Remove(_foreignDevices.Find(item => DateTime.Now > item.Value)); - // Send to all others, except the original sender - foreach (var client in _foreignDevices) - { - if (!client.Key.Equals(ePsender)) - _myBbmdTransport.Send(buffer, msgLength, client.Key); - } - } - } - - private static IPEndPoint BBMDSentAdd(IPEndPoint bbmd, IPAddress mask) - { - var bm = mask.GetAddressBytes(); - var bip = bbmd.Address.GetAddressBytes(); - - /* annotation in Steve Karg bacnet stack : - - The B/IP address to which the Forwarded-NPDU message is - sent is formed by inverting the broadcast distribution - mask in the BDT entry and logically ORing it with the - BBMD address of the same entry. This process - produces either the directed broadcast address of the remote - subnet or the unicast address of the BBMD on that subnet - depending on the contents of the broadcast distribution - mask. - - remark from me : - for instance remote BBMD 192.168.0.1 - mask 255.255.255.255 - messages are forward directly to 192.168.0.1 - remote BBMD 192.168.0.1 - mask 255.255.255.0 - messages are forward to 192.168.0.255, ie certainly the local broadcast - address, but these datagrams are generaly destroy by the final IP router - */ - - for (var i = 0; i < bm.Length; i++) - bip[i] = (byte)(bip[i] | ~bm[i]); - - return new IPEndPoint(new IPAddress(bip), bbmd.Port); - } - - // Send a Frame to each registered BBMD except the original sender - private void SendToBbmDs(byte[] buffer, int msgLength) - { - lock (_bbmds) - { - foreach (var e in _bbmds) - { - var endpoint = BBMDSentAdd(e.Key, e.Value); - _myBbmdTransport.Send(buffer, msgLength, endpoint); - } - } - } - - private static void First4BytesHeaderEncode(IList b, BacnetBvlcFunctions function, int msgLength) - { - b[0] = BVLL_TYPE_BACNET_IP; - b[1] = (byte)function; - b[2] = (byte)((msgLength & 0xFF00) >> 8); - b[3] = (byte)((msgLength & 0x00FF) >> 0); - } - - private void Forward_NPDU(byte[] buffer, int msgLength, bool toGlobalBroadcast, IPEndPoint ePsender) - { - // Forms the forwarded NPDU from the original one, and send it to all - // orignal - 4 bytes BVLC - NPDU - APDU - // change to - 10 bytes BVLC - NPDU - APDU - - // copy, 6 bytes shifted - var b = new byte[msgLength + 6]; // normaly only 'small' frames are present here, so no need to check if it's to big for Udp - Array.Copy(buffer, 0, b, 6, msgLength); - - // 10 bytes for the BVLC Header, with the embedded 6 bytes IP:Port of the original sender - First4BytesHeaderEncode(b, BacnetBvlcFunctions.BVLC_FORWARDED_NPDU, msgLength + 6); - BacnetIpUdpProtocolTransport.Convert(ePsender, out var bacSender); // to embbed in the forward BVLC header - for (var i = 0; i < bacSender.adr.Length; i++) - b[4 + i] = bacSender.adr[i]; - - // To BBMD - SendToBbmDs(b, msgLength + 6); - // To FD, except the sender - SendToFDs(b, msgLength + 6, ePsender); - // Broadcast if required - if (toGlobalBroadcast) - _myBbmdTransport.Send(b, msgLength + 6, new IPEndPoint(IPAddress.Parse(_broadcastAdd), _myBbmdTransport.SharedPort)); - } - - // Send ack or nack - private void SendResult(IPEndPoint sender, BacnetBvlcResults resultCode) - { - var b = new byte[6]; - First4BytesHeaderEncode(b, BacnetBvlcFunctions.BVLC_RESULT, 6); - b[4] = (byte)(((ushort)resultCode & 0xFF00) >> 8); - b[5] = (byte)((ushort)resultCode & 0xFF); - - _myBbmdTransport.Send(b, 6, sender); - } - - public void SendRegisterAsForeignDevice(IPEndPoint bbmd, short ttl) - { - var b = new byte[6]; - First4BytesHeaderEncode(b, BacnetBvlcFunctions.BVLC_REGISTER_FOREIGN_DEVICE, 6); - b[4] = (byte)((ttl & 0xFF00) >> 8); - b[5] = (byte)(ttl & 0xFF); - _myBbmdTransport.Send(b, 6, bbmd); - } - - public void SendReadBroadCastTable(IPEndPoint bbmd) - { - var b = new byte[4]; - First4BytesHeaderEncode(b, BacnetBvlcFunctions.BVLC_READ_BROADCAST_DIST_TABLE, 4); - _myBbmdTransport.Send(b, 4, bbmd); - } - - public void SendReadFDRTable(IPEndPoint bbmd) - { - var b = new byte[4]; - First4BytesHeaderEncode(b, BacnetBvlcFunctions.BVLC_READ_FOREIGN_DEVICE_TABLE, 4); - _myBbmdTransport.Send(b, 4, bbmd); - } - - public void SendWriteBroadCastTable(IPEndPoint bbmd, List> entries) - { - var b = new byte[4 + 10 * entries.Count]; - First4BytesHeaderEncode(b, BacnetBvlcFunctions.BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE, 4 + 10 * entries.Count); - - for (var i = 0; i < entries.Count; i++) - { - Array.Copy(entries[i].Item1.Address.GetAddressBytes(), 0, b, 4 + i * 10, 4); - b[8 + i * 10] = (byte)(entries[i].Item1.Port >> 8); - b[9 + i * 10] = (byte)(entries[i].Item1.Port & 0xFF); - Array.Copy(entries[i].Item2.GetAddressBytes(), 0, b, 10 + i * 10, 4); - } - - _myBbmdTransport.Send(b, 4 + 10 * entries.Count, bbmd); - } - - public void SendDeleteForeignDeviceEntry(IPEndPoint bbmd, IPEndPoint foreignDevice) - { - var b = new byte[4 + 6]; - First4BytesHeaderEncode(b, BacnetBvlcFunctions.BVLC_READ_FOREIGN_DEVICE_TABLE, 4 + 6); - Array.Copy(foreignDevice.Address.GetAddressBytes(), 0, b, 4, 4); - b[8] = (byte)(foreignDevice.Port >> 8); - b[9] = (byte)(foreignDevice.Port & 0xFF); - _myBbmdTransport.Send(b, 4 + 6, bbmd); - } - - public void SendRemoteWhois(byte[] buffer, IPEndPoint bbmd, int msgLength) - { - Encode(buffer, 0, BacnetBvlcFunctions.BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK, msgLength); - _myBbmdTransport.Send(buffer, msgLength, bbmd); - - } - - // Encode is called by internal services if the BBMD is also an active device - public int Encode(byte[] buffer, int offset, BacnetBvlcFunctions function, int msgLength) - { - // offset always 0, we are the first after udp - - // do the job - First4BytesHeaderEncode(buffer, function, msgLength); - - // optional BBMD service - if (_bbmdFdServiceActivated && function == BacnetBvlcFunctions.BVLC_ORIGINAL_BROADCAST_NPDU) - { - var me = _myBbmdTransport.LocalEndPoint; - // just sometime working, enable to get the local ep, always 0.0.0.0 if the socket is open with - // System.Net.IPAddress.Any - // So in this case don't send a bad message - if (me.Address.ToString() != "0.0.0.0") - Forward_NPDU(buffer, msgLength, false, me); // send to all BBMDs and FDs - } - return 4; // ready to send - } - - // Decode is called each time an Udp Frame is received - public int Decode(byte[] buffer, int offset, out BacnetBvlcFunctions function, out int msgLength, IPEndPoint sender) - { - // offset always 0, we are the first after udp - // and a previous test by the caller guaranteed at least 4 bytes into the buffer - - function = (BacnetBvlcFunctions)buffer[1]; - msgLength = (buffer[2] << 8) | (buffer[3] << 0); - if (buffer[0] != BVLL_TYPE_BACNET_IP || buffer.Length != msgLength) return -1; - - switch (function) - { - case BacnetBvlcFunctions.BVLC_RESULT: - var resultCode = (buffer[4] << 8) + buffer[5]; - MessageReceived?.Invoke(sender, function, (BacnetBvlcResults)resultCode, null); - return 0; // not for the upper layers - - case BacnetBvlcFunctions.BVLC_ORIGINAL_UNICAST_NPDU: - return 4; // only for the upper layers - - case BacnetBvlcFunctions.BVLC_ORIGINAL_BROADCAST_NPDU: // Normaly received in an IP local or global broadcast packet - // Send to FDs & BBMDs, not broadcast or it will be made twice ! - if (_bbmdFdServiceActivated) - Forward_NPDU(buffer, msgLength, false, sender); - return 4; // also for the upper layers - - case BacnetBvlcFunctions.BVLC_FORWARDED_NPDU: // Sent only by a BBMD, broadcast on it network, or broadcast demand by one of it's FDs - if (_bbmdFdServiceActivated && msgLength >= 10) - { - bool ret; - lock (_bbmds) - ret = _bbmds.Exists(items => items.Key.Address.Equals(sender.Address)); // verify sender (@ not Port!) presence in the table - - if (ret) // message from a know BBMD address, sent to all FDs and broadcast - { - SendToFDs(buffer, msgLength); // send without modification - - // Assume all BVLC_FORWARDED_NPDU are directly sent to me in the - // unicast mode and not by the way of the local broadcast address - // ie my mask must be 255.255.255.255 in the others BBMD tables - // If not, it's not really a big problem, devices on the local net will - // receive two times the message (after all it's just WhoIs, Iam, ...) - _myBbmdTransport.Send(buffer, msgLength, new IPEndPoint(IPAddress.Parse(_broadcastAdd), _myBbmdTransport.SharedPort)); - } - } - - return 10; // also for the upper layers - - case BacnetBvlcFunctions.BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK: // Sent by a Foreign Device, not a BBMD - if (_bbmdFdServiceActivated) - { - // Send to FDs except the sender, BBMDs and broadcast - lock (_foreignDevices) - { - if (_foreignDevices.Exists(item => item.Key.Equals(sender))) // verify previous registration - Forward_NPDU(buffer, msgLength, true, sender); - else - SendResult(sender, BacnetBvlcResults.BVLC_RESULT_DISTRIBUTE_BROADCAST_TO_NETWORK_NAK); - } - } - return 0; // not for the upper layers - - case BacnetBvlcFunctions.BVLC_REGISTER_FOREIGN_DEVICE: - if (_bbmdFdServiceActivated && msgLength == 6) - { - var ttl = (buffer[4] << 8) + buffer[5]; // unit is second - RegisterForeignDevice(sender, ttl); - SendResult(sender, BacnetBvlcResults.BVLC_RESULT_SUCCESSFUL_COMPLETION); // ack - } - return 0; // not for the upper layers - - // We don't care about Read/Write operation in the BBMD/FDR tables (who realy use it ?) - case BacnetBvlcFunctions.BVLC_READ_FOREIGN_DEVICE_TABLE: - SendResult(sender, BacnetBvlcResults.BVLC_RESULT_READ_FOREIGN_DEVICE_TABLE_NAK); - return 0; - - case BacnetBvlcFunctions.BVLC_DELETE_FOREIGN_DEVICE_TABLE_ENTRY: - SendResult(sender, BacnetBvlcResults.BVLC_RESULT_DELETE_FOREIGN_DEVICE_TABLE_ENTRY_NAK); - return 0; - - case BacnetBvlcFunctions.BVLC_READ_BROADCAST_DIST_TABLE: - SendResult(sender, BacnetBvlcResults.BVLC_RESULT_READ_BROADCAST_DISTRIBUTION_TABLE_NAK); - return 0; - - case BacnetBvlcFunctions.BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE: - case BacnetBvlcFunctions.BVLC_READ_BROADCAST_DIST_TABLE_ACK: - { - var nbEntries = (msgLength - 4) / 10; - var entries = new List>(); - - for (var i = 0; i < nbEntries; i++) - { - long add = BitConverter.ToInt32(buffer, 4 + i * 10); - - Array.Reverse(buffer, 8 + i * 10, 2); - var port = BitConverter.ToUInt16(buffer, 8 + i * 10); - - // new IPAddress(long) with 255.255.255.255 (ie -1) not OK - var mask = new byte[4]; - Array.Copy(buffer, 10 + i * 10, mask, 0, 4); - - var entry = Tuple.Create(new IPEndPoint(new IPAddress(add), port), new IPAddress(mask)); - entries.Add(entry); - } - - if (MessageReceived != null && function == BacnetBvlcFunctions.BVLC_READ_BROADCAST_DIST_TABLE_ACK) - MessageReceived(sender, function, BacnetBvlcResults.BVLC_RESULT_SUCCESSFUL_COMPLETION, entries); - - // Today we don't accept it - if (function == BacnetBvlcFunctions.BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE) - SendResult(sender, BacnetBvlcResults.BVLC_RESULT_WRITE_BROADCAST_DISTRIBUTION_TABLE_NAK); - - return 0; - } - - case BacnetBvlcFunctions.BVLC_READ_FOREIGN_DEVICE_TABLE_ACK: - { - var nbEntries = (msgLength - 4) / 10; - var entries = new List>(); - - for (var i = 0; i < nbEntries; i++) - { - long add = BitConverter.ToInt32(buffer, 4 + i * 10); - - Array.Reverse(buffer, 8 + i * 10, 2); - var port = BitConverter.ToUInt16(buffer, 8 + i * 10); - - Array.Reverse(buffer, 10 + i * 10, 2); - var ttl = BitConverter.ToUInt16(buffer, 10 + i * 10); - Array.Reverse(buffer, 12 + i * 10, 2); - var remainTtl = BitConverter.ToUInt16(buffer, 12 + i * 10); - - var entry = Tuple.Create(new IPEndPoint(new IPAddress(add), port), ttl, remainTtl); - entries.Add(entry); - } - - MessageReceived?.Invoke(sender, function, BacnetBvlcResults.BVLC_RESULT_SUCCESSFUL_COMPLETION, entries); - return 0; - } - - // error encoding function or experimental one - default: - return -1; - } - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/EncodeBuffer.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/EncodeBuffer.cs deleted file mode 100644 index c7113d7..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/EncodeBuffer.cs +++ /dev/null @@ -1,117 +0,0 @@ -namespace System.IO.BACnet.Serialize; - -public class EncodeBuffer -{ - public byte[] buffer; //buffer to serialize into - public int offset; //offset in buffer ... will go beyond max_offset (so that you may count what's needed) - public int max_offset; //don't write beyond this offset - public int serialize_counter; //used with 'min_limit' - public int min_limit; //don't write before this limit (used for segmentation) - public EncodeResult result; - public bool expandable; - - public EncodeBuffer() - { - expandable = true; - buffer = new byte[128]; - max_offset = buffer.Length - 1; - } - - public EncodeBuffer(byte[] buffer, int offset) - { - if (buffer == null) buffer = new byte[0]; - expandable = false; - this.buffer = buffer; - this.offset = offset; - max_offset = buffer.Length; - } - - public void Increment() - { - if (offset < max_offset) - { - if (serialize_counter >= min_limit) - offset++; - serialize_counter++; - } - else - { - if (serialize_counter >= min_limit) - offset++; - } - } - - public void Add(byte b) - { - if (offset < max_offset) - { - if (serialize_counter >= min_limit) - buffer[offset] = b; - } - else - { - if (expandable) - { - Array.Resize(ref buffer, buffer.Length * 2); - max_offset = buffer.Length - 1; - if (serialize_counter >= min_limit) - buffer[offset] = b; - } - else - result |= EncodeResult.NotEnoughBuffer; - } - - Increment(); - } - - public void Add(byte[] buffer, int count) - { - for (var i = 0; i < count; i++) - Add(buffer[i]); - } - - public int GetDiff(EncodeBuffer buffer) - { - var diff = Math.Abs(buffer.offset - offset); - diff = Math.Max(Math.Abs(buffer.serialize_counter - serialize_counter), diff); - return diff; - } - - public EncodeBuffer Copy() - { - return new EncodeBuffer - { - buffer = buffer, - max_offset = max_offset, - min_limit = min_limit, - offset = offset, - result = result, - serialize_counter = serialize_counter, - expandable = expandable - }; - } - - public byte[] ToArray() - { - var ret = new byte[offset]; - Array.Copy(buffer, 0, ret, 0, ret.Length); - return ret; - } - - public void Reset(int newOffset) - { - offset = newOffset; - serialize_counter = 0; - result = EncodeResult.Good; - } - - public override string ToString() - { - return offset + " - " + serialize_counter; - } - - public int GetLength() - { - return Math.Min(offset, max_offset); - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/EncodeResult.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/EncodeResult.cs deleted file mode 100644 index 2051215..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/EncodeResult.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace System.IO.BACnet.Serialize; - -[Flags] -public enum EncodeResult -{ - Good = 0, - NotEnoughBuffer = 1 -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/MSTP.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/MSTP.cs deleted file mode 100644 index 795ff40..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/MSTP.cs +++ /dev/null @@ -1,107 +0,0 @@ -namespace System.IO.BACnet.Serialize; - -public class MSTP -{ - public const byte MSTP_PREAMBLE1 = 0x55; - public const byte MSTP_PREAMBLE2 = 0xFF; - public const BacnetMaxAdpu MSTP_MAX_APDU = BacnetMaxAdpu.MAX_APDU480; - public const byte MSTP_HEADER_LENGTH = 8; - - public static byte CRC_Calc_Header(byte dataValue, byte crcValue) - { - var crc = (ushort)(crcValue ^ dataValue); - - /* Exclusive OR the terms in the table (top down) */ - crc = (ushort)(crc ^ (crc << 1) ^ (crc << 2) ^ (crc << 3) ^ (crc << 4) ^ (crc << 5) ^ (crc << 6) ^ (crc << 7)); - - /* Combine bits shifted out left hand end */ - return (byte)((crc & 0xfe) ^ ((crc >> 8) & 1)); - } - - public static byte CRC_Calc_Header(byte[] buffer, int offset, int length) - { - byte crc = 0xff; - for (var i = offset; i < offset + length; i++) - crc = CRC_Calc_Header(buffer[i], crc); - return (byte)~crc; - } - - public static ushort CRC_Calc_Data(byte dataValue, ushort crcValue) - { - var crcLow = (ushort)((crcValue & 0xff) ^ dataValue); - - /* Exclusive OR the terms in the table (top down) */ - return (ushort)((crcValue >> 8) ^ (crcLow << 8) ^ (crcLow << 3) - ^ (crcLow << 12) ^ (crcLow >> 4) - ^ (crcLow & 0x0f) ^ ((crcLow & 0x0f) << 7)); - } - - public static ushort CRC_Calc_Data(byte[] buffer, int offset, int length) - { - ushort crc = 0xffff; - for (var i = offset; i < offset + length; i++) - crc = CRC_Calc_Data(buffer[i], crc); - return (ushort)~crc; - } - - public static int Encode(byte[] buffer, int offset, BacnetMstpFrameTypes frameType, byte destinationAddress, byte sourceAddress, int msgLength) - { - buffer[offset + 0] = MSTP_PREAMBLE1; - buffer[offset + 1] = MSTP_PREAMBLE2; - buffer[offset + 2] = (byte)frameType; - buffer[offset + 3] = destinationAddress; - buffer[offset + 4] = sourceAddress; - buffer[offset + 5] = (byte)((msgLength & 0xFF00) >> 8); - buffer[offset + 6] = (byte)((msgLength & 0x00FF) >> 0); - buffer[offset + 7] = CRC_Calc_Header(buffer, offset + 2, 5); - if (msgLength > 0) - { - //calculate data crc - var dataCrc = CRC_Calc_Data(buffer, offset + 8, msgLength); - buffer[offset + 8 + msgLength + 0] = (byte)(dataCrc & 0xFF); //LSB first! - buffer[offset + 8 + msgLength + 1] = (byte)(dataCrc >> 8); - } - //optional pad (0xFF) - return MSTP_HEADER_LENGTH + msgLength + (msgLength > 0 ? 2 : 0); - } - - public static int Decode(byte[] buffer, int offset, int maxLength, out BacnetMstpFrameTypes frameType, out byte destinationAddress, out byte sourceAddress, out int msgLength) - { - if (maxLength < MSTP_HEADER_LENGTH) //not enough data - { - frameType = BacnetMstpFrameTypes.FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY; // don't care - destinationAddress = sourceAddress = 0; // don't care - msgLength = 0; - return -1; - } - - frameType = (BacnetMstpFrameTypes)buffer[offset + 2]; - destinationAddress = buffer[offset + 3]; - sourceAddress = buffer[offset + 4]; - msgLength = (buffer[offset + 5] << 8) | (buffer[offset + 6] << 0); - var crcHeader = buffer[offset + 7]; - ushort crcData = 0; - - if (msgLength > 0) - { - if (offset + 8 + msgLength + 1 >= buffer.Length) - return -1; - - crcData = (ushort)((buffer[offset + 8 + msgLength + 1] << 8) | (buffer[offset + 8 + msgLength + 0] << 0)); - } - - if (buffer[offset + 0] != MSTP_PREAMBLE1) - return -1; - - if (buffer[offset + 1] != MSTP_PREAMBLE2) - return -1; - - if (CRC_Calc_Header(buffer, offset + 2, 5) != crcHeader) - return -1; - - if (msgLength > 0 && maxLength >= MSTP_HEADER_LENGTH + msgLength + 2 && CRC_Calc_Data(buffer, offset + 8, msgLength) != crcData) - return -1; - - return 8 + msgLength + (msgLength > 0 ? 2 : 0); - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/NPDU.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/NPDU.cs deleted file mode 100644 index b4ce0f6..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/NPDU.cs +++ /dev/null @@ -1,134 +0,0 @@ -namespace System.IO.BACnet.Serialize; - -public class NPDU -{ - public const byte BACNET_PROTOCOL_VERSION = 1; - - public static BacnetNpduControls DecodeFunction(byte[] buffer, int offset) - { - if (buffer[offset + 0] != BACNET_PROTOCOL_VERSION) return 0; - return (BacnetNpduControls)buffer[offset + 1]; - } - - public static int Decode(byte[] buffer, int offset, out BacnetNpduControls function, out BacnetAddress destination, - out BacnetAddress source, out byte hopCount, out BacnetNetworkMessageTypes networkMsgType, out ushort vendorId) - { - var orgOffset = offset; - - offset++; - function = (BacnetNpduControls)buffer[offset++]; - - destination = null; - if ((function & BacnetNpduControls.DestinationSpecified) == BacnetNpduControls.DestinationSpecified) - { - destination = new BacnetAddress(BacnetAddressTypes.None, (ushort)((buffer[offset++] << 8) | (buffer[offset++] << 0)), null); - int adrLen = buffer[offset++]; - if (adrLen > 0) - { - destination.adr = new byte[adrLen]; - for (var i = 0; i < destination.adr.Length; i++) - destination.adr[i] = buffer[offset++]; - } - } - - source = null; - if ((function & BacnetNpduControls.SourceSpecified) == BacnetNpduControls.SourceSpecified) - { - source = new BacnetAddress(BacnetAddressTypes.None, (ushort)((buffer[offset++] << 8) | (buffer[offset++] << 0)), null); - int adrLen = buffer[offset++]; - if (adrLen > 0) - { - source.adr = new byte[adrLen]; - for (var i = 0; i < source.adr.Length; i++) - source.adr[i] = buffer[offset++]; - } - } - - hopCount = 0; - if ((function & BacnetNpduControls.DestinationSpecified) == BacnetNpduControls.DestinationSpecified) - { - hopCount = buffer[offset++]; - } - - networkMsgType = BacnetNetworkMessageTypes.NETWORK_MESSAGE_WHO_IS_ROUTER_TO_NETWORK; - vendorId = 0; - if (function.HasFlag(BacnetNpduControls.NetworkLayerMessage)) - { - networkMsgType = (BacnetNetworkMessageTypes)buffer[offset++]; - if ((byte)networkMsgType >= 0x80) - { - vendorId = (ushort)((buffer[offset++] << 8) | (buffer[offset++] << 0)); - } - //DAL - this originally made no sense as the higher level code would just ignore network messages - // else if (networkMsgType == BacnetNetworkMessageTypes.NETWORK_MESSAGE_WHO_IS_ROUTER_TO_NETWORK) - // offset += 2; // Don't care about destination network adress - } - - if (buffer[orgOffset + 0] != BACNET_PROTOCOL_VERSION) - return -1; - - return offset - orgOffset; - } - - public static void Encode(EncodeBuffer buffer, BacnetNpduControls function, BacnetAddress destination, - BacnetAddress source, byte hopCount, BacnetNetworkMessageTypes networkMsgType, ushort vendorId) - { - Encode(buffer, function, destination, source, hopCount); - - if (function.HasFlag(BacnetNpduControls.NetworkLayerMessage)) // sure it is, otherwise the other Encode is used - { - buffer.buffer[buffer.offset++] = (byte)networkMsgType; - if ((byte)networkMsgType >= 0x80) // who used this ??? sure nobody ! - { - buffer.buffer[buffer.offset++] = (byte)((vendorId & 0xFF00) >> 8); - buffer.buffer[buffer.offset++] = (byte)((vendorId & 0x00FF) >> 0); - } - } - } - - public static void Encode(EncodeBuffer buffer, BacnetNpduControls function, BacnetAddress destination, - BacnetAddress source = null, byte hopCount = 0xFF) - { - // Modif FC - var hasDestination = destination != null && destination.net > 0; // && destination.net != 0xFFFF; - var hasSource = source != null && source.net > 0 && source.net != 0xFFFF; - - buffer.buffer[buffer.offset++] = BACNET_PROTOCOL_VERSION; - buffer.buffer[buffer.offset++] = (byte)(function | (hasDestination ? BacnetNpduControls.DestinationSpecified : 0) | (hasSource ? BacnetNpduControls.SourceSpecified : 0)); - - if (hasDestination) - { - buffer.buffer[buffer.offset++] = (byte)((destination.net & 0xFF00) >> 8); - buffer.buffer[buffer.offset++] = (byte)((destination.net & 0x00FF) >> 0); - - if (destination.net == 0xFFFF) //patch by F. Chaxel - buffer.buffer[buffer.offset++] = 0; - else - { - buffer.buffer[buffer.offset++] = (byte)destination.adr.Length; - if (destination.adr.Length > 0) - { - foreach (var t in destination.adr) - buffer.buffer[buffer.offset++] = t; - } - } - } - - if (hasSource) - { - buffer.buffer[buffer.offset++] = (byte)((source.net & 0xFF00) >> 8); - buffer.buffer[buffer.offset++] = (byte)((source.net & 0x00FF) >> 0); - buffer.buffer[buffer.offset++] = (byte)source.adr.Length; - if (source.adr.Length > 0) - { - foreach (var t in source.adr) - buffer.buffer[buffer.offset++] = t; - } - } - - if (hasDestination) - { - buffer.buffer[buffer.offset++] = hopCount; - } - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/PTP.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/PTP.cs deleted file mode 100644 index 4c5a5a6..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/PTP.cs +++ /dev/null @@ -1,67 +0,0 @@ -namespace System.IO.BACnet.Serialize; - -public class PTP -{ - public const byte PTP_PREAMBLE1 = 0x55; - public const byte PTP_PREAMBLE2 = 0xFF; - public const byte PTP_GREETING_PREAMBLE1 = 0x42; - public const byte PTP_GREETING_PREAMBLE2 = 0x41; - public const BacnetMaxAdpu PTP_MAX_APDU = BacnetMaxAdpu.MAX_APDU480; - public const byte PTP_HEADER_LENGTH = 6; - - public static int Encode(byte[] buffer, int offset, BacnetPtpFrameTypes frameType, int msgLength) - { - buffer[offset + 0] = PTP_PREAMBLE1; - buffer[offset + 1] = PTP_PREAMBLE2; - buffer[offset + 2] = (byte)frameType; - buffer[offset + 3] = (byte)((msgLength & 0xFF00) >> 8); - buffer[offset + 4] = (byte)((msgLength & 0x00FF) >> 0); - buffer[offset + 5] = MSTP.CRC_Calc_Header(buffer, offset + 2, 3); - if (msgLength > 0) - { - //calculate data crc - var dataCrc = MSTP.CRC_Calc_Data(buffer, offset + 6, msgLength); - buffer[offset + 6 + msgLength + 0] = (byte)(dataCrc & 0xFF); //LSB first! - buffer[offset + 6 + msgLength + 1] = (byte)(dataCrc >> 8); - } - return PTP_HEADER_LENGTH + msgLength + (msgLength > 0 ? 2 : 0); - } - - public static int Decode(byte[] buffer, int offset, int maxLength, out BacnetPtpFrameTypes frameType, out int msgLength) - { - if (maxLength < PTP_HEADER_LENGTH) // not enough data - { - frameType = BacnetPtpFrameTypes.FRAME_TYPE_CONNECT_REQUEST; // don't care - msgLength = 0; - return -1; //not enough data - } - - frameType = (BacnetPtpFrameTypes)buffer[offset + 2]; - msgLength = (buffer[offset + 3] << 8) | (buffer[offset + 4] << 0); - var crcHeader = buffer[offset + 5]; - ushort crcData = 0; - - if (msgLength > 0) - { - if (offset + 6 + msgLength + 1 >= buffer.Length) - return -1; - - crcData = (ushort)((buffer[offset + 6 + msgLength + 1] << 8) | (buffer[offset + 6 + msgLength + 0] << 0)); - } - - if (buffer[offset + 0] != PTP_PREAMBLE1) - return -1; - - if (buffer[offset + 1] != PTP_PREAMBLE2) - return -1; - - if (MSTP.CRC_Calc_Header(buffer, offset + 2, 3) != crcHeader) - return -1; - - if (msgLength > 0 && maxLength >= PTP_HEADER_LENGTH + msgLength + 2 && MSTP.CRC_Calc_Data(buffer, offset + 6, msgLength) != crcData) - return -1; - - return 8 + msgLength + (msgLength > 0 ? 2 : 0); - } - -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/Services.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/Services.cs deleted file mode 100644 index 98728b4..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Serialize/Services.cs +++ /dev/null @@ -1,2664 +0,0 @@ -namespace System.IO.BACnet.Serialize; - -public class Services -{ - public static void EncodeIamBroadcast(EncodeBuffer buffer, uint deviceId, uint maxApdu, BacnetSegmentations segmentation, ushort vendorId) - { - ASN1.encode_application_object_id(buffer, BacnetObjectTypes.OBJECT_DEVICE, deviceId); - ASN1.encode_application_unsigned(buffer, maxApdu); - ASN1.encode_application_enumerated(buffer, (uint)segmentation); - ASN1.encode_application_unsigned(buffer, vendorId); - } - - public static int DecodeIamBroadcast(byte[] buffer, int offset, out uint deviceId, out uint maxApdu, out BacnetSegmentations segmentation, out ushort vendorId) - { - var apduLen = 0; - var orgOffset = offset; - BacnetObjectId objectId; - - deviceId = 0; - maxApdu = 0; - segmentation = BacnetSegmentations.SEGMENTATION_NONE; - vendorId = 0; - - /* OBJECT ID - object id */ - var len = ASN1.decode_tag_number_and_value(buffer, offset + apduLen, out var tagNumber, out var lenValue); - apduLen += len; - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID) - return -1; - len = ASN1.decode_object_id(buffer, offset + apduLen, out objectId.type, out objectId.instance); - apduLen += len; - if (objectId.type != BacnetObjectTypes.OBJECT_DEVICE) - return -1; - deviceId = objectId.instance; - /* MAX APDU - unsigned */ - len = - ASN1.decode_tag_number_and_value(buffer, offset + apduLen, out tagNumber, out lenValue); - apduLen += len; - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT) - return -1; - len = ASN1.decode_unsigned(buffer, offset + apduLen, lenValue, out var decodedValue); - apduLen += len; - maxApdu = decodedValue; - /* Segmentation - enumerated */ - len = - ASN1.decode_tag_number_and_value(buffer, offset + apduLen, out tagNumber, out lenValue); - apduLen += len; - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_ENUMERATED) - return -1; - len = ASN1.decode_enumerated(buffer, offset + apduLen, lenValue, out decodedValue); - apduLen += len; - if (decodedValue > (uint)BacnetSegmentations.SEGMENTATION_NONE) - return -1; - segmentation = (BacnetSegmentations)decodedValue; - /* Vendor ID - unsigned16 */ - len = - ASN1.decode_tag_number_and_value(buffer, offset + apduLen, out tagNumber, out lenValue); - apduLen += len; - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT) - return -1; - ASN1.decode_unsigned(buffer, offset + apduLen, lenValue, out decodedValue); - if (decodedValue > 0xFFFF) - return -1; - vendorId = (ushort)decodedValue; - - return offset - orgOffset; - } - - public static void EncodeIhaveBroadcast(EncodeBuffer buffer, BacnetObjectId deviceId, BacnetObjectId objectId, string objectName) - { - /* deviceIdentifier */ - ASN1.encode_application_object_id(buffer, deviceId.type, deviceId.instance); - /* objectIdentifier */ - ASN1.encode_application_object_id(buffer, objectId.type, objectId.instance); - /* objectName */ - ASN1.encode_application_character_string(buffer, objectName); - } - - public static void EncodeWhoHasBroadcast(EncodeBuffer buffer, int lowLimit, int highLimit, BacnetObjectId? objectId, string objectName) - { - /* optional limits - must be used as a pair */ - if (lowLimit >= 0 && lowLimit <= ASN1.BACNET_MAX_INSTANCE && highLimit >= 0 && highLimit <= ASN1.BACNET_MAX_INSTANCE) - { - ASN1.encode_context_unsigned(buffer, 0, (uint)lowLimit); - ASN1.encode_context_unsigned(buffer, 1, (uint)highLimit); - } - if (objectId != null) - { - ASN1.encode_context_object_id(buffer, 2, objectId.Value.type, objectId.Value.instance); - } - else - { - ASN1.encode_context_character_string(buffer, 3, objectName); - } - } - - public static void EncodeWhoIsBroadcast(EncodeBuffer buffer, int lowLimit, int highLimit) - { - /* optional limits - must be used as a pair */ - if (lowLimit >= 0 && lowLimit <= ASN1.BACNET_MAX_INSTANCE && - highLimit >= 0 && highLimit <= ASN1.BACNET_MAX_INSTANCE) - { - ASN1.encode_context_unsigned(buffer, 0, (uint)lowLimit); - ASN1.encode_context_unsigned(buffer, 1, (uint)highLimit); - } - } - - public static int DecodeWhoIsBroadcast(byte[] buffer, int offset, int apduLen, out int lowLimit, out int highLimit) - { - var len = 0; - - lowLimit = -1; - highLimit = -1; - - if (apduLen <= 0) return len; - - /* optional limits - must be used as a pair */ - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out var tagNumber, out var lenValue); - if (tagNumber != 0) - return -1; - if (apduLen > len) - { - len += ASN1.decode_unsigned(buffer, offset + len, lenValue, out var decodedValue); - if (decodedValue <= ASN1.BACNET_MAX_INSTANCE) - lowLimit = (int)decodedValue; - if (apduLen > len) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValue); - if (tagNumber != 1) - return -1; - if (apduLen > len) - { - len += ASN1.decode_unsigned(buffer, offset + len, lenValue, out decodedValue); - if (decodedValue <= ASN1.BACNET_MAX_INSTANCE) - highLimit = (int)decodedValue; - } - else - return -1; - } - else - return -1; - } - else - return -1; - - return len; - } - - // Added by thamersalek - public static int DecodeWhoHasBroadcast(byte[] buffer, int offset, int apduLen, out int lowLimit, out int highLimit, out BacnetObjectId? objId, out string objName) - { - var len = 0; - uint decodedValue; - - objName = null; - objId = null; - lowLimit = -1; - highLimit = -1; - - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out var tagNumber, out var lenValue); - - if (tagNumber == 0) - { - len += ASN1.decode_unsigned(buffer, offset + len, lenValue, out decodedValue); - if (decodedValue <= ASN1.BACNET_MAX_INSTANCE) - lowLimit = (int)decodedValue; - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValue); - } - - if (tagNumber == 1) - { - len += ASN1.decode_unsigned(buffer, offset + len, lenValue, out decodedValue); - if (decodedValue <= ASN1.BACNET_MAX_INSTANCE) - highLimit = (int)decodedValue; - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValue); - } - - if (tagNumber == 2) - { - len += ASN1.decode_object_id(buffer, offset + len, out ushort objType, out var objInst); - objId = new BacnetObjectId((BacnetObjectTypes)objType, objInst); - } - - if (tagNumber == 3) - len += ASN1.decode_character_string(buffer, offset + len, apduLen - (offset + len), lenValue, out objName); - - return len; - } - - public static void EncodeAlarmAcknowledge(EncodeBuffer buffer, uint ackProcessIdentifier, BacnetObjectId eventObjectIdentifier, uint eventStateAcked, string ackSource, BacnetGenericTime eventTimeStamp, BacnetGenericTime ackTimeStamp) - { - ASN1.encode_context_unsigned(buffer, 0, ackProcessIdentifier); - ASN1.encode_context_object_id(buffer, 1, eventObjectIdentifier.type, eventObjectIdentifier.instance); - ASN1.encode_context_enumerated(buffer, 2, eventStateAcked); - ASN1.bacapp_encode_context_timestamp(buffer, 3, eventTimeStamp); - ASN1.encode_context_character_string(buffer, 4, ackSource); - ASN1.bacapp_encode_context_timestamp(buffer, 5, ackTimeStamp); - } - // DAL - public static int DecodeAlarmAcknowledge(byte[] buffer, int offset, int apduLen, out uint ackProcessIdentifier, out BacnetObjectId eventObjectIdentifier, out uint eventStateAcked, out string ackSource, out BacnetGenericTime eventTimeStamp, out BacnetGenericTime ackTimeStamp) - { - eventTimeStamp = default; - ackTimeStamp = default; - ackSource = null; - var len = 0; - len += ASN1.decode_context_unsigned(buffer, offset + len, 0, out ackProcessIdentifier); - len += ASN1.decode_context_object_id(buffer, offset + len, 1, out ushort type, out eventObjectIdentifier.instance); - eventObjectIdentifier.type = (BacnetObjectTypes)type; - len += ASN1.decode_context_enumerated(buffer, offset + len, 2, out eventStateAcked); - if (ASN1.decode_is_context_tag(buffer, offset + len, 3)) - { - len += 2; // opening Tag 3 then 2 - len += ASN1.decode_application_date(buffer, offset + len, out var date); - len += ASN1.decode_application_time(buffer, offset + len, out var time); - eventTimeStamp.Time = new DateTime(date.Year, date.Month, date.Day, time.Hour, time.Minute, - time.Second, time.Millisecond); - - len += 2; // closing tag 2 then 3 - } - else - return -1; - len += ASN1.decode_context_character_string(buffer, offset + len, 256, 4, out ackSource); - if (ASN1.decode_is_context_tag(buffer, offset + len, 5)) - { - len += 2; // opening Tag 5 then 2 - len += ASN1.decode_application_date(buffer, offset + len, out var date); - len += ASN1.decode_application_time(buffer, offset + len, out var time); - ackTimeStamp.Time = new DateTime(date.Year, date.Month, date.Day, time.Hour, time.Minute, - time.Second, time.Millisecond); - len += 2; // closing tag 2 then 5 - } - else - return -1; - return len; - } - - public static void EncodeAtomicReadFile(EncodeBuffer buffer, bool isStream, BacnetObjectId objectId, int position, uint count) - { - ASN1.encode_application_object_id(buffer, objectId.type, objectId.instance); - var tagNumber = (byte)(isStream ? 0 : 1); - ASN1.encode_opening_tag(buffer, tagNumber); - ASN1.encode_application_signed(buffer, position); - ASN1.encode_application_unsigned(buffer, count); - ASN1.encode_closing_tag(buffer, tagNumber); - } - - public static int DecodeAtomicReadFile(byte[] buffer, int offset, int apduLen, out bool isStream, out BacnetObjectId objectId, out int position, out uint count) - { - var len = 0; - int tagLen; - - isStream = true; - objectId = new BacnetObjectId(); - position = -1; - count = 0; - - len = ASN1.decode_tag_number_and_value(buffer, offset + len, out var tagNumber, out var lenValueType); - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID) - return -1; - len += ASN1.decode_object_id(buffer, offset + len, out objectId.type, out objectId.instance); - if (ASN1.decode_is_opening_tag_number(buffer, offset + len, 0)) - { - /* a tag number is not extended so only one octet */ - len++; - /* fileStartPosition */ - tagLen = ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - len += tagLen; - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_SIGNED_INT) - return -1; - len += ASN1.decode_signed(buffer, offset + len, lenValueType, out position); - /* requestedOctetCount */ - tagLen = ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - len += tagLen; - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT) - return -1; - len += ASN1.decode_unsigned(buffer, offset + len, lenValueType, out count); - if (!ASN1.decode_is_closing_tag_number(buffer, offset + len, 0)) - return -1; - /* a tag number is not extended so only one octet */ - len++; - } - else if (ASN1.decode_is_opening_tag_number(buffer, offset + len, 1)) - { - isStream = false; - /* a tag number is not extended so only one octet */ - len++; - /* fileStartRecord */ - tagLen = - ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, - out lenValueType); - len += tagLen; - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_SIGNED_INT) - return -1; - len += ASN1.decode_signed(buffer, offset + len, lenValueType, out position); - /* RecordCount */ - tagLen = ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - len += tagLen; - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT) - return -1; - len += ASN1.decode_unsigned(buffer, offset + len, lenValueType, out count); - if (!ASN1.decode_is_closing_tag_number(buffer, offset + len, 1)) - return -1; - /* a tag number is not extended so only one octet */ - len++; - } - else - return -1; - - return len; - } - - public static void EncodeAtomicReadFileAcknowledge(EncodeBuffer buffer, bool isStream, bool endOfFile, int position, uint blockCount, byte[][] blocks, int[] counts) - { - ASN1.encode_application_boolean(buffer, endOfFile); - var tagNumber = (byte)(isStream ? 0 : 1); - ASN1.encode_opening_tag(buffer, tagNumber); - ASN1.encode_application_signed(buffer, position); - - if (isStream) - { - ASN1.encode_application_octet_string(buffer, blocks[0], 0, counts[0]); - } - else - { - ASN1.encode_application_unsigned(buffer, blockCount); - for (var i = 0; i < blockCount; i++) - ASN1.encode_application_octet_string(buffer, blocks[i], 0, counts[i]); - } - - ASN1.encode_closing_tag(buffer, tagNumber); - } - - public static void EncodeAtomicWriteFile(EncodeBuffer buffer, bool isStream, BacnetObjectId objectId, int position, uint blockCount, byte[][] blocks, int[] counts) - { - ASN1.encode_application_object_id(buffer, objectId.type, objectId.instance); - var tagNumber = (byte)(isStream ? 0 : 1); - - ASN1.encode_opening_tag(buffer, tagNumber); - ASN1.encode_application_signed(buffer, position); - - if (isStream) - { - ASN1.encode_application_octet_string(buffer, blocks[0], 0, counts[0]); - } - else - { - ASN1.encode_application_unsigned(buffer, blockCount); - for (var i = 0; i < blockCount; i++) - ASN1.encode_application_octet_string(buffer, blocks[i], 0, counts[i]); - } - - ASN1.encode_closing_tag(buffer, tagNumber); - } - - public static int DecodeAtomicWriteFile(byte[] buffer, int offset, int apduLen, out bool isStream, out BacnetObjectId objectId, out int position, out uint blockCount, out byte[][] blocks, out int[] counts) - { - var len = 0; - int tagLen; - - objectId = new BacnetObjectId(); - isStream = true; - position = -1; - blockCount = 0; - blocks = null; - counts = null; - - len = ASN1.decode_tag_number_and_value(buffer, offset + len, out var tagNumber, out var lenValueType); - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID) - return -1; - len += ASN1.decode_object_id(buffer, offset + len, out objectId.type, out objectId.instance); - if (ASN1.decode_is_opening_tag_number(buffer, offset + len, 0)) - { - /* a tag number of 2 is not extended so only one octet */ - len++; - /* fileStartPosition */ - tagLen = ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - len += tagLen; - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_SIGNED_INT) - return -1; - len += ASN1.decode_signed(buffer, offset + len, lenValueType, out position); - /* fileData */ - tagLen = ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - len += tagLen; - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_OCTET_STRING) - return -1; - blockCount = 1; - blocks = new byte[1][]; - blocks[0] = new byte[lenValueType]; - counts = new[] { (int)lenValueType }; - len += ASN1.decode_octet_string(buffer, offset + len, apduLen, blocks[0], 0, lenValueType); - if (!ASN1.decode_is_closing_tag_number(buffer, offset + len, 0)) - return -1; - /* a tag number is not extended so only one octet */ - len++; - } - else if (ASN1.decode_is_opening_tag_number(buffer, offset + len, 1)) - { - isStream = false; - /* a tag number is not extended so only one octet */ - len++; - /* fileStartRecord */ - tagLen = ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - len += tagLen; - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_SIGNED_INT) - return -1; - len += ASN1.decode_signed(buffer, offset + len, lenValueType, out position); - /* returnedRecordCount */ - tagLen = ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - len += tagLen; - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT) - return -1; - len += ASN1.decode_unsigned(buffer, offset + len, lenValueType, out blockCount); - /* fileData */ - blocks = new byte[blockCount][]; - counts = new int[blockCount]; - for (var i = 0; i < blockCount; i++) - { - tagLen = ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - len += tagLen; - blocks[i] = new byte[lenValueType]; - counts[i] = (int)lenValueType; - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_OCTET_STRING) - return -1; - len += ASN1.decode_octet_string(buffer, offset + len, apduLen, blocks[i], 0, lenValueType); - } - if (!ASN1.decode_is_closing_tag_number(buffer, offset + len, 1)) - return -1; - /* a tag number is not extended so only one octet */ - len++; - } - else - return -1; - - return len; - } - - // by Christopher Günter - public static void EncodeCreateProperty(EncodeBuffer buffer, BacnetObjectId objectId, ICollection valueList) - { - /* Tag 1: sequence of WriteAccessSpecification */ - ASN1.encode_opening_tag(buffer, 0); - ASN1.encode_context_object_id(buffer, 1, objectId.type, objectId.instance); - ASN1.encode_closing_tag(buffer, 0); - - if (valueList == null) - return; - - ASN1.encode_opening_tag(buffer, 1); - - foreach (var pValue in valueList) - { - ASN1.encode_context_enumerated(buffer, 0, pValue.property.propertyIdentifier); - - if (pValue.property.propertyArrayIndex != ASN1.BACNET_ARRAY_ALL) - ASN1.encode_context_unsigned(buffer, 1, pValue.property.propertyArrayIndex); - - ASN1.encode_opening_tag(buffer, 2); - foreach (var value in pValue.value) - { - ASN1.bacapp_encode_application_data(buffer, value); - } - ASN1.encode_closing_tag(buffer, 2); - - if (pValue.priority != ASN1.BACNET_NO_PRIORITY) - ASN1.encode_context_unsigned(buffer, 3, pValue.priority); - } - - ASN1.encode_closing_tag(buffer, 1); - } - - public static void EncodeAddListElement(EncodeBuffer buffer, BacnetObjectId objectId, uint propertyId, uint arrayIndex, IList valueList) - { - ASN1.encode_context_object_id(buffer, 0, objectId.type, objectId.instance); - ASN1.encode_context_enumerated(buffer, 1, propertyId); - - if (arrayIndex != ASN1.BACNET_ARRAY_ALL) - { - ASN1.encode_context_unsigned(buffer, 2, arrayIndex); - } - - ASN1.encode_opening_tag(buffer, 3); - foreach (var value in valueList) - { - ASN1.bacapp_encode_application_data(buffer, value); - } - - ASN1.encode_closing_tag(buffer, 3); - } - - public static void EncodeAtomicWriteFileAcknowledge(EncodeBuffer buffer, bool isStream, int position) - { - ASN1.encode_context_signed(buffer, (byte)(isStream ? 0 : 1), position); - } - - public static void EncodeCOVNotifyConfirmed(EncodeBuffer buffer, uint subscriberProcessIdentifier, uint initiatingDeviceIdentifier, BacnetObjectId monitoredObjectIdentifier, uint timeRemaining, IEnumerable values) - { - /* tag 0 - subscriberProcessIdentifier */ - ASN1.encode_context_unsigned(buffer, 0, subscriberProcessIdentifier); - /* tag 1 - initiatingDeviceIdentifier */ - ASN1.encode_context_object_id(buffer, 1, BacnetObjectTypes.OBJECT_DEVICE, initiatingDeviceIdentifier); - /* tag 2 - monitoredObjectIdentifier */ - ASN1.encode_context_object_id(buffer, 2, monitoredObjectIdentifier.type, monitoredObjectIdentifier.instance); - /* tag 3 - timeRemaining */ - ASN1.encode_context_unsigned(buffer, 3, timeRemaining); - /* tag 4 - listOfValues */ - ASN1.encode_opening_tag(buffer, 4); - foreach (var value in values) - { - /* tag 0 - propertyIdentifier */ - ASN1.encode_context_enumerated(buffer, 0, value.property.propertyIdentifier); - /* tag 1 - propertyArrayIndex OPTIONAL */ - if (value.property.propertyArrayIndex != ASN1.BACNET_ARRAY_ALL) - { - ASN1.encode_context_unsigned(buffer, 1, value.property.propertyArrayIndex); - } - /* tag 2 - value */ - /* abstract syntax gets enclosed in a context tag */ - ASN1.encode_opening_tag(buffer, 2); - foreach (var v in value.value) - { - ASN1.bacapp_encode_application_data(buffer, v); - } - ASN1.encode_closing_tag(buffer, 2); - /* tag 3 - priority OPTIONAL */ - if (value.priority != ASN1.BACNET_NO_PRIORITY) - { - ASN1.encode_context_unsigned(buffer, 3, value.priority); - } - /* is there another one to encode? */ - /* FIXME: check to see if there is room in the APDU */ - } - ASN1.encode_closing_tag(buffer, 4); - } - - public static void EncodeCOVNotifyUnconfirmed(EncodeBuffer buffer, uint subscriberProcessIdentifier, uint initiatingDeviceIdentifier, BacnetObjectId monitoredObjectIdentifier, uint timeRemaining, IEnumerable values) - { - /* tag 0 - subscriberProcessIdentifier */ - ASN1.encode_context_unsigned(buffer, 0, subscriberProcessIdentifier); - /* tag 1 - initiatingDeviceIdentifier */ - ASN1.encode_context_object_id(buffer, 1, BacnetObjectTypes.OBJECT_DEVICE, initiatingDeviceIdentifier); - /* tag 2 - monitoredObjectIdentifier */ - ASN1.encode_context_object_id(buffer, 2, monitoredObjectIdentifier.type, monitoredObjectIdentifier.instance); - /* tag 3 - timeRemaining */ - ASN1.encode_context_unsigned(buffer, 3, timeRemaining); - /* tag 4 - listOfValues */ - ASN1.encode_opening_tag(buffer, 4); - foreach (var value in values) - { - /* tag 0 - propertyIdentifier */ - ASN1.encode_context_enumerated(buffer, 0, value.property.propertyIdentifier); - /* tag 1 - propertyArrayIndex OPTIONAL */ - if (value.property.propertyArrayIndex != ASN1.BACNET_ARRAY_ALL) - { - ASN1.encode_context_unsigned(buffer, 1, value.property.propertyArrayIndex); - } - /* tag 2 - value */ - /* abstract syntax gets enclosed in a context tag */ - ASN1.encode_opening_tag(buffer, 2); - foreach (var v in value.value) - { - ASN1.bacapp_encode_application_data(buffer, v); - } - ASN1.encode_closing_tag(buffer, 2); - /* tag 3 - priority OPTIONAL */ - if (value.priority != ASN1.BACNET_NO_PRIORITY) - { - ASN1.encode_context_unsigned(buffer, 3, value.priority); - } - /* is there another one to encode? */ - /* FIXME: check to see if there is room in the APDU */ - } - ASN1.encode_closing_tag(buffer, 4); - } - - public static void EncodeSubscribeCOV(EncodeBuffer buffer, uint subscriberProcessIdentifier, BacnetObjectId monitoredObjectIdentifier, bool cancellationRequest, bool issueConfirmedNotifications, uint lifetime) - { - /* tag 0 - subscriberProcessIdentifier */ - ASN1.encode_context_unsigned(buffer, 0, subscriberProcessIdentifier); - /* tag 1 - monitoredObjectIdentifier */ - ASN1.encode_context_object_id(buffer, 1, monitoredObjectIdentifier.type, monitoredObjectIdentifier.instance); - /* - If both the 'Issue Confirmed Notifications' and - 'Lifetime' parameters are absent, then this shall - indicate a cancellation request. - */ - if (cancellationRequest) - return; - /* tag 2 - issueConfirmedNotifications */ - ASN1.encode_context_boolean(buffer, 2, issueConfirmedNotifications); - /* tag 3 - lifetime */ - ASN1.encode_context_unsigned(buffer, 3, lifetime); - } - - public static int DecodeSubscribeCOV(byte[] buffer, int offset, int apduLen, out uint subscriberProcessIdentifier, out BacnetObjectId monitoredObjectIdentifier, out bool cancellationRequest, out bool issueConfirmedNotifications, out uint lifetime) - { - var len = 0; - uint lenValue; - - subscriberProcessIdentifier = 0; - monitoredObjectIdentifier = new BacnetObjectId(); - cancellationRequest = false; - issueConfirmedNotifications = false; - lifetime = 0; - - /* tag 0 - subscriberProcessIdentifier */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 0)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_unsigned(buffer, offset + len, lenValue, out subscriberProcessIdentifier); - } - else - return -1; - /* tag 1 - monitoredObjectIdentifier */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 1)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_object_id(buffer, offset + len, out monitoredObjectIdentifier.type, out monitoredObjectIdentifier.instance); - } - else - return -1; - /* optional parameters - if missing, means cancellation */ - if (len < apduLen) - { - /* tag 2 - issueConfirmedNotifications - optional */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 2)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - issueConfirmedNotifications = buffer[offset + len] > 0; - len += (int)lenValue; - } - else - { - cancellationRequest = true; - } - /* tag 3 - lifetime - optional */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 3)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_unsigned(buffer, offset + len, lenValue, out lifetime); - } - else - { - lifetime = 0; - } - } - else - { - cancellationRequest = true; - } - - return len; - } - - public static void EncodeSubscribeProperty(EncodeBuffer buffer, uint subscriberProcessIdentifier, BacnetObjectId monitoredObjectIdentifier, bool cancellationRequest, bool issueConfirmedNotifications, uint lifetime, BacnetPropertyReference monitoredProperty, bool covIncrementPresent, float covIncrement) - { - /* tag 0 - subscriberProcessIdentifier */ - ASN1.encode_context_unsigned(buffer, 0, subscriberProcessIdentifier); - /* tag 1 - monitoredObjectIdentifier */ - ASN1.encode_context_object_id(buffer, 1, monitoredObjectIdentifier.type, monitoredObjectIdentifier.instance); - if (!cancellationRequest) - { - /* tag 2 - issueConfirmedNotifications */ - ASN1.encode_context_boolean(buffer, 2, issueConfirmedNotifications); - /* tag 3 - lifetime */ - ASN1.encode_context_unsigned(buffer, 3, lifetime); - } - /* tag 4 - monitoredPropertyIdentifier */ - ASN1.encode_opening_tag(buffer, 4); - ASN1.encode_context_enumerated(buffer, 0, monitoredProperty.propertyIdentifier); - if (monitoredProperty.propertyArrayIndex != ASN1.BACNET_ARRAY_ALL) - { - ASN1.encode_context_unsigned(buffer, 1, monitoredProperty.propertyArrayIndex); - } - ASN1.encode_closing_tag(buffer, 4); - - /* tag 5 - covIncrement */ - if (covIncrementPresent) - ASN1.encode_context_real(buffer, 5, covIncrement); - } - - public static int DecodeSubscribeProperty(byte[] buffer, int offset, int apduLen, out uint subscriberProcessIdentifier, out BacnetObjectId monitoredObjectIdentifier, out BacnetPropertyReference monitoredProperty, out bool cancellationRequest, out bool issueConfirmedNotifications, out uint lifetime, out float covIncrement) - { - var len = 0; - uint lenValue; - uint decodedValue; - - subscriberProcessIdentifier = 0; - monitoredObjectIdentifier = new BacnetObjectId(); - cancellationRequest = false; - issueConfirmedNotifications = false; - lifetime = 0; - covIncrement = 0; - monitoredProperty = new BacnetPropertyReference(); - - /* tag 0 - subscriberProcessIdentifier */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 0)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_unsigned(buffer, offset + len, lenValue, out subscriberProcessIdentifier); - } - else - return -1; - - /* tag 1 - monitoredObjectIdentifier */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 1)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_object_id(buffer, offset + len, out monitoredObjectIdentifier.type, out monitoredObjectIdentifier.instance); - } - else - return -1; - - /* tag 2 - issueConfirmedNotifications - optional */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 2)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - issueConfirmedNotifications = buffer[offset + len] > 0; - len++; - } - else - { - cancellationRequest = true; - } - - /* tag 3 - lifetime - optional */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 3)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_unsigned(buffer, offset + len, lenValue, out lifetime); - } - else - { - lifetime = 0; - } - - /* tag 4 - monitoredPropertyIdentifier */ - if (!ASN1.decode_is_opening_tag_number(buffer, offset + len, 4)) - return -1; - - /* a tag number of 4 is not extended so only one octet */ - len++; - /* the propertyIdentifier is tag 0 */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 0)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_enumerated(buffer, offset + len, lenValue, out decodedValue); - monitoredProperty.propertyIdentifier = decodedValue; - } - else - return -1; - - /* the optional array index is tag 1 */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 1)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_unsigned(buffer, offset + len, lenValue, out decodedValue); - monitoredProperty.propertyArrayIndex = decodedValue; - } - else - { - monitoredProperty.propertyArrayIndex = ASN1.BACNET_ARRAY_ALL; - } - - if (!ASN1.decode_is_closing_tag_number(buffer, offset + len, 4)) - return -1; - - /* a tag number of 4 is not extended so only one octet */ - len++; - /* tag 5 - covIncrement - optional */ - if (len < apduLen && ASN1.decode_is_context_tag(buffer, offset + len, 5)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_real(buffer, offset + len, out covIncrement); - } - else - { - covIncrement = 0; - } - - return len; - } - - // F Chaxel - public static int DecodeEventNotifyData(byte[] buffer, int offset, int apduLen, out BacnetEventNotificationData eventData) - { - var len = 0; - uint lenValue; - - eventData = new BacnetEventNotificationData(); - - /* tag 0 - processIdentifier */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 0)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_unsigned(buffer, offset + len, lenValue, out eventData.processIdentifier); - } - else - return -1; - - /* tag 1 - initiatingObjectIdentifier */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 1)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_object_id(buffer, offset + len, out eventData.initiatingObjectIdentifier.type, - out eventData.initiatingObjectIdentifier.instance); - } - else - return -1; - - /* tag 2 - eventObjectIdentifier */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 2)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_object_id(buffer, offset + len, out eventData.eventObjectIdentifier.type, - out eventData.eventObjectIdentifier.instance); - } - else - return -1; - - /* tag 3 - timeStamp */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 3)) - { - len += 2; // opening Tag 3 then 2 - len += ASN1.decode_application_date(buffer, offset + len, out var date); - len += ASN1.decode_application_time(buffer, offset + len, out var time); - eventData.timeStamp.Time = new DateTime(date.Year, date.Month, date.Day, time.Hour, time.Minute, - time.Second, time.Millisecond); - - len += 2; // closing tag 2 then 3 - } - else - return -1; - - /* tag 4 - noticicationClass */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 4)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_unsigned(buffer, offset + len, lenValue, out eventData.notificationClass); - } - else - return -1; - - /* tag 5 - priority */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 5)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_unsigned(buffer, offset + len, lenValue, out var priority); - if (priority > 0xFF) return -1; - eventData.priority = (byte)priority; - } - else - return -1; - - /* tag 6 - eventType */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 6)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_enumerated(buffer, offset + len, lenValue, out eventData.eventType); - } - else - return -1; - - /* optional tag 7 - messageText : never tested */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 7)) - { - // max_lenght 20000 sound like a joke - len += ASN1.decode_context_character_string(buffer, offset + len, 20000, 7, out eventData.messageText); - } - - /* tag 8 - notifyType */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 8)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_enumerated(buffer, offset + len, lenValue, out eventData.notifyType); - } - else - return -1; - - switch (eventData.notifyType) - { - case BacnetNotifyTypes.NOTIFY_ALARM: - case BacnetNotifyTypes.NOTIFY_EVENT: - /* tag 9 - ackRequired */ - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_unsigned8(buffer, offset + len, out var val); - eventData.ackRequired = Convert.ToBoolean(val); - - /* tag 10 - fromState */ - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_enumerated(buffer, offset + len, lenValue, out eventData.fromState); - break; - } - - /* tag 11 - toState */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 11)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_enumerated(buffer, offset + len, lenValue, out eventData.toState); - } - else - return -1; - - /* tag 12 - event values */ - switch (eventData.notifyType) - { - // In cases other than alarm and event there's no data, - // so do not return an error but break and continue normally - case BacnetNotifyTypes.NOTIFY_ACK_NOTIFICATION: - break; - - case BacnetNotifyTypes.NOTIFY_ALARM: - case BacnetNotifyTypes.NOTIFY_EVENT: - if (!ASN1.decode_is_opening_tag_number(buffer, offset + len, 12)) - return -1; - - len++; - if (!ASN1.decode_is_opening_tag_number(buffer, offset + len, (byte)eventData.eventType)) - return -1; - - len++; - switch (eventData.eventType) - { - case BacnetEventTypes.EVENT_CHANGE_OF_BITSTRING: - len += ASN1.decode_context_bitstring(buffer, offset + len, 0, out eventData.changeOfBitstring_referencedBitString); - len += ASN1.decode_context_bitstring(buffer, offset + len, 1, out eventData.changeOfBitstring_statusFlags); - break; - - case BacnetEventTypes.EVENT_CHANGE_OF_STATE: - len += ASN1.decode_context_property_state(buffer, offset + len, 0, out eventData.changeOfState_newState); - len += ASN1.decode_context_bitstring(buffer, offset + len, 1, out eventData.changeOfState_statusFlags); - break; - - case BacnetEventTypes.EVENT_CHANGE_OF_VALUE: - if (!ASN1.decode_is_opening_tag_number(buffer, offset + len, 0)) - return -1; - - len++; - if (ASN1.decode_is_context_tag(buffer, offset + len, (byte)BacnetCOVTypes.CHANGE_OF_VALUE_BITS)) - { - len += ASN1.decode_context_bitstring(buffer, offset + len, 0, out eventData.changeOfValue_changedBits); - eventData.changeOfValue_tag = BacnetCOVTypes.CHANGE_OF_VALUE_BITS; - } - else if (ASN1.decode_is_context_tag(buffer, offset + len, (byte)BacnetCOVTypes.CHANGE_OF_VALUE_REAL)) - { - len += ASN1.decode_context_real(buffer, offset + len, 1, out eventData.changeOfValue_changeValue); - eventData.changeOfValue_tag = BacnetCOVTypes.CHANGE_OF_VALUE_REAL; - } - else - { - return -1; - } - - if (!ASN1.decode_is_closing_tag_number(buffer, offset + len, 0)) - return -1; - - len++; - len += ASN1.decode_context_bitstring(buffer, offset + len, 0, out eventData.changeOfValue_statusFlags); - break; - - case BacnetEventTypes.EVENT_COMMAND_FAILURE: - if (!ASN1.decode_is_opening_tag_number(buffer, offset + len, 0)) - return -1; - - len++; - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_enumerated(buffer, offset + len, lenValue, out eventData.commandFailure_commandValue); - - if (!ASN1.decode_is_closing_tag_number(buffer, offset + len, 0)) - return -1; - - len++; - len += ASN1.decode_context_bitstring(buffer, offset + len, 1, out eventData.commandFailure_statusFlags); - - if (!ASN1.decode_is_opening_tag_number(buffer, offset + len, 2)) - return -1; - - len++; - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_enumerated(buffer, offset + len, lenValue, out eventData.commandFailure_feedbackValue); - - if (!ASN1.decode_is_closing_tag_number(buffer, offset + len, 2)) - return -1; - - len++; - break; - - case BacnetEventTypes.EVENT_FLOATING_LIMIT: - len += ASN1.decode_context_real(buffer, offset + len, 0, out eventData.floatingLimit_referenceValue); - len += ASN1.decode_context_bitstring(buffer, offset + len, 1, out eventData.floatingLimit_statusFlags); - len += ASN1.decode_context_real(buffer, offset + len, 2, out eventData.floatingLimit_setPointValue); - len += ASN1.decode_context_real(buffer, offset + len, 3, out eventData.floatingLimit_errorLimit); - break; - - case BacnetEventTypes.EVENT_OUT_OF_RANGE: - len += ASN1.decode_context_real(buffer, offset + len, 0, out eventData.outOfRange_exceedingValue); - len += ASN1.decode_context_bitstring(buffer, offset + len, 1, out eventData.outOfRange_statusFlags); - len += ASN1.decode_context_real(buffer, offset + len, 2, out eventData.outOfRange_deadband); - len += ASN1.decode_context_real(buffer, offset + len, 3, out eventData.outOfRange_exceededLimit); - break; - - case BacnetEventTypes.EVENT_CHANGE_OF_LIFE_SAFETY: - len += ASN1.decode_context_enumerated(buffer, offset + len, 0, out eventData.changeOfLifeSafety_newState); - len += ASN1.decode_context_enumerated(buffer, offset + len, 1, out eventData.changeOfLifeSafety_newMode); - len += ASN1.decode_context_bitstring(buffer, offset + len, 2, out eventData.changeOfLifeSafety_statusFlags); - len += ASN1.decode_context_enumerated(buffer, offset + len, 3, out eventData.changeOfLifeSafety_operationExpected); - break; - - case BacnetEventTypes.EVENT_BUFFER_READY: - // Too lazy for this one and not sure if really needed, somebody want to do it ? :) - break; - - case BacnetEventTypes.EVENT_UNSIGNED_RANGE: - len += ASN1.decode_context_unsigned(buffer, offset + len, 0, out eventData.unsignedRange_exceedingValue); - len += ASN1.decode_context_bitstring(buffer, offset + len, 1, out eventData.unsignedRange_statusFlags); - len += ASN1.decode_context_unsigned(buffer, offset + len, 2, out eventData.unsignedRange_exceededLimit); - break; - - case BacnetEventTypes.EVENT_EXTENDED: - len += ASN1.decode_context_unsigned(buffer, offset + len, 0, out eventData.extended_vendorId); - len += ASN1.decode_context_unsigned(buffer, offset + len, 1, out eventData.extended_eventType); - if (!ASN1.decode_is_opening_tag_number(buffer, offset + len, 2)) - return -1; - - len++; - eventData.extended_parameters = new object[0]; - - while (!ASN1.decode_is_closing_tag_number(buffer, offset + len, 2)) - { - var paramCount = eventData.extended_parameters.Length + 1; - Array.Resize(ref eventData.extended_parameters, paramCount); - - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out var tagNumber, out lenValue); - - switch ((BacnetApplicationTags)tagNumber) - { - case BacnetApplicationTags.BACNET_APPLICATION_TAG_ENUMERATED: - len += ASN1.decode_enumerated(buffer, offset + len, lenValue, out var enumeratedValue); - eventData.extended_parameters[paramCount - 1] = enumeratedValue; - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_BIT_STRING: - len += ASN1.decode_bitstring(buffer, offset + len, lenValue, out var bitStringValue); - eventData.extended_parameters[paramCount - 1] = bitStringValue; - break; - - case BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT: - len += ASN1.decode_unsigned(buffer, offset + len, lenValue, out var unsignedValue); - eventData.extended_parameters[paramCount - 1] = unsignedValue; - break; - - default: - var octetStringValue = new byte[lenValue]; - len += ASN1.decode_octet_string(buffer, offset + len, apduLen, octetStringValue, 0, lenValue); - eventData.extended_parameters[paramCount - 1] = octetStringValue; - break; - } - } - - len++; - break; - - default: - return -1; - } - - if (!ASN1.decode_is_closing_tag_number(buffer, offset + len, (byte)eventData.eventType)) - return -1; - - len++; - if (!ASN1.decode_is_closing_tag_number(buffer, offset + len, 12)) - return -1; - - len++; - break; - } - - return len; - } - - private static void EncodeEventNotifyData(EncodeBuffer buffer, BacnetEventNotificationData data) - { - /* tag 0 - processIdentifier */ - ASN1.encode_context_unsigned(buffer, 0, data.processIdentifier); - /* tag 1 - initiatingObjectIdentifier */ - ASN1.encode_context_object_id(buffer, 1, data.initiatingObjectIdentifier.type, data.initiatingObjectIdentifier.instance); - - /* tag 2 - eventObjectIdentifier */ - ASN1.encode_context_object_id(buffer, 2, data.eventObjectIdentifier.type, data.eventObjectIdentifier.instance); - - /* tag 3 - timeStamp */ - ASN1.bacapp_encode_context_timestamp(buffer, 3, data.timeStamp); - - /* tag 4 - noticicationClass */ - ASN1.encode_context_unsigned(buffer, 4, data.notificationClass); - - /* tag 5 - priority */ - ASN1.encode_context_unsigned(buffer, 5, data.priority); - - /* tag 6 - eventType */ - ASN1.encode_context_enumerated(buffer, 6, (uint)data.eventType); - - /* tag 7 - messageText */ - if (!string.IsNullOrEmpty(data.messageText)) - ASN1.encode_context_character_string(buffer, 7, data.messageText); - - /* tag 8 - notifyType */ - ASN1.encode_context_enumerated(buffer, 8, (uint)data.notifyType); - - switch (data.notifyType) - { - case BacnetNotifyTypes.NOTIFY_ALARM: - case BacnetNotifyTypes.NOTIFY_EVENT: - /* tag 9 - ackRequired */ - ASN1.encode_context_boolean(buffer, 9, data.ackRequired); - - /* tag 10 - fromState */ - ASN1.encode_context_enumerated(buffer, 10, (uint)data.fromState); - break; - } - - /* tag 11 - toState */ - ASN1.encode_context_enumerated(buffer, 11, (uint)data.toState); - - switch (data.notifyType) - { - case BacnetNotifyTypes.NOTIFY_ALARM: - case BacnetNotifyTypes.NOTIFY_EVENT: - /* tag 12 - event values */ - ASN1.encode_opening_tag(buffer, 12); - - switch (data.eventType) - { - case BacnetEventTypes.EVENT_CHANGE_OF_BITSTRING: - ASN1.encode_opening_tag(buffer, 0); - ASN1.encode_context_bitstring(buffer, 0, data.changeOfBitstring_referencedBitString); - ASN1.encode_context_bitstring(buffer, 1, data.changeOfBitstring_statusFlags); - ASN1.encode_closing_tag(buffer, 0); - break; - - case BacnetEventTypes.EVENT_CHANGE_OF_STATE: - ASN1.encode_opening_tag(buffer, 1); - ASN1.encode_opening_tag(buffer, 0); - ASN1.bacapp_encode_property_state(buffer, data.changeOfState_newState); - ASN1.encode_closing_tag(buffer, 0); - ASN1.encode_context_bitstring(buffer, 1, data.changeOfState_statusFlags); - ASN1.encode_closing_tag(buffer, 1); - break; - - case BacnetEventTypes.EVENT_CHANGE_OF_VALUE: - ASN1.encode_opening_tag(buffer, 2); - ASN1.encode_opening_tag(buffer, 0); - - switch (data.changeOfValue_tag) - { - case BacnetCOVTypes.CHANGE_OF_VALUE_REAL: - ASN1.encode_context_real(buffer, 1, data.changeOfValue_changeValue); - break; - - case BacnetCOVTypes.CHANGE_OF_VALUE_BITS: - ASN1.encode_context_bitstring(buffer, 0, data.changeOfValue_changedBits); - break; - - default: - throw new Exception("Hmm?"); - } - - ASN1.encode_closing_tag(buffer, 0); - ASN1.encode_context_bitstring(buffer, 1, data.changeOfValue_statusFlags); - ASN1.encode_closing_tag(buffer, 2); - break; - - case BacnetEventTypes.EVENT_FLOATING_LIMIT: - ASN1.encode_opening_tag(buffer, 4); - ASN1.encode_context_real(buffer, 0, data.floatingLimit_referenceValue); - ASN1.encode_context_bitstring(buffer, 1, data.floatingLimit_statusFlags); - ASN1.encode_context_real(buffer, 2, data.floatingLimit_setPointValue); - ASN1.encode_context_real(buffer, 3, data.floatingLimit_errorLimit); - ASN1.encode_closing_tag(buffer, 4); - break; - - case BacnetEventTypes.EVENT_OUT_OF_RANGE: - ASN1.encode_opening_tag(buffer, 5); - ASN1.encode_context_real(buffer, 0, data.outOfRange_exceedingValue); - ASN1.encode_context_bitstring(buffer, 1, data.outOfRange_statusFlags); - ASN1.encode_context_real(buffer, 2, data.outOfRange_deadband); - ASN1.encode_context_real(buffer, 3, data.outOfRange_exceededLimit); - ASN1.encode_closing_tag(buffer, 5); - break; - - case BacnetEventTypes.EVENT_CHANGE_OF_LIFE_SAFETY: - ASN1.encode_opening_tag(buffer, 8); - ASN1.encode_context_enumerated(buffer, 0, (uint)data.changeOfLifeSafety_newState); - ASN1.encode_context_enumerated(buffer, 1, (uint)data.changeOfLifeSafety_newMode); - ASN1.encode_context_bitstring(buffer, 2, data.changeOfLifeSafety_statusFlags); - ASN1.encode_context_enumerated(buffer, 3, (uint)data.changeOfLifeSafety_operationExpected); - ASN1.encode_closing_tag(buffer, 8); - break; - - case BacnetEventTypes.EVENT_BUFFER_READY: - ASN1.encode_opening_tag(buffer, 10); - ASN1.bacapp_encode_context_device_obj_property_ref(buffer, 0, data.bufferReady_bufferProperty); - ASN1.encode_context_unsigned(buffer, 1, data.bufferReady_previousNotification); - ASN1.encode_context_unsigned(buffer, 2, data.bufferReady_currentNotification); - ASN1.encode_closing_tag(buffer, 10); - - break; - - case BacnetEventTypes.EVENT_UNSIGNED_RANGE: - ASN1.encode_opening_tag(buffer, 11); - ASN1.encode_context_unsigned(buffer, 0, data.unsignedRange_exceedingValue); - ASN1.encode_context_bitstring(buffer, 1, data.unsignedRange_statusFlags); - ASN1.encode_context_unsigned(buffer, 2, data.unsignedRange_exceededLimit); - ASN1.encode_closing_tag(buffer, 11); - break; - - default: - throw new NotImplementedException(); - } - ASN1.encode_closing_tag(buffer, 12); - break; - - case BacnetNotifyTypes.NOTIFY_ACK_NOTIFICATION: - /* FIXME: handle this case */ - break; - } - } - - public static void EncodeEventNotifyConfirmed(EncodeBuffer buffer, BacnetEventNotificationData data) - { - EncodeEventNotifyData(buffer, data); - } - - public static void EncodeEventNotifyUnconfirmed(EncodeBuffer buffer, BacnetEventNotificationData data) - { - EncodeEventNotifyData(buffer, data); - } - - public static void EncodeAlarmSummary(EncodeBuffer buffer, BacnetObjectId objectIdentifier, uint alarmState, BacnetBitString acknowledgedTransitions) - { - /* tag 0 - Object Identifier */ - ASN1.encode_application_object_id(buffer, objectIdentifier.type, objectIdentifier.instance); - /* tag 1 - Alarm State */ - ASN1.encode_application_enumerated(buffer, alarmState); - /* tag 2 - Acknowledged Transitions */ - ASN1.encode_application_bitstring(buffer, acknowledgedTransitions); - } - - // FChaxel - public static int DecodeAlarmSummaryOrEvent(byte[] buffer, int offset, int apduLen, bool getEvent, ref IList alarms, out bool moreEvent) - { - var len = 0; ; - - if (getEvent) - len++; // peut être tag 0 - - while (apduLen - 3 - len > 0) - { - var value = new BacnetGetEventInformationData(); - - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out var tagNumber, out var lenValue); - len += ASN1.decode_object_id(buffer, offset + len, out value.objectIdentifier.type, out value.objectIdentifier.instance); - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValue); - len += ASN1.decode_enumerated(buffer, offset + len, lenValue, out value.eventState); - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValue); - len += ASN1.decode_bitstring(buffer, offset + len, lenValue, out value.acknowledgedTransitions); - - if (getEvent) - { - len++; // opening Tag 3 - value.eventTimeStamps = new BacnetGenericTime[3]; - - for (var i = 0; i < 3; i++) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValue); // opening tag - - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_NULL) - { - len += ASN1.decode_application_date(buffer, offset + len, out var date); - len += ASN1.decode_application_time(buffer, offset + len, out var time); - var timestamp = date.Date + time.TimeOfDay; - value.eventTimeStamps[i] = new BacnetGenericTime(timestamp, BacnetTimestampTags.TIME_STAMP_DATETIME); - len++; // closing tag - } - else - len += (int)lenValue; - } - - len++; // closing Tag 3 - - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValue); - len += ASN1.decode_enumerated(buffer, offset + len, lenValue, out value.notifyType); - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValue); - len += ASN1.decode_bitstring(buffer, offset + len, lenValue, out value.eventEnable); - - len++; // opening tag 6; - value.eventPriorities = new uint[3]; - for (var i = 0; i < 3; i++) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValue); - len += ASN1.decode_unsigned(buffer, offset + len, lenValue, out value.eventPriorities[i]); - } - len++; // closing Tag 6 - } - - alarms.Add(value); - } - - if (getEvent) - moreEvent = buffer[apduLen - 1] == 1; - else - moreEvent = false; - - return len; - } - // DAL - public static int DecodeAlarmSummaryOrEventRequest(byte[] buffer, int offset, int apduLen, bool getEvent, ref BacnetObjectId id) - { - var len = 0; - // object id may be there for get event info, but it is optional - if (getEvent && apduLen != 0) - { - len++; // past opening tag 0 - len += ASN1.decode_object_id(buffer, offset + len, out id.type, out id.instance); - } - return len; - } - - public static void EncodeGetEventInformation(EncodeBuffer buffer, bool sendLast, BacnetObjectId lastReceivedObjectIdentifier) - { - /* encode optional parameter */ - if (sendLast) - ASN1.encode_context_object_id(buffer, 0, lastReceivedObjectIdentifier.type, lastReceivedObjectIdentifier.instance); - } - - public static void EncodeGetEventInformationAcknowledge(EncodeBuffer buffer, BacnetGetEventInformationData[] events, bool moreEvents) - { - /* service ack follows */ - /* Tag 0: listOfEventSummaries */ - ASN1.encode_opening_tag(buffer, 0); - foreach (var eventData in events) - { - /* Tag 0: objectIdentifier */ - ASN1.encode_context_object_id(buffer, 0, eventData.objectIdentifier.type, eventData.objectIdentifier.instance); - /* Tag 1: eventState */ - ASN1.encode_context_enumerated(buffer, 1, (uint)eventData.eventState); - /* Tag 2: acknowledgedTransitions */ - ASN1.encode_context_bitstring(buffer, 2, eventData.acknowledgedTransitions); - /* Tag 3: eventTimeStamps */ - ASN1.encode_opening_tag(buffer, 3); - for (var i = 0; i < 3; i++) - { - ASN1.bacapp_encode_timestamp(buffer, eventData.eventTimeStamps[i]); - } - ASN1.encode_closing_tag(buffer, 3); - /* Tag 4: notifyType */ - ASN1.encode_context_enumerated(buffer, 4, (uint)eventData.notifyType); - /* Tag 5: eventEnable */ - ASN1.encode_context_bitstring(buffer, 5, eventData.eventEnable); - /* Tag 6: eventPriorities */ - ASN1.encode_opening_tag(buffer, 6); - for (var i = 0; i < 3; i++) - { - ASN1.encode_application_unsigned(buffer, eventData.eventPriorities[i]); - } - ASN1.encode_closing_tag(buffer, 6); - } - ASN1.encode_closing_tag(buffer, 0); - ASN1.encode_context_boolean(buffer, 1, moreEvents); - } - - public static void EncodeLifeSafetyOperation(EncodeBuffer buffer, uint processId, string requestingSrc, uint operation, BacnetObjectId targetObject) - { - /* tag 0 - requestingProcessId */ - ASN1.encode_context_unsigned(buffer, 0, processId); - /* tag 1 - requestingSource */ - ASN1.encode_context_character_string(buffer, 1, requestingSrc); - /* Operation */ - ASN1.encode_context_enumerated(buffer, 2, operation); - /* Object ID */ - ASN1.encode_context_object_id(buffer, 3, targetObject.type, targetObject.instance); - } - - public static void EncodePrivateTransferConfirmed(EncodeBuffer buffer, uint vendorID, uint serviceNumber, byte[] data) - { - ASN1.encode_context_unsigned(buffer, 0, vendorID); - ASN1.encode_context_unsigned(buffer, 1, serviceNumber); - ASN1.encode_opening_tag(buffer, 2); - buffer.Add(data, data.Length); - ASN1.encode_closing_tag(buffer, 2); - } - - public static void EncodePrivateTransferUnconfirmed(EncodeBuffer buffer, uint vendorID, uint serviceNumber, byte[] data) - { - ASN1.encode_context_unsigned(buffer, 0, vendorID); - ASN1.encode_context_unsigned(buffer, 1, serviceNumber); - ASN1.encode_opening_tag(buffer, 2); - buffer.Add(data, data.Length); - ASN1.encode_closing_tag(buffer, 2); - } - - public static void EncodePrivateTransferAcknowledge(EncodeBuffer buffer, uint vendorID, uint serviceNumber, byte[] data) - { - ASN1.encode_context_unsigned(buffer, 0, vendorID); - ASN1.encode_context_unsigned(buffer, 1, serviceNumber); - ASN1.encode_opening_tag(buffer, 2); - buffer.Add(data, data.Length); - ASN1.encode_closing_tag(buffer, 2); - } - - public static void EncodeDeviceCommunicationControl(EncodeBuffer buffer, uint timeDuration, uint enableDisable, string password) - { - /* optional timeDuration */ - if (timeDuration > 0) - ASN1.encode_context_unsigned(buffer, 0, timeDuration); - - /* enable disable */ - ASN1.encode_context_enumerated(buffer, 1, enableDisable); - - /* optional password */ - if (!string.IsNullOrEmpty(password)) - { - /* FIXME: must be at least 1 character, limited to 20 characters */ - ASN1.encode_context_character_string(buffer, 2, password); - } - } - - public static int DecodeDeviceCommunicationControl(byte[] buffer, int offset, int apduLen, out uint timeDuration, out uint enableDisable, out string password) - { - var len = 0; - uint lenValueType; - - timeDuration = 0; - enableDisable = 0; - password = ""; - - /* Tag 0: timeDuration, in minutes --optional-- - * But if not included, take it as indefinite, - * which we return as "very large" */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 0)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValueType); - len += ASN1.decode_unsigned(buffer, offset + len, lenValueType, out timeDuration); - } - - /* Tag 1: enable_disable */ - if (!ASN1.decode_is_context_tag(buffer, offset + len, 1)) - return -1; - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValueType); - len += ASN1.decode_enumerated(buffer, offset + len, lenValueType, out enableDisable); - - /* Tag 2: password --optional-- */ - if (len < apduLen) - { - if (!ASN1.decode_is_context_tag(buffer, offset + len, 2)) - return -1; - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValueType); - len += ASN1.decode_character_string(buffer, offset + len, apduLen - (offset + len), lenValueType, out password); - } - - return len; - } - - public static void EncodeReinitializeDevice(EncodeBuffer buffer, BacnetReinitializedStates state, string password) - { - ASN1.encode_context_enumerated(buffer, 0, (uint)state); - - /* optional password */ - if (!string.IsNullOrEmpty(password)) - { - /* FIXME: must be at least 1 character, limited to 20 characters */ - ASN1.encode_context_character_string(buffer, 1, password); - } - } - - public static int DecodeReinitializeDevice(byte[] buffer, int offset, int apduLen, out BacnetReinitializedStates state, out string password) - { - var len = 0; - - state = BacnetReinitializedStates.BACNET_REINIT_IDLE; - password = ""; - - /* Tag 0: reinitializedStateOfDevice */ - if (!ASN1.decode_is_context_tag(buffer, offset + len, 0)) - return -1; - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out var lenValueType); - len += ASN1.decode_enumerated(buffer, offset + len, lenValueType, out state); - /* Tag 1: password - optional */ - if (len < apduLen) - { - if (!ASN1.decode_is_context_tag(buffer, offset + len, 1)) - return -1; - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValueType); - len += ASN1.decode_character_string(buffer, offset + len, apduLen - (offset + len), lenValueType, out password); - } - - return len; - } - - public static void EncodeReadRange(EncodeBuffer buffer, BacnetObjectId objectId, uint propertyId, uint arrayIndex, BacnetReadRangeRequestTypes requestType, uint position, DateTime time, int count) - { - ASN1.encode_context_object_id(buffer, 0, objectId.type, objectId.instance); - ASN1.encode_context_enumerated(buffer, 1, propertyId); - - /* optional array index */ - if (arrayIndex != ASN1.BACNET_ARRAY_ALL) - { - ASN1.encode_context_unsigned(buffer, 2, arrayIndex); - } - - /* Build the appropriate (optional) range parameter based on the request type */ - switch (requestType) - { - case BacnetReadRangeRequestTypes.RR_BY_POSITION: - ASN1.encode_opening_tag(buffer, 3); - ASN1.encode_application_unsigned(buffer, position); - ASN1.encode_application_signed(buffer, count); - ASN1.encode_closing_tag(buffer, 3); - break; - - case BacnetReadRangeRequestTypes.RR_BY_SEQUENCE: - ASN1.encode_opening_tag(buffer, 6); - ASN1.encode_application_unsigned(buffer, position); - ASN1.encode_application_signed(buffer, count); - ASN1.encode_closing_tag(buffer, 6); - break; - - case BacnetReadRangeRequestTypes.RR_BY_TIME: - ASN1.encode_opening_tag(buffer, 7); - ASN1.encode_application_date(buffer, time); - ASN1.encode_application_time(buffer, time); - ASN1.encode_application_signed(buffer, count); - ASN1.encode_closing_tag(buffer, 7); - break; - - case BacnetReadRangeRequestTypes.RR_READ_ALL: /* to attempt a read of the whole array or list, omit the range parameter */ - break; - } - } - - public static int DecodeReadRange(byte[] buffer, int offset, int apduLen, out BacnetObjectId objectId, out BacnetPropertyReference property, out BacnetReadRangeRequestTypes requestType, out uint position, out DateTime time, out int count) - { - var len = 0; - - objectId = new BacnetObjectId(); - property = new BacnetPropertyReference(); - requestType = BacnetReadRangeRequestTypes.RR_READ_ALL; - position = 0; - time = new DateTime(1, 1, 1); - count = -1; - - /* Tag 0: Object ID */ - if (!ASN1.decode_is_context_tag(buffer, offset + len, 0)) - return -1; - len++; - len += ASN1.decode_object_id(buffer, offset + len, out ushort type, out objectId.instance); - objectId.type = (BacnetObjectTypes)type; - /* Tag 1: Property ID */ - len += - ASN1.decode_tag_number_and_value(buffer, offset + len, out var tagNumber, out var lenValueType); - if (tagNumber != 1) - return -1; - len += ASN1.decode_enumerated(buffer, offset + len, lenValueType, out property.propertyIdentifier); - - /* Tag 2: Optional Array Index */ - if (len < apduLen && ASN1.decode_is_context_tag(buffer, offset + len, 0)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - len += ASN1.decode_unsigned(buffer, offset + len, lenValueType, out property.propertyArrayIndex); - } - else - property.propertyArrayIndex = ASN1.BACNET_ARRAY_ALL; - - /* optional request type */ - if (len < apduLen) - { - len += ASN1.decode_tag_number(buffer, offset + len, out tagNumber); //opening tag - switch (tagNumber) - { - case 3: - requestType = BacnetReadRangeRequestTypes.RR_BY_POSITION; - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - len += ASN1.decode_unsigned(buffer, offset + len, lenValueType, out position); - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - len += ASN1.decode_signed(buffer, offset + len, lenValueType, out count); - break; - - case 6: - requestType = BacnetReadRangeRequestTypes.RR_BY_SEQUENCE; - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - len += ASN1.decode_unsigned(buffer, offset + len, lenValueType, out position); - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - len += ASN1.decode_signed(buffer, offset + len, lenValueType, out count); - break; - - case 7: - requestType = BacnetReadRangeRequestTypes.RR_BY_TIME; - len += ASN1.decode_application_date(buffer, offset + len, out var date); - len += ASN1.decode_application_time(buffer, offset + len, out time); - time = new DateTime(date.Year, date.Month, date.Day, time.Hour, time.Minute, time.Second, time.Millisecond); - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - len += ASN1.decode_signed(buffer, offset + len, lenValueType, out count); - break; - - default: - return -1; //don't know this type yet - } - len += ASN1.decode_tag_number(buffer, offset + len, out tagNumber); //closing tag - } - return len; - } - - public static void EncodeReadRangeAcknowledge(EncodeBuffer buffer, BacnetObjectId objectId, uint propertyId, uint arrayIndex, BacnetBitString resultFlags, uint itemCount, byte[] applicationData, BacnetReadRangeRequestTypes requestType, uint firstSequence) - { - /* service ack follows */ - ASN1.encode_context_object_id(buffer, 0, objectId.type, objectId.instance); - ASN1.encode_context_enumerated(buffer, 1, propertyId); - /* context 2 array index is optional */ - if (arrayIndex != ASN1.BACNET_ARRAY_ALL) - { - ASN1.encode_context_unsigned(buffer, 2, arrayIndex); - } - /* Context 3 BACnet Result Flags */ - ASN1.encode_context_bitstring(buffer, 3, resultFlags); - /* Context 4 Item Count */ - ASN1.encode_context_unsigned(buffer, 4, itemCount); - /* Context 5 Property list - reading the standard it looks like an empty list still - * requires an opening and closing tag as the tagged parameter is not optional - */ - ASN1.encode_opening_tag(buffer, 5); - if (itemCount != 0) - { - buffer.Add(applicationData, applicationData.Length); - } - ASN1.encode_closing_tag(buffer, 5); - - if (itemCount != 0 && requestType != BacnetReadRangeRequestTypes.RR_BY_POSITION && requestType != BacnetReadRangeRequestTypes.RR_READ_ALL) - { - /* Context 6 Sequence number of first item */ - ASN1.encode_context_unsigned(buffer, 6, firstSequence); - } - } - - // FC - public static uint DecodeReadRangeAcknowledge(byte[] buffer, int offset, int apduLen, out byte[] rangeBuffer) - { - var len = 0; - rangeBuffer = null; - - /* Tag 0: Object ID */ - if (!ASN1.decode_is_context_tag(buffer, offset + len, 0)) - return 0; - - len++; - len += ASN1.decode_object_id(buffer, offset + len, out ushort _, out _); - - /* Tag 1: Property ID */ - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out var tagNumber, out var lenValueType); - if (tagNumber != 1) - return 0; - len += ASN1.decode_enumerated(buffer, offset + len, lenValueType, out _); - - /* Tag 2: Optional Array Index or Tag 3: BACnet Result Flags */ - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - if (tagNumber == 2 && len < apduLen) - len += ASN1.decode_unsigned(buffer, offset + len, lenValueType, out _); - else - /* Tag 3: BACnet Result Flags */ - len += ASN1.decode_bitstring(buffer, offset + len, 2, out _); - - /* Tag 4 Item Count */ - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - len += ASN1.decode_unsigned(buffer, offset + len, lenValueType, out var itemCount); - - if (!ASN1.decode_is_opening_tag(buffer, offset + len)) - return 0; - len += 1; - - rangeBuffer = new byte[buffer.Length - offset - len - 1]; - - Array.Copy(buffer, offset + len, rangeBuffer, 0, rangeBuffer.Length); - - return itemCount; - } - - public static void EncodeReadProperty(EncodeBuffer buffer, BacnetObjectId objectId, uint propertyId, uint arrayIndex = ASN1.BACNET_ARRAY_ALL) - { - if ((int)objectId.type <= ASN1.BACNET_MAX_OBJECT) - { - /* check bounds so that we could create malformed - messages for testing */ - ASN1.encode_context_object_id(buffer, 0, objectId.type, objectId.instance); - } - if (propertyId <= (uint)BacnetPropertyIds.MAX_BACNET_PROPERTY_ID) - { - /* check bounds so that we could create malformed - messages for testing */ - ASN1.encode_context_enumerated(buffer, 1, propertyId); - } - /* optional array index */ - if (arrayIndex != ASN1.BACNET_ARRAY_ALL) - { - ASN1.encode_context_unsigned(buffer, 2, arrayIndex); - } - } - - public static int DecodeAtomicWriteFileAcknowledge(byte[] buffer, int offset, int apduLen, out bool isStream, out int position) - { - var len = 0; - - isStream = false; - position = 0; - - len = ASN1.decode_tag_number_and_value(buffer, offset + len, out var tagNumber, out var lenValueType); - switch (tagNumber) - { - case 0: - isStream = true; - len += ASN1.decode_signed(buffer, offset + len, lenValueType, out position); - break; - - case 1: - len += ASN1.decode_signed(buffer, offset + len, lenValueType, out position); - break; - - default: - return -1; - } - - return len; - } - - public static int DecodeAtomicReadFileAcknowledge(byte[] buffer, int offset, int apduLen, out bool endOfFile, out bool isStream, out int position, out uint count, out byte[] targetBuffer, out int targetOffset) - { - var len = 0; - - endOfFile = false; - isStream = false; - position = -1; - count = 0; - targetBuffer = null; - targetOffset = -1; - - len = ASN1.decode_tag_number_and_value(buffer, offset + len, out var tagNumber, out var lenValueType); - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_BOOLEAN) - return -1; - - endOfFile = lenValueType > 0; - if (ASN1.decode_is_opening_tag_number(buffer, offset + len, 0)) - { - isStream = true; - /* a tag number is not extended so only one octet */ - len++; - /* fileStartPosition */ - var tagLen = ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - len += tagLen; - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_SIGNED_INT) - return -1; - len += ASN1.decode_signed(buffer, offset + len, lenValueType, out position); - /* fileData */ - tagLen = ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - len += tagLen; - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_OCTET_STRING) - return -1; - //len += ASN1.decode_octet_string(buffer, offset + len, buffer.Length, target_buffer, target_offset, len_value_type); - targetBuffer = buffer; - targetOffset = offset + len; - count = lenValueType; - len += (int)count; - if (!ASN1.decode_is_closing_tag_number(buffer, offset + len, 0)) - return -1; - /* a tag number is not extended so only one octet */ - len++; - } - else if (ASN1.decode_is_opening_tag_number(buffer, offset + len, 1)) - { - throw new NotImplementedException("Non stream File transfers are not supported"); - ///* a tag number is not extended so only one octet */ - //len++; - ///* fileStartRecord */ - //tag_len = ASN1.decode_tag_number_and_value(buffer, offset + len, out tag_number, out len_value_type); - //len += tag_len; - //if (tag_number != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_SIGNED_INT) - // return -1; - //len += ASN1.decode_signed(buffer, offset + len, len_value_type, out position); - ///* returnedRecordCount */ - //tag_len = ASN1.decode_tag_number_and_value(buffer, offset + len, out tag_number, out len_value_type); - //len += tag_len; - //if (tag_number != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT) - // return -1; - //len += ASN1.decode_unsigned(buffer, offset + len, len_value_type, out count); - //for (i = 0; i < count; i++) - //{ - // /* fileData */ - // tag_len = ASN1.decode_tag_number_and_value(buffer, offset + len, out tag_number, out len_value_type); - // len += tag_len; - // if (tag_number != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_OCTET_STRING) - // return -1; - // len += ASN1.decode_octet_string(buffer, offset + len, buffer.Length, target_buffer, target_offset, len_value_type); - //} - //if (!ASN1.decode_is_closing_tag_number(buffer, offset + len, 1)) - // return -1; - ///* a tag number is not extended so only one octet */ - //len++; - } - else - return -1; - - return len; - } - - public static int DecodeReadProperty(byte[] buffer, int offset, int apduLen, out BacnetObjectId objectId, out BacnetPropertyReference property) - { - var len = 0; - - objectId = new BacnetObjectId(); - property = new BacnetPropertyReference(); - - // must have at least 2 tags , otherwise return reject code: Missing required parameter - if (apduLen < 7) - return -1; - - /* Tag 0: Object ID */ - if (!ASN1.decode_is_context_tag(buffer, offset + len, 0)) - return -2; - - len++; - len += ASN1.decode_object_id(buffer, offset + len, out ushort type, out objectId.instance); - objectId.type = (BacnetObjectTypes)type; - - /* Tag 1: Property ID */ - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out var tagNumber, out var lenValueType); - if (tagNumber != 1) - return -2; - - len += ASN1.decode_enumerated(buffer, offset + len, lenValueType, out property.propertyIdentifier); - - /* Tag 2: Optional Array Index */ - if (len < apduLen) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - if (tagNumber == 2 && len < apduLen) - { - len += ASN1.decode_unsigned(buffer, offset + len, lenValueType, out property.propertyArrayIndex); - } - else - return -2; - } - else - property.propertyArrayIndex = ASN1.BACNET_ARRAY_ALL; - - if (len < apduLen) - /* If something left over now, we have an invalid request */ - return -3; - - return len; - } - - public static void EncodeReadPropertyAcknowledge(EncodeBuffer buffer, BacnetObjectId objectId, uint propertyId, uint arrayIndex, IEnumerable valueList) - { - /* service ack follows */ - ASN1.encode_context_object_id(buffer, 0, objectId.type, objectId.instance); - ASN1.encode_context_enumerated(buffer, 1, propertyId); - /* context 2 array index is optional */ - if (arrayIndex != ASN1.BACNET_ARRAY_ALL) - { - ASN1.encode_context_unsigned(buffer, 2, arrayIndex); - } - - /* Value */ - ASN1.encode_opening_tag(buffer, 3); - foreach (BacnetValue value in valueList) - { - ASN1.bacapp_encode_application_data(buffer, value); - } - ASN1.encode_closing_tag(buffer, 3); - } - - public static int DecodeReadPropertyAcknowledge(BacnetAddress address, byte[] buffer, int offset, int apduLen, out BacnetObjectId objectId, out BacnetPropertyReference property, out IList valueList) - { - objectId = new BacnetObjectId(); - property = new BacnetPropertyReference(); - valueList = new List(); - - /* FIXME: check apduLen against the len during decode */ - /* Tag 0: Object ID */ - if (!ASN1.decode_is_context_tag(buffer, offset, 0)) - return -1; - var len = 1; - len += ASN1.decode_object_id(buffer, offset + len, out objectId.type, out objectId.instance); - /* Tag 1: Property ID */ - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out var tagNumber, out var lenValueType); - if (tagNumber != 1) - return -1; - len += ASN1.decode_enumerated(buffer, offset + len, lenValueType, out property.propertyIdentifier); - /* Tag 2: Optional Array Index */ - var tagLen = ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - if (tagNumber == 2) - { - len += tagLen; - len += ASN1.decode_unsigned(buffer, offset + len, lenValueType, out property.propertyArrayIndex); - } - else - property.propertyArrayIndex = ASN1.BACNET_ARRAY_ALL; - - /* Tag 3: opening context tag */ - if (ASN1.decode_is_opening_tag_number(buffer, offset + len, 3)) - { - /* a tag number of 3 is not extended so only one octet */ - len++; - - while (apduLen - len > 1) - { - tagLen = ASN1.bacapp_decode_application_data(address, buffer, offset + len, apduLen + offset, objectId.type, (BacnetPropertyIds)property.propertyIdentifier, out var value); - if (tagLen < 0) return -1; - len += tagLen; - valueList.Add(value); - } - } - else - return -1; - - if (!ASN1.decode_is_closing_tag_number(buffer, offset + len, 3)) - return -1; - len++; - - return len; - } - - public static void EncodeReadPropertyMultiple(EncodeBuffer buffer, IList properties) - { - foreach (var value in properties) - ASN1.encode_read_access_specification(buffer, value); - } - - public static void EncodeReadPropertyMultiple(EncodeBuffer buffer, BacnetObjectId objectId, IList properties) - { - EncodeReadPropertyMultiple(buffer, new[] { new BacnetReadAccessSpecification(objectId, properties) }); - } - - public static int DecodeReadPropertyMultiple(byte[] buffer, int offset, int apduLen, out IList properties) - { - var len = 0; - - var values = new List(); - properties = null; - - while (apduLen - len > 0) - { - var tmp = ASN1.decode_read_access_specification(buffer, offset + len, apduLen - len, out var value); - if (tmp < 0) return -1; - len += tmp; - values.Add(value); - } - - properties = values; - return len; - } - - public static void EncodeReadPropertyMultipleAcknowledge(EncodeBuffer buffer, IList values) - { - foreach (var value in values) - ASN1.encode_read_access_result(buffer, value); - } - - public static int DecodeReadPropertyMultipleAcknowledge(BacnetAddress address, byte[] buffer, int offset, int apduLen, out IList values) - { - var len = 0; - - var result = new List(); - - while (apduLen - len > 0) - { - var tmp = ASN1.decode_read_access_result(address, buffer, offset + len, apduLen - len, out var value); - if (tmp < 0) - { - values = null; - return -1; - } - len += tmp; - result.Add(value); - } - - values = result; - return len; - } - - public static void EncodeWriteProperty(EncodeBuffer buffer, BacnetObjectId objectId, uint propertyId, uint arrayIndex, uint priority, IEnumerable valueList) - { - ASN1.encode_context_object_id(buffer, 0, objectId.type, objectId.instance); - ASN1.encode_context_enumerated(buffer, 1, propertyId); - - /* optional array index; ALL is -1 which is assumed when missing */ - if (arrayIndex != ASN1.BACNET_ARRAY_ALL) - { - ASN1.encode_context_unsigned(buffer, 2, arrayIndex); - } - - /* propertyValue */ - ASN1.encode_opening_tag(buffer, 3); - foreach (var value in valueList) - { - ASN1.bacapp_encode_application_data(buffer, value); - } - ASN1.encode_closing_tag(buffer, 3); - - /* optional priority - 0 if not set, 1..16 if set */ - if (priority != ASN1.BACNET_NO_PRIORITY) - { - ASN1.encode_context_unsigned(buffer, 4, priority); - } - } - - public static int DecodeCOVNotifyUnconfirmed(BacnetAddress address, byte[] buffer, int offset, int apduLen, out uint subscriberProcessIdentifier, out BacnetObjectId initiatingDeviceIdentifier, out BacnetObjectId monitoredObjectIdentifier, out uint timeRemaining, out ICollection values) - { - var len = 0; - uint lenValue; - - subscriberProcessIdentifier = 0; - initiatingDeviceIdentifier = new BacnetObjectId(); - monitoredObjectIdentifier = new BacnetObjectId(); - timeRemaining = 0; - values = null; - - /* tag 0 - subscriberProcessIdentifier */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 0)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_unsigned(buffer, offset + len, lenValue, out subscriberProcessIdentifier); - } - else - return -1; - - /* tag 1 - initiatingDeviceIdentifier */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 1)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_object_id(buffer, offset + len, out initiatingDeviceIdentifier.type, out initiatingDeviceIdentifier.instance); - } - else - return -1; - - /* tag 2 - monitoredObjectIdentifier */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 2)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_object_id(buffer, offset + len, out monitoredObjectIdentifier.type, out monitoredObjectIdentifier.instance); - } - else - return -1; - - /* tag 3 - timeRemaining */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 3)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_unsigned(buffer, offset + len, lenValue, out timeRemaining); - } - else - return -1; - - /* tag 4: opening context tag - listOfValues */ - if (!ASN1.decode_is_opening_tag_number(buffer, offset + len, 4)) - return -1; - - /* a tag number of 4 is not extended so only one octet */ - len++; - var _values = new LinkedList(); - while (!ASN1.decode_is_closing_tag_number(buffer, offset + len, 4)) - { - var newEntry = new BacnetPropertyValue(); - - /* tag 0 - propertyIdentifier */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 0)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_enumerated(buffer, offset + len, lenValue, out newEntry.property.propertyIdentifier); - } - else - return -1; - - /* tag 1 - propertyArrayIndex OPTIONAL */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 1)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_unsigned(buffer, offset + len, lenValue, out newEntry.property.propertyArrayIndex); - } - else - newEntry.property.propertyArrayIndex = ASN1.BACNET_ARRAY_ALL; - - /* tag 2: opening context tag - value */ - if (!ASN1.decode_is_opening_tag_number(buffer, offset + len, 2)) - return -1; - - /* a tag number of 2 is not extended so only one octet */ - len++; - var bValues = new List(); - while (!ASN1.decode_is_closing_tag_number(buffer, offset + len, 2)) - { - var tmp = ASN1.bacapp_decode_application_data(address, buffer, offset + len, apduLen + offset, monitoredObjectIdentifier.type, (BacnetPropertyIds)newEntry.property.propertyIdentifier, out var bValue); - if (tmp < 0) return -1; - len += tmp; - bValues.Add(bValue); - } - newEntry.value = bValues; - - /* a tag number of 2 is not extended so only one octet */ - len++; - /* tag 3 - priority OPTIONAL */ - if (ASN1.decode_is_context_tag(buffer, offset + len, 3)) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out _, out lenValue); - len += ASN1.decode_unsigned(buffer, offset + len, lenValue, out var decodedValue); - newEntry.priority = (byte)decodedValue; - } - else - newEntry.priority = (byte)ASN1.BACNET_NO_PRIORITY; - - _values.AddLast(newEntry); - } - - values = _values; - return len; - } - - public static int DecodeWriteProperty(BacnetAddress address, byte[] buffer, int offset, int apduLen, out BacnetObjectId objectId, out BacnetPropertyValue value) - { - var len = 0; - - objectId = new BacnetObjectId(); - value = new BacnetPropertyValue(); - - /* Tag 0: Object ID */ - if (!ASN1.decode_is_context_tag(buffer, offset + len, 0)) - return -1; - len++; - len += ASN1.decode_object_id(buffer, offset + len, out objectId.type, out objectId.instance); - /* Tag 1: Property ID */ - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out var tagNumber, out var lenValueType); - if (tagNumber != 1) - return -1; - len += ASN1.decode_enumerated(buffer, offset + len, lenValueType, out value.property.propertyIdentifier); - /* Tag 2: Optional Array Index */ - /* note: decode without incrementing len so we can check for opening tag */ - var tagLen = ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - if (tagNumber == 2) - { - len += tagLen; - len += ASN1.decode_unsigned(buffer, offset + len, lenValueType, out value.property.propertyArrayIndex); - } - else - value.property.propertyArrayIndex = ASN1.BACNET_ARRAY_ALL; - /* Tag 3: opening context tag */ - if (!ASN1.decode_is_opening_tag_number(buffer, offset + len, 3)) - return -1; - len++; - - //data - var valueList = new List(); - while (apduLen - len > 1 && !ASN1.decode_is_closing_tag_number(buffer, offset + len, 3)) - { - var l = ASN1.bacapp_decode_application_data(address, buffer, offset + len, apduLen + offset, objectId.type, (BacnetPropertyIds)value.property.propertyIdentifier, out var bValue); - if (l <= 0) return -1; - len += l; - valueList.Add(bValue); - } - value.value = valueList; - - if (!ASN1.decode_is_closing_tag_number(buffer, offset + len, 3)) - return -2; - /* a tag number of 3 is not extended so only one octet */ - len++; - /* Tag 4: optional Priority - assumed MAX if not explicitly set */ - value.priority = (byte)ASN1.BACNET_MAX_PRIORITY; - if (len < apduLen) - { - tagLen = ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValueType); - if (tagNumber == 4) - { - len += tagLen; - len = ASN1.decode_unsigned(buffer, offset + len, lenValueType, out var unsignedValue); - if (unsignedValue >= ASN1.BACNET_MIN_PRIORITY && unsignedValue <= ASN1.BACNET_MAX_PRIORITY) - value.priority = (byte)unsignedValue; - else - return -1; - } - } - - return len; - } - - public static void EncodeWritePropertyMultiple(EncodeBuffer buffer, BacnetObjectId objectId, ICollection valueList) - { - ASN1.encode_context_object_id(buffer, 0, objectId.type, objectId.instance); - /* Tag 1: sequence of WriteAccessSpecification */ - ASN1.encode_opening_tag(buffer, 1); - - foreach (var pValue in valueList) - { - /* Tag 0: Property */ - ASN1.encode_context_enumerated(buffer, 0, pValue.property.propertyIdentifier); - - /* Tag 1: array index */ - if (pValue.property.propertyArrayIndex != ASN1.BACNET_ARRAY_ALL) - ASN1.encode_context_unsigned(buffer, 1, pValue.property.propertyArrayIndex); - - /* Tag 2: Value */ - ASN1.encode_opening_tag(buffer, 2); - foreach (var value in pValue.value) - { - ASN1.bacapp_encode_application_data(buffer, value); - } - ASN1.encode_closing_tag(buffer, 2); - - /* Tag 3: Priority */ - if (pValue.priority != ASN1.BACNET_NO_PRIORITY) - ASN1.encode_context_unsigned(buffer, 3, pValue.priority); - } - - ASN1.encode_closing_tag(buffer, 1); - } - - public static void EncodeWriteObjectMultiple(EncodeBuffer buffer, ICollection valueList) - { - foreach (var value in valueList) - EncodeWritePropertyMultiple(buffer, value.objectIdentifier, value.values); - } - - // By C. Gunter - // quite the same as DecodeWritePropertyMultiple - public static int DecodeCreateObject(BacnetAddress address, byte[] buffer, int offset, int apduLen, out BacnetObjectId objectId, out ICollection valuesRefs) - { - var len = 0; - - objectId = new BacnetObjectId(); - valuesRefs = null; - - //object id - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out var tagNumber, out var lenValue); - - if (tagNumber == 0 && apduLen > len) - { - apduLen -= len; - if (apduLen >= 4) - { - len += ASN1.decode_context_object_id(buffer, offset + len, 1, out var typenr, out objectId.instance); - objectId.type = (BacnetObjectTypes)typenr; - } - else - return -1; - } - else - return -1; - if (ASN1.decode_is_closing_tag(buffer, offset + len)) - len++; - //end objectid - - // No initial values ? - if (buffer.Length == offset + len) - return len; - - /* Tag 1: sequence of WriteAccessSpecification */ - if (!ASN1.decode_is_opening_tag_number(buffer, offset + len, 1)) - return -1; - len++; - - var _values = new LinkedList(); - while (apduLen - len > 1) - { - var newEntry = new BacnetPropertyValue(); - - /* tag 0 - Property Identifier */ - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValue); - uint propertyId; - if (tagNumber == 0) - len += ASN1.decode_enumerated(buffer, offset + len, lenValue, out propertyId); - else - return -1; - - /* tag 1 - Property Array Index - optional */ - var ulVal = ASN1.BACNET_ARRAY_ALL; - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValue); - if (tagNumber == 1) - { - len += ASN1.decode_unsigned(buffer, offset + len, lenValue, out ulVal); - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValue); - } - newEntry.property = new BacnetPropertyReference(propertyId, ulVal); - - /* tag 2 - Property Value */ - if (tagNumber == 2 && ASN1.decode_is_opening_tag(buffer, offset + len - 1)) - { - var values = new List(); - while (!ASN1.decode_is_closing_tag(buffer, offset + len)) - { - var l = ASN1.bacapp_decode_application_data(address, buffer, offset + len, apduLen + offset, objectId.type, (BacnetPropertyIds)propertyId, out var value); - if (l <= 0) return -1; - len += l; - values.Add(value); - } - len++; - newEntry.value = values; - } - else - return -1; - - _values.AddLast(newEntry); - } - - /* Closing tag 1 - List of Properties */ - if (!ASN1.decode_is_closing_tag_number(buffer, offset + len, 1)) - return -1; - len++; - - valuesRefs = _values; - - return len; - } - - public static int DecodeDeleteObject(byte[] buffer, int offset, int apduLen, out BacnetObjectId objectId) - { - objectId = new BacnetObjectId(); - ASN1.decode_tag_number_and_value(buffer, offset, out var tagNumber, out _); - - if (tagNumber != 12) - return -1; - - var len = 1; - len += ASN1.decode_object_id(buffer, offset + len, out objectId.type, out objectId.instance); - - if (len == apduLen) //check if packet was correct! - return len; - - return -1; - } - - public static void EncodeCreateObjectAcknowledge(EncodeBuffer buffer, BacnetObjectId objectId) - { - ASN1.encode_application_object_id(buffer, objectId.type, objectId.instance); - } - - public static int DecodeWritePropertyMultiple(BacnetAddress address, byte[] buffer, int offset, int apduLen, out BacnetObjectId objectId, out ICollection valuesRefs) - { - var len = 0; - objectId = new BacnetObjectId(); - valuesRefs = null; - - /* Context tag 0 - Object ID */ - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out var tagNumber, out var lenValue); - if (tagNumber == 0 && apduLen > len) - { - apduLen -= len; - if (apduLen >= 4) - { - len += ASN1.decode_object_id(buffer, offset + len, out objectId.type, out objectId.instance); - } - else - return -1; - } - else - return -1; - - /* Tag 1: sequence of WriteAccessSpecification */ - if (!ASN1.decode_is_opening_tag_number(buffer, offset + len, 1)) - return -1; - len++; - - var _values = new LinkedList(); - while (apduLen - len > 1) - { - var newEntry = new BacnetPropertyValue(); - - /* tag 0 - Property Identifier */ - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValue); - uint propertyId; - if (tagNumber == 0) - len += ASN1.decode_enumerated(buffer, offset + len, lenValue, out propertyId); - else - return -1; - - /* tag 1 - Property Array Index - optional */ - var ulVal = ASN1.BACNET_ARRAY_ALL; - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValue); - if (tagNumber == 1) - { - len += ASN1.decode_unsigned(buffer, offset + len, lenValue, out ulVal); - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValue); - } - newEntry.property = new BacnetPropertyReference(propertyId, ulVal); - - /* tag 2 - Property Value */ - if (tagNumber == 2 && ASN1.decode_is_opening_tag(buffer, offset + len - 1)) - { - var values = new List(); - while (!ASN1.decode_is_closing_tag(buffer, offset + len)) - { - var l = ASN1.bacapp_decode_application_data(address, buffer, offset + len, apduLen + offset, objectId.type, (BacnetPropertyIds)propertyId, out var value); - if (l <= 0) return -1; - len += l; - values.Add(value); - } - len++; - newEntry.value = values; - } - else - return -1; - - /* tag 3 - Priority - optional */ - ulVal = ASN1.BACNET_NO_PRIORITY; - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out lenValue); - if (tagNumber == 3) - len += ASN1.decode_unsigned(buffer, offset + len, lenValue, out ulVal); - else - len--; - newEntry.priority = (byte)ulVal; - - _values.AddLast(newEntry); - } - - /* Closing tag 1 - List of Properties */ - if (!ASN1.decode_is_closing_tag_number(buffer, offset + len, 1)) - return -1; - len++; - - valuesRefs = _values; - - return len; - } - - public static void EncodeTimeSync(EncodeBuffer buffer, DateTime time) - { - ASN1.encode_application_date(buffer, time); - ASN1.encode_application_time(buffer, time); - } - - public static int DecodeTimeSync(byte[] buffer, int offset, int length, out DateTime dateTime) - { - var len = 0; - dateTime = new DateTime(1, 1, 1); - - /* date */ - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out var tagNumber, out _); - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_DATE) - return -1; - len += ASN1.decode_date(buffer, offset + len, out var date); - /* time */ - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out tagNumber, out _); - if (tagNumber != (byte)BacnetApplicationTags.BACNET_APPLICATION_TAG_TIME) - return -1; - len += ASN1.decode_bacnet_time(buffer, offset + len, out var time); - - //merge - dateTime = new DateTime(date.Year, date.Month, date.Day, time.Hour, time.Minute, time.Second, time.Millisecond); - - return len; - } - - public static void EncodeError(EncodeBuffer buffer, BacnetErrorClasses errorClass, BacnetErrorCodes errorCode) - { - ASN1.encode_application_enumerated(buffer, (uint)errorClass); - ASN1.encode_application_enumerated(buffer, (uint)errorCode); - } - - public static int DecodeError(byte[] buffer, int offset, int length, out BacnetErrorClasses errorClass, out BacnetErrorCodes errorCode) - { - var orgOffset = offset; - - offset += ASN1.decode_tag_number_and_value(buffer, offset, out _, out var lenValueType); - /* FIXME: we could validate that the tag is enumerated... */ - offset += ASN1.decode_enumerated(buffer, offset, lenValueType, out errorClass); - offset += ASN1.decode_tag_number_and_value(buffer, offset, out _, out lenValueType); - /* FIXME: we could validate that the tag is enumerated... */ - offset += ASN1.decode_enumerated(buffer, offset, lenValueType, out errorCode); - - return offset - orgOffset; - } - - public static void EncodeLogRecord(EncodeBuffer buffer, BacnetLogRecord record) - { - /* Tag 0: timestamp */ - ASN1.encode_opening_tag(buffer, 0); - ASN1.encode_application_date(buffer, record.timestamp); - ASN1.encode_application_time(buffer, record.timestamp); - ASN1.encode_closing_tag(buffer, 0); - - /* Tag 1: logDatum */ - if (record.type != BacnetTrendLogValueType.TL_TYPE_NULL) - { - if (record.type == BacnetTrendLogValueType.TL_TYPE_ERROR) - { - ASN1.encode_opening_tag(buffer, 1); - ASN1.encode_opening_tag(buffer, 8); - var err = record.GetValue(); - EncodeError(buffer, err.error_class, err.error_code); - ASN1.encode_closing_tag(buffer, 8); - ASN1.encode_closing_tag(buffer, 1); - return; - } - - ASN1.encode_opening_tag(buffer, 1); - var tmp1 = new EncodeBuffer(); - switch (record.type) - { - case BacnetTrendLogValueType.TL_TYPE_ANY: - throw new NotImplementedException(); - case BacnetTrendLogValueType.TL_TYPE_BITS: - ASN1.encode_bitstring(tmp1, record.GetValue()); - break; - - case BacnetTrendLogValueType.TL_TYPE_BOOL: - tmp1.Add(record.GetValue() ? (byte)1 : (byte)0); - break; - - case BacnetTrendLogValueType.TL_TYPE_DELTA: - ASN1.encode_bacnet_real(tmp1, record.GetValue()); - break; - - case BacnetTrendLogValueType.TL_TYPE_ENUM: - ASN1.encode_application_enumerated(tmp1, record.GetValue()); - break; - - case BacnetTrendLogValueType.TL_TYPE_REAL: - ASN1.encode_bacnet_real(tmp1, record.GetValue()); - break; - - case BacnetTrendLogValueType.TL_TYPE_SIGN: - ASN1.encode_bacnet_signed(tmp1, record.GetValue()); - break; - - case BacnetTrendLogValueType.TL_TYPE_STATUS: - ASN1.encode_bitstring(tmp1, record.GetValue()); - break; - - case BacnetTrendLogValueType.TL_TYPE_UNSIGN: - ASN1.encode_bacnet_unsigned(tmp1, record.GetValue()); - break; - } - ASN1.encode_tag(buffer, (byte)record.type, true, (uint)tmp1.offset); - buffer.Add(tmp1.buffer, tmp1.offset); - ASN1.encode_closing_tag(buffer, 1); - } - - /* Tag 2: status */ - if (record.statusFlags.bits_used > 0) - { - ASN1.encode_opening_tag(buffer, 2); - ASN1.encode_application_bitstring(buffer, record.statusFlags); - ASN1.encode_closing_tag(buffer, 2); - } - } - - public static int DecodeLogRecord(byte[] buffer, int offset, int length, int nCurves, out BacnetLogRecord[] records) - { - var len = 0; - records = new BacnetLogRecord[nCurves]; - - len += ASN1.decode_tag_number(buffer, offset + len, out var tagNumber); - if (tagNumber != 0) return -1; - - // Date and Time in Tag 0 - len += ASN1.decode_application_date(buffer, offset + len, out var date); - len += ASN1.decode_application_time(buffer, offset + len, out var time); - - var dt = new DateTime(date.Year, date.Month, date.Day, time.Hour, time.Minute, time.Second, time.Millisecond); - - if (!ASN1.decode_is_closing_tag(buffer, offset + len)) return -1; - len++; - - // Value or error in Tag 1 - len += ASN1.decode_tag_number(buffer, offset + len, out tagNumber); - if (tagNumber != 1) return -1; - - // Not test for TrendLogMultiple - // Seems to be encoded like this somewhere in an Ashrae document - for (var curveNumber = 0; curveNumber < nCurves; curveNumber++) - { - len += ASN1.decode_tag_number_and_value(buffer, offset + len, out var contextTagType, out var lenValue); - records[curveNumber] = new BacnetLogRecord - { - timestamp = dt, - type = (BacnetTrendLogValueType)contextTagType - }; - - switch ((BacnetTrendLogValueType)contextTagType) - { - case BacnetTrendLogValueType.TL_TYPE_STATUS: - len += ASN1.decode_bitstring(buffer, offset + len, lenValue, out var sval); - records[curveNumber].Value = sval; - break; - - case BacnetTrendLogValueType.TL_TYPE_BOOL: - records[curveNumber].Value = buffer[offset + len] > 0; - len++; - break; - - case BacnetTrendLogValueType.TL_TYPE_REAL: - len += ASN1.decode_real(buffer, offset + len, out var rval); - records[curveNumber].Value = rval; - break; - - case BacnetTrendLogValueType.TL_TYPE_ENUM: - len += ASN1.decode_enumerated(buffer, offset + len, lenValue, out var eval); - records[curveNumber].Value = eval; - break; - - case BacnetTrendLogValueType.TL_TYPE_SIGN: - len += ASN1.decode_signed(buffer, offset + len, lenValue, out var ival); - records[curveNumber].Value = ival; - break; - - case BacnetTrendLogValueType.TL_TYPE_UNSIGN: - len += ASN1.decode_unsigned(buffer, offset + len, lenValue, out var uinval); - records[curveNumber].Value = uinval; - break; - - case BacnetTrendLogValueType.TL_TYPE_ERROR: - len += DecodeError(buffer, offset + len, length, out var errclass, out var errcode); - records[curveNumber].Value = new BacnetError(errclass, errcode); - len++; // Closing Tag 8 - break; - - case BacnetTrendLogValueType.TL_TYPE_NULL: - len++; - records[curveNumber].Value = null; - break; - // Time change (Automatic or Synch time) Delta in seconds - case BacnetTrendLogValueType.TL_TYPE_DELTA: - len += ASN1.decode_real(buffer, offset + len, out var dval); - records[curveNumber].Value = dval; - break; - // No way to handle these data types, sure it's the end of this download ! - case BacnetTrendLogValueType.TL_TYPE_ANY: - throw new NotImplementedException(); - case BacnetTrendLogValueType.TL_TYPE_BITS: - len += ASN1.decode_bitstring(buffer, offset + len, lenValue, out var bval); - records[curveNumber].Value = bval; - break; - - default: - return 0; - } - } - - if (!ASN1.decode_is_closing_tag(buffer, offset + len)) - return -1; - - len++; - - if (len >= length) - return len; - - var l = ASN1.decode_tag_number(buffer, offset + len, out tagNumber); - - // Optional Tag 2 - if (tagNumber != 2) - return len; - - len += l; - len += ASN1.decode_bitstring(buffer, offset + len, 2, out var statusFlags); - - //set status to all returns - for (var curveNumber = 0; curveNumber < nCurves; curveNumber++) - records[curveNumber].statusFlags = statusFlags; - - return len; - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Storage/DeviceStorage.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Storage/DeviceStorage.cs deleted file mode 100644 index 8422d39..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Storage/DeviceStorage.cs +++ /dev/null @@ -1,459 +0,0 @@ -/************************************************************************** -* MIT License -* -* Copyright (C) 2014 Morten Kvistgaard -* -* Permission is hereby granted, free of charge, to any person obtaining -* a copy of this software and associated documentation files (the -* "Software"), to deal in the Software without restriction, including -* without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to -* permit persons to whom the Software is furnished to do so, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -* -*********************************************************************/ - -namespace System.IO.BACnet.Storage; - -/// -/// This is a basic example of a BACNet storage. This one is XML based. It has no fancy optimizing or anything. -/// -[Serializable] -public class DeviceStorage -{ - [XmlIgnore] - public uint DeviceId { get; set; } - - public delegate void ChangeOfValueHandler(DeviceStorage sender, BacnetObjectId objectId, BacnetPropertyIds propertyId, uint arrayIndex, IList value); - public event ChangeOfValueHandler ChangeOfValue; - public delegate void ReadOverrideHandler(BacnetObjectId objectId, BacnetPropertyIds propertyId, uint arrayIndex, out IList value, out ErrorCodes status, out bool handled); - public event ReadOverrideHandler ReadOverride; - public delegate void WriteOverrideHandler(BacnetObjectId objectId, BacnetPropertyIds propertyId, uint arrayIndex, IList value, out ErrorCodes status, out bool handled); - public event WriteOverrideHandler WriteOverride; - - public Object[] Objects { get; set; } - - public DeviceStorage() - { - DeviceId = (uint)new Random().Next(); - Objects = new Object[0]; - } - - public Property FindProperty(BacnetObjectId objectId, BacnetPropertyIds propertyId) - { - //liniear search - var obj = FindObject(objectId); - return FindProperty(obj, propertyId); - } - - private static Property FindProperty(Object obj, BacnetPropertyIds propertyId) - { - //liniear search - return obj?.Properties.FirstOrDefault(p => p.Id == propertyId); - } - - private Object FindObject(BacnetObjectTypes objectType) - { - //liniear search - return Objects.FirstOrDefault(obj => obj.Type == objectType); - } - - public Object FindObject(BacnetObjectId objectId) - { - //liniear search - return Objects.FirstOrDefault(obj => obj.Type == objectId.type && obj.Instance == objectId.instance); - } - - public enum ErrorCodes - { - Good = 0, - GenericError = -1, - NotExist = -2, - NotForMe = -3, - WriteAccessDenied = -4, - UnknownObject = -5, - UnknownProperty = -6 - } - - public int ReadPropertyValue(BacnetObjectId objectId, BacnetPropertyIds propertyId) - { - if (ReadProperty(objectId, propertyId, Serialize.ASN1.BACNET_ARRAY_ALL, out IList value) != ErrorCodes.Good) - return 0; - - if (value == null || value.Count < 1) - return 0; - - return (int)Convert.ChangeType(value[0].Value, typeof(int)); - } - - public ErrorCodes ReadProperty(BacnetObjectId objectId, BacnetPropertyIds propertyId, uint arrayIndex, out IList value) - { - value = new BacnetValue[0]; - - //wildcard device_id - if (objectId.type == BacnetObjectTypes.OBJECT_DEVICE && objectId.instance >= Serialize.ASN1.BACNET_MAX_INSTANCE) - objectId.instance = DeviceId; - - //overrides - if (ReadOverride != null) - { - ReadOverride(objectId, propertyId, arrayIndex, out value, out ErrorCodes status, out bool handled); - if (handled) - return status; - } - - //find in storage - var obj = FindObject(objectId); - if (obj == null) - return ErrorCodes.UnknownObject; - - //object found now find property - Godot.GD.Print("object "+objectId+"|property "+propertyId); - var p = FindProperty(objectId, propertyId); - if (p == null) - return ErrorCodes.NotExist; - - //get value ... check for array index - if (arrayIndex == 0) - { - value = new[] { new BacnetValue(BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT, (uint)p.BacnetValue.Count) }; - } - else if (arrayIndex != Serialize.ASN1.BACNET_ARRAY_ALL) - { - value = new[] { p.BacnetValue[(int)arrayIndex - 1] }; - } - else - { - value = p.BacnetValue; - } - Godot.GD.Print("p "+p.BacnetValue.Count()); - - return ErrorCodes.Good; - } - - public void ReadPropertyMultiple(BacnetObjectId objectId, ICollection properties, out IList values) - { - var valuesRet = new List(); - - foreach (var entry in properties) - { - var newEntry = new BacnetPropertyValue { property = entry }; - - switch (ReadProperty(objectId, (BacnetPropertyIds)entry.propertyIdentifier, entry.propertyArrayIndex, out newEntry.value)) - { - case ErrorCodes.UnknownObject: - newEntry.value = new[] - { - new BacnetValue(BacnetApplicationTags.BACNET_APPLICATION_TAG_ERROR, - new BacnetError(BacnetErrorClasses.ERROR_CLASS_OBJECT, BacnetErrorCodes.ERROR_CODE_UNKNOWN_OBJECT)) - }; - break; - case ErrorCodes.NotExist: - newEntry.value = new[] - { - new BacnetValue(BacnetApplicationTags.BACNET_APPLICATION_TAG_ERROR, - new BacnetError(BacnetErrorClasses.ERROR_CLASS_PROPERTY, BacnetErrorCodes.ERROR_CODE_UNKNOWN_PROPERTY)) - }; - break; - } - - valuesRet.Add(newEntry); - } - - values = valuesRet; - } - - public bool ReadPropertyAll(BacnetObjectId objectId, out IList values) - { - //find - var obj = FindObject(objectId); - if (obj == null) - { - values = null; - return false; - } - - //build - var propertyValues = new BacnetPropertyValue[obj.Properties.Length]; - for (var i = 0; i < obj.Properties.Length; i++) - { - var newEntry = new BacnetPropertyValue - { - property = new BacnetPropertyReference((uint)obj.Properties[i].Id, Serialize.ASN1.BACNET_ARRAY_ALL) - }; - - if (ReadProperty(objectId, obj.Properties[i].Id, Serialize.ASN1.BACNET_ARRAY_ALL, out newEntry.value) != ErrorCodes.Good) - { - var bacnetError = new BacnetError(BacnetErrorClasses.ERROR_CLASS_OBJECT, BacnetErrorCodes.ERROR_CODE_UNKNOWN_PROPERTY); - newEntry.value = new[] { new BacnetValue(BacnetApplicationTags.BACNET_APPLICATION_TAG_ERROR, bacnetError) }; - } - - propertyValues[i] = newEntry; - } - - values = propertyValues; - return true; - } - - public void WritePropertyValue(BacnetObjectId objectId, BacnetPropertyIds propertyId, int value) - { - //get existing type - if (ReadProperty(objectId, propertyId, Serialize.ASN1.BACNET_ARRAY_ALL, out IList readValues) != ErrorCodes.Good) - return; - - if (readValues == null || readValues.Count == 0) - return; - - //write - WriteProperty(objectId, propertyId, Serialize.ASN1.BACNET_ARRAY_ALL, new[] - { - new BacnetValue(readValues[0].Tag, Convert.ChangeType(value, readValues[0].Value.GetType())) - }); - } - - - public void WriteProperty(BacnetObjectId objectId, BacnetPropertyIds propertyId, BacnetValue value) - { - WriteProperty(objectId, propertyId, Serialize.ASN1.BACNET_ARRAY_ALL, new[] { value }); - } - - public ErrorCodes WriteProperty(BacnetObjectId objectId, BacnetPropertyIds propertyId, uint arrayIndex, IList value, bool addIfNotExits = false) - { - //wildcard device_id - if (objectId.type == BacnetObjectTypes.OBJECT_DEVICE && objectId.instance >= Serialize.ASN1.BACNET_MAX_INSTANCE) - objectId.instance = DeviceId; - - //overrides - if (WriteOverride != null) - { - WriteOverride(objectId, propertyId, arrayIndex, value, out ErrorCodes status, out bool handled); - if (handled) - return status; - } - - //find - var p = FindProperty(objectId, propertyId); - if (p == null) - { - if (!addIfNotExits) return ErrorCodes.NotExist; - - //add obj - var obj = FindObject(objectId); - if (obj == null) - { - obj = new Object - { - Type = objectId.type, - Instance = objectId.instance - }; - var arr = Objects; - Array.Resize(ref arr, arr.Length + 1); - arr[arr.Length - 1] = obj; - Objects = arr; - } - - //add property - p = new Property { Id = propertyId }; - var props = obj.Properties; - Array.Resize(ref props, props.Length + 1); - props[props.Length - 1] = p; - obj.Properties = props; - } - - //set type if needed - if (p.Tag == BacnetApplicationTags.BACNET_APPLICATION_TAG_NULL && value != null) - { - foreach (var v in value) - { - if (v.Tag == BacnetApplicationTags.BACNET_APPLICATION_TAG_NULL) - continue; - - p.Tag = v.Tag; - break; - } - } - - //write - p.BacnetValue = value; - - //send event ... for subscriptions - ChangeOfValue?.Invoke(this, objectId, propertyId, arrayIndex, value); - - return ErrorCodes.Good; - } - - // Write PROP_PRESENT_VALUE or PROP_RELINQUISH_DEFAULT in an object with a 16 level PROP_PRIORITY_ARRAY (BACNET_APPLICATION_TAG_NULL) - public ErrorCodes WriteCommandableProperty(BacnetObjectId objectId, BacnetPropertyIds propertyId, BacnetValue value, uint priority) - { - - if (propertyId != BacnetPropertyIds.PROP_PRESENT_VALUE) - return ErrorCodes.NotForMe; - - var presentvalue = FindProperty(objectId, BacnetPropertyIds.PROP_PRESENT_VALUE); - if (presentvalue == null) - return ErrorCodes.NotForMe; - - var relinquish = FindProperty(objectId, BacnetPropertyIds.PROP_RELINQUISH_DEFAULT); - if (relinquish == null) - return ErrorCodes.NotForMe; - - var outOfService = FindProperty(objectId, BacnetPropertyIds.PROP_OUT_OF_SERVICE); - if (outOfService == null) - return ErrorCodes.NotForMe; - - var array = FindProperty(objectId, BacnetPropertyIds.PROP_PRIORITY_ARRAY); - if (array == null) - return ErrorCodes.NotForMe; - - var errorcode = ErrorCodes.GenericError; - - try - { - // If PROP_OUT_OF_SERVICE=True, value is accepted as is : http://www.bacnetwiki.com/wiki/index.php?title=Priority_Array - if ((bool)outOfService.BacnetValue[0].Value && propertyId == BacnetPropertyIds.PROP_PRESENT_VALUE) - { - WriteProperty(objectId, BacnetPropertyIds.PROP_PRESENT_VALUE, value); - return ErrorCodes.Good; - } - - IList valueArray = null; - - // Thank's to Steve Karg - // The 135-2016 text: - // 19.2.2 Application Priority Assignments - // All commandable objects within a device shall be configurable to accept writes to all priorities except priority 6 - if (priority == 6) - return ErrorCodes.WriteAccessDenied; - - // http://www.chipkin.com/changing-the-bacnet-present-value-or-why-the-present-value-doesn%E2%80%99t-change/ - // Write Property PROP_PRESENT_VALUE : A value is placed in the PROP_PRIORITY_ARRAY - if (propertyId == BacnetPropertyIds.PROP_PRESENT_VALUE) - { - errorcode = ErrorCodes.Good; - - valueArray = array.BacnetValue; - if (value.Value == null) - valueArray[(int)priority - 1] = new BacnetValue(null); - else - valueArray[(int)priority - 1] = value; - array.BacnetValue = valueArray; - } - - // Look on the priority Array to find the first value to be set in PROP_PRESENT_VALUE - if (errorcode == ErrorCodes.Good) - { - - var done = false; - for (var i = 0; i < 16; i++) - { - if (valueArray[i].Value == null) - continue; - - WriteProperty(objectId, BacnetPropertyIds.PROP_PRESENT_VALUE, valueArray[i]); - done = true; - break; - } - - if (done == false) // Nothing in the array : PROP_PRESENT_VALUE = PROP_RELINQUISH_DEFAULT - { - var defaultValue = relinquish.BacnetValue; - WriteProperty(objectId, BacnetPropertyIds.PROP_PRESENT_VALUE, defaultValue[0]); - } - } - } - catch - { - errorcode = ErrorCodes.GenericError; - } - - return errorcode; - } - - public ErrorCodes[] WritePropertyMultiple(BacnetObjectId objectId, ICollection values) - { - return values - .Select(v => WriteProperty(objectId, (BacnetPropertyIds)v.property.propertyIdentifier, v.property.propertyArrayIndex, v.value)) - .ToArray(); - } - - /// - /// Store the class, as XML file - /// - /// - public void Save(string path) - { - var s = new XmlSerializer(typeof(DeviceStorage)); - using var fs = new FileStream(path, FileMode.Create, FileAccess.Write); - s.Serialize(fs, this); - } - - /// - /// Load XML values into class - /// - /// Embedded or external file - /// Optional deviceId other than the one in the Xml file - /// - public static DeviceStorage Load(string path, uint? deviceId = null) - { - StreamReader textStreamReader; - - var assembly = Assembly.GetCallingAssembly(); - - try - { - // check if the xml file is an embedded resource - textStreamReader = new StreamReader(assembly.GetManifestResourceStream(path)); - } - catch - { - // if not check the external file - if (!File.Exists(path)) - throw new Exception("No AppSettings found"); - - textStreamReader = new StreamReader(path); - } - - var s = new XmlSerializer(typeof(DeviceStorage)); - - using (textStreamReader) - { - var ret = (DeviceStorage)s.Deserialize(textStreamReader); - - //set device_id - var obj = ret.FindObject(BacnetObjectTypes.OBJECT_DEVICE); - if (obj != null) - ret.DeviceId = obj.Instance; - - // use the deviceId in the Xml file or another one - if (!deviceId.HasValue) - return ret; - - ret.DeviceId = deviceId.Value; - if (obj == null) - return ret; - - // change the value - obj.Instance = deviceId.Value; - IList val = new[] - { - new BacnetValue(BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID, $"OBJECT_DEVICE:{deviceId.Value}") - }; - - ret.WriteProperty(new BacnetObjectId(BacnetObjectTypes.OBJECT_DEVICE, - Serialize.ASN1.BACNET_MAX_INSTANCE), BacnetPropertyIds.PROP_OBJECT_IDENTIFIER, 1, val, true); - - return ret; - } - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Storage/Object.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Storage/Object.cs deleted file mode 100644 index baecc62..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Storage/Object.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace System.IO.BACnet.Storage; - -[Serializable] -public class Object -{ - [XmlAttribute] - public BacnetObjectTypes Type { get; set; } - - [XmlAttribute] - public uint Instance { get; set; } - - public Property[] Properties { get; set; } - - public Object() - { - Properties = new Property[0]; - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Storage/Property.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Storage/Property.cs deleted file mode 100644 index b4d2418..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Storage/Property.cs +++ /dev/null @@ -1,127 +0,0 @@ -namespace System.IO.BACnet.Storage; - -[Serializable] -public class Property -{ - [XmlIgnore] - public BacnetPropertyIds Id { get; set; } - - [XmlAttribute("Id")] - public string IdText - { - get - { - return Id.ToString(); - } - set - { - Id = (BacnetPropertyIds)Enum.Parse(typeof(BacnetPropertyIds), value); - } - } - - [XmlAttribute] - public BacnetApplicationTags Tag { get; set; } - - [XmlElement] - public string[] Value { get; set; } - - public static BacnetValue DeserializeValue(string value, BacnetApplicationTags type) - { - switch (type) - { - case BacnetApplicationTags.BACNET_APPLICATION_TAG_NULL: - return value == "" - ? new BacnetValue(type, null) - : new BacnetValue(value); - case BacnetApplicationTags.BACNET_APPLICATION_TAG_BOOLEAN: - return new BacnetValue(type, bool.Parse(value)); - case BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT: - return new BacnetValue(type, uint.Parse(value)); - case BacnetApplicationTags.BACNET_APPLICATION_TAG_SIGNED_INT: - return new BacnetValue(type, int.Parse(value)); - case BacnetApplicationTags.BACNET_APPLICATION_TAG_REAL: - return new BacnetValue(type, float.Parse(value, CultureInfo.InvariantCulture)); - case BacnetApplicationTags.BACNET_APPLICATION_TAG_DOUBLE: - return new BacnetValue(type, double.Parse(value, CultureInfo.InvariantCulture)); - case BacnetApplicationTags.BACNET_APPLICATION_TAG_OCTET_STRING: - try - { - return new BacnetValue(type, Convert.FromBase64String(value)); - } - catch - { - return new BacnetValue(type, value); - } - case BacnetApplicationTags.BACNET_APPLICATION_TAG_CONTEXT_SPECIFIC_DECODED: - try - { - return new BacnetValue(type, Convert.FromBase64String(value)); - } - catch - { - return new BacnetValue(type, value); - } - case BacnetApplicationTags.BACNET_APPLICATION_TAG_CHARACTER_STRING: - return new BacnetValue(type, value); - case BacnetApplicationTags.BACNET_APPLICATION_TAG_BIT_STRING: - return new BacnetValue(type, BacnetBitString.Parse(value)); - case BacnetApplicationTags.BACNET_APPLICATION_TAG_ENUMERATED: - return new BacnetValue(type, uint.Parse(value)); - case BacnetApplicationTags.BACNET_APPLICATION_TAG_DATE: - return new BacnetValue(type, DateTime.Parse(value)); - case BacnetApplicationTags.BACNET_APPLICATION_TAG_TIME: - return new BacnetValue(type, DateTime.Parse(value)); - case BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_ID: - return new BacnetValue(type, BacnetObjectId.Parse(value)); - case BacnetApplicationTags.BACNET_APPLICATION_TAG_READ_ACCESS_SPECIFICATION: - return new BacnetValue(type, BacnetReadAccessSpecification.Parse(value)); - case BacnetApplicationTags.BACNET_APPLICATION_TAG_OBJECT_PROPERTY_REFERENCE: - return new BacnetValue(type, BacnetDeviceObjectPropertyReference.Parse(value)); - default: - return new BacnetValue(type, null); - } - } - - public static string SerializeValue(BacnetValue value, BacnetApplicationTags type) - { - switch (type) - { - case BacnetApplicationTags.BACNET_APPLICATION_TAG_NULL: - return value.ToString(); // Modif FC - case BacnetApplicationTags.BACNET_APPLICATION_TAG_REAL: - return ((float)value.Value).ToString(CultureInfo.InvariantCulture); - case BacnetApplicationTags.BACNET_APPLICATION_TAG_DOUBLE: - return ((double)value.Value).ToString(CultureInfo.InvariantCulture); - case BacnetApplicationTags.BACNET_APPLICATION_TAG_OCTET_STRING: - return Convert.ToBase64String((byte[])value.Value); - case BacnetApplicationTags.BACNET_APPLICATION_TAG_CONTEXT_SPECIFIC_DECODED: - { - return value.Value is byte[]? Convert.ToBase64String((byte[])value.Value) - : string.Join(";", ((BacnetValue[])value.Value) - .Select(v => SerializeValue(v, v.Tag))); - } - default: - return value.Value.ToString(); - } - } - - [XmlIgnore] - public IList BacnetValue - { - get - { - if (Value == null) - return new BacnetValue[0]; - - var ret = new BacnetValue[Value.Length]; - for (var i = 0; i < ret.Length; i++) - ret[i] = DeserializeValue(Value[i], Tag); - - return ret; - } - set - { - Value = value.Select(v => SerializeValue(v, Tag)).ToArray(); - } - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BVLCV6.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BVLCV6.cs deleted file mode 100644 index 012cfe8..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BVLCV6.cs +++ /dev/null @@ -1,351 +0,0 @@ -namespace System.IO.BACnet; - -// Only some elements here are really tested -// all FDR, BBMD activities is just a copy/adaptation of my IPv4 code -// Code for V4 working fine, for V6 sure not before a series of tests -public class BVLCV6 -{ - public const byte BVLL_TYPE_BACNET_IPV6 = 0x82; - public const byte BVLC_HEADER_LENGTH = 10; // Not all the time, could be 7 for bacnet broadcast - public const BacnetMaxAdpu BVLC_MAX_APDU = BacnetMaxAdpu.MAX_APDU1476; - // Contains the rules to accept FRD based on the IP adress - // If empty it's equal to * , everyone allows - private readonly List _autorizedFDR = new(); - - private bool _bbmdFdServiceActivated; - private readonly List _bbmds = new(); - private readonly BacnetAddress _broadcastAdd; - // Two lists for optional BBMD activity - private readonly List> _foreignDevices = new(); - private readonly BacnetIpV6UdpProtocolTransport _myTransport; - public bool RandomVmac; - - public byte[] VMAC = new byte[3]; - public ILog Log { get; set; } = LogManager.GetLogger(); - - public BVLCV6(BacnetIpV6UdpProtocolTransport transport, int vMac) - { - _myTransport = transport; - _broadcastAdd = _myTransport.GetBroadcastAddress(); - - if (vMac == -1) - { - RandomVmac = true; - new Random().NextBytes(VMAC); - VMAC[0] = (byte)((VMAC[0] & 0x7F) | 0x40); // ensure 01xxxxxx on the High byte - - // Open with default interface specified, cannot send it or - // it will generate an uncheckable continuous local loopback - if (!_myTransport.LocalEndPoint.ToString().Contains("[::]")) - SendAddressResolutionRequest(VMAC); - else - RandomVmac = false; // back to false avoiding loop back - } - else // Device Id is the Vmac Id - { - VMAC[0] = (byte)((vMac >> 16) & 0x3F); // ensure the 2 high bits are 0 on the High byte - VMAC[1] = (byte)((vMac >> 8) & 0xFF); - VMAC[2] = (byte)(vMac & 0xFF); - // unicity is guaranteed by the end user ! - } - } - - public void AddFDRAutorisationRule(Regex ipRule) - { - _autorizedFDR.Add(ipRule); - } - - // Used to initiate the BBMD & FD behaviour, if BBMD is null it start the FD activity only - public void AddBBMDPeer(IPEndPoint bbmd) - { - _bbmdFdServiceActivated = true; - - if (bbmd == null) - return; - - lock (_bbmds) - _bbmds.Add(bbmd); - } - - // Add a FD to the table or renew it - private void RegisterForeignDevice(IPEndPoint sender, int ttl) - { - lock (_foreignDevices) - { - // remove it, if any - _foreignDevices.Remove(_foreignDevices.Find(item => item.Key.Equals(sender))); - // TTL + 30s grace period - var Expiration = DateTime.Now.AddSeconds(ttl + 30); - // add it - if (_autorizedFDR.Count == 0) // No rules, accept all - { - _foreignDevices.Add(new KeyValuePair(sender, Expiration)); - return; - } - - if (_autorizedFDR.Any(r => r.Match(sender.Address.ToString()).Success)) - { - _foreignDevices.Add(new KeyValuePair(sender, Expiration)); - return; - } - - Log.Info($"Rejected FDR registration, IP : {sender.Address}"); - } - } - - // Send a Frame to each registered foreign devices, except the original sender - private void SendToFDs(byte[] buffer, int msgLength, IPEndPoint epSender = null) - { - lock (_foreignDevices) - { - // remove oldest Device entries (Time expiration > TTL + 30s delay) - _foreignDevices.Remove(_foreignDevices.Find(item => DateTime.Now > item.Value)); - // Send to all others, except the original sender - foreach (var client in _foreignDevices) - { - if (!client.Key.Equals(epSender)) - _myTransport.Send(buffer, msgLength, client.Key); - } - } - } - - // Send a Frame to each registered BBMD - private void SendToBBMDs(byte[] buffer, int msgLength) - { - lock (_bbmds) - { - foreach (var ep in _bbmds) - { - _myTransport.Send(buffer, msgLength, ep); - } - } - } - - // Never tested - private void Forward_NPDU(byte[] buffer, int msgLength, bool toGlobalBroadcast, IPEndPoint epSender, BacnetAddress bacSender) - { - // Forms the forwarded NPDU from the original (broadcast npdu), and send it to all - - // copy, 18 bytes shifted (orignal bvlc header : 7 bytes, new one : 25 bytes) - var b = new byte[msgLength + 18]; - // normaly only 'small' frames are present here, so no need to check if it's to big for Udp - Array.Copy(buffer, 0, b, 18, msgLength); - - // 7 bytes for the BVLC Header, with the embedded 6 bytes IP:Port of the original sender - First7BytesHeaderEncode(b, BacnetBvlcV6Functions.BVLC_FORWARDED_NPDU, msgLength + 18); - // replace my Vmac by the orignal source vMac - Array.Copy(bacSender.VMac, 0, b, 4, 3); - // Add IpV6 endpoint - Array.Copy(bacSender.adr, 0, b, 7, 18); - // Send To BBMD - SendToBBMDs(b, msgLength + 18); - // Send To FD, except the sender - SendToFDs(b, msgLength + 18, epSender); - // Broadcast if required - if (toGlobalBroadcast) - { - BacnetIpV6UdpProtocolTransport.Convert(_broadcastAdd, out IPEndPoint ep); - _myTransport.Send(b, msgLength + 18, ep); - } - } - - private void First7BytesHeaderEncode(byte[] b, BacnetBvlcV6Functions function, int msgLength) - { - b[0] = BVLL_TYPE_BACNET_IPV6; - b[1] = (byte)function; - b[2] = (byte)((msgLength & 0xFF00) >> 8); - b[3] = (byte)((msgLength & 0x00FF) >> 0); - Array.Copy(VMAC, 0, b, 4, 3); - } - - // Send ack or nack - private void SendResult(IPEndPoint sender, BacnetBvlcV6Results resultCode) - { - var b = new byte[9]; - First7BytesHeaderEncode(b, BacnetBvlcV6Functions.BVLC_RESULT, 9); - b[7] = (byte)(((ushort)resultCode & 0xFF00) >> 8); - b[8] = (byte)((ushort)resultCode & 0xFF); - _myTransport.Send(b, 9, sender); - } - - public void SendRegisterAsForeignDevice(IPEndPoint bbmd, short ttl) - { - var b = new byte[9]; - First7BytesHeaderEncode(b, BacnetBvlcV6Functions.BVLC_REGISTER_FOREIGN_DEVICE, 9); - b[7] = (byte)((ttl & 0xFF00) >> 8); - b[8] = (byte)(ttl & 0xFF); - _myTransport.Send(b, 9, bbmd); - } - - public void SendRemoteWhois(byte[] buffer, IPEndPoint bbmd, int msgLength) - { - // 7 bytes for the BVLC Header - First7BytesHeaderEncode(buffer, BacnetBvlcV6Functions.BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK, msgLength); - _myTransport.Send(buffer, msgLength, bbmd); - } - - // Send ack - private void SendAddressResolutionAck(IPEndPoint sender, byte[] vMacDest, BacnetBvlcV6Functions function) - { - var b = new byte[10]; - First7BytesHeaderEncode(b, function, 10); - Array.Copy(vMacDest, 0, b, 7, 3); - _myTransport.Send(b, 10, sender); - } - - // quite the same frame as the previous one - private void SendAddressResolutionRequest(byte[] vMacDest) - { - BacnetIpV6UdpProtocolTransport.Convert(_broadcastAdd, out IPEndPoint ep); - - var b = new byte[10]; - First7BytesHeaderEncode(b, BacnetBvlcV6Functions.BVLC_ADDRESS_RESOLUTION, 10); - Array.Copy(vMacDest, 0, b, 7, 3); - _myTransport.Send(b, 10, ep); - } - - // Encode is called by internal services if the BBMD is also an active device - public int Encode(byte[] buffer, int offset, BacnetBvlcV6Functions function, int msgLength, BacnetAddress address) - { - // offset always 0, we are the first after udp - First7BytesHeaderEncode(buffer, function, msgLength); - - // BBMD service - if (function == BacnetBvlcV6Functions.BVLC_ORIGINAL_BROADCAST_NPDU && _bbmdFdServiceActivated) - { - var me = _myTransport.LocalEndPoint; - BacnetIpV6UdpProtocolTransport.Convert(me, out var bacme); - Array.Copy(VMAC, bacme.VMac, 3); - - Forward_NPDU(buffer, msgLength, false, me, bacme); // send to all BBMDs and FDs - - return 7; // ready to send - } - - if (function != BacnetBvlcV6Functions.BVLC_ORIGINAL_UNICAST_NPDU) - return 0; // ? - - buffer[7] = address.VMac[0]; - buffer[8] = address.VMac[1]; - buffer[9] = address.VMac[2]; - return 10; // ready to send - } - - // Decode is called each time an Udp Frame is received - public int Decode(byte[] buffer, int offset, out BacnetBvlcV6Functions function, out int msgLength, - IPEndPoint sender, BacnetAddress remoteAddress) - { - // offset always 0, we are the first after udp - // and a previous test by the caller guaranteed at least 4 bytes into the buffer - - function = (BacnetBvlcV6Functions)buffer[1]; - msgLength = (buffer[2] << 8) | (buffer[3] << 0); - if (buffer[0] != BVLL_TYPE_BACNET_IPV6 || buffer.Length != msgLength) return -1; - - Array.Copy(buffer, 4, remoteAddress.VMac, 0, 3); - - switch (function) - { - case BacnetBvlcV6Functions.BVLC_RESULT: - return 9; // only for the upper layers - - case BacnetBvlcV6Functions.BVLC_ORIGINAL_UNICAST_NPDU: - return 10; // only for the upper layers - - case BacnetBvlcV6Functions.BVLC_ORIGINAL_BROADCAST_NPDU: - // Send to FDs & BBMDs, not broadcast or it will be made twice ! - if (_bbmdFdServiceActivated) - Forward_NPDU(buffer, msgLength, false, sender, remoteAddress); - return 7; // also for the upper layers - - case BacnetBvlcV6Functions.BVLC_ADDRESS_RESOLUTION: - // need to verify that the VMAC is mine - if (VMAC[0] == buffer[7] && VMAC[1] == buffer[8] && VMAC[2] == buffer[9]) - // coming from myself ? avoid loopback - if (!_myTransport.LocalEndPoint.Equals(sender)) - SendAddressResolutionAck(sender, remoteAddress.VMac, - BacnetBvlcV6Functions.BVLC_ADDRESS_RESOLUTION_ACK); - return 0; // not for the upper layers - - case BacnetBvlcV6Functions.BVLC_FORWARDED_ADDRESS_RESOLUTION: - // no need to verify the target VMAC, should be OK - SendAddressResolutionAck(sender, remoteAddress.VMac, - BacnetBvlcV6Functions.BVLC_ADDRESS_RESOLUTION_ACK); - return 0; // not for the upper layers - - case BacnetBvlcV6Functions.BVLC_ADDRESS_RESOLUTION_ACK: // adresse conflict - if (VMAC[0] == buffer[4] && VMAC[1] == buffer[5] && VMAC[2] == buffer[6] && RandomVmac) - { - new Random().NextBytes(VMAC); - VMAC[0] = (byte)((VMAC[0] & 0x7F) | 0x40); - SendAddressResolutionRequest(VMAC); - } - return 0; // not for the upper layers - - case BacnetBvlcV6Functions.BVLC_VIRTUAL_ADDRESS_RESOLUTION: - SendAddressResolutionAck(sender, remoteAddress.VMac, - BacnetBvlcV6Functions.BVLC_VIRTUAL_ADDRESS_RESOLUTION_ACK); - return 0; // not for the upper layers - - case BacnetBvlcV6Functions.BVLC_VIRTUAL_ADDRESS_RESOLUTION_ACK: - return 0; // not for the upper layers - - case BacnetBvlcV6Functions.BVLC_FORWARDED_NPDU: - if (_myTransport.LocalEndPoint.Equals(sender)) return 0; - - // certainly TODO the same code I've put in the IPV4 implementation - if (_bbmdFdServiceActivated && msgLength >= 25) - { - bool ret; - lock (_bbmds) - ret = _bbmds.Exists(items => items.Equals(sender)); // verify sender presence in the table - // avoid also loopback - - if (ret) // message from a know BBMD address, sent to all FDs and broadcast - { - SendToFDs(buffer, msgLength); // send without modification - // Assume all BVLC_FORWARDED_NPDU are directly sent to me in the - // unicast mode and not by the way of the multicast address - // If not, it's not really a big problem, devices on the local net will - // receive two times the message (after all it's just WhoIs, Iam, ...) - BacnetIpV6UdpProtocolTransport.Convert(_broadcastAdd, out IPEndPoint ep); - _myTransport.Send(buffer, msgLength, ep); - } - } - return 25; // for the upper layers - - case BacnetBvlcV6Functions.BVLC_REGISTER_FOREIGN_DEVICE: - if (_bbmdFdServiceActivated && msgLength == 9) - { - var TTL = (buffer[7] << 8) + buffer[8]; // unit is second - RegisterForeignDevice(sender, TTL); - SendResult(sender, BacnetBvlcV6Results.SUCCESSFUL_COMPLETION); // ack - } - return 0; // not for the upper layers - - case BacnetBvlcV6Functions.BVLC_DELETE_FOREIGN_DEVICE_TABLE_ENTRY: - return 0; // not for the upper layers - - case BacnetBvlcV6Functions.BVLC_SECURE_BVLC: - return 0; // not for the upper layers - - case BacnetBvlcV6Functions.BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK: // Sent by a Foreign Device, not a BBMD - if (_bbmdFdServiceActivated) - { - // Send to FDs except the sender, BBMDs and broadcast - lock (_foreignDevices) - { - if (_foreignDevices.Exists(item => item.Key.Equals(sender))) // verify previous registration - Forward_NPDU(buffer, msgLength, true, sender, remoteAddress); - else - SendResult(sender, BacnetBvlcV6Results.DISTRIBUTE_BROADCAST_TO_NETWORK_NAK); - } - } - return 0; // not for the upper layers - - // error encoding function or experimental one - default: - return -1; - } - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetIpUdpProtocolTransport.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetIpUdpProtocolTransport.cs deleted file mode 100644 index 249b7c7..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetIpUdpProtocolTransport.cs +++ /dev/null @@ -1,465 +0,0 @@ -/************************************************************************** -* MIT License -* -* Copyright (C) 2014 Morten Kvistgaard -* -* Permission is hereby granted, free of charge, to any person obtaining -* a copy of this software and associated documentation files (the -* "Software"), to deal in the Software without restriction, including -* without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to -* permit persons to whom the Software is furnished to do so, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -* -*********************************************************************/ - -namespace System.IO.BACnet; - -/// -/// This is the standard BACNet udp transport -/// -public class BacnetIpUdpProtocolTransport : BacnetTransportBase -{ - private UdpClient _sharedConn; - private UdpClient _exclusiveConn; - private readonly bool _exclusivePort; - private readonly bool _dontFragment; - private readonly string _localEndpoint; - private BacnetAddress _broadcastAddress; - private bool _disposing; - - public BVLC Bvlc { get; private set; } - public int SharedPort { get; } - public int ExclusivePort { get; } - - // Give 0.0.0.0:xxxx if the socket is open with System.Net.IPAddress.Any - // Today only used by _GetBroadcastAddress method & the bvlc layer class in BBMD mode - // Some more complex solutions could avoid this, that's why this property is virtual - public virtual IPEndPoint LocalEndPoint => (IPEndPoint)_exclusiveConn.Client.LocalEndPoint; - - public BacnetIpUdpProtocolTransport(int port, bool useExclusivePort = false, bool dontFragment = false, - int maxPayload = 1472, string localEndpointIp = "") - { - SharedPort = port; - MaxBufferLength = maxPayload; - Type = BacnetAddressTypes.IP; - HeaderLength = BVLC.BVLC_HEADER_LENGTH; - MaxAdpuLength = BVLC.BVLC_MAX_APDU; - - _exclusivePort = useExclusivePort; - _dontFragment = dontFragment; - _localEndpoint = localEndpointIp; - } - - public BacnetIpUdpProtocolTransport(int sharedPort, int exclusivePort, bool dontFragment = false, - int maxPayload = 1472, string localEndpointIp = "") - : this(sharedPort, false, dontFragment, maxPayload, localEndpointIp) - { - ExclusivePort = exclusivePort; - } - - public override bool Equals(object obj) - { - var a = obj as BacnetIpUdpProtocolTransport; - return a?.SharedPort == SharedPort; - } - - public override int GetHashCode() - { - return SharedPort.GetHashCode(); - } - - public override string ToString() - { - return $"Udp:{SharedPort}"; - } - - private void Open() - { - if (!_exclusivePort) - { - /* We need a shared broadcast "listen" port. This is the 0xBAC0 port */ - /* This will enable us to have more than 1 client, on the same machine. Perhaps it's not that important though. */ - /* We (might) only recieve the broadcasts on this. Any unicasts to this might be eaten by another local client */ - if (_sharedConn == null) - { - _sharedConn = new UdpClient { ExclusiveAddressUse = false }; - _sharedConn.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); - var ep = new IPEndPoint(IPAddress.Any, SharedPort); - if (!string.IsNullOrEmpty(_localEndpoint)) ep = new IPEndPoint(IPAddress.Parse(_localEndpoint), SharedPort); - DisableConnReset(_sharedConn); - _sharedConn.Client.Bind(ep); - SetDontFragment(_sharedConn, _dontFragment); - Log.Info($"Binded shared {ep} using UDP"); - } - /* This is our own exclusive port. We'll recieve everything sent to this. */ - /* So this is how we'll present our selves to the world */ - if (_exclusiveConn == null) - { - var ep = new IPEndPoint(IPAddress.Any, ExclusivePort); - if (!string.IsNullOrEmpty(_localEndpoint)) ep = new IPEndPoint(IPAddress.Parse(_localEndpoint), ExclusivePort); - _exclusiveConn = new UdpClient(ep); - - // Gets the Endpoint : the assigned Udp port number in fact - ep = (IPEndPoint)_exclusiveConn.Client.LocalEndPoint; - // closes the socket - _exclusiveConn.Close(); - // Re-opens it with the freeed port number, to be sure it's a real active/server socket - // which cannot be disarmed for listen by .NET for incoming call after a few inactivity - // minutes ... yes it's like this at least on several systems - _exclusiveConn = new UdpClient(ep) - { - EnableBroadcast = true - }; - SetDontFragment(_exclusiveConn, _dontFragment); - DisableConnReset(_exclusiveConn); - } - } - else - { - var ep = new IPEndPoint(IPAddress.Any, SharedPort); - if (!string.IsNullOrEmpty(_localEndpoint)) ep = new IPEndPoint(IPAddress.Parse(_localEndpoint), SharedPort); - _exclusiveConn = new UdpClient { ExclusiveAddressUse = true }; - DisableConnReset(_exclusiveConn); - _exclusiveConn.Client.Bind(ep); - SetDontFragment(_exclusiveConn, _dontFragment); - _exclusiveConn.EnableBroadcast = true; - Log.Info($"Binded exclusively to {ep} using UDP"); - } - - Bvlc = new BVLC(this); - } - - /// - /// Prevent exception on setting Don't Fragment on OSX - /// - /// - /// https://github.com/dotnet/runtime/issues/27653 - /// - /// - /// - private void SetDontFragment(UdpClient client, bool dontFragment) - { - if (Environment.OSVersion.Platform != PlatformID.MacOSX) - { - try - { - client.DontFragment = dontFragment; - } - catch (SocketException e) - { - Log.WarnFormat("Unable to set DontFragment", e); - } - } - } - - /// - /// Done to prevent exceptions in Socket.BeginReceive() - /// - /// - /// http://microsoft.public.win32.programmer.networks.narkive.com/RlxW2V6m/udp-comms-and-connection-reset-problem - /// - private static void DisableConnReset(UdpClient client) - { - if (Environment.OSVersion.Platform == PlatformID.Win32NT) - { - const uint IOC_IN = 0x80000000; - const uint IOC_VENDOR = 0x18000000; - const uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12; - - client?.Client.IOControl(unchecked((int)SIO_UDP_CONNRESET), - new[] { System.Convert.ToByte(false) }, null); - } - } - - protected void Close() - { - _exclusiveConn.Close(); - } - - public override void Start() - { - _disposing = false; - - Open(); - - _sharedConn?.BeginReceive(OnReceiveData, _sharedConn); - _exclusiveConn?.BeginReceive(OnReceiveData, _exclusiveConn); - } - - private void OnReceiveData(IAsyncResult asyncResult) - { - var connection = (UdpClient)asyncResult.AsyncState; - - try - { - IPEndPoint ep = null; - byte[] receiveBuffer; - - try - { - receiveBuffer = connection.EndReceive(asyncResult, ref ep); - } - finally - { - if (connection.Client != null && !_disposing) - { - try - { - // BeginReceive ASAP to enable parallel processing (e.g. query additional data while processing a notification) - connection.BeginReceive(OnReceiveData, connection); - } - catch (Exception ex) - { - Log.Error($"Failed to restart data receive. {ex}"); - } - } - } - - var receiveBufferHex = ConvertToHex(receiveBuffer); - var receivedLength = receiveBuffer.Length; - - if (receivedLength == 0) // Empty frame : port scanner maybe - return; - - //verify message - Convert(ep, out var remoteAddress); - - if (receivedLength < BVLC.BVLC_HEADER_LENGTH) - { - Log.Warn($"Some garbage data got in: {receiveBufferHex}"); - return; - } - - // Basic Header lenght - var headerLength = Bvlc.Decode(receiveBuffer, 0, out var function, out var _, ep); - - if (headerLength == -1) - { - Log.Warn($"Unknow BVLC Header in: {receiveBufferHex}"); - return; - } - - switch (function) - { - case BacnetBvlcFunctions.BVLC_RESULT: - // response to BVLC_REGISTER_FOREIGN_DEVICE, could be BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK - // but we are not a BBMD, we don't care - Log.Debug("Receive Register as Foreign Device Response"); - break; - - case BacnetBvlcFunctions.BVLC_FORWARDED_NPDU: - // BVLC_FORWARDED_NPDU frame by a BBMD, change the remote_address to the original one - // stored in the BVLC header, we don't care about the BBMD address - var ip = ((long)receiveBuffer[7] << 24) + ((long)receiveBuffer[6] << 16) + - ((long)receiveBuffer[5] << 8) + receiveBuffer[4]; - - var port = (receiveBuffer[8] << 8) + receiveBuffer[9]; // 0xbac0 maybe - Convert(new IPEndPoint(ip, port), out remoteAddress); - break; - } - - if (function != BacnetBvlcFunctions.BVLC_ORIGINAL_UNICAST_NPDU && - function != BacnetBvlcFunctions.BVLC_ORIGINAL_BROADCAST_NPDU && - function != BacnetBvlcFunctions.BVLC_FORWARDED_NPDU) - { - Log.Debug($"{function} - ignoring"); - return; - } - - if (receivedLength <= headerLength) - { - Log.Warn($"Missing data, only header received: {receiveBufferHex}"); - return; - } - - InvokeMessageRecieved(receiveBuffer, headerLength, receivedLength - headerLength, remoteAddress); - } - catch (ObjectDisposedException) - { - Log.Debug("Connection has been disposed"); - } - catch (Exception e) - { - if (connection.Client == null || _disposing) - return; - - Log.Error("Exception in OnRecieveData", e); - } - } - - public bool SendRegisterAsForeignDevice(IPEndPoint bbmd, short ttl) - { - if (bbmd.AddressFamily != AddressFamily.InterNetwork) - return false; - - Bvlc.SendRegisterAsForeignDevice(bbmd, ttl); - return true; - } - public bool SendRemoteWhois(byte[] buffer, IPEndPoint bbmd, int msgLength) - { - if (bbmd.AddressFamily != AddressFamily.InterNetwork) - return false; - - Bvlc.SendRemoteWhois(buffer, bbmd, msgLength); - return true; - } - - public static string ConvertToHex(byte[] buffer) - { - return BitConverter.ToString(buffer).Replace("-", ""); - } - - public int Send(byte[] buffer, int dataLength, IPEndPoint ep) - { - // return _exclusiveConn.Send(buffer, data_length, ep); - ThreadPool.QueueUserWorkItem(o => - { - try - { - _exclusiveConn.Send(buffer, dataLength, ep); - } - catch - { - // not much you can do about at this point - } - }, null); - - return dataLength; - } - - public override int Send(byte[] buffer, int offset, int dataLength, BacnetAddress address, bool waitForTransmission, int timeout) - { - if (_exclusiveConn == null) return 0; - - //add header - var fullLength = dataLength + HeaderLength; - Bvlc.Encode(buffer, offset - BVLC.BVLC_HEADER_LENGTH, address.net == 0xFFFF - ? BacnetBvlcFunctions.BVLC_ORIGINAL_BROADCAST_NPDU - : BacnetBvlcFunctions.BVLC_ORIGINAL_UNICAST_NPDU, fullLength); - - //create end point - Convert(address, out var ep); - - try - { - // broadcasts are transported from our local unicast socket also - return _exclusiveConn.Send(buffer, fullLength, ep); - } - catch - { - return 0; - } - } - - public static void Convert(IPEndPoint ep, out BacnetAddress address) - { - var tmp1 = ep.Address.GetAddressBytes(); - var tmp2 = BitConverter.GetBytes((ushort)ep.Port); - Array.Reverse(tmp2); - Array.Resize(ref tmp1, tmp1.Length + tmp2.Length); - Array.Copy(tmp2, 0, tmp1, tmp1.Length - tmp2.Length, tmp2.Length); - address = new BacnetAddress(BacnetAddressTypes.IP, 0, tmp1); - } - - public static void Convert(BacnetAddress address, out IPEndPoint ep) - { - long ipAddress = BitConverter.ToUInt32(address.adr, 0); - var port = (ushort)((address.adr[4] << 8) | (address.adr[5] << 0)); - ep = new IPEndPoint(ipAddress, port); - } - - // Get the IPAddress only if one is present - // this could be usefull to find the broadcast address even if the socket is open on the default interface - // removes somes virtual interfaces (certainly not all) - private static UnicastIPAddressInformation GetAddressDefaultInterface() - { - var unicastAddresses = NetworkInterface.GetAllNetworkInterfaces() - .Where(i => i.OperationalStatus == OperationalStatus.Up) - .Where(i => i.NetworkInterfaceType != NetworkInterfaceType.Loopback) - .Where(i => !(i.Name.Contains("VirtualBox") || i.Name.Contains("VMware"))) - .SelectMany(i => i.GetIPProperties().UnicastAddresses) - .Where(a => a.Address.AddressFamily == AddressFamily.InterNetwork) - .ToArray(); - - return unicastAddresses.Length == 1 - ? unicastAddresses.Single() - : null; - } - - // A lot of problems on Mono (Raspberry) to get the correct broadcast @ - // so this method is overridable (this allows the implementation of operating system specific code) - // Marc solution http://stackoverflow.com/questions/8119414/how-to-query-the-subnet-masks-using-mono-on-linux for instance - protected virtual BacnetAddress _GetBroadcastAddress() - { - // general broadcast by default if nothing better is found - var ep = new IPEndPoint(IPAddress.Parse("255.255.255.255"), SharedPort); - - UnicastIPAddressInformation ipAddr = null; - - if (LocalEndPoint.Address.ToString() == "0.0.0.0") - { - ipAddr = GetAddressDefaultInterface(); - } - else - { - // restricted local broadcast (directed ... routable) - foreach (var adapter in NetworkInterface.GetAllNetworkInterfaces()) - foreach (var ip in adapter.GetIPProperties().UnicastAddresses) - if (LocalEndPoint.Address.Equals(ip.Address)) - { - ipAddr = ip; - break; - } - } - - if (ipAddr != null) - { - try - { - var strCurrentIP = ipAddr.Address.ToString().Split('.'); - var strIPNetMask = ipAddr.IPv4Mask.ToString().Split('.'); - var broadcastStr = new StringBuilder(); - for (var i = 0; i < 4; i++) - { - broadcastStr.Append(((byte)(int.Parse(strCurrentIP[i]) | ~int.Parse(strIPNetMask[i]))).ToString()); - if (i != 3) broadcastStr.Append('.'); - } - ep = new IPEndPoint(IPAddress.Parse(broadcastStr.ToString()), SharedPort); - } - catch - { - // on mono IPv4Mask feature not implemented - } - } - - Convert(ep, out var broadcast); - broadcast.net = 0xFFFF; - return broadcast; - } - - public override BacnetAddress GetBroadcastAddress() - { - return _broadcastAddress ??= _GetBroadcastAddress(); - } - - public override void Dispose() - { - _disposing = true; - _exclusiveConn?.Close(); - _exclusiveConn = null; - _sharedConn?.Close(); - _sharedConn = null; - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetIpV6UdpProtocolTransport.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetIpV6UdpProtocolTransport.cs deleted file mode 100644 index b03aca4..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetIpV6UdpProtocolTransport.cs +++ /dev/null @@ -1,362 +0,0 @@ -/************************************************************************** -* MIT License -* -* Copyright (C) 2015 Frederic Chaxel -* Morten Kvistgaard -* Permission is hereby granted, free of charge, to any person obtaining -* a copy of this software and associated documentation files (the -* "Software"), to deal in the Software without restriction, including -* without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to -* permit persons to whom the Software is furnished to do so, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -* -*********************************************************************/ - -// based on Addendum 135-2012aj-4 - -namespace System.IO.BACnet; - -public class BacnetIpV6UdpProtocolTransport : BacnetTransportBase -{ - private readonly bool _exclusivePort; - private readonly string _localEndpoint; - private readonly int _vMac; - private bool _dontFragment; - private UdpClient _exclusiveConn; - private UdpClient _sharedConn; - - public BVLCV6 Bvlc { get; private set; } - public int SharedPort { get; } - - // Give [::]:xxxx if the socket is open with System.Net.IPAddress.IPv6Any - // Used the bvlc layer class in BBMD mode - // Some more complex solutions could avoid this, that's why this property is virtual - public virtual IPEndPoint LocalEndPoint => (IPEndPoint)_exclusiveConn.Client.LocalEndPoint; - - public BacnetIpV6UdpProtocolTransport(int port, int vMac = -1, bool useExclusivePort = false, - bool dontFragment = false, int maxPayload = 1472, string localEndpointIp = "") - { - SharedPort = port; - MaxBufferLength = maxPayload; - Type = BacnetAddressTypes.IPV6; - MaxAdpuLength = BVLCV6.BVLC_MAX_APDU; - - // Two frames type, unicast with 10 bytes or broadcast with 7 bytes - // Here it's the biggest header, resize will be done after, if needed - HeaderLength = BVLCV6.BVLC_HEADER_LENGTH; - - _exclusivePort = useExclusivePort; - _dontFragment = dontFragment; - _localEndpoint = localEndpointIp; - _vMac = vMac; - } - - public override void Start() - { - Open(); - - _sharedConn?.BeginReceive(OnReceiveData, _sharedConn); - _exclusiveConn?.BeginReceive(OnReceiveData, _exclusiveConn); - } - - public override int Send(byte[] buffer, int offset, int dataLength, BacnetAddress address, - bool waitForTransmission, int timeout) - { - if (_exclusiveConn == null) return 0; - - //add header - var fullLength = dataLength + HeaderLength; - - if (address.net == 0xFFFF) - { - var newBuffer = new byte[fullLength - 3]; - Array.Copy(buffer, 3, newBuffer, 0, fullLength - 3); - fullLength -= 3; - buffer = newBuffer; - Bvlc.Encode(buffer, offset - BVLCV6.BVLC_HEADER_LENGTH, - BacnetBvlcV6Functions.BVLC_ORIGINAL_BROADCAST_NPDU, fullLength, address); - } - else - { - Bvlc.Encode(buffer, offset - BVLCV6.BVLC_HEADER_LENGTH, BacnetBvlcV6Functions.BVLC_ORIGINAL_UNICAST_NPDU, - fullLength, address); - } - - // create end point - Convert(address, out var ep); - - try - { - // send - // multicast are transported from our local unicast socket also - return _exclusiveConn.Send(buffer, fullLength, ep); - } - catch - { - return 0; - } - } - - public override BacnetAddress GetBroadcastAddress() - { - // could be FF08, FF05, FF04, FF02 - var ep = new IPEndPoint(IPAddress.Parse("[FF0E::BAC0]"), SharedPort); - Convert(ep, out var ret); - ret.net = 0xFFFF; - return ret; - } - - public override void Dispose() - { - _exclusiveConn?.Close(); - _exclusiveConn = null; - _sharedConn?.Close(); - _sharedConn = null; - } - - public override bool Equals(object obj) - { - var a = obj as BacnetIpV6UdpProtocolTransport; - return a?.SharedPort == SharedPort; - } - - public override int GetHashCode() - { - return SharedPort.GetHashCode(); - } - - public override string ToString() - { - return "Udp IPv6:" + SharedPort; - } - - private void Open() - { - UdpClient multicastListener = null; - - if (!_exclusivePort) - { - /* We need a shared multicast "listen" port. This is the 0xBAC0 port */ - /* This will enable us to have more than 1 client, on the same machine. Perhaps it's not that important though. */ - /* We (might) only receive the multicast on this. Any unicasts to this might be eaten by another local client */ - if (_sharedConn == null) - { - _sharedConn = new UdpClient(AddressFamily.InterNetworkV6) { ExclusiveAddressUse = false }; - _sharedConn.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); - EndPoint ep = new IPEndPoint(IPAddress.IPv6Any, SharedPort); - if (!string.IsNullOrEmpty(_localEndpoint)) - ep = new IPEndPoint(IPAddress.Parse(_localEndpoint), SharedPort); - _sharedConn.Client.Bind(ep); - multicastListener = _sharedConn; - } - /* This is our own exclusive port. We'll recieve everything sent to this. */ - /* So this is how we'll present our selves to the world */ - if (_exclusiveConn == null) - { - EndPoint ep = new IPEndPoint(IPAddress.IPv6Any, 0); - if (!string.IsNullOrEmpty(_localEndpoint)) ep = new IPEndPoint(IPAddress.Parse(_localEndpoint), 0); - _exclusiveConn = new UdpClient((IPEndPoint)ep); - } - } - else - { - EndPoint ep = new IPEndPoint(IPAddress.IPv6Any, SharedPort); - if (!string.IsNullOrEmpty(_localEndpoint)) - ep = new IPEndPoint(IPAddress.Parse(_localEndpoint), SharedPort); - _exclusiveConn = new UdpClient(AddressFamily.InterNetworkV6) - { - ExclusiveAddressUse = true - }; - _exclusiveConn.Client.Bind((IPEndPoint)ep); - multicastListener = _exclusiveConn; - } - - multicastListener.JoinMulticastGroup(IPAddress.Parse("[FF02::BAC0]")); - multicastListener.JoinMulticastGroup(IPAddress.Parse("[FF04::BAC0]")); - multicastListener.JoinMulticastGroup(IPAddress.Parse("[FF05::BAC0]")); - multicastListener.JoinMulticastGroup(IPAddress.Parse("[FF08::BAC0]")); - multicastListener.JoinMulticastGroup(IPAddress.Parse("[FF0E::BAC0]")); - - // If this option is enabled Yabe cannot see itself ! - // multicastListener.MulticastLoopback = false; - - Bvlc = new BVLCV6(this, _vMac); - } - - protected void Close() - { - _sharedConn?.BeginReceive(OnReceiveData, _sharedConn); - _exclusiveConn?.BeginReceive(OnReceiveData, _exclusiveConn); - } - - private void OnReceiveData(IAsyncResult asyncResult) - { - var conn = (UdpClient)asyncResult.AsyncState; - try - { - var ep = new IPEndPoint(IPAddress.Any, 0); - byte[] localBuffer; - int rx; - - try - { - localBuffer = conn.EndReceive(asyncResult, ref ep); - rx = localBuffer.Length; - } - catch (Exception) // ICMP port unreachable - { - //restart data receive - conn.BeginReceive(OnReceiveData, conn); - return; - } - - if (rx == 0) // Empty frame : port scanner maybe - { - //restart data receive - conn.BeginReceive(OnReceiveData, conn); - return; - } - - try - { - //verify message - Convert(ep, out var remoteAddress); - if (rx < BVLCV6.BVLC_HEADER_LENGTH - 3) - { - Log.Warn("Some garbage data got in"); - } - else - { - // Basic Header lenght - var headerLength = Bvlc.Decode(localBuffer, 0, out var function, out _, ep, remoteAddress); - - switch (headerLength) - { - case 0: - return; - case -1: - Log.Debug("Unknow BVLC Header"); - return; - } - - // response to BVLC_REGISTER_FOREIGN_DEVICE (could be BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK ... but we are not a BBMD, don't care) - if (function == BacnetBvlcV6Functions.BVLC_RESULT) - { - Log.Debug("Receive Register as Foreign Device Response"); - } - - // a BVLC_FORWARDED_NPDU frame by a BBMD, change the remote_address to the original one (stored in the BVLC header) - // we don't care about the BBMD address - if (function == BacnetBvlcV6Functions.BVLC_FORWARDED_NPDU) - { - Array.Copy(localBuffer, 7, remoteAddress.adr, 0, 18); - } - - if (function != BacnetBvlcV6Functions.BVLC_ORIGINAL_UNICAST_NPDU && - function != BacnetBvlcV6Functions.BVLC_ORIGINAL_BROADCAST_NPDU && - function != BacnetBvlcV6Functions.BVLC_FORWARDED_NPDU) - return; - - if (rx > headerLength) - InvokeMessageRecieved(localBuffer, headerLength, rx - headerLength, remoteAddress); - } - } - catch (Exception ex) - { - Log.Error("Exception in udp recieve", ex); - } - finally - { - //restart data receive - conn.BeginReceive(OnReceiveData, conn); - } - } - catch (Exception ex) - { - //restart data receive - if (conn.Client != null) - { - Log.Error("Exception in Ip OnRecieveData", ex); - conn.BeginReceive(OnReceiveData, conn); - } - } - } - - public static string ConvertToHex(byte[] buffer, int length) - { - var ret = ""; - - for (var i = 0; i < length; i++) - ret += buffer[i].ToString("X2"); - - return ret; - } - - // Modif FC : used for BBMD communication - public int Send(byte[] buffer, int dataLength, IPEndPoint ep) - { - try - { - // return _exclusiveConn.Send(buffer, data_length, ep); - ThreadPool.QueueUserWorkItem(o => _exclusiveConn.Send(buffer, dataLength, ep), null); - return dataLength; - } - catch - { - return 0; - } - } - - public bool SendRegisterAsForeignDevice(IPEndPoint bbmd, short ttl) - { - if (bbmd.AddressFamily != AddressFamily.InterNetworkV6) - return false; - - Bvlc.SendRegisterAsForeignDevice(bbmd, ttl); - return true; - } - - public bool SendRemoteWhois(byte[] buffer, IPEndPoint bbmd, int msgLength) - { - if (bbmd.AddressFamily != AddressFamily.InterNetworkV6) - return false; - - // This message was build using the default (10) header lenght, but it's smaller (7) - var newBuffer = new byte[msgLength - 3]; - Array.Copy(buffer, 3, newBuffer, 0, msgLength - 3); - msgLength -= 3; - - Bvlc.SendRemoteWhois(newBuffer, bbmd, msgLength); - return true; - } - - public static void Convert(IPEndPoint ep, out BacnetAddress address) - { - var tmp1 = ep.Address.GetAddressBytes(); - var tmp2 = BitConverter.GetBytes((ushort)ep.Port); - Array.Reverse(tmp2); - Array.Resize(ref tmp1, tmp1.Length + tmp2.Length); - Array.Copy(tmp2, 0, tmp1, tmp1.Length - tmp2.Length, tmp2.Length); - address = new BacnetAddress(BacnetAddressTypes.IPV6, 0, tmp1); - } - - public static void Convert(BacnetAddress address, out IPEndPoint ep) - { - var port = (ushort)((address.adr[16] << 8) | (address.adr[17] << 0)); - var ipv6 = new byte[16]; - Array.Copy(address.adr, ipv6, 16); - ep = new IPEndPoint(new IPAddress(ipv6), port); - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetMstpProtocolTransport.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetMstpProtocolTransport.cs deleted file mode 100644 index 94ca7b7..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetMstpProtocolTransport.cs +++ /dev/null @@ -1,917 +0,0 @@ -namespace System.IO.BACnet; - -/// -/// This is the standard BACNet MSTP transport -/// -public class BacnetMstpProtocolTransport : BacnetTransportBase -{ - public delegate void FrameRecievedHandler(BacnetMstpProtocolTransport sender, BacnetMstpFrameTypes frameType, - byte destinationAddress, byte sourceAddress, int msgLength); - - public enum GetMessageStatus - { - Good, - Timeout, - SubTimeout, - ConnectionClose, - ConnectionError, - DecodeError - } - - /// - /// The minimum time (ms) without a DataAvailable or ReceiveError event within a frame before a receiving node may discard the frame. - /// - public const int T_FRAME_ABORT = 80; - - /// - /// The time (ms) without a DataAvailable or ReceiveError event before declaration of loss of token - /// - public const int T_NO_TOKEN = 500; - - /// - /// The minimum time (ms) without a DataAvailable or ReceiveError event that a node must wait for a station to begin replying to a confirmed request - /// - public const int T_REPLY_TIMEOUT = 295; - - /// - /// The minimum time (ms) without a DataAvailable or ReceiveError event that a node must wait for a remote node to begin using a token or replying to a Poll For Master frame: - /// - public const int T_USAGE_TIMEOUT = 95; - - /// - /// The maximum time (ms) a node may wait after reception of a frame that expects a reply before sending the first octet of a reply or Reply Postponed frame - /// - public const int T_REPLY_DELAY = 250; - - public const int ETIMEDOUT = 110; - - private IBacnetSerialTransport _port; - private byte _frameCount; - private readonly byte[] _localBuffer; - private int _localOffset; - - /// - /// The number of tokens received or used before a Poll For Master cycle is executed - /// - private const byte MaxPoll = 50; - - /// - /// "Next Station," the MAC address of the node to which This Station passes the token. If the Next Station is unknown, NS shall be equal to TS - /// - private byte _ns; - - /// - /// "Poll Station," the MAC address of the node to which This Station last sent a Poll For Master. This is used during token maintenance - /// - private byte _ps; - - private MessageFrame _reply; - private readonly ManualResetEvent _replyMutex = new(false); - private byte _replySource; - private const byte RetryToken = 1; - private readonly LinkedList _sendQueue = new(); - private bool _soleMaster; - private byte _tokenCount; - private Thread _transmitThread; - - public short SourceAddress { get; set; } - public byte MaxMaster { get; set; } - public bool IsRunning { get; private set; } = true; - - public BacnetMstpProtocolTransport(IBacnetSerialTransport transport, short sourceAddress = -1, - byte maxMaster = 127, byte maxInfoFrames = 1) - { - SourceAddress = sourceAddress; - MaxMaster = maxMaster; - Type = BacnetAddressTypes.MSTP; - HeaderLength = MSTP.MSTP_HEADER_LENGTH; - MaxBufferLength = 502; - MaxAdpuLength = MSTP.MSTP_MAX_APDU; - MaxInfoFrames = maxInfoFrames; - - _localBuffer = new byte[MaxBufferLength]; - _port = transport; - } - - public BacnetMstpProtocolTransport(string portName, int baudRate, short sourceAddress = -1, - byte maxMaster = 127, byte maxInfoFrames = 1) - : this(new BacnetSerialPortTransport(portName, baudRate), sourceAddress, maxMaster, maxInfoFrames) - { - } - - public override void Start() - { - if (_port == null) return; - _port.Open(); - - _transmitThread = new Thread(MstpThread) - { - IsBackground = true, - Name = "MSTP Thread", - Priority = ThreadPriority.Highest - }; - _transmitThread.Start(); - } - - public override int Send(byte[] buffer, int offset, int dataLength, BacnetAddress address, - bool waitForTransmission, int timeout) - { - if (SourceAddress == -1) throw new Exception("Source address must be set up before sending messages"); - - //add to queue - var function = NPDU.DecodeFunction(buffer, offset); - var frameType = (function & BacnetNpduControls.ExpectingReply) == BacnetNpduControls.ExpectingReply - ? BacnetMstpFrameTypes.FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY - : BacnetMstpFrameTypes.FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY; - var copy = new byte[dataLength + MSTP.MSTP_HEADER_LENGTH + 2]; - Array.Copy(buffer, offset, copy, MSTP.MSTP_HEADER_LENGTH, dataLength); - var f = new MessageFrame(frameType, address.adr[0], copy, dataLength); - lock (_sendQueue) - _sendQueue.AddLast(f); - if (_reply == null) - { - _reply = f; - _replyMutex.Set(); - } - - if (!waitForTransmission) - return dataLength; - - //wait for message to be sent - if (!f.SendMutex.WaitOne(timeout)) - return -ETIMEDOUT; - - return dataLength; - } - - public override bool WaitForAllTransmits(int timeout) - { - while (_sendQueue.Count > 0) - { - ManualResetEvent ev; - lock (_sendQueue) - ev = _sendQueue.First.Value.SendMutex; - - if (ev.WaitOne(timeout)) - return false; - } - return true; - } - - public override BacnetAddress GetBroadcastAddress() - { - return new BacnetAddress(BacnetAddressTypes.MSTP, 0xFFFF, new byte[] { 0xFF }); - } - - public override void Dispose() - { - _port?.Close(); - _port = null; - } - - public event FrameRecievedHandler FrameRecieved; - - public override bool Equals(object obj) - { - if (obj is not BacnetMstpProtocolTransport) return false; - var a = (BacnetMstpProtocolTransport)obj; - return _port.Equals(a._port); - } - - public override int GetHashCode() - { - return _port.GetHashCode(); - } - - public override string ToString() - { - return _port.ToString(); - } - - private void QueueFrame(BacnetMstpFrameTypes frameType, byte destinationAddress) - { - lock (_sendQueue) - _sendQueue.AddLast(new MessageFrame(frameType, destinationAddress, null, 0)); - } - - private void SendFrame(BacnetMstpFrameTypes frameType, byte destinationAddress) - { - SendFrame(new MessageFrame(frameType, destinationAddress, null, 0)); - } - - private void SendFrame(MessageFrame frame) - { - if (SourceAddress == -1 || _port == null) return; - int tx; - if (frame.Data == null || frame.Data.Length == 0) - { - var tmpTransmitBuffer = new byte[MSTP.MSTP_HEADER_LENGTH]; - tx = MSTP.Encode(tmpTransmitBuffer, 0, frame.FrameType, frame.DestinationAddress, - (byte)SourceAddress, 0); - _port.Write(tmpTransmitBuffer, 0, tx); - } - else - { - tx = MSTP.Encode(frame.Data, 0, frame.FrameType, frame.DestinationAddress, (byte)SourceAddress, - frame.DataLength); - _port.Write(frame.Data, 0, tx); - } - frame.SendMutex.Set(); - Log.Debug($"{frame.FrameType} {frame.DestinationAddress:X2}"); - } - - private void RemoveCurrentMessage(int msgLength) - { - var fullMsgLength = MSTP.MSTP_HEADER_LENGTH + msgLength + (msgLength > 0 ? 2 : 0); - if (_localOffset > fullMsgLength) - Array.Copy(_localBuffer, fullMsgLength, _localBuffer, 0, _localOffset - fullMsgLength); - _localOffset -= fullMsgLength; - } - - private StateChanges PollForMaster() - { - while (true) - { - //send - SendFrame(BacnetMstpFrameTypes.FRAME_TYPE_POLL_FOR_MASTER, _ps); - - //wait - var status = GetNextMessage(T_USAGE_TIMEOUT, out var frameType, out var destinationAddress, - out var sourceAddress, out var msgLength); - - if (status == GetMessageStatus.Good) - { - try - { - if (frameType == BacnetMstpFrameTypes.FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER && - destinationAddress == SourceAddress) - { - _soleMaster = false; - _ns = sourceAddress; - _ps = (byte)SourceAddress; - _tokenCount = 0; - return StateChanges.ReceivedReplyToPFM; - } - else - return StateChanges.ReceivedUnexpectedFrame; - } - finally - { - RemoveCurrentMessage(msgLength); - } - } - if (_soleMaster) - { - /* SoleMaster */ - _frameCount = 0; - return StateChanges.SoleMaster; - } - if (_ns != SourceAddress) - { - /* DoneWithPFM */ - return StateChanges.DoneWithPFM; - } - if ((_ps + 1) % (MaxMaster + 1) != SourceAddress) - { - /* SendNextPFM */ - _ps = (byte)((_ps + 1) % (MaxMaster + 1)); - } - else - { - /* DeclareSoleMaster */ - _soleMaster = true; - _frameCount = 0; - return StateChanges.DeclareSoleMaster; - } - } - } - - private StateChanges DoneWithToken() - { - if (_frameCount < MaxInfoFrames) - { - /* SendAnotherFrame */ - return StateChanges.SendAnotherFrame; - } - if (!_soleMaster && _ns == SourceAddress) - { - /* NextStationUnknown */ - _ps = (byte)((SourceAddress + 1) % (MaxMaster + 1)); - return StateChanges.NextStationUnknown; - } - if (_tokenCount < MaxPoll - 1) - { - _tokenCount++; - if (_soleMaster && _ns != (SourceAddress + 1) % (MaxMaster + 1)) - { - /* SoleMaster */ - _frameCount = 0; - return StateChanges.SoleMaster; - } - /* SendToken */ - return StateChanges.SendToken; - } - if ((_ps + 1) % (MaxMaster + 1) == _ns) - { - if (!_soleMaster) - { - /* ResetMaintenancePFM */ - _ps = (byte)SourceAddress; - _tokenCount = 1; - return StateChanges.ResetMaintenancePFM; - } - /* SoleMasterRestartMaintenancePFM */ - _ps = (byte)((_ns + 1) % (MaxMaster + 1)); - _ns = (byte)SourceAddress; - _tokenCount = 1; - return StateChanges.SoleMasterRestartMaintenancePFM; - } - /* SendMaintenancePFM */ - _ps = (byte)((_ps + 1) % (MaxMaster + 1)); - return StateChanges.SendMaintenancePFM; - } - - private StateChanges WaitForReply() - { - //fetch message - var status = GetNextMessage(T_REPLY_TIMEOUT, out var frameType, out var destinationAddress, - out var sourceAddress, out var msgLength); - - if (status == GetMessageStatus.Good) - { - try - { - if (destinationAddress == (byte)SourceAddress && - (frameType == BacnetMstpFrameTypes.FRAME_TYPE_TEST_RESPONSE || - frameType == BacnetMstpFrameTypes.FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY)) - { - //signal upper layer - if (frameType != BacnetMstpFrameTypes.FRAME_TYPE_TEST_RESPONSE) - { - var remoteAddress = new BacnetAddress(BacnetAddressTypes.MSTP, 0, new[] { sourceAddress }); - try - { - InvokeMessageRecieved(_localBuffer, MSTP.MSTP_HEADER_LENGTH, msgLength, remoteAddress); - } - catch (Exception ex) - { - Log.Error("Exception in MessageRecieved event", ex); - } - } - - /* ReceivedReply */ - return StateChanges.ReceivedReply; - } - else if (frameType == BacnetMstpFrameTypes.FRAME_TYPE_REPLY_POSTPONED) - { - /* ReceivedPostpone */ - return StateChanges.ReceivedPostpone; - } - else - { - /* ReceivedUnexpectedFrame */ - return StateChanges.ReceivedUnexpectedFrame; - } - } - finally - { - RemoveCurrentMessage(msgLength); - } - } - - if (status != GetMessageStatus.Timeout) - return StateChanges.InvalidFrame; - - /* ReplyTimeout */ - _frameCount = MaxInfoFrames; - return StateChanges.ReplyTimeOut; - /* InvalidFrame */ - } - - private StateChanges UseToken() - { - if (_sendQueue.Count == 0) - { - /* NothingToSend */ - _frameCount = MaxInfoFrames; - return StateChanges.NothingToSend; - } - /* SendNoWait / SendAndWait */ - MessageFrame messageFrame; - lock (_sendQueue) - { - messageFrame = _sendQueue.First.Value; - _sendQueue.RemoveFirst(); - } - SendFrame(messageFrame); - _frameCount++; - if (messageFrame.FrameType == BacnetMstpFrameTypes.FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY || - messageFrame.FrameType == BacnetMstpFrameTypes.FRAME_TYPE_TEST_REQUEST) - return StateChanges.SendAndWait; - return StateChanges.SendNoWait; - } - - private StateChanges PassToken() - { - for (var i = 0; i <= RetryToken; i++) - { - //send - SendFrame(BacnetMstpFrameTypes.FRAME_TYPE_TOKEN, _ns); - - //wait for it to be used - var status = GetNextMessage(T_USAGE_TIMEOUT, out _, out _, out _, out _); - if (status == GetMessageStatus.Good || status == GetMessageStatus.DecodeError) - return StateChanges.SawTokenUser; //don't remove current message - } - - //give up - _ps = (byte)((_ns + 1) % (MaxMaster + 1)); - _ns = (byte)SourceAddress; - _tokenCount = 0; - return StateChanges.FindNewSuccessor; - } - - private StateChanges Idle() - { - var noTokenTimeout = T_NO_TOKEN + 10 * SourceAddress; - - while (_port != null) - { - //get message - var status = GetNextMessage(noTokenTimeout, out var frameType, out var destinationAddress, - out var sourceAddress, out var msgLength); - - if (status == GetMessageStatus.Good) - { - try - { - if (destinationAddress == SourceAddress || destinationAddress == 0xFF) - { - switch (frameType) - { - case BacnetMstpFrameTypes.FRAME_TYPE_POLL_FOR_MASTER: - if (destinationAddress == 0xFF) - QueueFrame(BacnetMstpFrameTypes.FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER, - sourceAddress); - else - { - //respond to PFM - SendFrame(BacnetMstpFrameTypes.FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER, - sourceAddress); - } - break; - case BacnetMstpFrameTypes.FRAME_TYPE_TOKEN: - if (destinationAddress != 0xFF) - { - _frameCount = 0; - _soleMaster = false; - return StateChanges.ReceivedToken; - } - break; - case BacnetMstpFrameTypes.FRAME_TYPE_TEST_REQUEST: - if (destinationAddress == 0xFF) - QueueFrame(BacnetMstpFrameTypes.FRAME_TYPE_TEST_RESPONSE, sourceAddress); - else - { - //respond to test - SendFrame(BacnetMstpFrameTypes.FRAME_TYPE_TEST_RESPONSE, sourceAddress); - } - break; - case BacnetMstpFrameTypes.FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY: - case BacnetMstpFrameTypes.FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY: - try - { - //signal upper layer - var remoteAddress = new BacnetAddress(BacnetAddressTypes.MSTP, 0, new[] { sourceAddress }); - InvokeMessageRecieved(_localBuffer, MSTP.MSTP_HEADER_LENGTH, msgLength, remoteAddress); - } - catch (Exception ex) - { - Log.Error("Exception in MessageRecieved event", ex); - } - if (frameType == BacnetMstpFrameTypes.FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY) - { - _replySource = sourceAddress; - _reply = null; - _replyMutex.Reset(); - return StateChanges.ReceivedDataNeedingReply; - } - break; - } - } - } - finally - { - RemoveCurrentMessage(msgLength); - } - } - else if (status == GetMessageStatus.Timeout) - { - /* GenerateToken */ - _ps = (byte)((SourceAddress + 1) % (MaxMaster + 1)); - _ns = (byte)SourceAddress; - _tokenCount = 0; - return StateChanges.GenerateToken; - } - else if (status == GetMessageStatus.ConnectionClose) - { - Log.Debug("No connection"); - } - else if (status == GetMessageStatus.ConnectionError) - { - Log.Debug("Connection Error"); - } - else - { - Log.Debug("Garbage"); - } - } - - return StateChanges.Reset; - } - - private StateChanges AnswerDataRequest() - { - if (_replyMutex.WaitOne(T_REPLY_DELAY)) - { - SendFrame(_reply); - lock (_sendQueue) - _sendQueue.Remove(_reply); - return StateChanges.Reply; - } - SendFrame(BacnetMstpFrameTypes.FRAME_TYPE_REPLY_POSTPONED, _replySource); - return StateChanges.DeferredReply; - } - - private StateChanges Initialize() - { - _tokenCount = MaxPoll; /* cause a Poll For Master to be sent when this node first receives the token */ - _frameCount = 0; - _soleMaster = false; - _ns = (byte)SourceAddress; - _ps = (byte)SourceAddress; - return StateChanges.DoneInitializing; - } - - private void MstpThread() - { - try - { - var stateChange = StateChanges.Reset; - - while (_port != null) - { - Log.Debug(stateChange); - - switch (stateChange) - { - case StateChanges.Reset: - stateChange = Initialize(); - break; - case StateChanges.DoneInitializing: - case StateChanges.ReceivedUnexpectedFrame: - case StateChanges.Reply: - case StateChanges.DeferredReply: - case StateChanges.SawTokenUser: - stateChange = Idle(); - break; - case StateChanges.GenerateToken: - case StateChanges.FindNewSuccessor: - case StateChanges.SendMaintenancePFM: - case StateChanges.SoleMasterRestartMaintenancePFM: - case StateChanges.NextStationUnknown: - stateChange = PollForMaster(); - break; - case StateChanges.DoneWithPFM: - case StateChanges.ResetMaintenancePFM: - case StateChanges.ReceivedReplyToPFM: - case StateChanges.SendToken: - stateChange = PassToken(); - break; - case StateChanges.ReceivedDataNeedingReply: - stateChange = AnswerDataRequest(); - break; - case StateChanges.ReceivedToken: - case StateChanges.SoleMaster: - case StateChanges.DeclareSoleMaster: - case StateChanges.SendAnotherFrame: - stateChange = UseToken(); - break; - case StateChanges.NothingToSend: - case StateChanges.SendNoWait: - case StateChanges.ReplyTimeOut: - case StateChanges.InvalidFrame: - case StateChanges.ReceivedReply: - case StateChanges.ReceivedPostpone: - stateChange = DoneWithToken(); - break; - case StateChanges.SendAndWait: - stateChange = WaitForReply(); - break; - } - } - Log.Debug("MSTP thread is closing down"); - } - catch (Exception ex) - { - Log.Error("Exception in MSTP thread", ex); - } - - IsRunning = false; - } - - private void RemoveGarbage() - { - //scan for preambles - for (var i = 0; i < _localOffset - 1; i++) - { - if (_localBuffer[i] != MSTP.MSTP_PREAMBLE1 || _localBuffer[i + 1] != MSTP.MSTP_PREAMBLE2) - continue; - - if (i <= 0) - return; - - //move back - Array.Copy(_localBuffer, i, _localBuffer, 0, _localOffset - i); - _localOffset -= i; - Log.Debug("Garbage"); - return; - } - - //one preamble? - if (_localOffset > 0 && _localBuffer[_localOffset - 1] == MSTP.MSTP_PREAMBLE1) - { - if (_localOffset != 1) - { - _localBuffer[0] = MSTP.MSTP_PREAMBLE1; - _localOffset = 1; - Log.Debug("Garbage"); - } - return; - } - - //no preamble? - if (_localOffset > 0) - { - _localOffset = 0; - Log.Debug("Garbage"); - } - } - - private GetMessageStatus GetNextMessage(int timeoutMs, out BacnetMstpFrameTypes frameType, - out byte destinationAddress, out byte sourceAddress, out int msgLength) - { - int timeout; - - frameType = BacnetMstpFrameTypes.FRAME_TYPE_TOKEN; - destinationAddress = 0; - sourceAddress = 0; - msgLength = 0; - - //fetch header - while (_localOffset < MSTP.MSTP_HEADER_LENGTH) - { - if (_port == null) return GetMessageStatus.ConnectionClose; - - timeout = _localOffset > 0 - ? T_FRAME_ABORT // set sub timeout - : timeoutMs; // set big silence timeout - - //read - var rx = _port.Read(_localBuffer, _localOffset, MSTP.MSTP_HEADER_LENGTH - _localOffset, timeout); - if (rx == -ETIMEDOUT) - { - //drop message - var status = _localOffset == 0 ? GetMessageStatus.Timeout : GetMessageStatus.SubTimeout; - _localBuffer[0] = 0xFF; - RemoveGarbage(); - return status; - } - if (rx < 0) - { - //drop message - _localBuffer[0] = 0xFF; - RemoveGarbage(); - return GetMessageStatus.ConnectionError; - } - if (rx == 0) - { - //drop message - _localBuffer[0] = 0xFF; - RemoveGarbage(); - return GetMessageStatus.ConnectionClose; - } - _localOffset += rx; - - //remove paddings & garbage - RemoveGarbage(); - } - - //decode - if (MSTP.Decode(_localBuffer, 0, _localOffset, out frameType, out destinationAddress, - out sourceAddress, out msgLength) < 0) - { - //drop message - _localBuffer[0] = 0xFF; - RemoveGarbage(); - return GetMessageStatus.DecodeError; - } - - //valid length? - var fullMsgLength = msgLength + MSTP.MSTP_HEADER_LENGTH + (msgLength > 0 ? 2 : 0); - if (msgLength > MaxBufferLength) - { - //drop message - _localBuffer[0] = 0xFF; - RemoveGarbage(); - return GetMessageStatus.DecodeError; - } - - //fetch data - if (msgLength > 0) - { - timeout = T_FRAME_ABORT; //set sub timeout - while (_localOffset < fullMsgLength) - { - //read - var rx = _port.Read(_localBuffer, _localOffset, fullMsgLength - _localOffset, timeout); - if (rx == -ETIMEDOUT) - { - //drop message - var status = _localOffset == 0 ? GetMessageStatus.Timeout : GetMessageStatus.SubTimeout; - _localBuffer[0] = 0xFF; - RemoveGarbage(); - return status; - } - if (rx < 0) - { - //drop message - _localBuffer[0] = 0xFF; - RemoveGarbage(); - return GetMessageStatus.ConnectionError; - } - if (rx == 0) - { - //drop message - _localBuffer[0] = 0xFF; - RemoveGarbage(); - return GetMessageStatus.ConnectionClose; - } - _localOffset += rx; - } - - //verify data crc - if ( - MSTP.Decode(_localBuffer, 0, _localOffset, out frameType, out destinationAddress, - out sourceAddress, out msgLength) < 0) - { - //drop message - _localBuffer[0] = 0xFF; - RemoveGarbage(); - return GetMessageStatus.DecodeError; - } - } - - //signal frame event - if (FrameRecieved != null) - { - var frameTypeCopy = frameType; - var destinationAddressCopy = destinationAddress; - var sourceAddressCopy = sourceAddress; - var msgLengthCopy = msgLength; - - ThreadPool.QueueUserWorkItem( - o => { FrameRecieved(this, frameTypeCopy, destinationAddressCopy, sourceAddressCopy, msgLengthCopy); }, null); - } - - Log.Debug($"{frameType} {destinationAddress:X2}"); - - //done - return GetMessageStatus.Good; - } - - private class MessageFrame - { - public readonly byte[] Data; - public readonly int DataLength; - public readonly byte DestinationAddress; - public readonly BacnetMstpFrameTypes FrameType; - public readonly ManualResetEvent SendMutex; - - public MessageFrame(BacnetMstpFrameTypes frameType, byte destinationAddress, byte[] data, int dataLength) - { - FrameType = frameType; - DestinationAddress = destinationAddress; - Data = data; - DataLength = dataLength; - SendMutex = new ManualResetEvent(false); - } - } - - private enum StateChanges - { - /* Initializing */ - Reset, - DoneInitializing, - - /* Idle, NoToken */ - GenerateToken, - ReceivedDataNeedingReply, - ReceivedToken, - - /* PollForMaster */ - ReceivedUnexpectedFrame, //also from WaitForReply - DoneWithPFM, - ReceivedReplyToPFM, - SoleMaster, //also from DoneWithToken - DeclareSoleMaster, - - /* UseToken */ - SendAndWait, - NothingToSend, - SendNoWait, - - /* DoneWithToken */ - SendToken, - ResetMaintenancePFM, - SendMaintenancePFM, - SoleMasterRestartMaintenancePFM, - SendAnotherFrame, - NextStationUnknown, - - /* WaitForReply */ - ReplyTimeOut, - InvalidFrame, - ReceivedReply, - ReceivedPostpone, - - /* PassToken */ - FindNewSuccessor, - SawTokenUser, - - /* AnswerDataRequest */ - Reply, - DeferredReply - } - - #region " Sniffer mode " - - // Used in Sniffer only mode - public delegate void RawMessageReceivedHandler(byte[] buffer, int offset, int lenght); - - public event RawMessageReceivedHandler RawMessageRecieved; - - public void StartSpyMode() - { - if (_port == null) return; - _port.Open(); - - var th = new Thread(MstpThreadSniffer) { IsBackground = true }; - th.Start(); - } - - // Just Sniffer mode, no Bacnet activity generated here - // Modif FC - private void MstpThreadSniffer() - { - while (true) - { - try - { - var status = GetNextMessage(T_NO_TOKEN, out _, out _, out _, out var msgLength); - - switch (status) - { - case GetMessageStatus.ConnectionClose: - _port = null; - return; - - case GetMessageStatus.Good: - // frame event client ? - if (RawMessageRecieved != null) - { - var length = msgLength + MSTP.MSTP_HEADER_LENGTH + (msgLength > 0 ? 2 : 0); - - // Array copy - // after that it could be put asynchronously another time in the Main message loop - // without any problem - var packet = new byte[length]; - Array.Copy(_localBuffer, 0, packet, 0, length); - - // No need to use the thread pool, if the pipe is too slow - // frames task list will grow infinitly - RawMessageRecieved(packet, 0, length); - } - RemoveCurrentMessage(msgLength); - break; - } - } - catch - { - _port = null; - } - } - } - - #endregion -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetPipeTransport.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetPipeTransport.cs deleted file mode 100644 index 6d73437..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetPipeTransport.cs +++ /dev/null @@ -1,255 +0,0 @@ -namespace System.IO.BACnet; - -public class BacnetPipeTransport : IBacnetSerialTransport -{ - private PipeStream _conn; - private IAsyncResult _currentRead; - private IAsyncResult _currentConnect; - private readonly bool _isServer; - - public string Name { get; } - public int BytesToRead => PeekPipe(); - - public static string[] AvailablePorts - { - get - { - try - { - var listOfPipes = Directory.GetFiles(@"\\.\pipe\"); - for (var i = 0; i < listOfPipes.Length; i++) - listOfPipes[i] = listOfPipes[i].Replace(@"\\.\pipe\", ""); - return listOfPipes; - } - catch (Exception ex) - { - var log = LogManager.GetLogger(); - log.Warn("Exception in AvailablePorts", ex); - return InteropAvailablePorts; - } - } - } - - public BacnetPipeTransport(string name, bool isServer = false) - { - Name = name; - _isServer = isServer; - } - - /// - /// Get the available byte count. (The .NET pipe interface has a few lackings. See also the "InteropAvailablePorts" function) - /// - [DllImport("kernel32.dll", EntryPoint = "PeekNamedPipe", SetLastError = true)] - private static extern bool PeekNamedPipe(IntPtr handle, IntPtr buffer, uint nBufferSize, IntPtr bytesRead, ref uint bytesAvail, IntPtr bytesLeftThisMessage); - - public int PeekPipe() - { - uint bytesAvail = 0; - return PeekNamedPipe(_conn.SafePipeHandle.DangerousGetHandle(), IntPtr.Zero, 0, IntPtr.Zero, ref bytesAvail, IntPtr.Zero) - ? (int)bytesAvail - : 0; - } - - public override string ToString() - { - return Name; - } - - public override int GetHashCode() - { - return Name.GetHashCode(); - } - - public override bool Equals(object obj) - { - if (obj is not BacnetPipeTransport) return false; - var a = (BacnetPipeTransport)obj; - return Name.Equals(a.Name); - } - - public void Open() - { - if (_conn != null) Close(); - - if (!_isServer) - { - _conn = new NamedPipeClientStream(".", Name, PipeDirection.InOut, PipeOptions.Asynchronous); - ((NamedPipeClientStream)_conn).Connect(3000); - } - else - { - _conn = new NamedPipeServerStream(Name, PipeDirection.InOut, 20, PipeTransmissionMode.Byte, PipeOptions.Asynchronous); - } - } - - public void Write(byte[] buffer, int offset, int length) - { - if (!_conn.IsConnected) return; - try - { - //doing syncronous writes (to an Asynchronous pipe) seems to be a bad thing - _conn.BeginWrite(buffer, offset, length, (r) => { _conn.EndWrite(r); }, null); - } - catch (IOException) - { - Disconnect(); - } - } - - private void Disconnect() - { - if (_conn is NamedPipeServerStream stream) - { - try - { - stream.Disconnect(); - } - catch - { - } - _currentConnect = null; - } - _currentRead = null; - } - - private bool WaitForConnection(int timeoutMs) - { - if (_conn.IsConnected) return true; - if (_conn is not NamedPipeServerStream) return true; - - var server = (NamedPipeServerStream)_conn; - - if (_currentConnect == null) - { - try - { - _currentConnect = server.BeginWaitForConnection(null, null); - } - catch (IOException) - { - Disconnect(); - _currentConnect = server.BeginWaitForConnection(null, null); - } - } - - if (_currentConnect.IsCompleted || _currentConnect.AsyncWaitHandle.WaitOne(timeoutMs)) - { - try - { - server.EndWaitForConnection(_currentConnect); - } - catch (IOException) - { - Disconnect(); - } - _currentConnect = null; - } - - return _conn.IsConnected; - } - - public int Read(byte[] buffer, int offset, int length, int timeoutMs) - { - if (!WaitForConnection(timeoutMs)) return -BacnetMstpProtocolTransport.ETIMEDOUT; - - if (_currentRead == null) - { - try - { - _currentRead = _conn.BeginRead(buffer, offset, length, null, null); - } - catch (Exception) - { - Disconnect(); - return -1; - } - } - - if (!_currentRead.IsCompleted && !_currentRead.AsyncWaitHandle.WaitOne(timeoutMs)) - return -BacnetMstpProtocolTransport.ETIMEDOUT; - - try - { - var rx = _conn.EndRead(_currentRead); - _currentRead = null; - return rx; - } - catch (Exception) - { - Disconnect(); - return -1; - } - } - - public void Close() - { - if (_conn == null) return; - _conn.Close(); - _conn = null; - } - - public void Dispose() - { - Close(); - } - - #region " Interop Get Pipe Names " - // ReSharper disable All - - [StructLayout(LayoutKind.Sequential)] - private struct FILETIME - { - public uint dwLowDateTime; - public uint dwHighDateTime; - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - private struct WIN32_FIND_DATA - { - public uint dwFileAttributes; - public FILETIME ftCreationTime; - public FILETIME ftLastAccessTime; - public FILETIME ftLastWriteTime; - public uint nFileSizeHigh; - public uint nFileSizeLow; - public uint dwReserved0; - public uint dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] - public string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - public string cAlternateFileName; - } - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] - private static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData); - [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] - private static extern int FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData); - [DllImport("kernel32.dll")] - private static extern bool FindClose(IntPtr hFindFile); - - /// - /// The built-in functions for pipe enumeration isn't perfect, I'm afraid. Hence this messy interop. - /// - private static string[] InteropAvailablePorts - { - get - { - var ret = new List(); - var handle = FindFirstFile(@"\\.\pipe\*", out var data); - if (handle == new IntPtr(-1)) - return ret.ToArray(); - - do - { - ret.Add(data.cFileName); - } - while (FindNextFile(handle, out data) != 0); - - FindClose(handle); - return ret.ToArray(); - } - } - - // ReSharper restore - #endregion -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetPtpProtocolTransport.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetPtpProtocolTransport.cs deleted file mode 100644 index f4f7c07..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetPtpProtocolTransport.cs +++ /dev/null @@ -1,607 +0,0 @@ -namespace System.IO.BACnet; - -/// -/// This is the standard BACNet PTP transport -/// -public class BacnetPtpProtocolTransport : BacnetTransportBase -{ - public const int T_HEARTBEAT = 15000; - public const int T_FRAME_ABORT = 2000; - private bool _isConnected; - private readonly bool _isServer; - private readonly ManualResetEvent _maySend = new(false); - private IBacnetSerialTransport _port; - private bool _sequenceCounter; - private Thread _thread; - - public string Password { get; set; } - - public BacnetPtpProtocolTransport(IBacnetSerialTransport transport, bool isServer) - { - _port = transport; - _isServer = isServer; - Type = BacnetAddressTypes.PTP; - HeaderLength = PTP.PTP_HEADER_LENGTH; - MaxBufferLength = 502; - MaxAdpuLength = PTP.PTP_MAX_APDU; - } - - public BacnetPtpProtocolTransport(string portName, int baudRate, bool isServer) - : this(new BacnetSerialPortTransport(portName, baudRate), isServer) - { - } - - public override int Send(byte[] buffer, int offset, int dataLength, BacnetAddress address, bool waitForTransmission, - int timeout) - { - var frameType = BacnetPtpFrameTypes.FRAME_TYPE_DATA0; - if (_sequenceCounter) frameType = BacnetPtpFrameTypes.FRAME_TYPE_DATA1; - _sequenceCounter = !_sequenceCounter; - - //add header - var fullLength = PTP.Encode(buffer, offset - PTP.PTP_HEADER_LENGTH, frameType, dataLength); - - //wait for send allowed - if (!_maySend.WaitOne(timeout)) - return -BacnetMstpProtocolTransport.ETIMEDOUT; - - Log.Debug(frameType); - - //send - SendWithXonXoff(buffer, offset - HeaderLength, fullLength); - return dataLength; - } - - public override BacnetAddress GetBroadcastAddress() - { - return new BacnetAddress(BacnetAddressTypes.PTP, 0xFFFF, new byte[0]); - } - - public override void Start() - { - if (_port == null) return; - - _thread = new Thread(PTPThread) - { - Name = "PTP Read", - IsBackground = true - }; - _thread.Start(); - } - - public override void Dispose() - { - _port?.Close(); - _port = null; - } - - public override bool Equals(object obj) - { - if (obj is not BacnetPtpProtocolTransport) return false; - var a = (BacnetPtpProtocolTransport)obj; - return _port.Equals(a._port); - } - - public override int GetHashCode() - { - return _port.GetHashCode(); - } - - public override string ToString() - { - return _port.ToString(); - } - - private void SendGreeting() - { - Log.Debug("Sending Greeting"); - byte[] greeting = { PTP.PTP_GREETING_PREAMBLE1, PTP.PTP_GREETING_PREAMBLE2, 0x43, 0x6E, 0x65, 0x74, 0x0D }; // BACnet\n - _port.Write(greeting, 0, greeting.Length); - } - - private static bool IsGreeting(IList buffer, int offset, int maxOffset) - { - byte[] greeting = { PTP.PTP_GREETING_PREAMBLE1, PTP.PTP_GREETING_PREAMBLE2, 0x43, 0x6E, 0x65, 0x74, 0x0D }; // BACnet\n - maxOffset = Math.Min(offset + greeting.Length, maxOffset); - for (var i = offset; i < maxOffset; i++) - if (buffer[i] != greeting[i - offset]) - return false; - return true; - } - - private static void RemoveGreetingGarbage(byte[] buffer, ref int maxOffset) - { - while (maxOffset > 0) - { - while (maxOffset > 0 && buffer[0] != 0x42) - { - if (maxOffset > 1) - Array.Copy(buffer, 1, buffer, 0, maxOffset - 1); - maxOffset--; - } - if (maxOffset > 1 && buffer[1] != 0x41) - buffer[0] = 0xFF; - else if (maxOffset > 2 && buffer[2] != 0x43) - buffer[0] = 0xFF; - else if (maxOffset > 3 && buffer[3] != 0x6E) - buffer[0] = 0xFF; - else if (maxOffset > 4 && buffer[4] != 0x65) - buffer[0] = 0xFF; - else if (maxOffset > 5 && buffer[5] != 0x74) - buffer[0] = 0xFF; - else if (maxOffset > 6 && buffer[6] != 0x0D) - buffer[0] = 0xFF; - else - break; - } - } - - private bool WaitForGreeting(int timeout) - { - if (_port == null) return false; - var buffer = new byte[7]; - var offset = 0; - while (offset < 7) - { - var currentTimeout = offset == 0 ? timeout : T_FRAME_ABORT; - var rx = _port.Read(buffer, offset, 7 - offset, currentTimeout); - if (rx <= 0) return false; - offset += rx; - - //remove garbage - RemoveGreetingGarbage(buffer, ref offset); - } - return true; - } - - private bool Reconnect() - { - _isConnected = false; - _maySend.Reset(); - - if (_port == null) - return false; - - try - { - _port.Close(); - } - catch - { - } - - try - { - _port.Open(); - } - catch - { - return false; - } - - //connect procedure - if (_isServer) - { - ////wait for greeting - //if (!WaitForGreeting(-1)) - //{ - // Log.Debug("Garbage Greeting"); - // return false; - //} - //if (StateLogging) - // Log.Debug("Got Greeting"); - - ////request connection - //SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_CONNECT_REQUEST); - } - else - { - //send greeting - SendGreeting(); - } - - _isConnected = true; - return true; - } - - private void RemoveGarbage(byte[] buffer, ref int length) - { - //scan for preambles - for (var i = 0; i < length - 1; i++) - { - if ((buffer[i] != PTP.PTP_PREAMBLE1 || buffer[i + 1] != PTP.PTP_PREAMBLE2) && !IsGreeting(buffer, i, length)) - continue; - - if (i <= 0) - return; - - //move back - Array.Copy(buffer, i, buffer, 0, length - i); - length -= i; - Log.Debug("Garbage"); - return; - } - - //one preamble? - if (length > 0 && - (buffer[length - 1] == PTP.PTP_PREAMBLE1 || buffer[length - 1] == PTP.PTP_GREETING_PREAMBLE1)) - { - buffer[0] = buffer[length - 1]; - length = 1; - Log.Debug("Garbage"); - return; - } - - //no preamble? - if (length <= 0) - return; - - length = 0; - Log.Debug("Garbage"); - } - - private static void RemoveXonOff(byte[] buffer, int offset, ref int maxOffset, ref bool complimentNext) - { - //X'10' (DLE) => X'10' X'90' - //X'11' (XON) => X'10' X'91' - //X'13' (XOFF) => X'10' X'93' - - for (var i = offset; i < maxOffset; i++) - { - if (complimentNext) - { - buffer[i] &= 0x7F; - complimentNext = false; - } - else if (buffer[i] == 0x11 || buffer[i] == 0x13 || buffer[i] == 0x10) - { - if (buffer[i] == 0x10) complimentNext = true; - if (maxOffset - i > 0) - Array.Copy(buffer, i + 1, buffer, i, maxOffset - i); - maxOffset--; - i--; - } - } - } - - private void SendWithXonXoff(byte[] buffer, int offset, int length) - { - var escape = new byte[1] { 0x10 }; - var maxOffset = length + offset; - - //scan - for (var i = offset; i < maxOffset; i++) - { - if (buffer[i] != 0x10 && buffer[i] != 0x11 && buffer[i] != 0x13) - continue; - - _port.Write(buffer, offset, i - offset); - _port.Write(escape, 0, 1); - buffer[i] |= 0x80; - offset = i; - } - - //leftover - _port.Write(buffer, offset, maxOffset - offset); - } - - private void SendFrame(BacnetPtpFrameTypes frameType, byte[] buffer = null, int msgLength = 0) - { - if (_port == null) - return; - - var fullLength = PTP.PTP_HEADER_LENGTH + msgLength + (msgLength > 0 ? 2 : 0); - if (buffer == null) buffer = new byte[fullLength]; - PTP.Encode(buffer, 0, frameType, msgLength); - - Log.Debug(frameType); - - //send - SendWithXonXoff(buffer, 0, fullLength); - } - - private void SendDisconnect(BacnetPtpDisconnectReasons bacnetPtpDisconnectReasons) - { - var buffer = new byte[PTP.PTP_HEADER_LENGTH + 1 + 2]; - buffer[PTP.PTP_HEADER_LENGTH] = (byte)bacnetPtpDisconnectReasons; - SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_DISCONNECT_REQUEST, buffer, 1); - } - - private BacnetMstpProtocolTransport.GetMessageStatus ProcessRxStatus(byte[] buffer, ref int offset, int rx) - { - if (rx == -BacnetMstpProtocolTransport.ETIMEDOUT) - { - //drop message - var status = offset == 0 - ? BacnetMstpProtocolTransport.GetMessageStatus.Timeout - : BacnetMstpProtocolTransport.GetMessageStatus.SubTimeout; - buffer[0] = 0xFF; - RemoveGarbage(buffer, ref offset); - return status; - } - if (rx < 0) - { - //drop message - buffer[0] = 0xFF; - RemoveGarbage(buffer, ref offset); - return BacnetMstpProtocolTransport.GetMessageStatus.ConnectionError; - } - - if (rx != 0) - return BacnetMstpProtocolTransport.GetMessageStatus.Good; - - //drop message - buffer[0] = 0xFF; - RemoveGarbage(buffer, ref offset); - return BacnetMstpProtocolTransport.GetMessageStatus.ConnectionClose; - } - - private BacnetMstpProtocolTransport.GetMessageStatus GetNextMessage(byte[] buffer, ref int offset, - int timeoutMs, out BacnetPtpFrameTypes frameType, out int msgLength) - { - BacnetMstpProtocolTransport.GetMessageStatus status; - var timeout = timeoutMs; - - frameType = BacnetPtpFrameTypes.FRAME_TYPE_HEARTBEAT_XOFF; - msgLength = 0; - var complimentNext = false; - - //fetch header - while (offset < PTP.PTP_HEADER_LENGTH) - { - if (_port == null) return BacnetMstpProtocolTransport.GetMessageStatus.ConnectionClose; - - timeout = offset > 0 ? T_FRAME_ABORT : timeoutMs; - - //read - var rx = _port.Read(buffer, offset, PTP.PTP_HEADER_LENGTH - offset, timeout); - status = ProcessRxStatus(buffer, ref offset, rx); - if (status != BacnetMstpProtocolTransport.GetMessageStatus.Good) return status; - - //remove XON/XOFF - var newOffset = offset + rx; - RemoveXonOff(buffer, offset, ref newOffset, ref complimentNext); - offset = newOffset; - - //remove garbage - RemoveGarbage(buffer, ref offset); - } - - //greeting - if (IsGreeting(buffer, 0, offset)) - { - //get last byte - var rx = _port.Read(buffer, offset, 1, timeout); - status = ProcessRxStatus(buffer, ref offset, rx); - if (status != BacnetMstpProtocolTransport.GetMessageStatus.Good) return status; - offset += 1; - if (IsGreeting(buffer, 0, offset)) - { - frameType = BacnetPtpFrameTypes.FRAME_TYPE_GREETING; - Log.Debug(frameType); - return BacnetMstpProtocolTransport.GetMessageStatus.Good; - } - //drop message - buffer[0] = 0xFF; - RemoveGarbage(buffer, ref offset); - return BacnetMstpProtocolTransport.GetMessageStatus.DecodeError; - } - - //decode - if (PTP.Decode(buffer, 0, offset, out frameType, out msgLength) < 0) - { - //drop message - buffer[0] = 0xFF; - RemoveGarbage(buffer, ref offset); - return BacnetMstpProtocolTransport.GetMessageStatus.DecodeError; - } - - //valid length? - var fullMsgLength = msgLength + PTP.PTP_HEADER_LENGTH + (msgLength > 0 ? 2 : 0); - if (msgLength > MaxBufferLength) - { - //drop message - buffer[0] = 0xFF; - RemoveGarbage(buffer, ref offset); - return BacnetMstpProtocolTransport.GetMessageStatus.DecodeError; - } - - //fetch data - if (msgLength > 0) - { - timeout = T_FRAME_ABORT; //set sub timeout - while (offset < fullMsgLength) - { - //read - var rx = _port.Read(buffer, offset, fullMsgLength - offset, timeout); - status = ProcessRxStatus(buffer, ref offset, rx); - if (status != BacnetMstpProtocolTransport.GetMessageStatus.Good) return status; - - //remove XON/XOFF - var newOffset = offset + rx; - RemoveXonOff(buffer, offset, ref newOffset, ref complimentNext); - offset = newOffset; - } - - //verify data crc - if (PTP.Decode(buffer, 0, offset, out frameType, out msgLength) < 0) - { - //drop message - buffer[0] = 0xFF; - RemoveGarbage(buffer, ref offset); - return BacnetMstpProtocolTransport.GetMessageStatus.DecodeError; - } - } - - Log.Debug(frameType); - - //done - return BacnetMstpProtocolTransport.GetMessageStatus.Good; - } - - private void PTPThread() - { - var buffer = new byte[MaxBufferLength]; - try - { - while (_port != null) - { - //connect if needed - if (!_isConnected) - { - if (!Reconnect()) - { - Thread.Sleep(1000); - continue; - } - } - - //read message - var offset = 0; - var status = GetNextMessage(buffer, ref offset, T_HEARTBEAT, out var frameType, out var msgLength); - - //action - switch (status) - { - case BacnetMstpProtocolTransport.GetMessageStatus.ConnectionClose: - case BacnetMstpProtocolTransport.GetMessageStatus.ConnectionError: - Log.Warn("Connection disturbance"); - Reconnect(); - break; - - case BacnetMstpProtocolTransport.GetMessageStatus.DecodeError: - Log.Warn("PTP decode error"); - break; - - case BacnetMstpProtocolTransport.GetMessageStatus.SubTimeout: - Log.Warn("PTP frame abort"); - break; - - case BacnetMstpProtocolTransport.GetMessageStatus.Timeout: - SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_HEARTBEAT_XON); - //both server and client will send this - break; - - case BacnetMstpProtocolTransport.GetMessageStatus.Good: - - //action - switch (frameType) - { - case BacnetPtpFrameTypes.FRAME_TYPE_GREETING: - //request connection - SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_CONNECT_REQUEST); - break; - - case BacnetPtpFrameTypes.FRAME_TYPE_HEARTBEAT_XON: - _maySend.Set(); - break; - - case BacnetPtpFrameTypes.FRAME_TYPE_HEARTBEAT_XOFF: - _maySend.Reset(); - break; - - case BacnetPtpFrameTypes.FRAME_TYPE_DATA0: - //send confirm - SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_DATA_ACK0_XON); - - //notify the sky! - InvokeMessageRecieved(buffer, PTP.PTP_HEADER_LENGTH, msgLength, GetBroadcastAddress()); - break; - - case BacnetPtpFrameTypes.FRAME_TYPE_DATA1: - //send confirm - SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_DATA_ACK1_XON); - //notify the sky! - InvokeMessageRecieved(buffer, PTP.PTP_HEADER_LENGTH, msgLength, GetBroadcastAddress()); - break; - - case BacnetPtpFrameTypes.FRAME_TYPE_DATA_ACK0_XOFF: - case BacnetPtpFrameTypes.FRAME_TYPE_DATA_ACK1_XOFF: - //so, the other one got the message, eh? - _maySend.Reset(); - break; - - case BacnetPtpFrameTypes.FRAME_TYPE_DATA_ACK0_XON: - case BacnetPtpFrameTypes.FRAME_TYPE_DATA_ACK1_XON: - //so, the other one got the message, eh? - _maySend.Set(); - break; - - case BacnetPtpFrameTypes.FRAME_TYPE_DATA_NAK0_XOFF: - case BacnetPtpFrameTypes.FRAME_TYPE_DATA_NAK1_XOFF: - _maySend.Reset(); - //denial, eh? - break; - - case BacnetPtpFrameTypes.FRAME_TYPE_DATA_NAK0_XON: - case BacnetPtpFrameTypes.FRAME_TYPE_DATA_NAK1_XON: - _maySend.Set(); - //denial, eh? - break; - - case BacnetPtpFrameTypes.FRAME_TYPE_CONNECT_REQUEST: - //also send a password perhaps? - if (!string.IsNullOrEmpty(Password)) - { - var pass = Encoding.ASCII.GetBytes(Password); - var tmpBuffer = new byte[PTP.PTP_HEADER_LENGTH + pass.Length + 2]; - Array.Copy(pass, 0, tmpBuffer, PTP.PTP_HEADER_LENGTH, pass.Length); - SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_CONNECT_RESPONSE, tmpBuffer, - pass.Length); - } - else - SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_CONNECT_RESPONSE); - //we're ready - SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_HEARTBEAT_XON); - break; - - case BacnetPtpFrameTypes.FRAME_TYPE_CONNECT_RESPONSE: - if (msgLength > 0 && !string.IsNullOrEmpty(Password)) - { - var password = Encoding.ASCII.GetString(buffer, PTP.PTP_HEADER_LENGTH, - msgLength); - if (password != Password) - SendDisconnect(BacnetPtpDisconnectReasons.PTP_DISCONNECT_INVALID_PASSWORD); - else - SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_HEARTBEAT_XON); //we're ready - } - else - { - //we're ready - SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_HEARTBEAT_XON); - } - break; - - case BacnetPtpFrameTypes.FRAME_TYPE_DISCONNECT_REQUEST: - var reason = BacnetPtpDisconnectReasons.PTP_DISCONNECT_OTHER; - if (msgLength > 0) - reason = (BacnetPtpDisconnectReasons)buffer[PTP.PTP_HEADER_LENGTH]; - SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_DISCONNECT_RESPONSE); - Log.Debug($"Disconnect requested: {reason}"); - Reconnect(); - break; - - case BacnetPtpFrameTypes.FRAME_TYPE_DISCONNECT_RESPONSE: - _maySend.Reset(); - //hopefully we'll be closing down now - break; - - case BacnetPtpFrameTypes.FRAME_TYPE_TEST_REQUEST: - SendFrame(BacnetPtpFrameTypes.FRAME_TYPE_TEST_RESPONSE, buffer, msgLength); - break; - - case BacnetPtpFrameTypes.FRAME_TYPE_TEST_RESPONSE: - //good - break; - } - break; - } - } - Log.Debug("PTP thread is closing down"); - } - catch (Exception ex) - { - Log.Error($"Exception in PTP thread", ex); - } - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetSerialPortTransport.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetSerialPortTransport.cs deleted file mode 100644 index 3ff2b07..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetSerialPortTransport.cs +++ /dev/null @@ -1,72 +0,0 @@ -namespace System.IO.BACnet; - -public class BacnetSerialPortTransport : IBacnetSerialTransport -{ - private readonly string _portName; - private readonly SerialPort _port; - - public int BytesToRead => _port?.BytesToRead ?? 0; - - public BacnetSerialPortTransport(string portName, int baudRate) - { - _portName = portName; - _port = new SerialPort(_portName, baudRate, Parity.None, 8, StopBits.One); - } - - public override bool Equals(object obj) - { - if (obj is not BacnetSerialPortTransport) return false; - var a = (BacnetSerialPortTransport)obj; - return _portName.Equals(a._portName); - } - - public override int GetHashCode() - { - return _portName.GetHashCode(); - } - - public override string ToString() - { - return _portName; - } - - public void Open() - { - _port.Open(); - } - - public void Write(byte[] buffer, int offset, int length) - { - _port?.Write(buffer, offset, length); - } - - public int Read(byte[] buffer, int offset, int length, int timeoutMs) - { - if (_port == null) return 0; - _port.ReadTimeout = timeoutMs; - - try - { - var rx = _port.Read(buffer, offset, length); - return rx; - } - catch (TimeoutException) - { - return -BacnetMstpProtocolTransport.ETIMEDOUT; - } - catch (Exception) - { - return -1; - } - } - - public void Close() - { - _port?.Close(); - } - - public void Dispose() - { - Close(); - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetTransportBase.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetTransportBase.cs deleted file mode 100644 index d6975cc..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetTransportBase.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace System.IO.BACnet; - -public abstract class BacnetTransportBase : IBacnetTransport -{ - public ILog Log { get; set; } - public int HeaderLength { get; protected set; } - public int MaxBufferLength { get; protected set; } - public BacnetAddressTypes Type { get; protected set; } - public BacnetMaxAdpu MaxAdpuLength { get; protected set; } - public byte MaxInfoFrames { get; set; } = 0xFF; - - protected BacnetTransportBase() - { - Log = LogManager.GetLogger(GetType()); - } - - public abstract void Start(); - - public abstract BacnetAddress GetBroadcastAddress(); - - public virtual bool WaitForAllTransmits(int timeout) - { - return true; // not used - } - - public abstract int Send(byte[] buffer, int offset, int dataLength, BacnetAddress address, bool waitForTransmission, int timeout); - - public event MessageRecievedHandler MessageRecieved; - - protected void InvokeMessageRecieved(byte[] buffer, int offset, int msgLength, BacnetAddress remoteAddress) - { - MessageRecieved?.Invoke(this, buffer, offset, msgLength, remoteAddress); - } - - public abstract void Dispose(); -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetTransportEthernet.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetTransportEthernet.cs deleted file mode 100644 index 273bea8..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/BacnetTransportEthernet.cs +++ /dev/null @@ -1,224 +0,0 @@ -/************************************************************************** -* MIT License -* -* Copyright (C) 2015 Frederic Chaxel -* -* lot of code ported from https://github.com/LorenVS/bacstack -* Copyright (C) 2014 Loren Van Spronsen, thank to him. -* Thank to Christopher Gunther for the idea, and the starting code -* -* Permission is hereby granted, free of charge, to any person obtaining -* a copy of this software and associated documentation files (the -* "Software"), to deal in the Software without restriction, including -* without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to -* permit persons to whom the Software is furnished to do so, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -* -*********************************************************************/ - -namespace System.IO.BACnet; - -// A reference to PacketDotNet.dll & SharpPcap.dll should be made -// in order to use this code -// This class is not in the file BacnetTransport.cs to avoid integration -// of two dll when Bacnet/Ethernet is not used - -internal class BacnetEthernetProtocolTransport : BacnetTransportBase -{ - private LibPcapLiveDevice _device; - private byte[] _deviceMac; // Mac of the device - private readonly string _deviceName; - - /// - /// - /// Something like "Local Lan 1", "Wireless network", ... - public BacnetEthernetProtocolTransport(string friendlydeviceName) - { - _deviceName = friendlydeviceName; - Type = BacnetAddressTypes.Ethernet; - MaxAdpuLength = BacnetMaxAdpu.MAX_APDU1476; - HeaderLength = 6 + 6 + 2 + 3; - MaxBufferLength = 1500; - } - - public override BacnetAddress GetBroadcastAddress() - { - return new BacnetAddress(BacnetAddressTypes.Ethernet, "FF-FF-FF-FF-FF-FF", 65535); - } - - public override void Start() - { - _device = Open(); - if (_device == null) throw new Exception("Cannot open Ethernet interface"); - - _deviceMac = _device.Interface.MacAddress.GetAddressBytes(); - - // filter to only bacnet packets - _device.Filter = "ether proto 0x82"; - - var th = new Thread(CaptureThread) { IsBackground = true }; - th.Start(); - } - - public override int Send(byte[] buffer, int offset, int dataLength, BacnetAddress address, - bool waitForTransmission, int timeout) - { - var hdrOffset = 0; - - for (var i = 0; i < 6; i++) - buffer[hdrOffset++] = address.adr[i]; - - // write the source mac address bytes - for (var i = 0; i < 6; i++) - buffer[hdrOffset++] = _deviceMac[i]; - - // the next 2 bytes are used for the packet length - buffer[hdrOffset++] = (byte)(((dataLength + 3) & 0xFF00) >> 8); - buffer[hdrOffset++] = (byte)((dataLength + 3) & 0xFF); - - // DSAP and SSAP - buffer[hdrOffset++] = 0x82; - buffer[hdrOffset++] = 0x82; - - // LLC control field - buffer[hdrOffset] = 0x03; - - lock (_device) - { - _device.SendPacket(buffer, dataLength + HeaderLength); - } - - return dataLength + HeaderLength; - } - - public override void Dispose() - { - lock (_device) - _device.Close(); - } - - public override string ToString() - { - return "Ethernet"; - } - - private LibPcapLiveDevice Open() - { - var devices = LibPcapLiveDeviceList.Instance.Where(dev => dev.Interface != null); - - if (!string.IsNullOrEmpty(_deviceName)) // specified interface - { - try - { - var device = devices.FirstOrDefault(dev => dev.Interface.FriendlyName == _deviceName); - device?.Open(DeviceMode.Normal, 1000); // 1000 ms read timeout - return device; - } - catch - { - return null; - } - } - foreach (var device in devices) - { - device.Open(DeviceMode.Normal, 1000); // 1000 ms read timeout - if (device.LinkType == LinkLayers.Ethernet - && device.Interface.MacAddress != null) - return device; - device.Close(); - } - - return null; - } - - private void CaptureThread() - { - _device.NonBlockingMode = true; // Without that it's very, very slow - while (true) - { - try - { - var packet = _device.GetNextPacket(); - if (packet != null) - OnPacketArrival(packet); - else - Thread.Sleep(10); // NonBlockingMode, we need to slow the overhead - } - catch - { - return; - } // closed interface sure ! - } - } - - private bool _isOutboundPacket(IList buffer, int offset) - { - // check to see if the source mac 100% - // matches the device mac address of the local device - - for (var i = 0; i < 6; i++) - { - if (buffer[offset + i] != _deviceMac[i]) - return false; - } - - return true; - } - - private static byte[] Mac(byte[] buffer, int offset) - { - var b = new byte[6]; - Buffer.BlockCopy(buffer, offset, b, 0, 6); - return b; - } - - private void OnPacketArrival(RawCapture packet) - { - // don't process any packet too short to not be valid - if (packet.Data.Length <= 17) - return; - - var buffer = packet.Data; - var offset = 0; - - // Got frames send by me, not for me, not broadcast - var dest = Mac(buffer, offset); - if (!_isOutboundPacket(dest, 0) && dest[0] != 255) - return; - - offset += 6; - - // source address - var bacSource = new BacnetAddress(BacnetAddressTypes.Ethernet, 0, Mac(buffer, offset)); - offset += 6; - - // len - var length = buffer[offset] * 256 + buffer[offset + 1]; - offset += 2; - - // 3 bytes LLC hearder - var dsap = buffer[offset++]; - var ssap = buffer[offset++]; - var control = buffer[offset++]; - - length -= 3; // Bacnet content length eq. ethernet lenght minus LLC header length - - // don't process non-BACnet packets - if (dsap != 0x82 || ssap != 0x82 || control != 0x03) - return; - - InvokeMessageRecieved(buffer, HeaderLength, length, bacSource); - } -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/IBacnetSerialTransport.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/IBacnetSerialTransport.cs deleted file mode 100644 index 3157ba8..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/IBacnetSerialTransport.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace System.IO.BACnet; - -public interface IBacnetSerialTransport : IDisposable -{ - int BytesToRead { get; } - - void Open(); - void Close(); - int Read(byte[] buffer, int offset, int length, int timeoutMs); - void Write(byte[] buffer, int offset, int length); -} diff --git a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/IBacnetTransport.cs b/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/IBacnetTransport.cs deleted file mode 100644 index 67d4ad6..0000000 --- a/addons/EGFramework/Third_Part_SourceCode/BacNetPlugin/Transport/IBacnetTransport.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace System.IO.BACnet; - -public interface IBacnetTransport : IDisposable -{ - byte MaxInfoFrames { get; set; } - int HeaderLength { get; } - int MaxBufferLength { get; } - BacnetAddressTypes Type { get; } - BacnetMaxAdpu MaxAdpuLength { get; } - - void Start(); - BacnetAddress GetBroadcastAddress(); - bool WaitForAllTransmits(int timeout); - int Send(byte[] buffer, int offset, int dataLength, BacnetAddress address, bool waitForTransmission, int timeout); - - event MessageRecievedHandler MessageRecieved; -}