Giter VIP home page Giter VIP logo

bacnet's Introduction

.NET library for BACnet

License: MIT NuGet version Donate

This library was originally developed by Morten Kvistgaard with a lot of contributions from F. Chaxel and Steve Karg and the BACnet Stack (in C). It is used as a core library in YABE (Yet Another BACnet Explorer). It has been forked here from the SourceForge SVN source, splitted into separate repositories and made available to download via NuGet.

How to use it

You can get it by grabbing the latest NuGet package.

Getting Started

See examples to learn how to use this library.

bacnet's People

Contributors

cemremengu avatar darkstards9 avatar discolai avatar gralin avatar helynranta avatar ladsoft avatar msschl avatar patrick-3000 avatar sam1308 avatar shaggygi avatar skarg avatar yarektyshchenko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bacnet's Issues

MSTP bacnetAdress

Hello I tried to create a bacnetAdress with MSTP protocol but there are bacnetAdress only for IP and Ethernet , any idea?
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);
        }
    }

First stab at decoding notification values

As mentioned in issue #9, here is my first stab in an attempt to decode the notification values, I used the bacnet-stack C library implementation as a direct conversion. The modification of BacnetPropetyState causes a breaking change for bacapp_encode_property_state.

Any help, ideas, suggestions appreciated to take this forward.


Services.cs

/* tag 12 - event values */
switch (eventData.notifyType)
{
	case BacnetNotifyTypes.NOTIFY_ALARM:
	case BacnetNotifyTypes.NOTIFY_EVENT:

		if (ASN1.decode_is_opening_tag_number(buffer, offset + len, 12))
			len++;
		else
			return -1;

		if (ASN1.decode_is_opening_tag_number(buffer, offset + len, (byte)eventData.eventType))
			len++;
		else
			return -1;

		switch (eventData.eventType)
		{
			case BacnetEventTypes.EVENT_CHANGE_OF_STATE:

				len += ASN1.bacapp_decode_context_property_state(buffer, offset + len, 0, out var changeOfState_newState);
				break;

                        // and many more cases... :(
		}

		break;

	//In cases other than alarm and event
	//there's no data, so do not return an error
	//but continue normally
	case BacnetNotifyTypes.NOTIFY_ACK_NOTIFICATION:
	default:
		break;
}

ASN1.cs

public static int bacapp_decode_context_property_state(byte[] buffer, int offset, byte tagNumber, out BacnetPropetyState value)
{
	int len = 0;
	int sectionLength;
	value = new BacnetPropetyState();

	if (decode_is_opening_tag_number(buffer, offset + len, tagNumber))
	{
		len++;
		sectionLength = bacapp_decode_property_state(buffer, offset + len, out value);

		if (sectionLength == -1)
		{
			len = -1;
		}
		else
		{
			len += sectionLength;

			if (decode_is_closing_tag_number(buffer, offset + len, tagNumber))
			{
				len++;
			}
			else
			{
				len = -1;
			}
		}
	}
	else
	{
		len = -1;
	}

	return len;
}

private static int bacapp_decode_property_state(byte[] buffer, int offset, out BacnetPropetyState value)
{
	int len = 0;
	uint len_value_type;
	int section_length;
	uint enumValue;
	byte tagnum;

	value.tag = 0;
	value.state = new BacnetPropetyState.State();

	section_length = decode_tag_number_and_value(buffer, offset + len, out tagnum, out len_value_type);

	if (section_length == -1)
	{
		return -1;
	}

	value.tag = 0;

	value.tag = (BacnetPropetyState.BacnetPropertyStateTypes)tagnum;
	len += section_length;

	switch (value.tag)
	{
		case BacnetPropetyState.BacnetPropertyStateTypes.BOOLEAN_VALUE:
			value.state.boolean_value = len_value_type == 1 ? true : false;
			break;

		case BacnetPropetyState.BacnetPropertyStateTypes.BINARY_VALUE:
			section_length = decode_enumerated(buffer, offset + len, len_value_type, out enumValue);

			if (section_length == -1)
			{
				return -1;
			}

			value.state.binaryValue = (BacnetPropetyState.BACNET_BINARY_PV)enumValue;
			break;

		case BacnetPropetyState.BacnetPropertyStateTypes.EVENT_TYPE:

			section_length = decode_enumerated(buffer, offset + len, len_value_type, out enumValue);

			if (section_length == -1)
			{
				return -1;
			}
			value.state.eventType = (BacnetEventTypes)enumValue;
			break;

		case BacnetPropetyState.BacnetPropertyStateTypes.STATE:

			section_length = decode_enumerated(buffer, offset + len, len_value_type, out enumValue);

			if (section_length == -1)
			{
				return -1;
			}
			value.state.state = (BacnetEventStates)enumValue;
			break;

		case BacnetPropetyState.BacnetPropertyStateTypes.UNSIGNED_VALUE:

			section_length = decode_unsigned(buffer, offset + len, len_value_type, out value.state.unsignedValue);

			if (section_length == -1)
			{
				return -1;
			}
			break;

		default:
			return -1;
	}

	len += section_length;

	return len;
}

