ela-compil / BACnet

BACnet protocol library for .NET :satellite:
https://www.nuget.org/packages/bacnet/
MIT License
215 stars 95 forks source link

Notification Class not receiving all notifications in .Net 6.0 Windows/Linux #132

Open Zedstron opened 9 months ago

Zedstron commented 9 months ago

Hi there, I am using this library to create a BACnet application for Linux using .Net 6.0, such that the code structure is following.

The main Engine.cs class

using System.IO.BACnet;
using System.IO.BACnet.Storage;
using System.Threading.Channels;

namespace BACnet_Engine
{
    public class Engine
    {
        private readonly BacnetClient _client;
        private readonly DeviceStorage _storage;

        public Engine(int port) 
        {
            var transport = new BacnetIpUdpProtocolTransport(port, false, false, 1472, BASE_IP);
            _client = new BacnetClient(transport);
        }

        public async Task Start() 
        {
            try
            {
                _client.OnIam += OnIAm;
                _client.OnWhoIs += OnWhoIs;
                _client.OnEventNotify += OnEventNotify;

                _client.Start();
                _client.Iam(_storage.DeviceId, new BacnetSegmentations());

                _client.whoIs();

                Console.WriteLine($"BACnet engine is now running {_storage.DeviceId} of Vendor ID {_client.VendorId}!");

                await new TaskCompletionSource<object>().Task;
            }
            catch (Exception ex) 
            {
                Console.WriteLine(ex.ToString());
            }
        }

        private async void OnIAm(BacnetClient sender, BacnetAddress adr, uint device_id, uint max_apdu, BacnetSegmentations segmentation, ushort vendor_id)
        {
            ushort net = adr.RoutedSource?.net > 0 ? adr.RoutedSource.net : (ushort)0;
            string mac = adr.RoutedSource?.net > 0 ? adr.RoutedSource.ToString() : String.Empty;

            Console.WriteLine($"Device Discovered in the network {device_id} AT {adr} Net {net} MAC {mac}");
        }

        private void OnEventNotify(BacnetClient sender, BacnetAddress adr, byte invokeId, BacnetEventNotificationData eventData, bool needConfirm)
        {
            Console.WriteLine($"New Event received from {adr} which is {eventData.fromState} -> {eventData.toState} Ack needed {needConfirm}");

            if (needConfirm)
                sender.SimpleAckResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_EVENT_NOTIFICATION, invokeId);
        }

        private void OnWhoIs(BacnetClient sender, BacnetAddress adr, int lowLimit, int highLimit)
        {
            Console.WriteLine($"{Colors.BLUE} Got WhoIS Request From [{adr}] {Colors.RESET}");
            if (lowLimit != -1 && _storage.DeviceId < lowLimit) return;
            else if (highLimit != -1 && _storage.DeviceId > highLimit) return;
            else if (adr.ToString() != BASE_IP) return;
            sender.Iam(_storage.DeviceId, new BacnetSegmentations());
        }
    }
}

and this is how to keep the console application running I wrote Programe.cs file

class Program
{
    static void Main()
    {
        Engine e = new(0xBAC0);
        Task.Run(async () => await e.Start()).Wait();
    }
}

Now that it is working good at least no errors and shows the notifications as I am using the BACnet Device Simulator by Scada to test the application, I defined the notification class a point and added the id of this application into the recipient list of the notification class.

The Actual Strange Problem

The Actual problem is here, it does not show all notifications instead I don't know the patterns some notifications are shown, some are shown late, some I think are missed.

On the other hand, I also added the YABE as recipient to test if it's my application or the simulator problem, the Yabe is working perfectly fine, it is showing every update of notification, what I am doing wrong, I inspected the code of YABE there is no change in how I am receiving & acknowledging the notification. The only diff YABE is using GUI to display I am using console.

Your help is greatly appreciated in advance!