BACpypes
repository·master·Indexed 43 days ago
https://github.com/joelbender/bacpypesA Python-based implementation of the BACnet application and network layers. It enables developers to build BACnet-compliant daemons, automation scripts, and graphical user interfaces (GUIs). The library supports UDP communication, including unicast and broadcast messages, and provides tools for device discovery and network analysis.
What's inside BACpypes
- BACpypes is a Python implementation of the BACnet application layer and network layer. It is designed to be used for building BACnet daemons, automation scripts, and graphical user interfaces (GUIs). Note that this repository is the active project and is distinct from the legacy version hosted on SourceForge.
Analyze PCAP files with the analysis module
masterTheanalysismodule provides tools for inspecting and decoding BACnet traffic captured in PCAP files. It includes functions for decoding various network layers (Ethernet, VLAN, IP, UDP) and high-level functions for processing entire files or individual packet strings.What is an IO Control Block (IOCB)?
masterAn IO Control Block (IOCB) is a data structure used to store parameters for a specific processing task and to retrieve the results once that task is complete.
In the BACpypes model:
- The IOCB holds the input arguments, keyword arguments, the resulting output, and any error values encountered during processing.
- The IOController (
IOController) acts as the executor that performs the processing defined by the IOCB.
This pattern is modeled after the VAX/VMS IO subsystem API, allowing for asynchronous operations where an application can be notified of completion via event flags, semaphores, or callback functions rather than waiting synchronously for the operation to finish.
# Conceptual model of IOCB usage: # result = some_function(arg1, arg2, kwarg1=1) # # 1. IOCB stores: arg1, arg2, kwarg1 # 2. IOController (some_function) executes the task # 3. IOCB stores: result (or error value if processing fails)What is a Protocol Data Unit (PDU) in BACpypes?
masterA Protocol Data Unit (PDU) is a collection of information passed between two entities. In the
commmodule, a PDU is composed of two main parts:- Protocol Control Information (PCI): Contains addressing (source and destination) and processing instructions.
- PDUData: The actual payload or data being transmitted.
The
PDUclass combines these two components into a single object. While thecommmodule provides these abstractions, the classes themselves are not strictly limited to the BACnet protocol.Understand PDU class hierarchies
masterBACpypes organizes PDUs into several functional hierarchies:
Basic PDU Classes
These classes represent the fundamental types of PDUs:
ConfirmedRequestPDUUnconfirmedRequestPDUSimpleAckPDUComplexAckPDUSegmentAckPDUErrorPDURejectPDU
Sequence Classes
Sequence classes combine APCI with specific PDU types, often used for higher-level protocol implementations:
APCISequence(APCI, Sequence)ConfirmedRequestSequence(APCISequence, ConfirmedRequestPDU)ComplexAckSequence(APCISequence, ComplexAckPDU)UnconfirmedRequestSequence(APCISequence, UnconfirmedRequestPDU)ErrorSequence(APCISequence, ErrorPDU)
Create client-only applications
masterIn BACpypes v0.15.0+, the
Applicationclass no longer requireslocalDeviceorlocalAddressparameters.Applications that omit these parameters function as client-only applications. These are useful for:
- Network analysis applications.
- Simple trend data gather applications.
- Applications running in Docker containers or cloud environments.
Note: Client-only applications can only initiate confirmed or unconfirmed services that do not require local device/address information. They cannot respond to incoming requests like
Who-Is.Manage device information with DeviceInfo and DeviceInfoCache
masterBACpypes uses
DeviceInfoobjects to store metadata about remote devices, such as their device identifier, network address, maximum APDU length, and segmentation support. This information is critical for constructing confirmed services and performing device-address binding.To manage this data, use
DeviceInfoCache. AnApplicationuses a cache to store information gathered from the network (e.g., viaIAmRequest) or from a database. You can extendDeviceInfoCacheto implement custom persistence logic, such as updating a database whenupdate_device_infois called or implementing custom expiration logic inrelease_device_info.Understand Capability ordering via _zIndex
masterIn theCapabilitymodule, functions are ordered based on the_zIndexattribute. When usingCollector.capability_functions(fn), the generator yields functions in the order determined by this attribute.Understand ConnectionState access states
masterThe
ConnectionStateobject tracks the lifecycle of a BSLL connection. TheaccessStateattribute transitions through the following values:NOT_AUTHENTICATED: No authentication has been attempted.REQUESTED: An access request has been sent to the server (Client side).CHALLENGED: An access challenge has been sent to the client (Server side).AUTHENTICATED: Authentication was successful.
How the capability module works for mixing functionality
masterThe
bacpypes.capabilitymodule provides a mechanism to mix together classes that offer separate or overlapping functionality. It uses a component-based architecture where functionality is added to a base class via multiple inheritance.Key classes include:
Capability: The base class for defining specific pieces of functionality (e.g., a specific data transformation).Collector: A base class used to aggregate and execute functions provided by mixed-inCapabilityclasses.
By mixing a
Collectorwith multipleCapabilityclasses, you can create a pipeline where theCollectoriterates through all registered functions of a specific type (retrieved viacapability_functions()) and applies them to a value.from bacpypes.capability import Capability, CollectorUse Network Layer Service Requests
masterThe
npdumodule defines several service request classes used for routing and network management. Most of these classes implementencode(npdu)anddecode(npdu)methods, accepting anNPDUbuffer as a parameter.Router Discovery and Management
WhoIsRouterToNetwork(NPCI): Used to find the router for a specific network or to allow routers to update routing tables.IAmRouterToNetwork(NPCI): Response toWhoIsRouterToNetwork; contains network numbers the router provides access to.ICouldBeRouterToNetwork(NPCI): Response toWhoIsRouterToNetwork; contains network numbers a half-router could provide access to via a PTP connection (connection not yet established).
Error and Traffic Control
RejectMessageToNetwork(NPCI): Sent when a network layer message is rejected due to an error.RouterBusyToNetwork(NPCI): Sent by a router to temporarily stop messages to specific destination networks.RouterAvailableToNetwork(NPCI): Sent by a router to enable or re-enable messages to specific destination networks.
Routing Table and Connection Management
InitializeRoutingTable(NPCI): Used to initialize a router's routing table or retrieve the current table.InitializeRoutingTableAck(NPCI): Indicates the routing table has changed or been initialized.EstablishConnectionToNetwork(NPCI): Tells a half-router to establish a PTP connection to a network.DisconnectConnectionToNetwork(NPCI): Tells a half-router to close a PTP connection to a network.
How COV subscriptions and detection algorithms work together
masterBACpypes uses a layered approach for Change of Value (COV) services:
ChangeOfValueServices: The central manager that handles the lifecycle of subscriptions and the dispatching of notifications.Subscription: Represents an active subscription with a specific lifetime. It acts as aOneShotTaskthat automatically cancels itself when its lifetime expires.COVDetection: ADetectionAlgorithmthat monitors object properties. When a change is detected, it callssend_cov_notifications()to alert all associatedSubscriptionobjects.ActiveCOVSubscriptions: APropertyadded to a local device object. When read, it returns a list ofCOVSubscriptionobjects, allowing the device to report its current COV state.