BacnetPropertyState.cs

public struct BacnetPropetyState
{
	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 enum BACNET_BINARY_PV
	{
		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 */
	}

	public BacnetPropertyStateTypes tag;
	public State state; // !!!BREAKING CHANGE!!!! for encoding bacapp_encode_property_state

	public struct State
	{
		public bool boolean_value;
		public BACNET_BINARY_PV binaryValue;
		public BacnetEventTypes eventType;
		public BacnetEventStates state;
		public uint unsignedValue;
	}

	public override string ToString()
	{
		return $"{tag}:{state}";
	}
}

useExclusivePort & dontFragment set to true don't work from Docker container

I created a console app that runs from a docker container.
I have 2 bacnet gateways, one that doesn't require useExclusivePort & dontFragment, and it works fine, but the other one does require useExclusivePort & dontFragment to be set to true, and I keep getting the error "No response within 00:00:01".

I have no idea where to look, any suggestion appreciated!

How to use ReadPropertyMultipleRequest

I'm starting to go round in circles with ReadPropertyMultipleRequest...

My understanding is that I need to pass in a BacnetAddress and a List<BacnetReadAccessSpecification>. Each BacnetReadAccessSpecification has a BacnetObjectId and a List<BacnetPropertyReference>. And a BacnetPropertyReference is a bacnet property ID (a uint, e.g. 85 for PRESENT_VALUE) and an array index.

So, as an example, if I wanted to get PROP_PRESENT_VALUE, PROP_DESCRIPTION, PROP_UNITS for some ANALOG_VALUE of instance 0 I think I should do this:

var adr = new BacnetAddress(BacnetAddressTypes.IP, "192.168.0.123:47808");
var objId = new BacnetObjectId(BacnetObjectTypes.OBJECT_ANALOG_VALUE, 0);

var propRefs = new List<BacnetPropertyReference>();
propRefs.Add(new BacnetPropertyReference(85, 0));    // PROP_PRESENT_VALUE
propRefs.Add(new BacnetPropertyReference(28, 1));    // PROP_DESCRIPTION
propRefs.Add(new BacnetPropertyReference(117, 2));   // PROP_UNITS

var spec = new BacnetReadAccessSpecification(objId, propRefs);

var specs = new List<BacnetReadAccessSpecification>();
specs.Add(spec);

IList<BacnetReadAccessResult> results;
bacnet_client.ReadPropertyMultipleRequest(adr, specs, out results);

This is always giving me an error ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY. I'm probably interpreting the purpose of the various objects the wrong way.

Can someone help out?

Bacnet Server sends too many unconfirmed COV notifications

Hello!
I have bacnet client (192.168.5.80) and bacnet server (192.168.5.81).

Bacnet client sends subscribe COV request with params: SubscribeCOVRequest(..., cancel = false, issueConfirmedNotifications=false, lifetime = 600) one a minute, life time 10 minutes.

After client send 'write property', bacnet server sends response and then many the same unconfirmed messages. Sometimes 5, sometimes 10 or 20, 30.

For client and server i use the same library (BACnet).

1

Attached wireshark file in zip format.
Test_BacNet.zip

System.ObjectDisposedException in BacnetIpUdpProtocolTransport.OnReceiveData

Hi,
We keep reciving System.ObjectDisposedException that is not caught by try catch for some reason, causing our whole application to crash (as this runs on a separate thread). Looking at the OnReceiveData function, it's pretty much completely wrapped in try catch with should catch it. Except the first line:

