ela-compil / BACnet

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

How to access device without IAm response? #90

Open asyura opened 2 years ago

asyura commented 2 years ago

Hi, some device has no IAm response, how to ReadPropertyRequest with ip address and device id, thx.

lligios commented 2 years ago

try this:

BacnetAddress adr = new BacnetAddress(BacnetAddressTypes.IP, ":"); adr.RoutedSource = new BacnetAddress(BacnetAddressTypes.None, , new byte[] { ,0, 0, 0, 0, 0 }); var BacnetObject = new BacnetObjectId(BacnetObjectTypes.OBJECT_ANALOG_VALUE,0); var BacnetProperty = BacnetPropertyIds.PROP_PRESENT_VALUE; bacnet_client.ReadPropertyRequest(adr2, BacnetObject, BacnetProperty, out NoScalarValue)

mustafa-issa commented 2 years ago

@lligios can you share the full code

gralin commented 2 years ago

@mustafa-issa share your code that you made based on suggestion from @lligios and if it doesn't work we will help you fix it.

mustafa-issa commented 2 years ago

@gralin Actually, what I am trying to do is to list all devices without the OnIam delegate. The suggestion above needs a BACnet client object, that I don't know how to initialize.

lligios commented 2 years ago

this is my code example.. assume _bacnet_client as a BacnetClient Object

 internal static bool ReadScalarValueFromBacnet(
        uint device_id, 
        BacnetObjectId BacnetObject, 
        BacnetPropertyIds BacnetPropertyId, 
        ushort BacnetNetwork,  
        string BacnetIp,
        int BacnetPort,
        out BacnetValue Value)
        {
            Value = new BacnetValue(null);
            try
            {
                IList<BacnetValue> NoScalarValue;

                    BacnetAddress adr = new BacnetAddress(BacnetAddressTypes.IP,$"{BacnetIp}:{BacnetPort}");
                    byte[] bb = null;
                    if (device_id > 256)
                    {
                        bb = new byte[] { (byte)(device_id & 255  ), (byte)((device_id>>8) & 255), (byte)((device_id >> 16) & 255), (byte)((device_id >> 24) & 255), (byte)((device_id >> 32) & 255), (byte)((device_id >> 32) & 255) };
                    }
                    else
                    {
                        bb = new byte[] { (byte)(device_id & 8), 0, 0, 0, 0, 0 };
                    }
                    adr.RoutedSource = new BacnetAddress(BacnetAddressTypes.None, BacnetNetwork, bb);
                    try
                    {
                        var DeviceName = string.Empty;
                        var deviceObjId = new BacnetObjectId(BacnetObjectTypes.OBJECT_DEVICE, device_id);
                        var objectIdList = _bacnet_client.ReadPropertyAsync(adr, deviceObjId, BacnetPropertyIds.PROP_OBJECT_NAME).Result;
                        if (objectIdList.Any())
                        {
                            DeviceName = (string)objectIdList.First().Value;

                        }
                    }
                    catch (Exception ex)
                    {
                        //log   
                    }
                    if (_bacnet_client.ReadPropertyRequest(adr, BacnetObject, BacnetPropertyId, out NoScalarValue) == false)
                        return false;
                    Value = NoScalarValue[0];
                    return true;

            }
            catch (Exception ex)
            {
                //log               
            }
            return false;
        }
gralin commented 2 years ago

One simple way of reading something from a device without a need of sending WHO-IS and receiving I-AM is this:

var client = new BacnetClient();
client.Start();

var deviceAddress = new BacnetAddress(BacnetAddressTypes.IP, "192.168.1.2");
var deviceObject = new BacnetObjectId(BacnetObjectTypes.OBJECT_ANALOG_VALUE, 1);
var presentValue = await client.ReadPropertyAsync(deviceAddress, deviceObject, BacnetPropertyIds.PROP_PRESENT_VALUE);

Console.WriteLine(presentValue.Single().Value);

If you have more complex scenario then you might want to fiddle with the deviceAddress and set its RoutedSource property like @lligios suggested