Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Iam response to whois #158

Merged
merged 2 commits into from
Sep 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 41 additions & 4 deletions BAC0/core/app/ScriptApplication.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
from bacpypes.bvllservice import BIPSimple, BIPForeign, AnnexJCodec, UDPMultiplexer
from bacpypes.appservice import StateMachineAccessPoint, ApplicationServiceAccessPoint
from bacpypes.comm import ApplicationServiceElement, bind
from bacpypes.iocb import IOCB
from bacpypes.core import deferred

# basic services
from bacpypes.service.device import WhoIsIAmServices
Expand Down Expand Up @@ -62,12 +64,14 @@ def __init__(
bbmdTTL=0,
deviceInfoCache=None,
aseID=None,
iam_req=None,
):

ApplicationIOController.__init__(
self, localDevice, deviceInfoCache, aseID=aseID
)

self.iam_req = iam_req
# local address might be useful for subclasses
if isinstance(localAddress, Address):
self.localAddress = localAddress
Expand Down Expand Up @@ -116,7 +120,7 @@ def __init__(

def do_IAmRequest(self, apdu):
"""Given an I-Am request, cache it."""
self.log("do_IAmRequest {!r}".format(apdu))
self._log.debug("do_IAmRequest {!r}".format(apdu))

# build a key from the source, just use the instance number
key = (str(apdu.pduSource), apdu.iAmDeviceIdentifier[1])
Expand All @@ -125,7 +129,7 @@ def do_IAmRequest(self, apdu):

def do_WhoIsRequest(self, apdu):
"""Respond to a Who-Is request."""
self.log("do_WhoIsRequest {!r}".format(apdu))
self._log.debug("do_WhoIsRequest {!r}".format(apdu))

# build a key from the source and parameters
key = (
Expand All @@ -136,6 +140,23 @@ def do_WhoIsRequest(self, apdu):

# count the times this has been received
self.who_is_counter[key] += 1
low_limit = key[1]
high_limit = key[2]

# count the times this has been received
self.who_is_counter[key] += 1

if low_limit is not None:
if self.localDevice.objectIdentifier[1] < low_limit:
return
if high_limit is not None:
if self.localDevice.objectIdentifier[1] > high_limit:
return
# generate an I-Am
self._log.info("Responding to Who is by a Iam")
self.iam_req.pduDestination = apdu.pduSource
iocb = IOCB(self.iam_req) # make an IOCB
deferred(self.request_io, iocb)

def close_socket(self):
# pass to the multiplexer, then down to the sockets
Expand Down Expand Up @@ -172,12 +193,14 @@ def __init__(
bbmdTTL=0,
deviceInfoCache=None,
aseID=None,
iam_req=None,
):

ApplicationIOController.__init__(
self, localDevice, deviceInfoCache, aseID=aseID
)

self.iam_req = iam_req
# local address might be useful for subclasses
if isinstance(localAddress, Address):
self.localAddress = localAddress
Expand Down Expand Up @@ -225,7 +248,7 @@ def __init__(

def do_IAmRequest(self, apdu):
"""Given an I-Am request, cache it."""
self.log("do_IAmRequest {!r}".format(apdu))
self._log.debug("do_IAmRequest {!r}".format(apdu))

# build a key from the source, just use the instance number
key = (str(apdu.pduSource), apdu.iAmDeviceIdentifier[1])
Expand All @@ -235,18 +258,32 @@ def do_IAmRequest(self, apdu):

def do_WhoIsRequest(self, apdu):
"""Respond to a Who-Is request."""
self.log("do_WhoIsRequest {!r}".format(apdu))
self._log.debug("do_WhoIsRequest {!r}".format(apdu))

# build a key from the source and parameters
key = (
str(apdu.pduSource),
apdu.deviceInstanceRangeLowLimit,
apdu.deviceInstanceRangeHighLimit,
)
low_limit = key[1]
high_limit = key[2]

# count the times this has been received
self.who_is_counter[key] += 1

if low_limit is not None:
if self.localDevice.objectIdentifier[1] < low_limit:
return
if high_limit is not None:
if self.localDevice.objectIdentifier[1] > high_limit:
return
# generate an I-Am
self._log.debug("Responding to Who is by a Iam")
self.iam_req.pduDestination = apdu.pduSource
iocb = IOCB(self.iam_req) # make an IOCB
deferred(self.request_io, iocb)

def close_socket(self):
# pass to the multiplexer, then down to the sockets
self.mux.close_socket()
38 changes: 27 additions & 11 deletions BAC0/core/functions/Discover.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,32 @@ def whois(self, *args, global_broadcast=False):
self.discoveredDevices = self.this_application.i_am_counter
return self.this_application._last_i_am_received

def iam(self):
def _iam_request(self, dest=None):
"""
Build the IOCB request for a I Am
"""
try:
# build a response
request = IAmRequest()
if dest:
request.pduDestination = dest
else:
request.pduDestination = GlobalBroadcast()

# fill the response with details about us (from our device object)
request.iAmDeviceIdentifier = self.this_device.objectIdentifier
request.maxAPDULengthAccepted = self.this_device.maxApduLengthAccepted
request.segmentationSupported = self.this_device.segmentationSupported
request.vendorID = self.this_device.vendorIdentifier
self._log.debug("{:>12} {}".format("- request:", request))

return request

except Exception as error:
self._log.error("exception: {!r}".format(error))
raise

def iam(self, dest=None):
"""
Build an IAm response. IAm are sent in response to a WhoIs request that;
matches our device ID, whose device range includes us, or is a broadcast.
Expand All @@ -243,16 +268,7 @@ def iam(self):

try:
# build a response
request = IAmRequest()
request.pduDestination = GlobalBroadcast()

# fill the response with details about us (from our device object)
request.iAmDeviceIdentifier = self.this_device.objectIdentifier
request.maxAPDULengthAccepted = self.this_device.maxApduLengthAccepted
request.segmentationSupported = self.this_device.segmentationSupported
request.vendorID = self.this_device.vendorIdentifier
self._log.debug("{:>12} {}".format("- request:", request))

request = self._iam_request(dest=dest)
iocb = IOCB(request) # make an IOCB
deferred(self.this_application.request_io, iocb)
iocb.wait()
Expand Down
2 changes: 1 addition & 1 deletion BAC0/infos.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@
__email__ = "christian.tremblay@servisys.com"
__url__ = "https://github.com/ChristianTremblay/BAC0"
__download_url__ = "https://github.com/ChristianTremblay/BAC0/archive/master.zip"
__version__ = "19.9.8"
__version__ = "19.9.9dev1"
__license__ = "LGPLv3"
3 changes: 2 additions & 1 deletion BAC0/scripts/Base.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,11 +172,12 @@ def startApp(self):
self.localIPAddr,
bbmdAddress=self.bbmdAddress,
bbmdTTL=self.bbmdTTL,
iam_req=self._iam_request(),
)
app_type = "Foreign Device"
else:
self.this_application = BAC0Application(
self.this_device, self.localIPAddr
self.this_device, self.localIPAddr, iam_req=self._iam_request()
)
app_type = "Simple BACnet/IP App"
self._log.debug("Starting")
Expand Down