"private void OnReceiveData(IAsyncResult asyncResult)
{
var connection = (UdpClient)asyncResult.AsyncState;"

Which from documentation and trying my self to make it throw the exception doesn't seem to be the cause.
We have only got this error from compiled code from a client, and haven't been able to cause/catch it ourselves.

Any idรฉas?

Stacktrace below:
Description: The process was terminated due to an unhandled exception.
Exception Info: System.ObjectDisposedException
at System.Net.Sockets.UdpClient.BeginReceive(System.AsyncCallback, System.Object)
at System.IO.BACnet.BacnetIpUdpProtocolTransport.OnReceiveData(System.IAsyncResult)
at System.Net.LazyAsyncResult.Complete(IntPtr)
at System.Net.ContextAwareResult.CompleteCallback(System.Object)
at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
at System.Net.ContextAwareResult.Complete(IntPtr)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(System.Object, IntPtr)
at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)

Error when subscribing data from PLC..

Hi, I am not so good in BACnet. But here is the problem.
We have a PLC which is trying to subscribe AnalogValue parameters from a Windows service which is based on this library. The problem is that the server decodes an error after bacnetClient.Notify function. The error comes in this function in BacnetClient class:
private void OnRecieve(IBacnetTransport sender, byte[] buffer, int offset, int msgLength, BacnetAddress remoteAddress)
The buffer[] contains the following data:
[0] 129
{1] 10
[2] 0
[3] 13
[4] 1
[5] 0
[6] 80
[7] 1
[8] 1
[9] 145
[10] 5
[11] 145
[12] 7
The offset parameter is 6 which points to 80 => Error
The subscribing works with Yabe.. but not with the PLC because this error.

Decoding negative integer values with a length of 3 byte (24bit) is not correct

A negative integer value of 3 bytes in length (for example -8336180) is incorrectly decoded from BACnet. That values are decoding in C# to an integer type (32 bit), but the highest 8 bits are not set to TRUE. That's necessary to get a negative 2's complement integer value.

Original code in ASN1.cs (starting at line 1176):

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;
    return 3;
}

Modified code that should be work:

public static int decode_signed24(byte[] buffer, int offset, out int value)
{
    value = (buffer[offset + 0] << 16) & 0x00ff0000;
    if ((value & 0x800000) != 0)
        unchecked { value |= (int)0xff000000; }
    value |= (buffer[offset + 1] << 8) & 0x0000ff00;
    value |= buffer[offset + 2] & 0x000000ff;
    return 3;
}

Weekday in trendlog

Hi,
When I use a trend log object and I try to read the data I'm getting weekday errors. In wireshark you can see that sunday is given day 0 instead of 7.

I have changed something in the Serialize/ASN1.cs, encode_bacnet_date

    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);
        int DayOfWeek = (int)value.DayOfWeek;
            if (DayOfWeek == 0) DayOfWeek = 7;
        buffer.Add((byte)DayOfWeek);
    }

After I changed this I still cannot read a trendlog (only with YABE it works) , but my weekday errors are gone

OBJECT_BINARY_VALUE write data error

Hello, first of all thank you for your provide BACnet for C#,I met problem in use process, would you please help me to look at. I use OBJECT_BINARY_VALUE write data happen error: Error from device: ERROR_CLASS_PROPERTY - ERROR_CODE_INVALID_DATA_TYPE, thank you very much!
BacnetObjectId oBacnetObjectId = new BacnetObjectId(); oBacnetObjectId.Type = BacnetObjectTypes.OBJECT_BINARY_VALUE; oBacnetObjectId.Instance = 123456; bool bIsWrite = oBacnetClient.WritePropertyRequest(oBacnetAddress, oBacnetObjectId, BacnetPropertyIds.PROP_PRESENT_VALUE, new List<BacnetValue> { new BacnetValue(true) });

Need Routing Info

on BIP the standard way to handle multiple device objects internal to one physical server device seems to be to have a router and set the source/destination fields appropriately. In particular packets sourced from the device holds a SOURCE field in the NPDU header and coming into the device the DESTINATION field in the NPDU header tells which device to route to (the router device itself reacts to an empty destination and fills in an empty source).

To access messages properly then I need access to the destination field on incoming messages; but I don't seem to have that. F Chaxel added the incoming SOURCE address to the BacnetAddress structure (as the RoutedSource) and I'm proposing you do similar for the incoming DESTINATION address. E.g add a RoutedDestination field in the BacnetAddress structure, and initialize it at the same time the RoutedSource field is initialized. Then I can use the destination address to do the appropriate routing.

