JoelBender / bacpypes

BACpypes provides a BACnet application layer and network layer written in Python for daemons, scripting, and graphical interfaces.
MIT License
296 stars 128 forks source link

Accessing multiple BACnet device instances under the same IP address #159

Open mehtajn opened 6 years ago

mehtajn commented 6 years ago

Hello,

I am dealing with a situation where I need to read data from multiple BACnet device instances that are all on the same IP address. It is a software where multiple virtual BACnet device instances can be created each with their own set of objects. It is possible to assign a network number.

I am not able to understand how can I read data from a particular BACnet device instance (using the device id) when running ReadProperty.py. I have tried but I am not able to figure out how to pass the 'BACnet device id' as the 'addr'.

I am able to read data using the IP address of the server if only 1 BACnet device instance is created using 'read 192.168.1.202 analogValue 192 presentValue' But if there are multiple BACnet devices with similar object instance numbers they can only be resolved by the device id. Hence how do I pass the device id while querying data for an object?

JoelBender commented 6 years ago

The APDU requests that are created are given a BACnet address, in your case it will be the network number of the BACnet network on the "other side" of the BACnet/IP router. BACnet provides the Who-Is and I-Am services to "discover" the network address given the device instance number. When you generate a Who-Is request, the BACnet address in the I-Am responses will contain the combination of network number and MAC address.

Let's say that your IP devices are on IP Network 192.168.1.0/24 which is BACnet network 10, and the BACnet/IP router goes to virtual network 11, and the MAC addresses on the virtual network are simple octets like they would be for an MS/TP or ARCNET network, then your read command would say read 11:15 analogValue 5 presentValue and the stack will discover that 192.168.1.202 is the router to network 11 (if the network discovery doesn't work, let me know).

There is a BACpypes sample application BBMD2VLANRouter.py which is very similar to your router, with the additional twist that the IP side also acts like a BBMD.

The idea of being able to provide a device object identifier like ('device', 712) and have the library do the Who-Is/I-Am work automagically on your behalf is interesting, basically overloading the pduSource and pduDestination properties to be Address instances or ObjectIdentifier values.

mehtajn commented 6 years ago

Thank you for your inputs. I will try using the network number and the MAC address of BACnet MSTP devices behind a router. However I have a BACnet IP device server in which I can create multiple virtual devices with unique BACnet device ids. All the virtual devices I create will have the same network number because and since it they are purely BACnet IP there is no MAC id. Would there be a method to access them in such a situation?

JoelBender commented 6 years ago

All the virtual devices need to have unique BACnet addresses, so your BACnet IP device server will be a router to a virtual network of virtual devices like the sample. There is a new IP2VLANRouter.py in case the other sample did more than you needed.

Hareesh1708 commented 3 years ago

Hi @JoelBender @ChristianTremblay , can you suggest some simple method for writing an analog value to a device and then reading that value from another device. I have tried out WhoIsIAm Service and it is working fine for me. Now I want to read and write to devices.

JoelBender commented 3 years ago

There is a sample application ReadWriteProperty.py that you can run on as many devices as you would like. Let's say you are running it on a device A and sending Write Property requests to a device B, you can run the same application on device C and send read requests to B and see the results.

Hareesh1708 commented 3 years ago

Hi @JoelBender , tried the ReadWriteProperty.py. Really helps. Though I can only read the device properties (as in .ini file). I am not able to read the binaryValue or analog value. Where can I find the list of property values I can read? And also please tell the command to write to a specific device. Not able to find it. ( I am running my laptop and another PC as BACnet devices) Thanks

Hareesh1708 commented 3 years ago

image

Hi @JoelBender , I am trying to read , like mentioned in the above image. I am not sure whether it has binary value or analog value. 600 is my BACnet device number. What does 15 mean here? I am new to BACnet. Sorry for asking basic questions. And can you also provide me what is the correct command for write property. Is it similar to read ? just replace read with write?

Thanks in advance.

JoelBender commented 3 years ago

1) The first parameter to read is the BACnet address. The format that you have provided is a network number followed by the address on that network. In this case 600:15 is network 600 and address 15 on that network. This address format is common if you have a BACnet/IP to ARCNET or BACnet/IP to MS/TP router and there is some, usually small, zone controller on that network.

2) The write command is very similar, in addition to providing the object identifier and property you also provide a value to write. For most of the properties you are going to be working with, simple Python-like values are good enough like 12 for Integer and Unsigned, or 75.3 for Real and Double.

3) For more interesting content, try the Sample4_RandomAnalogValueObject.py application on the B side which will have Analog Value objects with random present values.

4) For most modern BACnet devices, you can read the Object_List property, Clause 11.12.16, to see what is available in the device, in your case try read (addr) device:600 objectList where (addr) is the IP address of the device.

kubieduber commented 10 months ago

@JoelBender can you provide some more context on how to identify the BACnet address and network number to control a device that is provided by the router example? Are you saying that if I provide 1:192.168.1.34 I should be able to control the 192.168.1.34 device from a network other than 1 (if the command is issued on a network with a router to the 1 network)? If so, can you explain how to issue the "whois" to find that information programmatically?

JoelBender commented 10 months ago

@kubieduber This is part of the basics of BACnet. Assume you have three devices, (A) is your testings device at 192.168.0.10, (B) is a router to network 600 at address 192.168.0.12, and (C) is a "field bus device" connected to the serial port on (B) with an address of 14 (just a single octet). A read request from (A) will be like read 600:14 device,12 objectName, but before that message can be sent (A) needs to learn that (B) is the router to network 600...

1) (A) sends out a broadcast Who-Is-Router-To-Network 600? 2) (B) responds with an I-Am-Router-To-Network 600 back to (A) - which could be unicast or broadcast 3) (A) sends the ReadProperty request to (B) saying "please send this to 14" 4) (B) forwards the request to (C) with an SNET/SLEN/SADR that tells (C) where the request actually came from 5) (C) sends the response to (B) with a DNET/DLEN/DADR saying "please send this to (A)" 6) (B) forwards the response to (A)

Take a deep dive into Clause 6, it's all in there.