1
0
mirror of https://github.com/JoelBender/bacpypes synced 2025-09-28 22:15:23 +08:00
bacpypes/sandbox/bip_vlan.py
2017-09-13 13:13:38 -04:00

181 lines
4.8 KiB
Python
Executable File

#!/usr/bin/env python
"""
B/IP VLAN
"""
import sys
from bacpypes.debugging import bacpypes_debugging, ModuleLogger
from bacpypes.consolelogging import ArgumentParser
from bacpypes.console import ConsoleClient
from bacpypes.comm import Client, Server, Debug, bind
from bacpypes.pdu import Address, LocalBroadcast, PDU, unpack_ip_addr
from bacpypes.core import run, stop
from bacpypes.vlan import IPNetwork, IPNode
from bacpypes.bvllservice import BIPSimple, AnnexJCodec
# some debugging
_debug = 0
_log = ModuleLogger(globals())
# globals
network = None
#
# FauxMultiplexer
#
@bacpypes_debugging
class FauxMultiplexer(Client, Server):
def __init__(self, addr, network=None, cid=None, sid=None):
if _debug: FauxMultiplexer._debug("__init__")
Client.__init__(self, cid)
Server.__init__(self, sid)
# allow the address to be cast
if isinstance(addr, Address):
self.address = addr
else:
self.address = Address(addr)
# get the unicast and broadcast tuples
self.unicast_tuple = addr.addrTuple
self.broadcast_tuple = addr.addrBroadcastTuple
# make an internal node and bind to it, this takes the place of
# both the direct port and broadcast port of the real UDPMultiplexer
self.node = IPNode(addr, network)
bind(self, self.node)
def indication(self, pdu):
if _debug: FauxMultiplexer._debug("indication %r", pdu)
# check for a broadcast message
if pdu.pduDestination.addrType == Address.localBroadcastAddr:
dest = self.broadcast_tuple
if _debug: FauxMultiplexer._debug(" - requesting local broadcast: %r", dest)
elif pdu.pduDestination.addrType == Address.localStationAddr:
dest = unpack_ip_addr(pdu.pduDestination.addrAddr)
if _debug: FauxMultiplexer._debug(" - requesting local station: %r", dest)
else:
raise RuntimeError("invalid destination address type")
# continue downstream
self.request(PDU(pdu, source=self.unicast_tuple, destination=dest))
def confirmation(self, pdu):
if _debug: FauxMultiplexer._debug("confirmation %r", pdu)
# the PDU source and destination are tuples, convert them to Address instances
src = Address(pdu.pduSource)
# see if the destination was our broadcast address
if pdu.pduDestination == self.broadcast_tuple:
dest = LocalBroadcast()
else:
dest = Address(pdu.pduDestination)
# continue upstream
self.response(PDU(pdu, source=src, destination=dest))
#
# MiddleMan
#
@bacpypes_debugging
class MiddleMan(Client, Server):
def indication(self, pdu):
if _debug: MiddleMan._debug('indication %r', pdu)
# empty downstream packets mean EOF
if not pdu.pduData:
stop()
return
# decode the line and trim off the eol
line = str(pdu.pduData.decode('utf-8'))[:-1]
if _debug: MiddleMan._debug(' - line: %r', line)
line_parts = line.split(' ', 1)
if _debug: MiddleMan._debug(' - line_parts: %r', line_parts)
if len(line_parts) != 2:
sys.stderr.write("err: invalid line: %r\n" % (line,))
return
addr, msg = line_parts
# check the address
dest = Address(addr)
if _debug: MiddleMan._debug(' - dest: %r', dest)
# send it along
try:
self.request(PDU(msg.encode('utf_8'), destination=dest))
except Exception as err:
sys.stderr.write("err: %r\n" % (err,))
return
def confirmation(self, pdu):
if _debug: MiddleMan._debug('confirmation %r', pdu)
# decode the line
line = str(pdu.pduData.decode('utf-8'))
if _debug: MiddleMan._debug(' - line: %r', line)
sys.stdout.write("received %r from %s\n" % (line, pdu.pduSource))
#
# __main__
#
def main():
# parse the command line arguments
parser = ArgumentParser(usage=__doc__)
args = parser.parse_args()
if _debug: _log.debug("initialization")
if _debug: _log.debug(" - args: %r", args)
# make a network
network = IPNetwork()
console = ConsoleClient()
middle_man = MiddleMan()
bip = BIPSimple()
annexj = AnnexJCodec()
mux = FauxMultiplexer("192.168.0.1/24", network)
bind(console, middle_man, bip, annexj, mux)
# add some more debugging nodes
for i in range(2, 4):
debug_address = "192.168.0.{}/24".format(i)
debug_debug = Debug(debug_address)
debug_bip = BIPSimple()
debug_annexj = AnnexJCodec()
debug_mux = FauxMultiplexer(debug_address, network)
bind(debug_debug, debug_bip, debug_annexj, debug_mux)
_log.debug("running")
run()
_log.debug("fini")
if __name__ == "__main__":
main()