Technically speaking there may be further issues with actually sending the source on various messages (e.g. I'm not sure if I can specify a SOURCE for functions like SimpleAck or ComplexAck). But I'm not so worried about that as I can do simple workarounds for those kinds of issues at least in the short term.

It would be really helpful though if you could add something like a RoutedDestination field to the BacnetAddress structure, then I think I would have enough to be able to make a switch to the nuget package.

More tests needed

Now that we started to add tests, we should add more. Currently, DotCover reports the following coverage:

bacnet_testcoverage

It should be relatively easy to improve on this with back to back tests (like in EventNotificationTests/should_raise_oneventnotify_when_sending_changeoflifesafety_data) which provides much coverage with little effort.

To make sure that we are complying with the standard, more tests like ServiceTests/should_encode_logrecord_according_to_ashrae_example should be added - which can only be done by people having access to the documents.

Any takers? I'll work on additional tests for EventNotifications, covering other EventValues next. I'd suggest to comment here who is working on what to coordinate our efforts, but @gralin may have a better idea?! ๐Ÿ˜‰

VMAC length 6 support

Are VMAC addresses up to length 6 currently supported? It does not currently seem to be the case based on looking at the BacnetAddress class. The devices we need to talk to which have VMACs of length 6 are going through a Siemens bacnet router. Is there a recommended way to use this library for these types of devices?

Happy to help provide support where I can.

Race condition within BacnetAsyncResult

In the following code it is possible for the event handlers, in my case, it was the OnSimpleAck to be called before the instantiation of the ManualResetEvent.

This results in the possibility of a NullReferenceException, and can be fixed by moving the creation of the ManualResetEvent prior to event registration.

        public BacnetAsyncResult(BacnetClient comm, BacnetAddress adr, byte invokeId,
            byte[] transmitBuffer, int transmitLength, bool waitForTransmit, TimeSpan 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);
        }

Read Properties of devices on a BACNET IP router

Has anyone been able to successfully read properties from devices on a BACNET IP router?

I am able to read properties of the BACNET router and I can pull the PROP_OBJECT_LIST which returns all the instance ids of the devices on the router. However, when I try to read properties with the instance Ids of the devices from the PROP_OBJECT_LIST I get unknown property errors.

Am I doing something wrong? How do you read from devices attached to bacnet router?

Discovering on non-0.0.0.0 ip not working

