#!/usr/bin/env python

"""
This application presents a 'console' prompt to the user asking for Who-Is and I-Am
commands which create the related APDUs, then for each I-Am that is returned, reads
the object name of the device object (often called simply the device name).
"""

import sys

from bacpypes.debugging import bacpypes_debugging, ModuleLogger
from bacpypes.consolelogging import ConfigArgumentParser
from bacpypes.consolecmd import ConsoleCmd

from bacpypes.core import run, enable_sleeping
from bacpypes.iocb import IOCB

from bacpypes.pdu import Address, GlobalBroadcast
from bacpypes.apdu import WhoIsRequest, ReadPropertyRequest, ReadPropertyACK
from bacpypes.primitivedata import CharacterString
from bacpypes.errors import MissingRequiredParameter

from bacpypes.app import BIPForeignApplication
from bacpypes.local.device import LocalDeviceObject

# some debugging
_debug = 1
_log = ModuleLogger(globals())

# globals
this_device = None
this_application = None

#
#   DiscoveryApplication
#

@bacpypes_debugging
class DiscoveryApplication(BIPForeignApplication):

    def __init__(self, *args):
        if _debug: DiscoveryApplication._debug("__init__ %r", args)
        BIPForeignApplication.__init__(self, *args)

        # keep track of requests to line up responses
        self.who_is_request = None

    def request(self, apdu):
        """Sniff for Who-Is requests going downstream."""
        if _debug: DiscoveryApplication._debug("request %r", apdu)

        # save a copy of just the Who-Is request
        if isinstance(apdu, WhoIsRequest):
            self.who_is_request = apdu

        # forward it along
        BIPForeignApplication.request(self, apdu)

    def do_IAmRequest(self, apdu):
        """Do something with incoming I-Am requests."""
        if _debug: DiscoveryApplication._debug("do_IAmRequest %r", apdu)

        # check for required parameters
        if apdu.iAmDeviceIdentifier is None:
            raise MissingRequiredParameter("iAmDeviceIdentifier required")
        if apdu.maxAPDULengthAccepted is None:
            raise MissingRequiredParameter("maxAPDULengthAccepted required")
        if apdu.segmentationSupported is None:
            raise MissingRequiredParameter("segmentationSupported required")
        if apdu.vendorID is None:
            raise MissingRequiredParameter("vendorID required")

        # extract the device instance number
        device_instance = apdu.iAmDeviceIdentifier[1]
        if _debug: DiscoveryApplication._debug("    - device_instance: %r", device_instance)

        # extract the source address
        device_address = apdu.pduSource
        if _debug: DiscoveryApplication._debug("    - device_address: %r", device_address)

        # we didn't request anything yet
        if not self.who_is_request:
            return