We have BACnet implemented in a .NET core application running in Docker.
BACnet runs on port 47808 on the host machine. So when I want to discover devices I use the IP of the host machine. But when I do that, it returns an error. When I check the IP and port with NMap (from within the Docker container), it shows that the port is available with service "BACnet" behind it.`

I recieve the following error:

{
    "ClassName": "System.Net.Sockets.SocketException",
    "Message": "Cannot assign requested address",
    "Data": null,
    "InnerException": null,
    "HelpURL": null,
    "StackTraceString": "   at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, String callerName)\n   at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)\n   at System.Net.Sockets.Socket.Bind(EndPoint localEP)\n   at System.IO.BACnet.BacnetIpUdpProtocolTransport.Open()\n   at System.IO.BACnet.BacnetIpUdpProtocolTransport.Start()\n   at System.IO.BACnet.BacnetClient.Start()\n   at AgentCore.Services.BACnetDiscoveryService.Discover() in /app/AgentCore/Services/BACnetDiscoveryService.cs:line 41\n   at AgentApi.Controllers.DevicesController.Get() in /app/AgentApi/Controllers/DevicesController.cs:line 30",
    "RemoteStackTraceString": null,
    "RemoteStackIndex": 0,
    "ExceptionMethod": null,
    "HResult": -2147467259,
    "Source": "System.Net.Sockets",
    "WatsonBuckets": null,
    "NativeErrorCode": 99
}

Can someone enlighten me and point me in the right direction? Or is it just not possible with the library to use another ipaddress than 0.0.0.0?

Segmentation NotSupported Exception

Hi,

I'm getting a exception, probably caused by segmentation.
there is a timeline for the implementation of segmentation ?

System.Transactions Critical: 0 : http://msdn.microsoft.com/TraceCodes/System/ActivityTracing/2004/07/Reliability/Exception/UnhandledUnhandled exceptionBacnetConsoleApp.exeSystem.NotSupportedException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089Specified method is not supported. at System.IO.BACnet.BacnetTransportBase.set_MaxInfoFrames(Byte value)
at System.IO.BACnet.BacnetClient.&lt;&gt;c__DisplayClass270_0.&lt;HandleSegmentationResponse&gt;b__0(Object o)
at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()System.NotSupportedException: Specified method is not supported.
at System.IO.BACnet.BacnetTransportBase.set_MaxInfoFrames(Byte value)
at System.IO.BACnet.BacnetClient.&lt;&gt;c__DisplayClass270_0.&lt;HandleSegmentationResponse&gt;b__0(Object o)
at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

Receiving events (OnEventNotify) is not working

With BacnetClient I have used OnEventNotify event, but it seems that it is never called. However, OnUnconfirmedServiceRequest does work.
I have used "AnotherStorageImplementation" example which is sending those events.

I think the problem lies in Serialize\Services.cs DecodeEventNotifyData method.

How to reproduce

Create new C# console, install BACnet.Core via NuGet.
Write code, such as:

class Program
{
    static void Main(string[] args)
    {
        BacnetClient client = new BacnetClient();
        client.OnIam += Client_OnIam;
        client.OnEventNotify += Client_OnEventNotify;
        client.OnUnconfirmedServiceRequest += Client_OnUnconfirmedServiceRequest;
        client.Start();

        Console.ReadLine();
    }

    private static void Client_OnUnconfirmedServiceRequest(BacnetClient sender, BacnetAddress adr, BacnetPduTypes type, BacnetUnconfirmedServices service, byte[] buffer, int offset, int length)
    {
        Console.WriteLine("Client_OnUnconfirmedServiceRequest");
    }

    private static void Client_OnEventNotify(BacnetClient sender, BacnetAddress adr, byte invokeId, BacnetEventNotificationData eventData, bool needConfirm)
    {
        Console.WriteLine("Client_OnEventNotify");
    }

    private static void Client_OnIam(BacnetClient sender, BacnetAddress adr, uint deviceId, uint maxAPDU, BacnetSegmentations segmentation, ushort vendorId)
    {
        Console.WriteLine("Got I am.");
    }
}

And now test it with "AnotherStorageImplementation" example.
Client_OnEventNotify is never called.

Edit:
It seems like there is a problem in the part where it is "tag 12 - event values".
ASN1.decode_is_closing_tag_number is false, and then it returns -1.

Raspberry Pi Example Has Exception - Platform not supported

I tried to run the RP example with Mono, and with .Net Core 2.2 Both trials return similar message at this line

bacnet_client.Start();

platform not supported exception socket.iocontrol, handles Windows-specific control codes and is not supported on this platform.

How to Stop Bacnet Activity?

static void StartActivity(int? bacNetServerId, out BacnetClient bacnet_client)
        {
            var port = Convert.ToInt32(bacNetServerId.ToString());
            // Bacnet on UDP/IP/Ethernet
            bacnet_client = new BacnetClient(new BacnetIpUdpProtocolTransport(port, false));
            try
            {   
                bacnet_client.Start();    
               // go

                // Send WhoIs in order to get back all the Iam responses :  
                bacnet_client.OnIam += new BacnetClient.IamHandler(handler_OnIam);

                bacnet_client.WhoIs();
            }
            catch(Exception ex)
            {
                new WebServiceDataAccess().logger.LogError(ex, "StartActivity");
            }
        }

How to stop this activity?(Start()/WhoIs/WhoIs())
How to dispose bacnet_client object? I am getting port permissions denied error.

MSTP Read/write example

I didn't see any examples for read/write MSTP devices including the ip address, network number, MAC address, and instance id.

Can you create an example?

WriteScalarValue issue

I got an exception unhandled when I was trying to write a value to multi-state-value. It say "System.Exception: 'Error from device: ERROR_CLASS_PROPERTY - ERROR_CODE_INVALID_DATA_TYPE'"
Here is my code.
uint bacnetinstaid = Convert.ToUInt32(changemode.Bacnet_Instance_ID); int bacnetid = Convert.ToInt32(changemode.Bacnet_Instance_ID); WriteScalarValue(deviceid, new BacnetObjectId(BacnetObjectTypes.OBJECT_MULTI_STATE_VALUE, bacnetinstaid), BacnetPropertyIds.PROP_PRESENT_VALUE,new BacnetValue(2) );
What am I doing wrong here? also what does invalid data type mean?

Could not run BACShark in parallel

Hi,

I am using this library.

When I use it as: BacnetIpUdpProtocolTransport udp_transport = new BacnetIpUdpProtocolTransport(c_bacnetPort,false) it works perfect but the problem is that I have 2 network cards on my PC and sometimes it sends the data through the wrong card.
I tried: BacnetIpUdpProtocolTransport udp_transport = new BacnetIpUdpProtocolTransport(c_bacnetPort,false,false,1472,bacnet_IP); here the data is sent on the specified card (mentioned in bacnet_IP) however it is reserving the network card (i am not able to launch the BacShark to check the result, I can see it via the yabe application, but I have to use BACShark...).

c_bacnetPort is always equal to 47808
bacnet_IP is the IP of my PC, let's say "10.110.45.20"
the other network card IP is: 2.1.1.1

Any help to get out of this please ?

Thank you
Rony

Schedule Object write

Hi,
I'm trying to update the value of a Schedule Object but I'm experiencing an issue.

This is the code snippet:
Client.WritePropertyRequest(new BacnetAddress(BacnetAddressTypes.IP, bacnetServer.Url+":"+bacnetServer.Port),
bacnetSchedulerIdentifier, BacnetPropertyIds.PROP_WEEKLY_SCHEDULE, valueWeeklyScheduleList);

the thrown Exception says "I cannot encode this".
Looking at source code it looks like this kind of objects are not managed, am I wrong? Have you ever worked with schedule objects before?

Thanks

How to change the Source port ?

Hi,

Each time I run the application i have a new random source port while the destination port is always 47808.
How can I fix the source port ? I need it to be 47808 as well.

Thank you

Cant figure out how to trigger event notification

I tried everything (including setting an event enrollment with a notification class) but cannot figure out how to trigger event notification

bacnet_client.OnEventNotify += new BacnetClient.EventNotificationCallbackHandler(handler_OnEventNotify);

Is this the right way to use it? Any help is greatly appreciated and thanks for this great library!

Method overload of ReadRangeRequest() for RR_BY_TIME missing

Hello,

my requirements include reading trend log data starting from a certain point in time onwards. I can't use the ReadRangeRequest() method as I don't know from which index on I have to read data.

Therefore, I would like to ask if you could provide a method overload of the ReadRangeRequest() method, taking a DateTime from parameter? Seems like EncodeReadRange already supports RR_BY_TIME, so it would basically be necessary to propagate this enum to the method signature.

Furthermore, I'd like to ask if there is any documentation regarding this library available? I've seen some examples, but those do not represent a proper documentation.

Best regards,

compile fail

I downloaded bacnet.core 1.0.30 version from nuget and wrote simple codes to send whois.
But When I compile the code I faced the error message below.

The type or namespace name 'BACnet' does not exist in the namespace 'System.IO' (are you missing an assembly reference?)

Of course I added the code "using System.IO.BACnet;"
I think it's namespace collision. How do I solve this problem.

Abort from device, reason: BUFFER_OVERFLOW

We have a device that has over a thousand objects and we get an overflow when trying to detect them using the code provided in the ObjectBrowseSample example.

Unhandled exception. System.Exception: Abort from device, reason: BUFFER_OVERFLOW
   at System.IO.BACnet.BacnetClient.ReadPropertyRequest(BacnetAddress adr, BacnetObjectId objectId, BacnetPropertyIds propertyId, IList`1& valueList, Byte invokeId, UInt32 arrayIndex)
   at System.IO.BACnet.BacnetClient.<>c__DisplayClass215_0.<ReadPropertyAsync>b__0()
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.<>c.<.cctor>b__274_0(Object obj)
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location where exception was thrown ---
   at Discover.Program.OnIAm(BacnetClient sender, BacnetAddress adr, UInt32 deviceid, UInt32 maxapdu, BacnetSegmentations segmentation, UInt16 vendorid) in C:\Sources\Tests\BacnetTests\Discover\Program.cs:line 27
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__139_1(Object state)
   at System.Threading.QueueUserWorkItemCallbackDefaultContext.Execute()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

Here "C:\Sources\Tests\BacnetTests\Discover\Program.cs:line 27" refers to this line

I'm no BACnet expert so I have no idea what to do, any suggestion will be appreciated ๐Ÿ‘

Thanks!

BACnetClient is not thread safe

I have two threads in a same program, each thread is executed every seconds, they call ReadPropertyRequest function.
First thread get a BinaryValue (0 or 1), second thread get an AnalogValue (between 20 and 30).
Sometimes ReadPropertyRequest of BinaryValue return the AnalogValue!
Can someone have a solution of my problem?
PS: i call ReadPropertyRequest because COV does'nt seem to work for me

WritePropertyRequest issue

I am trying to write a value to the Room Controller simulator, but am not getting it to work. It returns false all the time.

This is my code:

public bool WriteScalarValue(int deviceId, int typeId, int instanceId, BacnetPropertyIds property, double value)
{
    BacnetObjectId bacnetObject = new BacnetObjectId((BacnetObjectTypes)typeId, (uint)instanceId);
    BacnetValue bacnetValue = new BacnetValue(Convert.ToSingle(value));

    // Looking for the device
    Device device = _deviceService.GetByName(deviceId.ToString(), _currentNetwork);
    if (device == null)
    {
        return false;  // not found
    }
    BacnetAddress bacnetAddress = new BacnetAddress(BacnetAddressTypes.IP, device.Ip + ":" + device.Port);

    // Property Write
    BacnetValue[] NoScalarValue = { bacnetValue };
    if (bacnet_client.WritePropertyRequest(bacnetAddress, bacnetObject, property, NoScalarValue) == false)
    {
        return false;
    }

    return true;
}

The BacnetObjectId I am trying to write to is OBJECT_ANALOG_VALUE:0, which results in the Setpoint.value property.

Am I missing something?

Bacnet Client in Failover Clustering

Hi

We have configured Windows failover clustered network IP, Bacnet Client API is not discovering in yabe explorer.

Please Suggest any changes to be done in Bacnet client dll.

Please do the needful

Abort from device: 4

For a couple of devices a try to talk with, I get the following error when using the ReadPropertyRequest function: "Abort from device: 4". I looked the byte up and I saw that it means: Invalid APDU in this state.
Can I adjust this state in the driver?

Priority Array read throwing ERROR CODE UNKNOWN PROPERTY

I'm able to read properties and values from the object list without issue until I try to read the priority array.

Code below and screenshot of console output attached.

public BacnetDevice ReadDeviceProperties(BacnetDevice objDevice)
{
  Bacnet_client.ReadPropertyRequest(objDevice.Address, new BacnetObjectId(BacnetObjectTypes.OBJECT_DEVICE, objDevice.InstanceId), BacnetPropertyIds.PROP_OBJECT_LIST, out IList<BacnetValue> value_list);
  LinkedList<BacnetObjectId> object_list = new LinkedList<BacnetObjectId>();
  StringBuilder strOut = new StringBuilder();


  foreach (BacnetValue value in value_list)
  {
    if (Enum.IsDefined(typeof(BacnetObjectTypes), ((BacnetObjectId)value.Value).Type))
      object_list.AddLast((BacnetObjectId)value.Value);
  }

  foreach (BacnetObjectId object_id in object_list)
  {
    //read all properties
    IList<BacnetValue> values = null;
    IList<BacnetValue> priority = null;
    IList<BacnetValue> names = null;
    bool listProps = true;
    


    try
    {
      if (!Bacnet_client.ReadPropertyRequest(objDevice.Address, object_id, BacnetPropertyIds.PROP_OBJECT_NAME, out names))
      {

      }

      if (!Bacnet_client.ReadPropertyRequest(objDevice.Address, object_id, BacnetPropertyIds.PROP_PRESENT_VALUE, out values))
      {
        
      }

      strOut.AppendLine("Device id:" + objDevice.InstanceId + " Property Name:" + names[0] + " Value:" + values[0]);

      if (!Bacnet_client.ReadPropertyRequest(objDevice.Address, object_id, BacnetPropertyIds.PROP_PRIORITY_ARRAY, out priority))
      {

      }

      if (listProps)
        foreach (BacnetValue v in priority)
        {
          strOut.AppendLine("Priority: " + v);
        }

      continue;
    }
    catch (Exception ex)
    {
      strOut.AppendLine("Exception:" + ex.Message);
      //perhaps the 'present value' is non existing - ignore
      continue;
    }
  }
  Console.Write(strOut.ToString());
  return objDevice;
}

image

Discovered device is always offline

Using stable version 1.0.13, I can discover my bacnet server from the controller panel and upload objects. However with the latest version from master branch (at the time of posting this) there seems to be a bug.

I can discover the device (whois, iam packets look fine) but I get the error that the device is offline and cant upload the objects (or communicate with the device). Not sure what might be causing this but just dropping this here so you can investigate.

I will try to provide more details.

NetStandard Version

It would be a good solution to have a Net Standard version of the SDK. I think the only problem will be with serial port. One nice solution would be to have a base DLL compiled with Net Standard, and a Net 4.0 DLL based on that solution, adding the Serial Port MSTP implementation.
It could allow the Bacnet IP implementation on Linux, Mac, Xamarin, etc.

Event notification (alarms) not working

Hello, I implemented EventNotificationCallbackHandler and registered it under BacnetClient's OnEventNotify to recieve notifications about alarms, but I nevere recieved one. I know that I should be notified about this event, becouase Yabe is but my app is not. How can I fix this?

Thank you

Bacnet Client not discovering on Diffrent networks

Hi

I am using Bacnet client dll ver 1.1.4.0. Bacnet devices not discovering in yabe and BDT (Bacnet Discovery tool) on different Networks.
It is working for the same networks.

e.g

  1. I have 172.16.1.64 (Yabe Explorer) and 172.16.1.23 (Bacnet device) it is working fine
  2. 172.16.1.23 (Bacnet device) and 192.168.2.200 (Yabe Explorer) not discovering Bacnet Devices

Please do the needful.

Bacnet Client Notify always returns false for issueConfirmedNotifications

The current code expects a bool to be returned, presumably indicating success, however EndConfirmedNotify in this instance seems to only exit when an exception is thrown.

This results in false always being returned for confirmed notifications.

using (var result = BeginConfirmedNotify(address, subscriberProcessIdentifier, initiatingDeviceIdentifier, monitoredObjectIdentifier, timeRemaining, values, true))
                EndConfirmedNotify(result);

return false;

vs.

            using (var result = BeginConfirmedNotify(address, subscriberProcessIdentifier, initiatingDeviceIdentifier, monitoredObjectIdentifier, timeRemaining, values, true))
            {
                // the only way this should not be a success is if an exception is thrown
                EndConfirmedNotify(result);

                return result.Error != null ? false : true;
            }

bacnetClient on eth1 on raspberryPi

I use BACnet package with dotnet core 2.2 and the code works fine with linux-arm runtime, my code (F#) is quite simple
let bacnetClient = new BacnetClient(new BacnetIpUdpProtocolTransport(0xBAC0, false))
bacnetClient.Start()
However, it always runs on eth0, I want it to run on eth1 (an usb-lan adapter), is there a way to do so? Thanks

Can't JSON Deserialize BacnetAddress

I'd like to use Newtonsoft.Json to serialize and then deserialize a List
I can serialize it, but I can't deserialize it. Why doesn't BacnetAddress have a default constructor? Can it? :)

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
---> Newtonsoft.Json.JsonSerializationException: Unable to find a constructor to use for type System.IO.BACnet.BacnetAddress. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute. Path '[0].Address.net', line 1, position 19.

Bacnet BBMD Read request fail

I am facing issue while connecting and reading Bacnet device objects through BBMD configuration. Though i get response of complex-Ack i am not able to read any object values. Please check the code below what i have used to read the bacnet object and wireshark packet details.

public void ReadBacnetObject()
{
    IList<BacnetValue> Value;
    BacnetIpUdpProtocolTransport bacnetIpUdpProtocolTransport = new BacnetIpUdpProtocolTransport(0xBAC0, true);
    bacnetIpUdpProtocolTransport.Start();
    bacnetIpUdpProtocolTransport.Bvlc.AddBBMDPeer(new IPEndPoint(IPAddress.Parse("10.155.60.3"), 47808), IPAddress.Parse("255.255.255.255"));
    bacnet_client = new BacnetClient(bacnetIpUdpProtocolTransport);
    bacnet_client.OnIam += new BacnetClient.IamHandler(handler_OnIam);
    //bacnet_client.RegisterAsForeignDevice("10.155.60.3", 30);
    //bacnet_client.RemoteWhoIs("10.155.60.3");
    //Thread.Sleep(20);
    if (bacnet_client.ReadPropertyRequest(new BacnetAddress(BacnetAddressTypes.IP, "10.155.60.23:47808"),  new BacnetObjectId(BacnetObjectTypes.OBJECT_DEVICE, 2000001), BacnetPropertyIds.PROP_OBJECT_LIST, out Value) == false)
    {
        foreach (var item in Value)
        {
            Console.WriteLine($"Able to read data  {item.Tag} + {item.Value} ");
        }
    }
}

image

Kindly request check if anything went wrong?

Wrong application tag if decoding BACnetDeviceObjectPropertyReference values?

In ASN1.cs (@ line 1989):

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;
}

Would not be BACNET_APPLICATION_TAG_DEVICE_OBJECT_PROPERTY_REFERENCE the right one?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.