def __init__(self, baseConfig, pInBoundEventQueue, pOutBoundEventQueue,
                 loggingQueue):

        super(MQTTClientModule, self).__init__()
        self.config = baseConfig
        self.alive = True
        self.inQueue = pInBoundEventQueue

        # Module config
        self.moduleConfig = configLoader.load(self.loggingQueue, __name__)

        # Constants
        self._keepAlive = self.moduleConfig['MqttKeepAlive']
        self._feedName = self.moduleConfig['MqttFeedName']
        self._username = self.moduleConfig['MqttUsername']
        self._key = self.moduleConfig['MqttKey']
        self._host = self.moduleConfig['MqttHost']
        self._port = self.moduleConfig['MqttPort']
        self._publishJson = self.moduleConfig['MqttPublishJson']

        # MQTT setup
        self._client = mqtt.Client()
        self._client.username_pw_set(self._username, self._key)
        self._client.on_connect = self.onConnect
        self._client.on_disconnect = self.onDisconnect
        self._client.on_message = self.onMessage
        self.mqttConnected = False

        # Logging setup
        self.logger = ThreadsafeLogger(loggingQueue, "MQTT")
Ejemplo n.º 2
0
    def __init__(self, collectionPointConfig, loggingQueue):
        # Logger
        self.loggingQueue = loggingQueue
        self.logger = ThreadsafeLogger(loggingQueue, __name__)

        self.rClients = {}  #registered clients
        self.collectionPointConfig = collectionPointConfig  #collection point config
    def __init__(self, baseConfig, pInBoundQueue, pOutBoundQueue, loggingQueue):
        """ 
        Initialize new CollectionModule instance.
        """
        super(CollectionModule, self).__init__(baseConfig, pInBoundQueue, pOutBoundQueue, loggingQueue)

        # Most collection modules will follow a similar pattern...

        # 1. Set up some variables on the self object
        # Queues
        self.outQueue = pOutBoundQueue
        self.inQueue= pInBoundQueue
        self.loggingQueue = loggingQueue
        self.threadProcessQueue = None
        self.alive = False

        self.context = None
        self.reader = None

        # 2. Load the module's configuration file
        # Configs
        self.moduleConfig = configLoader.load(self.loggingQueue, __name__)
        self.config = baseConfig

        # 3. Set some constants to the self object from config parameters (if you want)
        self._id = self.moduleConfig['CollectionPointId']
        self._type = self.moduleConfig['CollectionPointType']
        self._port = self.moduleConfig['ReaderPortNumber']

        # 4. Create a threadsafe logger object
        self.logger = ThreadsafeLogger(loggingQueue, __name__)
Ejemplo n.º 4
0
    def __init__(self, callbacks, btleConfig, loggingQueue, debugMode=False):
        super().__init__()
        # Logger
        self.loggingQueue = loggingQueue
        self.logger = ThreadsafeLogger(loggingQueue, __name__)
        self.alive = True
        self.callbacks = self.sanitizeCallbacks(callbacks)
        self.btleConfig = btleConfig

        # consts
        self._majorMin = self.btleConfig['BtleAdvertisingMajorMin']
        self._majorMax = self.btleConfig['BtleAdvertisingMajorMax']
        self._minorMin = self.btleConfig['BtleAdvertisingMinorMin']
        self._minorMax = self.btleConfig['BtleAdvertisingMinorMax']
        self._uuidFocusList = self.btleConfig['BtleUuidFocusList']

        if ('any' in self._uuidFocusList or 
            'all' in self._uuidFocusList or
            len(self._uuidFocusList)==0):
            self.filterOnUuid = False
        else:
            self.filterOnUuid = True

        # self.queue = queue
        self.device = BluegigaDevice(
            self.scanCallback,
            self.btleConfig,
            self.loggingQueue)
Ejemplo n.º 5
0
    def __init__(self, baseConfig, pInBoundQueue, pOutBoundQueue,
                 loggingQueue):
        """ Initialize new CamCollectionPoint instance.
        Setup queues, variables, configs, constants and loggers.
        """
        super(BtleCollectionPoint, self).__init__()
        self.loggingQueue = loggingQueue
        self.logger = ThreadsafeLogger(loggingQueue, __name__)

        # Queues
        self.outQueue = pOutBoundQueue  # Messages from this thread to the main process
        self.inQueue = pInBoundQueue
        self.queueBLE = mp.Queue()

        # Configs
        self.moduleConfig = configLoader.load(self.loggingQueue)
        self.config = baseConfig

        # Variables and objects
        self.registeredClientRegistry = RegisteredClientRegistry(
            self.moduleConfig, self.loggingQueue)
        self.eventManager = EventManager(self.moduleConfig, pOutBoundQueue,
                                         self.registeredClientRegistry,
                                         self.loggingQueue)
        self.alive = True
        self.btleThread = None
        self.BLEThread = None
        self.repeatTimerSweepClients = None

        # Constants
        self._cleanupInterval = self.moduleConfig[
            'AbandonedClientCleanupInterval']
Ejemplo n.º 6
0
    def __init__(self, detectedClient, collectionPointConfig, loggingQueue):
        self.loggingQueue = loggingQueue
        self.logger = ThreadsafeLogger(loggingQueue, __name__)

        # Counters and variables
        self.clientInRangeTrigerCount = 2
        self.prevClientInMsgTime = -1
        self.prevClientOutMsgTime = -1
        self.numClientInRange = 0
        self.numClientOutRange = 0
        self.timeInCollectionPointInMilliseconds = 0
        self.firstRegisteredTime = time.time()
        self.collectionPointConfig = collectionPointConfig
        try:
            self.uidMap = UIDMap()
        except Exception as e:
            print('cant instantiate uid map: %s ' % e)
        # Constants
        self._rssiClientInThresh = self.collectionPointConfig[
            'BtleRssiClientInThreshold']
        self._rssiErrorVar = self.collectionPointConfig[
            'BtleRssiErrorVariance']
        self.__clientOutThresholdMin = int(self._rssiClientInThresh +
                                           (self._rssiClientInThresh *
                                            self._rssiErrorVar))

        # Initiate event when client is detected
        self.handleNewDetectedClientEvent(detectedClient)
Ejemplo n.º 7
0
    def __init__(self, collectionPointConfig, pOutBoundQueue,
                 registeredClientRegistry, loggingQueue):
        self.loggingQueue = loggingQueue
        self.logger = ThreadsafeLogger(loggingQueue, __name__)

        self.__stats_totalRemoveEvents = 0
        self.__stats_totalNewEvents = 0
        self.registeredClientRegistry = registeredClientRegistry
        self.registeredClientRegistry.eventRegisteredClientAdded += self.__newClientRegistered
        self.registeredClientRegistry.eventRegisteredClientRemoved += self.__removedRegisteredClient
        self.collectionPointConfig = collectionPointConfig
        self.outBoundEventQueue = pOutBoundQueue
    def __init__(self,
                 clientEventHandler,
                 btleConfig,
                 loggingQueue,
                 debugMode=False):
        # Logger
        self.loggingQueue = loggingQueue
        self.logger = ThreadsafeLogger(loggingQueue, __name__)

        self.btleConfig = btleConfig
        self.clientEventHandler = clientEventHandler
        self.debug = debugMode
        # define basic BGAPI parser
        self.bgapi_rx_buffer = []
        self.bgapi_rx_expected_length = 0
Ejemplo n.º 9
0
    def __init__(self,
                 scanCallback,
                 btleConfig,
                 loggingQueue,
                 debugMode=False):
        # Logger
        self.loggingQueue = loggingQueue
        self.logger = ThreadsafeLogger(loggingQueue, __name__)

        self.btleConfig = btleConfig
        self.scanCallback = scanCallback
        self.debug = debugMode
        # define basic BGAPI parser
        self.bgapi_rx_buffer = []
        self.bgapi_rx_expected_length = 0
Ejemplo n.º 10
0
    def __init__(self, kind="KCF", moduleConfig=None, loggingQueue=None):
        """ Create an initialize new MultiTracker. Set up constants and parameters. """

        self.config = moduleConfig
        self.trackers = []  # List of trackers
        self.kind = kind
        self.focus = None
        self.loggingQueue = loggingQueue

        # Constants
        self._useVelocity = self.config['UseVelocity']
        self._closestThreshold = self.config["ClosestThreshold"]
        self._primaryTarget = self.config['PrimaryTarget']

        # Setup logging queue
        self.logger = ThreadsafeLogger(loggingQueue, __name__)
Ejemplo n.º 11
0
    def __init__(self, moduleConfig, pOutBoundQueue, clientRegistry,
                 loggingQueue):
        self.loggingQueue = loggingQueue
        self.logger = ThreadsafeLogger(loggingQueue, __name__)

        self.__stats_totalRemoveEvents = 0
        self.__stats_totalNewEvents = 0
        self.clientRegistry = clientRegistry
        self.clientRegistry.onClientAdded += self.clientRegistered
        self.clientRegistry.onClientRemoved += self.clientRemoved
        self.moduleConfig = moduleConfig
        self.outBoundEventQueue = pOutBoundQueue
        self.alive = True

        self._sendClientInMessages = self.moduleConfig['SendClientInMessages']
        self._sendClientOutMessages = self.moduleConfig[
            'SendClientOutMessages']
        self._sendUpdateMessages = self.moduleConfig['SendUpdateMessages']

        self._rssiClientInThresh = self.moduleConfig[
            'BtleRssiClientInThreshold']
        self._rssiErrorVar = self.moduleConfig['BtleRssiErrorVariance']
        self.__clientOutThresholdMin = int(self._rssiClientInThresh +
                                           (self._rssiClientInThresh *
                                            self._rssiErrorVar / 2))

        if self._sendUpdateMessages:
            self._updateFPS = self.moduleConfig['UpdateFPS']
            self.updateLoopThread = Thread(target=self.updateLoop)
            self.updateLoopThread.start()
def load(loggingQueue, name):
    """ Load module specific config into dictionary, return it"""
    logger = ThreadsafeLogger(loggingQueue,
                              '{0}-{1}'.format(name, 'ConfigLoader'))
    thisConfig = {}
    configParser = configparser.ConfigParser()

    thisConfig = loadSecrets(thisConfig, logger, configParser)
    thisConfig = loadModule(thisConfig, logger, configParser)
    return thisConfig
Ejemplo n.º 13
0
	def __init__(self, bbox, frame, kind, moduleConfig, loggingQueue):
		""" Create and initialize a new Tracker. Set up constants and parameters. """

		if kind in ["KCF", "MIL", "MEDIANFLOW", "GOTURN", "TLD", "BOOSTING"]:
			self.tracker = cv2.Tracker_create(kind)
			self.tracker.init(frame, (bbox['x'], bbox['y'], bbox['w'], bbox['h']))
			self.created = time()
			self.bbox = (bbox['x'], bbox['y'], bbox['w'], bbox['h'])
			self.velocity = (0, 0)
			self.updateTime = self.created
			self.config = moduleConfig

			# Constants
			self._useVelocity = self.config['UseVelocity']
			self._horizontalVelocityBuffer = self.config['HorizontalVelocityBuffer']
			self._verticalVelocityBuffer = self.config['VerticalVelocityBuffer']

			# Setup logging queue
			self.logger = ThreadsafeLogger(loggingQueue, __name__)
		else:
			self.logger.error("Type %s not supported by mTracker" % kind)
    def __init__(self, baseConfig, pInBoundEventQueue, pOutBoundEventQueue, loggingQueue):

        super(WebsocketClientModule, self).__init__()
        
        self.alive = True
        self.config = baseConfig
        self.inQueue = pInBoundEventQueue  # inQueue are messages from the main process to websocket clients
        self.outQueue = pOutBoundEventQueue  # outQueue are messages from clients to main process
        self.websocketClient = None
        self.loggingQueue = loggingQueue
        self.threadProcessQueue = None

        # Configs
        self.moduleConfig = configLoader.load(self.loggingQueue, __name__)

        # Constants
        self._port = self.moduleConfig['WebsocketPort']
        self._host = self.moduleConfig['WebsocketHost']

        # logging setup
        self.logger = ThreadsafeLogger(loggingQueue, __name__)
    def __init__(self, baseConfig, pInBoundQueue, pOutBoundQueue,
                 loggingQueue):
        """ Initialize new CamCollectionPoint instance.
        Setup queues, variables, configs, constants and loggers.
        """
        super().__init__()
        # super().__init__(baseConfig, pInBoundQueue, pOutBoundQueue, loggingQueue)
        self.loggingQueue = loggingQueue
        self.logger = ThreadsafeLogger(loggingQueue, __name__)

        # Queues
        self.outQueue = pOutBoundQueue  # Messages from this thread to the main process
        self.inQueue = pInBoundQueue

        # Configs
        self.moduleConfig = configLoader.load(self.loggingQueue, __name__)
        self.config = baseConfig

        # Variables and objects
        self.alive = True
        self.callbacks = {_ON_SCAN: self.handleBtleClientEvent}
        self.clientRegistry = ClientRegistry(self.moduleConfig,
                                             self.loggingQueue)

        self.eventManager = EventManager(self.moduleConfig, pOutBoundQueue,
                                         self.clientRegistry,
                                         self.loggingQueue)

        # Threads
        self.btleThread = None
        self.repeatTimerSweepClients = None

        self.lastUpdate = datetime.now()

        # Constants
        self._cleanupInterval = self.moduleConfig[
            'AbandonedClientCleanupInterval']
Ejemplo n.º 16
0
    def __init__(self, detectionData, collectionPointConfig, loggingQueue):
        self.loggingQueue = loggingQueue
        self.logger = ThreadsafeLogger(loggingQueue, "BtleRegisteredClient")
        
        # Counters and variables
        self.clientInRangeTrigerCount = 1
        self.prevClientInMsgTime = None
        self.prevClientOutMsgTime = None
        self.numClientInRange=0
        self.numClientOutRange=0
        self.timeInCollectionPointInMilliseconds = 0
        self.firstRegisteredTime = datetime.now()
        self.collectionPointConfig = collectionPointConfig
        self.filter = Filter(detectionData.extraData['rssi'])
        try:
            self.uidMap = UIDMap()
        except Exception as e:
            self.logger.warning('cant instantiate uid map: %s '%e)

        # Constants
        self._proximityEventInterval = self.collectionPointConfig['ProximityEventInterval']
        self._outClientThreshold = self.collectionPointConfig['BtleClientOutCountThreshold']

        self._gatewayType = self.collectionPointConfig['GatewayType']

        self._rssiClientInThresh = self.collectionPointConfig['BtleRssiClientInThreshold']
        self._rssiErrorVar = self.collectionPointConfig['BtleRssiErrorVariance']
        self.__clientOutThresholdMin = int(
            self._rssiClientInThresh + 
            (self._rssiClientInThresh * self._rssiErrorVar)
            )
        self._clientInThreshType = self.collectionPointConfig['BtleRssiClientInThresholdType']
        self._debugEventManager = self.collectionPointConfig['EventManagerDebug']

        # Initiate event when client is detected
        self.handleNewDetectedClientEvent(detectionData)
class WebsocketClientModule(ModuleProcess):

    def __init__(self, baseConfig, pInBoundEventQueue, pOutBoundEventQueue, loggingQueue):

        super(WebsocketClientModule, self).__init__()
        
        self.alive = True
        self.config = baseConfig
        self.inQueue = pInBoundEventQueue  # inQueue are messages from the main process to websocket clients
        self.outQueue = pOutBoundEventQueue  # outQueue are messages from clients to main process
        self.websocketClient = None
        self.loggingQueue = loggingQueue
        self.threadProcessQueue = None

        # Configs
        self.moduleConfig = configLoader.load(self.loggingQueue, __name__)

        # Constants
        self._port = self.moduleConfig['WebsocketPort']
        self._host = self.moduleConfig['WebsocketHost']

        # logging setup
        self.logger = ThreadsafeLogger(loggingQueue, __name__)

    def run(self):

        """ Main thread entry point.

        Sets up websocket server and event callbacks.
        Starts thread to monitor inbound message queue.
        """

        self.logger.info("Starting %s" % __name__)
        self.connect()

    def listen(self):
        self.threadProcessQueue = Thread(target=self.processQueue)
        self.threadProcessQueue.setDaemon(True)
        self.threadProcessQueue.start()

    def connect(self):
        #websocket.enableTrace(True)
        ws = websocket.WebSocketApp("ws://%s:%s"%(self._host, self._port),
        on_message = self.onMessage,
        on_error = self.onError,
        on_close = self.onClose)
        ws.on_open = self.onOpen
        ws.run_forever()

    def onError(self, ws, message):
        self.logger.error("Error callback fired, message: %s"%message)

    def onClose(self, ws):
        if self.alive:
            self.logger.warn("Closed")
            self.alive = False
            # TODO: reconnect timer
        else:
            self.logger.info("Closed")

    def onMessage(self, ws, message):
        self.logger.info("Message from websocket server: %s"%message)
        # Could put message on the out queue here to handle incoming coms

    def onOpen(self, ws):
        self.alive = True
        self.websocketClient = ws
        self.listen()

    def shutdown(self):
        """ Handle shutdown message. 
        Close and shutdown websocket server.
        Join queue processing thread.
        """

        self.logger.info("Shutting down %s"%__name__)

        try:
            self.logger.info("Closing websocket")
            self.websocketClient.close()
        except Exception as e:
            self.logger.error("Websocket close error : %s " %e)

        self.alive = False
        
        self.threadProcessQueue.join()

        time.sleep(1)
        self.exit = True

    def sendOutMessage(self, message):
        """ Send message to server """

        self.websocketClient.send(json.dumps(message.__dict__))

    def processQueue(self):
        """ Monitor queue of messages from main process to this thread. """

        while self.alive:
            if (self.inQueue.empty() == False):
                try:
                    message = self.inQueue.get(block=False,timeout=1)
                    if message is not None:
                        if (message.topic.upper()=="SHUTDOWN" and
                            message.sender_id.lower()=="main"):
                            self.logger.debug("SHUTDOWN handled")
                            self.shutdown()
                        else:
                            self.sendOutMessage(message)
                except Exception as e:
                    self.logger.error("Websocket unable to read queue : %s " %e)
            else:
                time.sleep(.25)
Ejemplo n.º 18
0
class EventManager(object):
    def __init__(self, collectionPointConfig, pOutBoundQueue,
                 registeredClientRegistry, loggingQueue):
        self.loggingQueue = loggingQueue
        self.logger = ThreadsafeLogger(loggingQueue, __name__)

        self.__stats_totalRemoveEvents = 0
        self.__stats_totalNewEvents = 0
        self.registeredClientRegistry = registeredClientRegistry
        self.registeredClientRegistry.eventRegisteredClientAdded += self.__newClientRegistered
        self.registeredClientRegistry.eventRegisteredClientRemoved += self.__removedRegisteredClient
        self.collectionPointConfig = collectionPointConfig
        self.outBoundEventQueue = pOutBoundQueue

    def registerDetectedClient(self, detectedClient):
        self.logger.debug("Registering detected client %s" %
                          detectedClient.extraData["beaconMac"])
        eClient = self.registeredClientRegistry.getRegisteredClient(
            detectedClient.extraData["beaconMac"])

        #check for existing
        if eClient == None:
            #Newly found client
            if self.collectionPointConfig['InterfaceType'] == 'btle':
                rClient = BtleRegisteredClient(detectedClient,
                                               self.collectionPointConfig,
                                               self.loggingQueue)
            self.logger.debug("New client with MAC %s found." %
                              detectedClient.extraData["beaconMac"])

            if rClient.shouldSendClientInEvent():
                self.__sendEventToController(rClient, "clientIn")
            elif rClient.shouldSendClientOutEvent():
                self.logger.debug(
                    "########################################## SENDING CLIENT OUT eClient ##########################################"
                )
                self.__sendEventToController(rClient, "clientOut")

            self.registeredClientRegistry.addNewRegisteredClient(rClient)

        else:
            eClient.updateWithNewDetectedClientData(detectedClient)
            if eClient.shouldSendClientInEvent():
                #self.logger.debug("########################################## SENDING CLIENT IN ##########################################")
                self.__sendEventToController(eClient, "clientIn")
            elif eClient.shouldSendClientOutEvent():
                self.logger.debug(
                    "########################################## SENDING CLIENT OUT rClient ##########################################"
                )
                self.__sendEventToController(eClient, "clientOut")

            self.registeredClientRegistry.updateRegisteredClient(eClient)

    def registerClients(self, detectedClients):
        for detectedClient in detectedClients:
            self.registerDetectedClient(detectedClient)

    def getEventAuditData(self):
        """Returns a dict with the total New and Remove events the engine has seen since startup"""
        return {
            'NewEvents': self.__stats_totalNewEvents,
            'RemoveEvents': self.__stats_totalRemoveEvents
        }

    def __newClientRegistered(self, sender, registeredClient):
        self.logger.debug(
            "######### NEW CLIENT REGISTERED %s #########" %
            registeredClient.detectedClient.extraData["beaconMac"])

        #we dont need to count for ever and eat up all the memory
        if self.__stats_totalNewEvents > 1000000:
            self.__stats_totalNewEvents = 0
        else:
            self.__stats_totalNewEvents += 1

    def __removedRegisteredClient(self, sender, registeredClient):
        self.logger.debug(
            "######### REGISTERED REMOVED %s #########" %
            registeredClient.detectedClient.extraData["beaconMac"])
        if registeredClient.sweepShouldSendClientOutEvent():
            self.__sendEventToController(registeredClient, "clientOut")

        #we dont need to count for ever and eat up all the memory
        if self.__stats_totalRemoveEvents > 1000000:
            self.__stats_totalRemoveEvents = 0
        else:
            self.__stats_totalRemoveEvents += 1

    def __sendEventToController(self, registeredClient, eventType):

        eventMessage = Message(
            topic=eventType,
            sender_id=self.collectionPointConfig['CollectionPointId'],
            sender_type=self.collectionPointConfig['GatewayType'],
            extended_data=registeredClient.getExtendedDataForEvent(),
            timestamp=registeredClient.lastRegisteredTime)

        if eventType == 'clientIn':
            registeredClient.setClientInMessageSentToController()
        elif eventType == 'clientOut':
            registeredClient.setClientOutMessageSentToController()

        #update reg
        self.registeredClientRegistry.updateRegisteredClient(registeredClient)

        self.outBoundEventQueue.put(eventMessage)
class BtleThreadCollectionPoint(object):
    def __init__(self,
                 clientEventHandler,
                 btleConfig,
                 loggingQueue,
                 debugMode=False):
        # Logger
        self.loggingQueue = loggingQueue
        self.logger = ThreadsafeLogger(loggingQueue, __name__)

        self.btleConfig = btleConfig
        self.clientEventHandler = clientEventHandler
        self.debug = debugMode
        # define basic BGAPI parser
        self.bgapi_rx_buffer = []
        self.bgapi_rx_expected_length = 0

    def start(self):
        packet_mode = False

        # create BGLib object
        self.ble = BGLib()
        self.ble.packet_mode = packet_mode
        self.ble.debug = self.debug

        # add handler for BGAPI timeout condition (hopefully won't happen)
        self.ble.on_timeout += self.my_timeout

        # on busy hander
        self.ble.on_busy = self.on_busy

        # add handler for the gap_scan_response event
        self.ble.ble_evt_gap_scan_response += self.clientEventHandler

        # create serial port object and flush buffers
        self.logger.info(
            "Establishing serial connection to BLED112 on com port %s at baud rate %s"
            % (self.btleConfig['BtleDeviceId'],
               self.btleConfig['BtleDeviceBaudRate']))
        self.serial = Serial(port=self.btleConfig['BtleDeviceId'],
                             baudrate=self.btleConfig['BtleDeviceBaudRate'],
                             timeout=1)
        self.serial.flushInput()
        self.serial.flushOutput()

        # disconnect if we are connected already
        self.ble.send_command(self.serial,
                              self.ble.ble_cmd_connection_disconnect(0))
        self.ble.check_activity(self.serial, 1)

        # stop advertising if we are advertising already
        self.ble.send_command(self.serial, self.ble.ble_cmd_gap_set_mode(0, 0))
        self.ble.check_activity(self.serial, 1)

        # stop scanning if we are scanning already
        self.ble.send_command(self.serial,
                              self.ble.ble_cmd_gap_end_procedure())
        self.ble.check_activity(self.serial, 1)

        # set the TX
        # range 0 to 15 (real TX power from -23 to +3dBm)
        #self.ble.send_command(self.serial, self.ble.ble_cmd_hardware_set_txpower(self.btleConfig['btleDeviceTxPower']))
        #self.ble.check_activity(self.serial,1)

        #ble_cmd_connection_update connection: 0 (0x00) interval_min: 30 (0x001e) interval_max: 46 (0x002e) latency: 0 (0x0000) timeout: 100 (0x0064)
        #interval_min 6-3200
        #interval_man 6-3200
        #latency 0-500
        #timeout 10-3200
        self.ble.send_command(
            self.serial,
            self.ble.ble_cmd_connection_update(0x00, 0x001e, 0x002e, 0x0000,
                                               0x0064))
        self.ble.check_activity(self.serial, 1)

        # set scan parameters
        #scan_interval 0x4 - 0x4000
        #Scan interval defines the interval when scanning is re-started in units of 625us
        # Range: 0x4 - 0x4000
        # Default: 0x4B (75ms)
        # After every scan interval the scanner will change the frequency it operates at
        # at it will cycle through all the three advertisements channels in a round robin
        # fashion. According to the Bluetooth specification all three channels must be
        # used by a scanner.
        #
        #scan_window 0x4 - 0x4000
        # Scan Window defines how long time the scanner will listen on a certain
        # frequency and try to pick up advertisement packets. Scan window is defined
        # as units of 625us
        # Range: 0x4 - 0x4000
        # Default: 0x32 (50 ms)
        # Scan windows must be equal or smaller than scan interval
        # If scan window is equal to the scan interval value, then the Bluetooth module
        # will be scanning at a 100% duty cycle.
        # If scan window is half of the scan interval value, then the Bluetooth module
        # will be scanning at a 50% duty cycle.
        #
        #active 1=active 0=passive
        # 1: Active scanning is used. When an advertisement packet is received the
        # Bluetooth stack will send a scan request packet to the advertiser to try and
        # read the scan response data.
        # 0: Passive scanning is used. No scan request is made.
        #self.ble.send_command(self.serial, self.ble.ble_cmd_gap_set_scan_parameters(0x4B,0x32,1))
        self.ble.send_command(
            self.serial,
            self.ble.ble_cmd_gap_set_scan_parameters(0xC8, 0xC8, 0))
        self.ble.check_activity(self.serial, 1)

        # start scanning now
        self.ble.send_command(self.serial, self.ble.ble_cmd_gap_discover(1))
        self.ble.check_activity(self.serial, 1)

    # handler to notify of an API parser timeout condition
    def my_timeout(self, sender, args):
        self.logger.error(
            "BGAPI timed out. Make sure the BLE device is in a known/idle state."
        )
        # might want to try the following lines to reset, though it probably
        # wouldn't work at this point if it's already timed out:
        self.ble.send_command(self.serial, self.ble.ble_cmd_system_reset(0))
        self.ble.check_activity(self.serial, 1)
        self.ble.send_command(self.serial, self.ble.ble_cmd_gap_discover(1))
        self.ble.check_activity(self.serial, 1)

    def on_busy(self, sender, args):
        self.logger.warn("BGAPI device is busy.")

    def scan(self):
        # check for all incoming data (no timeout, non-blocking)
        self.ble.check_activity(self.serial)
Ejemplo n.º 20
0
class BtleCollectionPoint(ModuleProcess):
    def __init__(self, baseConfig, pInBoundQueue, pOutBoundQueue,
                 loggingQueue):
        """ Initialize new CamCollectionPoint instance.
        Setup queues, variables, configs, constants and loggers.
        """
        super(BtleCollectionPoint, self).__init__()
        self.loggingQueue = loggingQueue
        self.logger = ThreadsafeLogger(loggingQueue, __name__)

        # Queues
        self.outQueue = pOutBoundQueue  # Messages from this thread to the main process
        self.inQueue = pInBoundQueue
        self.queueBLE = mp.Queue()

        # Configs
        self.moduleConfig = configLoader.load(self.loggingQueue)
        self.config = baseConfig

        # Variables and objects
        self.registeredClientRegistry = RegisteredClientRegistry(
            self.moduleConfig, self.loggingQueue)
        self.eventManager = EventManager(self.moduleConfig, pOutBoundQueue,
                                         self.registeredClientRegistry,
                                         self.loggingQueue)
        self.alive = True
        self.btleThread = None
        self.BLEThread = None
        self.repeatTimerSweepClients = None

        # Constants
        self._cleanupInterval = self.moduleConfig[
            'AbandonedClientCleanupInterval']

    def run(self):
        ###Pausing Startup to wait for things to start after a system restart
        self.logger.info(
            "Pausing execution 15 seconds waiting for other system services to start"
        )
        time.sleep(15)
        self.logger.info(
            "Done with our nap.  Time to start looking for clients")

        self.btleThread = BlueGigaBtleCollectionPointThread(
            self.queueBLE, self.moduleConfig, self.loggingQueue)
        self.BLEThread = Thread(target=self.btleThread.bleDetect,
                                args=(__name__, 10))
        self.BLEThread.daemon = True
        self.BLEThread.start()

        # Setup repeat task to run the sweep every X interval
        self.repeatTimerSweepClients = RepeatedTimer(
            (self._cleanupInterval / 1000),
            self.registeredClientRegistry.sweepOldClients)

        # Process queue from main thread for shutdown messages
        self.threadProcessQueue = Thread(target=self.processQueue)
        self.threadProcessQueue.setDaemon(True)
        self.threadProcessQueue.start()

        #read the queue
        while self.alive:
            if not self.queueBLE.empty():
                result = self.queueBLE.get(block=False, timeout=1)
                self.__handleBtleClientEvents(result)

    def processQueue(self):
        self.logger.info(
            "Starting to watch collection point inbound message queue")
        while self.alive:
            if not self.inQueue.empty():
                self.logger.info("Queue size is %s" % self.inQueue.qsize())
                try:
                    message = self.inQueue.get(block=False, timeout=1)
                    if message is not None:
                        if (message.topic == "SHUTDOWN"
                                and message.sender_id == 'main'):
                            self.logger.info("SHUTDOWN command handled on %s" %
                                             __name__)
                            self.shutdown()
                        else:
                            self.handleMessage(message)
                except Exception as e:
                    self.logger.error("Unable to read queue, error: %s " % e)
                    self.shutdown()
                self.logger.info("Queue size is %s after" %
                                 self.inQueue.qsize())
            else:
                time.sleep(.25)

    def __handleBtleClientEvents(self, detectedClients):
        for client in detectedClients:
            self.logger.debug("--- Found client ---")
            self.logger.debug(vars(client))
            self.logger.debug("--- Found client end ---")
            self.eventManager.registerDetectedClient(client)

    def handleMessage(self, msg):
        # Handle incoming messages, eg. from other collection points
        pass

    def shutdown(self):
        self.logger.info("Shutting down")
        self.repeatTimerSweepClients.stop()
        self.btleThread.stop()
        self.alive = False
        time.sleep(1)
        self.exit = True
class BtleCollectionPoint(Thread):
    def __init__(self, baseConfig, pInBoundQueue, pOutBoundQueue,
                 loggingQueue):
        """ Initialize new CamCollectionPoint instance.
        Setup queues, variables, configs, constants and loggers.
        """
        super().__init__()
        # super().__init__(baseConfig, pInBoundQueue, pOutBoundQueue, loggingQueue)
        self.loggingQueue = loggingQueue
        self.logger = ThreadsafeLogger(loggingQueue, __name__)

        # Queues
        self.outQueue = pOutBoundQueue  # Messages from this thread to the main process
        self.inQueue = pInBoundQueue

        # Configs
        self.moduleConfig = configLoader.load(self.loggingQueue, __name__)
        self.config = baseConfig

        # Variables and objects
        self.alive = True
        self.callbacks = {_ON_SCAN: self.handleBtleClientEvent}
        self.clientRegistry = ClientRegistry(self.moduleConfig,
                                             self.loggingQueue)

        self.eventManager = EventManager(self.moduleConfig, pOutBoundQueue,
                                         self.clientRegistry,
                                         self.loggingQueue)

        # Threads
        self.btleThread = None
        self.repeatTimerSweepClients = None

        self.lastUpdate = datetime.now()

        # Constants
        self._cleanupInterval = self.moduleConfig[
            'AbandonedClientCleanupInterval']

    def run(self):
        """
        Main thread entrypoint.
        Sets up and starts the DeviceThread.
        Loops repeatedly reading incoming messages.
        """
        # Pause for a bit to let things bootup on host machine
        self.logger.info("Pausing execution 15 seconds" +
                         " waiting for other system services to start")
        time.sleep(15)
        self.logger.info("Done with our nap. " +
                         "Time to start looking for clients")

        # Start device thread, handles IO
        self.deviceThread = BlueGigaDeviceThread(self.callbacks,
                                                 self.moduleConfig,
                                                 self.loggingQueue)
        self.deviceThread.start()

        # Setup repeat task to run the sweep every X interval
        self.repeatTimerSweepClients = RepeatedTimer(
            (self._cleanupInterval / 1000),
            self.clientRegistry.sweepOldClients)

        self.logger.info(
            "Starting to watch collection point inbound message queue")
        while self.alive:
            if not self.inQueue.empty():
                self.logger.info("Queue size is %s" % self.inQueue.qsize())
                try:
                    message = self.inQueue.get(block=False, timeout=1)
                    if message is not None:
                        if (message.topic == "SHUTDOWN"
                                and message.sender_id == 'main'):
                            self.logger.info("SHUTDOWN command handled on %s" %
                                             __name__)
                            self.shutdown()
                        else:
                            self.handleMessage(message)
                except Exception as e:
                    self.logger.error("Unable to read queue, error: %s " % e)
                    self.shutdown()
                self.logger.info("Queue size is %s after" %
                                 self.inQueue.qsize())
            else:
                time.sleep(.45)

    def handleBtleClientEvent(self, detectedClient):
        self.eventManager.registerDetectedClient(detectedClient)

    def handleMessage(self, msg):
        # Handle incoming messages, eg. from other collection points
        pass

    def killProcess(self, proc, timeout=1):
        """
        Kill a process, given a timeout to join.
        """
        self.logger.info('Joining process: %s' % proc)
        proc.join()
        p_sec = 0
        for second in range(timeout):
            if proc.is_alive():
                time.sleep(1)
                p_sec += 1
        if p_sec >= timeout:
            self.logger.info('Terminating process: %s' % proc)
            proc.terminate()

    def shutdown(self):
        self.logger.info("Shutting down")
        self.repeatTimerSweepClients.stop()
        self.eventManager.stop()
        self.deviceThread.stop()
        # self.killProcess(self.deviceThread)
        self.alive = False
        time.sleep(1)
        self.exit = True
Ejemplo n.º 22
0
class MultiTracker(object):
    def __init__(self, kind="KCF", moduleConfig=None, loggingQueue=None):
        """ Create an initialize new MultiTracker. Set up constants and parameters. """

        self.config = moduleConfig
        self.trackers = []  # List of trackers
        self.kind = kind
        self.focus = None
        self.loggingQueue = loggingQueue

        # Constants
        self._useVelocity = self.config['UseVelocity']
        self._closestThreshold = self.config["ClosestThreshold"]
        self._primaryTarget = self.config['PrimaryTarget']

        # Setup logging queue
        self.logger = ThreadsafeLogger(loggingQueue, __name__)

    def add(self, bbox, frame, kind="KCF"):
        """ Add new tracker with default type KCF. """
        aTracker = Tracker(bbox, frame, kind, self.config, self.loggingQueue)
        self.trackers.append(aTracker)

    def removeAt(self, i):
        """ Remove Tracker at index i. """
        self.trackers.pop(i)

    def remove(self, aTracker):
        """ Remove tracker provided as parameter. """
        self.trackers.remove(aTracker)

    def update(self, frame):
        """ Loop through each tracker updating bounding box, keep track of failures. """

        bboxes = []
        ind = 0
        failed = []
        for aTracker in self.trackers:
            ok, bbox = aTracker.update(frame)
            if not ok:
                failed.append(ind)
            else:
                bboxes.append(bbox)
            ind += 1
        if len(failed) == 0:
            return True, bboxes, None
        else:
            self.logger.error('Failed to update all trackers')
            return False, bboxes, failed

    def clear(self):
        """ Remove all trackers. """
        self.trackers.clear()
        self.focus = None

    def bboxContainsPt(self, bbox, pt, vBuffer):
        """ Check if bbox contains pt. 
		Optionally provide velocity buffer to spread containing space. 
		"""
        if ((bbox['x'] - vBuffer[0] <= pt[0] <=
             (bbox['x'] + bbox['w'] + vBuffer[0]))
                and (bbox['y'] - vBuffer[1] <= pt[1] <=
                     (bbox['y'] + bbox['h'] + vBuffer[1]))):
            return True
        else:
            return False

    def projectedLocationMatches(self, tracker, bbox):
        """ Check if the velocity of the tracker could put it in the same spot as the bbox. """
        if tracker.velocity:
            return self.bboxContainsPt(bbox,
                                       tracker.getProjectedLocation(time()),
                                       tracker.getVelocityBuffer())
        else:
            return False

    def intersects(self, tracker, bbox):
        """ Check if the bbox and the trackers bounds intersect. """
        if (tracker.right() < bbox['x']
                or bbox['x'] + bbox['w'] < tracker.left()
                or tracker.top() < bbox['y']
                or bbox['y'] + bbox['h'] < tracker.bottom()):
            return False  # intersection is empty
        else:
            return True  # intersection is not empty

    def contains(self, bbox):
        """ Check if the MultiTracker already has a tracker for the object detected. 
		Uses intersections and projected locations to determine if the tracker overlaps others.
		This means objects that overlap when first detected will not _both_ be added to the MultiTracker.
		"""

        for aTracker in self.trackers:
            if self._useVelocity:
                if self.intersects(aTracker,
                                   bbox) and self.projectedLocationMatches(
                                       aTracker, bbox):
                    return True
            elif self.intersects(aTracker, bbox):
                return True
        return False

    def length(self):
        """ Get number of Trackers in the MultiTracker. """
        return len(self.trackers)

    def getFocus(self):
        """ Get focal object based on primaryTarget configuration.
		Currently only closest is supported - checks whether there is a tracker
		that is larger than the previous closest tracker by the configured threshold.
		"""

        if self._primaryTarget == "closest":
            focusChanged = False
            if self.focus:
                # area = self.focus.area()
                area = self.focus.area()
            else:
                area = None
            for aTracker in self.trackers:
                # If there's no focus or aTracker is larger than focus, and they aren't the same tracker
                if not self.focus or (
                        aTracker.area() > area *
                    (1 + (self._closestThreshold / 100))
                        and self.focus.getCreated() != aTracker.getCreated()):
                    focusChanged = True
                    self.focus = aTracker
                    area = aTracker.area()
            if focusChanged:
                return self.focus
            else:
                return None

        elif self._primaryTarget == "closest_engaged":
            #TODO
            self.logger.error('Primary Target %s is not implemented.' %
                              self._primaryTarget)
            return None
        else:
            self.logger.error('Primary Target %s is not implemented.' %
                              self._primaryTarget)
            return None

    def checkFocus(self):
        """ Check if focal Tracker has changed by updating the focus. """

        focus = self.getFocus()
        if focus:
            return True, focus.bbox
        else:
            return False, None
Ejemplo n.º 23
0
class DeviceThread(Thread):
    """
    Controller thread, manage the instance of BluegigaDevice.
    """
    def __init__(self, callbacks, btleConfig, loggingQueue, debugMode=False):
        super().__init__()
        # Logger
        self.loggingQueue = loggingQueue
        self.logger = ThreadsafeLogger(loggingQueue, __name__)
        self.alive = True
        self.callbacks = self.sanitizeCallbacks(callbacks)
        self.btleConfig = btleConfig

        # consts
        self._majorMin = self.btleConfig['BtleAdvertisingMajorMin']
        self._majorMax = self.btleConfig['BtleAdvertisingMajorMax']
        self._minorMin = self.btleConfig['BtleAdvertisingMinorMin']
        self._minorMax = self.btleConfig['BtleAdvertisingMinorMax']
        self._uuidFocusList = self.btleConfig['BtleUuidFocusList']

        if ('any' in self._uuidFocusList or 
            'all' in self._uuidFocusList or
            len(self._uuidFocusList)==0):
            self.filterOnUuid = False
        else:
            self.filterOnUuid = True

        # self.queue = queue
        self.device = BluegigaDevice(
            self.scanCallback,
            self.btleConfig,
            self.loggingQueue)

    def run(self):
        """
        Main thread entry point.
        Repeatedly call scan() method on
        device controller BluegigaDevice.

        Send results or failures back to main
        thread via callbacks.
        """
        try:
            self.device.start()
        except Exception as e:
            self.logger.error("Unable to connect to BTLE device: %s"%e)
            self.sendFailureNotice("Unable to connect to BTLE device")
            self.stop()

        while self.alive:
            # try:
            self.device.scan()
            # except Exception as e:
            #     self.logger.error("Unable to scan BTLE device: %s"%e)
            #     self.sendFailureNotice("Unable to connect to BTLE device to perform a scan")
            #     self.stop()

            # don't burden the CPU
            time.sleep(0.01)

    def scanCallback(self,sender,args):
        """
        Callback for the scan event on the device controller.
        Prints the event in a formatted way for tuning purposes.
        """
        #check to make sure there is enough data to be a beacon
        if len(args["data"]) > 15:
            try:
                majorNumber = args["data"][26] | (args["data"][25] << 8)
                # self.logger.debug("majorNumber=%i"%majorNumber)
            except:
                majorNumber = 0
            try:
                minorNumber = args["data"][28] | (args["data"][27] << 8)
                # self.logger.debug("minorNumber=%i"%minorNumber)
            except:
                minorNumber = 0

            try:
                udid = "%s" % ''.join(['%02X' % b for b in args["data"][9:25]])
            except:
                pass

            if (self.filterOnUuid and udid not in self._uuidFocusList):
                return

            if (not (self._majorMin <= majorNumber <= self._majorMax) or 
                not (self._minorMin <= minorNumber <= self._minorMax)):
                    return

            rssi = args["rssi"]
            beaconMac = "%s" % ''.join(['%02X' % b for b in args["sender"][::-1]])

            if len(args["data"]) > 29:
                rawTxPower = args["data"][29]
            else:
                rawTxPower = 0

            if rawTxPower <= 127:
                txPower = rawTxPower
            else:
                txPower = rawTxPower - 256

            if self.btleConfig['BtleTestMode']:
                self.logger.debug("=============================== eventScanResponse START ===============================")
                #self.logger.debug("self.btleConfig['BtleAdvertisingMinor'] == %i and self.btleConfig['BtleAdvertisingMinor'] == %i "%(majorNumber,minorNumber))
                #self.logger.debug("yep, we care about this major and minor so lets create a detected client and pass it to the event manager")
                self.logger.debug("Major=%s"%majorNumber)
                self.logger.debug("Minor=%s"%minorNumber)
                self.logger.debug("UDID=%s"%udid)
                self.logger.debug("rssi=%s"%rssi)
                self.logger.debug("beaconMac=%s"%beaconMac)
                self.logger.debug("txPower=%i"%txPower)
                self.logger.debug("rawTxPower=%i"%rawTxPower)
                self.logger.debug("================================= eventScanResponse END =================================")

            #package it up for sending to the queue
            detectionData = DetectionData(
                'btle',
                udid=udid,
                beaconMac=beaconMac,
                majorNumber=majorNumber,
                minorNumber=minorNumber,
                tx=txPower,
                rssi=rssi)
            
            #put it on the queue for the event manager to pick up
            self.callbacks[_ON_SCAN](detectionData)

    def sanitizeCallbacks(self, cbs):
        """
        Make sure required callbacks are included and callable.
        Return only the required callbacks.
        """
        assert(callable(cbs[_ON_SCAN]))
        if len(cbs) > 1:
            return [cbs[_ON_SCAN]]
        return cbs

    def stop(self):
        self.alive = False

    def sendFailureNotice(self, msg):
        if len(self.btleConfig['SlackChannelWebhookUrl']) > 10:
            myMsg = ("Help, I've fallen and can't get up! "+
                "\n %s. \nSent from %s"%(msg,platform.node()))
            payload = {'text': myMsg}
            r = requests.post(
                self.btleConfig['SlackChannelWebhookUrl'], 
                data = json.dumps(payload))
Ejemplo n.º 24
0
class CollectionModule(ModuleProcess):

    # You can keep these parameters the same, all modules receive the same params
    # self - reference to self
    # baseConfig - configuration settings defined in /simplesensor/config/base.conf 
    #               (https://github.com/AdobeAtAdobe/SimpleSensor/blob/master/config/base.conf)
    # pInBoundQueue - messages from handler to this module
    # pOutBoundQueue - messages from this module to other modules
    # loggingQueue - logging messages for threadsafe logger

    def __init__(self, baseConfig, pInBoundQueue, pOutBoundQueue, loggingQueue):
        """ 
        Initialize new CollectionModule instance.
        """
        super(CollectionModule, self).__init__(baseConfig, pInBoundQueue, pOutBoundQueue, loggingQueue)

        # Most collection modules will follow a similar pattern...

        # 1. Set up some variables on the self object
        # Queues
        self.outQueue = pOutBoundQueue
        self.inQueue= pInBoundQueue
        self.loggingQueue = loggingQueue
        self.threadProcessQueue = None
        self.alive = False

        self.context = None
        self.reader = None

        # 2. Load the module's configuration file
        # Configs
        self.moduleConfig = configLoader.load(self.loggingQueue, __name__)
        self.config = baseConfig

        # 3. Set some constants to the self object from config parameters (if you want)
        self._id = self.moduleConfig['CollectionPointId']
        self._type = self.moduleConfig['CollectionPointType']
        self._port = self.moduleConfig['ReaderPortNumber']

        # 4. Create a threadsafe logger object
        self.logger = ThreadsafeLogger(loggingQueue, __name__)

    def run(self):
        """
        Main process method, run when the thread's start() function is called.
        Starts monitoring inbound messages to this module, and collection logic goes here.
        For example, you could put a loop with a small delay to keep polling the sensor, etc.
        When something is detected that's relevant, put a message on the outbound queue.
        """

        # Monitor inbound queue on own thread
        self.listen()
        self.alive = True

        while self.context == None:
            self.establish_context()

        while self.alive:
            while self.reader == None:
                self.reader = self.get_reader()
                if self.reader is None:
                    self.logger.info('Waiting for 5 seconds before '
                    + 'trying to find readers again. Is it plugged in?')
                    time.sleep(5)

            # connect to card
            card = self.get_card()
            if card is None: 
                continue

            # get block #10 and 11 of card,
            # contains the attendee ID
            msg = [0xFF, 0xB0, 0x00, bytes([10])[0], 0x04]
            chunk_one = self.send_transmission(card, msg)
            if chunk_one is None:
                self.reader = None
                continue
            msg = [0xFF, 0xB0, 0x00, bytes([11])[0], 0x04]
            chunk_two = self.send_transmission(card, msg)
            if chunk_two is None:
                self.reader = None
                continue

            # the id is in B1-3 of block 10
            # and B0-2 of block 11
            attendee_id_bytes = bytearray(chunk_one[1:4]+chunk_two[0:3])
            attendee_id = attendee_id_bytes.decode('UTF-8')
            xdata = {
                'attendee_id': attendee_id
            }
            msg = self.build_message(topic='scan_in', extendedData=xdata)
            self.logger.info('Sending message: {}'.format(msg))
            self.put_message(msg)

            self.reader = None

            # sleep for a bit to avoid double scanning
            time.sleep(5)

    def establish_context(self):
        hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
        if hresult != SCARD_S_SUCCESS:
            self.logger.error(
                'Unable to establish context: {}'.format(
                    SCardGetErrorMessage(hresult)))
            return
        self.context = hcontext

    def get_reader(self):
        hresult, readers = SCardListReaders(self.context, [])
        if hresult != SCARD_S_SUCCESS:
            self.logger.error(
                'Failed to list readers: {}'.format(
                    SCardGetErrorMessage(hresult)))
            return
        if len(readers)<1 or len(readers)-1<self._port:
            self.logger.error(
                'Not enough readers attached. {} needed, {} attached'.format(
                    (self._port+1), (len(readers))))
            return
        else:
            return readers[self._port]

    def get_card(self, mode=None, protocol=None):
        hresult, hcard, dwActiveProtocol = SCardConnect(
                self.context,
                self.reader,
                mode or SCARD_SHARE_SHARED, 
                protocol or (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1))
        if hresult != SCARD_S_SUCCESS:
            return
        else:
            return hcard

    def send_transmission(self, card, msg, protocol=None):
        hresult, response = SCardTransmit(
                            card, 
                            protocol or SCARD_PCI_T1, 
                            msg)
        if hresult != SCARD_S_SUCCESS:
            self.logger.error(
                'Failed to send transmission: {}'.format(
                    SCardGetErrorMessage(hresult)))
            return
        else:
            return response[:-2]

    def listen(self):
        """
        Start thread to monitor inbound messages, declare module alive.
        """
        self.threadProcessQueue = Thread(target=self.process_queue)
        self.threadProcessQueue.setDaemon(True)
        self.threadProcessQueue.start()

    def build_message(self, topic, extendedData={}, recipients=['communication_modules']):
        """
        Create a Message instance.

        topic (required): message type
        sender_id (required): id property of original sender
        sender_type (optional): type of sender, ie. collection point type, module name, hostname, etc
        extended_data (optional): payload to deliver to recipient(s)
        recipients (optional): module name, which module(s) the message will be delivered to, ie. `websocket_server`.
                                use an array of strings to define multiple modules to send to.
                                use 'all' to send to all available modules.
                                use 'local_only' to send only to modules with `low_cost` prop set to True.
                                [DEFAULT] use 'communication_modules' to send only to communication modules.
                                use 'collection_modules' to send only to collection modules.
        """

        msg = Message(
            topic=topic,
            sender_id=self._id, 
            sender_type=self._type, 
            extended_data=extendedData, 
            recipients=recipients, 
            timestamp=datetime.datetime.utcnow())
        return msg

    def put_message(self, msg):
        """
        Put message onto outgoing queue.
        """
        self.outQueue.put(msg)

    def process_queue(self):
        """
        Process inbound messages on separate thread.
        When a message is encountered, trigger an event to handle it.
        Sleep for some small amount of time to avoid overloading.
        Also receives a SHUTDOWN message from the main process when 
        the user presses the esc key.
        """

        self.logger.info("Starting to watch collection point inbound message queue")
        while self.alive:
            if (self.inQueue.empty() == False):
                self.logger.info("Queue size is %s" % self.inQueue.qsize())
                try:
                    message = self.inQueue.get(block=False,timeout=1)
                    if message is not None:
                        self.handle_message(message)
                except Exception as e:
                    self.logger.error("Error, unable to read queue: %s " %e)
                    self.shutdown()
                self.logger.info("Queue size is %s after" % self.inQueue.qsize())
            else:
                time.sleep(.25)

    def handle_message(self, message):
        """
        Handle messages from other modules to this one.
        Switch on the message topic, do something with the data fields.
        """
        if message.topic.upper()=='SHUTDOWN' and message.sender_id=='main':
            self.shutdown()

    def shutdown(self):
        """
        Shutdown the collection module.
        Set alive flag to false so it stops looping.
        Wait for things to die, then exit.
        """

        self.alive = False
        print("Shutting down nfc_bcard_reader")
        time.sleep(1)
        self.exit = True
Ejemplo n.º 25
0
class RegisteredClientRegistry(object):
    eventRegisteredClientRemoved = RegistryEvent()
    eventRegisteredClientAdded = RegistryEvent()
    eventRegisteredClientUpdated = RegistryEvent()
    eventSweepComplete = RegistryEvent()

    def __init__(self, collectionPointConfig, loggingQueue):
        # Logger
        self.loggingQueue = loggingQueue
        self.logger = ThreadsafeLogger(loggingQueue, __name__)

        self.rClients = {}  #registered clients
        self.collectionPointConfig = collectionPointConfig  #collection point config

    def getRegisteredClient(self, udid):
        """Get an existing registered client by udid and if its found return it.  If no existing registered client is found return None."""
        try:
            eClient = self.rClients[udid]
        except KeyError:
            eClient = None

        return eClient

    def sweepOldClients(self):
        """look at the registry and look for expired inactive clients.  Returns a list of removed clients"""
        self.logger.debug("*** Sweeping clients existing count %s***" %
                          len(self.rClients))

        clientsToBeRemoved = []  #list of clients to be cleaned up

        currentExpireTime = time.time() - (
            self.collectionPointConfig['AbandonedClientTimeout'] / 1000)

        for udid in self.rClients:
            regClient = self.rClients[udid]

            if regClient.lastRegisteredTime < currentExpireTime:
                clientsToBeRemoved.append(regClient)

        for client in clientsToBeRemoved:
            self.logger.debug("Client sweep removing udid %s" %
                              client.getUdid())
            self.removeRegisteredClient(client)

        self.logger.debug("*** End of sweeping tags existing count %s***" %
                          len(self.rClients))

        self.eventSweepComplete(clientsToBeRemoved)

        return clientsToBeRemoved

    def addNewRegisteredClient(self, registeredClient):
        self.logger.debug("in addNewRegisteredClient with %s" %
                          registeredClient.getUdid())
        self.rClients[registeredClient.getUdid()] = registeredClient
        self.eventRegisteredClientAdded(registeredClient)  #throw event

    def updateRegisteredClient(self, registeredClient):
        self.logger.debug("in updateRegisteredClient with %s" %
                          registeredClient.getUdid())
        self.rClients[registeredClient.getUdid()] = registeredClient
        self.eventRegisteredClientUpdated(registeredClient)  #throw event

    def removeRegisteredClient(self, registeredClient):
        self.logger.debug("in removeRegisteredClient with %s" %
                          registeredClient.getUdid())
        self.rClients.pop(registeredClient.getUdid())
        self.eventRegisteredClientRemoved(registeredClient)  #throw event
Ejemplo n.º 26
0
class ClientRegistry(object):
    onClientRemoved = RegistryEvent()
    onClientAdded = RegistryEvent()
    onClientUpdated = RegistryEvent()
    onSweepComplete = RegistryEvent()

    def __init__(self,collectionPointConfig,loggingQueue):
        # Logger
        self.loggingQueue = loggingQueue
        self.logger = ThreadsafeLogger(loggingQueue, __name__)

        self.rClients = {}  #registered clients
        self.collectionPointConfig = collectionPointConfig

    def getAll(self, thresh=-68):
        """
        Get registered clients as dict
        Only return clients above thresh RSSI
        """
        toret = {}
        for k, v in self.rClients.items():
            xdata = v.getExtendedDataForEvent()
            if xdata['rssi']>thresh:
                toret[k] = xdata
        return toret

    def getUpdateData(self, thresh=-68):
        return {'nearby': self.getAll(thresh)}

    def getClient(self,mac):
        """
        Get an existing registered client by mac 
        and if its found return it. 
        If no existing registered client is found 
        return None.
        """
        try:
            eClient = self.rClients[mac]
        except KeyError:
            eClient = None

        return eClient

    def sweepOldClients(self):
        """
        Look at the registry and look for expired
        and inactive clients.  

        Returns a list of removed clients.
        """
        self.logger.debug("*** Sweeping clients existing count" +
            " %s***"%len(self.rClients))

        clientsToBeRemoved=[] #list of clients to be cleaned up

        clientTimeout = self.collectionPointConfig['AbandonedClientTimeout']
        now = datetime.now()

        for mac in self.rClients:
            regClient = self.rClients[mac]

            # self.logger.debug('now-regClient.lastRegisteredTime ---- clientTimeout >0 : %s ---- %s'%(((now-regClient.lastRegisteredTime).total_seconds()*1000), clientTimeout))
            # if regClient.sweepShouldSendClientOutEvent():
            if (now-regClient.lastRegisteredTime).total_seconds()*1000-clientTimeout>0:
                clientsToBeRemoved.append(regClient)

        for client in clientsToBeRemoved:
            # self.logger.debug("Client sweep removing mac %s"%client.getMac())
            self.removeClient(client)

        self.logger.debug("*** End of sweeping tags existing count "+
            "%s***"%len(self.rClients))

        self.onSweepComplete(clientsToBeRemoved)

        return clientsToBeRemoved

    def addClient(self,client):
        #self.logger.debug("in addNewRegisteredClient with %s"%client.getUdid())
        self.rClients[client.getMac()] = client
        self.onClientAdded(client)

    def updateClient(self,client):
        #self.logger.debug("in updateRegisteredClient with %s"%client.getUdid())
        self.rClients[client.getMac()] = client
        self.onClientUpdated(client)

    def removeClient(self,client):
        #self.logger.debug("in removeRegisteredClient with %s"%client.getUdid())
        self.logger.info('length before remove: %s'%len(self.rClients))
        self.rClients.pop(client.getMac())
        self.logger.info('length after remove: %s'%len(self.rClients))
        self.onClientRemoved(client)
Ejemplo n.º 27
0
class MQTTClientModule(ModuleProcess):
    """ Threaded MQTT client for processing and publishing outbound messages"""
    def __init__(self, baseConfig, pInBoundEventQueue, pOutBoundEventQueue,
                 loggingQueue):

        super(MQTTClientModule, self).__init__()
        self.config = baseConfig
        self.alive = True
        self.inQueue = pInBoundEventQueue

        # Module config
        self.moduleConfig = configLoader.load(self.loggingQueue, __name__)

        # Constants
        self._keepAlive = self.moduleConfig['MqttKeepAlive']
        self._feedName = self.moduleConfig['MqttFeedName']
        self._username = self.moduleConfig['MqttUsername']
        self._key = self.moduleConfig['MqttKey']
        self._host = self.moduleConfig['MqttHost']
        self._port = self.moduleConfig['MqttPort']
        self._publishJson = self.moduleConfig['MqttPublishJson']

        # MQTT setup
        self._client = mqtt.Client()
        self._client.username_pw_set(self._username, self._key)
        self._client.on_connect = self.onConnect
        self._client.on_disconnect = self.onDisconnect
        self._client.on_message = self.onMessage
        self.mqttConnected = False

        # Logging setup
        self.logger = ThreadsafeLogger(loggingQueue, "MQTT")

    def onConnect(self, client, userdata, flags, rc):
        self.logger.debug('MQTT onConnect called')
        # Result code 0 is success
        if rc == 0:
            self.mqttConnected = True

            # Subscribe to feed here
        else:
            self.logger.error('MQTT failed to connect: %s' % rc)
            raise RuntimeError('MQTT failed to connect: %s' % rc)

    def onDisconnect(self, client, userdata, rc):
        self.logger.debug('MQTT onDisconnect called')
        self.mqttConnected = False
        if rc != 0:
            self.logger.debug('MQTT disconnected unexpectedly: %s' % rc)
            self.handleReconnect(rc)

    def onMessage(self, client, userdata, msg):
        self.logger.debug('MQTT onMessage called for client: %s' % client)

    def connect(self):
        """ Connect to MQTT broker
        Skip calling connect if already connected.
        """
        if self.mqttConnected:
            return

        self._client.connect(self._host,
                             port=self._port,
                             keepalive=self._keepAlive)

    def disconnect(self):
        """ Check if connected"""
        if self.mqttConnected:
            self._client.disconnect()

    def subscribe(self, feed=False):
        """Subscribe to feed, defaults to feed specified in config"""
        if not feed: feed = self._feedName
        self._client.subscribe('{0}/feeds/{1}'.format(self._username, feed))

    def publish(self, value, feed=False):
        """Publish a value to a feed"""
        if not feed: feed = self._feedName
        self._client.publish('{0}/feeds/{1}'.format(self._username, feed),
                             payload=value)

    def flattenDict(self, aDict):
        """ Get average of simple dictionary of numerical values """
        try:
            val = float(sum(aDict[key] for key in aDict)) / len(aDict)
        except Exception as e:
            self.logger.error('Error flattening dict, returning 0: %s' % e)
            return 0
        return val

    def publishJsonMessage(self, message):
        msg_str = self.stringifyMessage(message)
        self.publish(msg_str)

    def stringifyMessage(self, message):
        """ Dump into JSON string """
        return json.dumps(message.__dict__).encode('utf8')

    def processQueue(self):
        """ Process incoming messages. """

        while self.alive:
            # Pump the loop
            self._client.loop(timeout=1)
            if (self.inQueue.empty() == False):
                try:
                    message = self.inQueue.get(block=False, timeout=1)
                    if message is not None and self.mqttConnected:
                        if (message.topic.upper() == "SHUTDOWN"
                                and message.sender_id.lower() == 'main'):
                            self.logger.debug("SHUTDOWN command handled")
                            self.shutdown()
                        else:
                            # Send message as string or split into channels
                            if self._publishJson:
                                self.publishJsonMessage(message)
                            else:
                                self.publishValues(message)

                except Exception as e:
                    self.logger.error("MQTT unable to read queue : %s " % e)
            else:
                time.sleep(.25)

    def shutdown(self):
        self.logger.info("Shutting down")
        self.alive = False
        time.sleep(1)
        self.exit = True

    def run(self):
        """ Thread start method"""
        self.logger.info("Running MQTT")

        self.connect()
        self.alive = True

        # Start queue loop
        self.processQueue()
class WebsocketServerModule(ModuleProcess):
    def __init__(self, baseConfig, pInBoundQueue, pOutBoundQueue,
                 loggingQueue):

        # super(WebsocketServerModule, self).__init__()
        ModuleProcess.__init__(self, baseConfig, pInBoundQueue, pOutBoundQueue,
                               loggingQueue)
        self.alive = False
        self.config = baseConfig
        self.inQueue = pInBoundQueue  # inQueue are messages from the main process to websocket clients
        self.outQueue = pOutBoundQueue  # outQueue are messages from clients to main process
        self.websocketServer = None
        self.loggingQueue = loggingQueue
        self.threadProcessQueue = None

        # Configs
        self.moduleConfig = configLoader.load(self.loggingQueue, __name__)

        # Constants
        self._port = self.moduleConfig['WebsocketPort']
        self._host = self.moduleConfig['WebsocketHost']

        # logging setup
        self.logger = ThreadsafeLogger(loggingQueue, __name__)

    def run(self):
        """ Main thread entry point.

        Sets up websocket server and event callbacks.
        Starts thread to monitor inbound message queue.
        """

        self.logger.info("Starting websocket server")
        self.alive = True
        self.listen()

        self.websocketServer = WebsocketServer(self._port, host=self._host)
        self.websocketServer.set_fn_new_client(self.new_websocket_client)
        self.websocketServer.set_fn_message_received(
            self.websocket_message_received)
        self.websocketServer.run_forever()

    def new_websocket_client(self, client, server):
        """ Client joined callback - called whenever a new client joins. """

        self.logger.debug("Client joined")

    def websocket_message_received(self, client, server, message):
        """ Message received callback - called whenever a new message is received. """

        self.logger.debug('Message received: %s' % message)
        message = json.loads(message)
        self.logger.info("message jsond: %s" % message)
        _msg = Message(topic=message['topic'], sender_id=message['sender_id'])
        if 'sender_type' in message:
            _msg.sender_type = message['sender_type']
        if 'recipients' in message:
            _msg.recipients = message['recipients']
        if 'extended_data' in message:
            _msg.extended_data = message['extended_data']

        self.put_message(_msg)

    def listen(self):
        self.threadProcessQueue = Thread(target=self.process_queue)
        self.threadProcessQueue.setDaemon(True)
        self.threadProcessQueue.start()

    def shutdown(self):
        """ Handle shutdown message. 
        Close and shutdown websocket server.
        Join queue processing thread.
        """

        self.logger.info("Shutting down websocket server")

        try:
            self.logger.info("Closing websocket")
            self.websocketServer.server_close()
        except Exception as e:
            self.logger.error("Websocket close error : %s " % e)

        try:
            self.logger.info("Shutdown websocket")
            self.websocketServer.shutdown()
        except Exception as e:
            self.logger.error("Websocket shutdown error : %s " % e)

        self.alive = False

        self.threadProcessQueue.join()

        time.sleep(1)
        self.exit = True

    def handle_message(self, message):
        """ Send message to listening clients. """
        self.websocketServer.send_message_to_all(json.dumps(message.__dict__))

    def process_queue(self):
        """ Monitor queue of messages from main process to this thread. """

        while self.alive:
            if (self.inQueue.empty() == False):
                try:
                    message = self.inQueue.get(block=False, timeout=1)
                    if message is not None:
                        if (message.topic.upper() == "SHUTDOWN"
                                and message.sender_id.lower() == 'main'):
                            self.logger.debug("SHUTDOWN handled")
                            self.shutdown()
                        else:
                            self.handle_message(message)
                except Exception as e:
                    self.logger.error("Websocket unable to read queue : %s " %
                                      e)
            else:
                time.sleep(.25)
Ejemplo n.º 29
0
class Tracker():
	def __init__(self, bbox, frame, kind, moduleConfig, loggingQueue):
		""" Create and initialize a new Tracker. Set up constants and parameters. """

		if kind in ["KCF", "MIL", "MEDIANFLOW", "GOTURN", "TLD", "BOOSTING"]:
			self.tracker = cv2.Tracker_create(kind)
			self.tracker.init(frame, (bbox['x'], bbox['y'], bbox['w'], bbox['h']))
			self.created = time()
			self.bbox = (bbox['x'], bbox['y'], bbox['w'], bbox['h'])
			self.velocity = (0, 0)
			self.updateTime = self.created
			self.config = moduleConfig

			# Constants
			self._useVelocity = self.config['UseVelocity']
			self._horizontalVelocityBuffer = self.config['HorizontalVelocityBuffer']
			self._verticalVelocityBuffer = self.config['VerticalVelocityBuffer']

			# Setup logging queue
			self.logger = ThreadsafeLogger(loggingQueue, __name__)
		else:
			self.logger.error("Type %s not supported by mTracker" % kind)

	def getCreated(self):
		""" Get created time """
		return self.created

	def right(self):
		""" Get right bound of tracker """
		return self.bbox[0] + self.bbox[2]

	def top(self):
		""" Get top bound of tracker """
		return self.bbox[1] + self.bbox[3]

	def bottom(self):
		""" Get bottom bound of tracker """
		return self.bbox[1]

	def left(self):
		""" Get left bound of tracker """
		return self.bbox[0]

	def area(self):
		""" Get area of tracker bounding box """
		return abs(self.right() - self.left())*abs(self.top() - self.bottom())

	def update(self, frame):
		""" Update tracker.
		If velocity hack is being used, calculate the new velocity of the midpoint. 
		"""
		ok, bbox = self.tracker.update(frame)

		if self._useVelocity:
			# Set velocity (pixels/sec)
			deltaT = time() - self.updateTime
			centreNow = ((bbox[0]+bbox[2]/2), (bbox[1]+bbox[3]/2))
			centreLast = ((self.bbox[0]+self.bbox[2]/2), (self.bbox[1]+self.bbox[3]/2))
			Vx = (centreNow[0] - centreLast[0])/deltaT
			Vy = (centreNow[1] - centreLast[1])/deltaT
			self.velocity = (Vx, Vy)
			self.logger.debug('New velocity: %s' % str(self.velocity[0])+', '+str(self.velocity[1]))

			self.updateTime = time()

		self.bbox = bbox

		return ok, bbox

	def getProjectedLocation(self, time):
		""" Get the estimated location of the bounding box, based on previous velocity. """

		deltaT = max((time - self.updateTime), 1)
		centreNow = ((self.bbox[0]+self.bbox[2]/2), (self.bbox[1]+self.bbox[3]/2))
		projectedX = centreNow[0]+(self.velocity[0]*deltaT)
		projectedY = centreNow[1]+(self.velocity[1]*deltaT)
		return (projectedX, projectedY)

	def getVelocityBuffer(self):
		''' Another hack to improve low frame rate tracking.
		"Spread" out the bounding box based on velocity.
		'''
		return (abs(self.velocity[0])*self._horizontalVelocityBuffer,
			abs(self.velocity[1])*self._verticalVelocityBuffer)
Ejemplo n.º 30
0
class BtleClient(object):
    def __init__(self, detectionData, collectionPointConfig, loggingQueue):
        self.loggingQueue = loggingQueue
        self.logger = ThreadsafeLogger(loggingQueue, "BtleRegisteredClient")
        
        # Counters and variables
        self.clientInRangeTrigerCount = 1
        self.prevClientInMsgTime = None
        self.prevClientOutMsgTime = None
        self.numClientInRange=0
        self.numClientOutRange=0
        self.timeInCollectionPointInMilliseconds = 0
        self.firstRegisteredTime = datetime.now()
        self.collectionPointConfig = collectionPointConfig
        self.filter = Filter(detectionData.extraData['rssi'])
        try:
            self.uidMap = UIDMap()
        except Exception as e:
            self.logger.warning('cant instantiate uid map: %s '%e)

        # Constants
        self._proximityEventInterval = self.collectionPointConfig['ProximityEventInterval']
        self._outClientThreshold = self.collectionPointConfig['BtleClientOutCountThreshold']

        self._gatewayType = self.collectionPointConfig['GatewayType']

        self._rssiClientInThresh = self.collectionPointConfig['BtleRssiClientInThreshold']
        self._rssiErrorVar = self.collectionPointConfig['BtleRssiErrorVariance']
        self.__clientOutThresholdMin = int(
            self._rssiClientInThresh + 
            (self._rssiClientInThresh * self._rssiErrorVar)
            )
        self._clientInThreshType = self.collectionPointConfig['BtleRssiClientInThresholdType']
        self._debugEventManager = self.collectionPointConfig['EventManagerDebug']

        # Initiate event when client is detected
        self.handleNewDetectedClientEvent(detectionData)

    def updateWithNewDetectedClientData(self, detectionData):
        """
        updateWithNewDetectedClientData
        part of interface for Registered Client
        """
        self.timeInCollectionPointInMilliseconds = (datetime.now() - self.firstRegisteredTime).total_seconds()*1000
        # standard shared methods when we see a detected client
        self.handleNewDetectedClientEvent(detectionData)

    # Common methods are handled here for updateWithNewDetectedClientData and init
    def handleNewDetectedClientEvent(self, detectionData):
        self.lastRegisteredTime = datetime.now()
        self.detectionData = detectionData
        self.txPower = detectionData.extraData['tx']
        self.beaconId = detectionData.extraData['udid']
        self.filter.update(self.detectionData.extraData['rssi'])
        self.incrementInternalClientEventCounts(detectionData)

    def incrementInternalClientEventCounts(self, detectionData):
        if self._gatewayType == 'proximity':
            if self._clientInThreshType == 'rssi':
                # Are they in or are they out of range 
                # Increment internal count, used to normalize events.
                if (self.detectionData.extraData['rssi'] >= self._rssiClientInThresh):
                    self.numClientInRange += 1
                    self.numClientOutRange = 0
                    self.logClientRange("CLIENTIN")
                elif (self.detectionData.extraData['rssi'] < self.__clientOutThresholdMin):
                    self.numClientOutRange += 1
                    self.numClientInRange = 0
                    self.logClientRange("CLIENTOUT")

    #part of interface for Registered Client
    def shouldSendClientInEvent(self):
        if self._gatewayType == 'proximity':
            if (self.prevClientInMsgTime == None or 
                (self.prevClientOutMsgTime != None and 
                    (self.prevClientOutMsgTime-self.prevClientInMsgTime).total_seconds() > 0) or
                (datetime.now() - self.prevClientInMsgTime).total_seconds()*1000 >= self._proximityEventInterval):
                    if self.numClientInRange > self.clientInRangeTrigerCount:
                        # self.logClientEventSend(" ClientIN event sent to controller ")
                        self.zeroEventRangeCounters()
                        return True

        #TODO add in other types of gateway types
        # self.logger.debug("NOT SENDING CLIENT IN")
        return False

    #part of interface for Registered Client
    def shouldSendClientOutEvent(self):
        if self._gatewayType == 'proximity':
            #check the time to see if we need to send a message
            #have we ever sent an IN event? if not we dont need to send an out event
            if self.prevClientInMsgTime:
                #have we sent a client out since the last client in?  if so we dont need to throw another
                if (self.prevClientOutMsgTime == None or self.prevClientOutMsgTime < self.prevClientInMsgTime):
                    #do we have enought qualifying out events. we dont want to throw one too soon
                    if (self.numClientOutRange >= self._outClientThreshold):
                        # self.logClientEventSend("ClientOUT event a sent to controller")
                        self.logger.debug("out case B: client %s"%self.detectionData.extraData["beaconMac"])
                        self.zeroEventRangeCounters()
                        return True
                elif (self.prevClientOutMsgTime != None and 
                    self.prevClientOutMsgTime > self.prevClientInMsgTime):
                        return False

                #check timing on last event sent
                if (self.prevClientOutMsgTime is not None and
                    (datetime.now() - self.prevClientOutMsgTime).total_seconds()*1000 > self._proximityEventInterval):
                        # self.logClientEventSend("ClientOUT event b sent to controller")
                        self.logger.debug("out case A: client %s"%self.detectionData.extraData["beaconMac"])
                        self.zeroEventRangeCounters()
                        return True
                elif self.prevClientOutMsgTime is not None:
                    return False
            elif self.numClientOutRange > self._outClientThreshold:
                # self.logger.debug("Client out count "+
                #    "%i is past max.  Resetting." %self.numClientOutRange)
                self.numClientOutRange = 0

        #TODO add in other types of gateway types
        return False

    #part of interface for Registered Client
    def sweepShouldSendClientOutEvent(self):
        self.logger.debug("trace 1")
        if self._gatewayType == 'proximity':
            # has an in event been sent yet? if not, no sweep needed
            self.logger.debug("trace 2")
            if self.prevClientInMsgTime:
                self.logger.debug("trace 3")
                # sweep old clients, so check most recent message sent
                # if no message has been sent in the past proximityEventInterval*3 milliseconds
                # sweep the client because it is probably gone
                if (self.prevClientOutMsgTime is None or 
                    (self.prevClientInMsgTime>self.prevClientOutMsgTime and
                    (datetime.now() - self.prevClientOutMsgTime).total_seconds()*1000 > 
                        self._proximityEventInterval*3)):
                            self.logger.debug("trace 4")
                            self.logger.debug("sweep: client %s"%self.detectionData.extraData["beaconMac"])
                            # self.logClientEventSend("Sweep case a is sending ClientOUT on")
                            self.zeroEventRangeCounters()
                            return True
                else:
                    self.logger.debug("trace 5")
                    return False
            else:
                self.logger.debug("trace 6")
                return False
        #TODO add in other types of gateway types
        self.logger.debug("trace 7")
        return False

    #part of interface for Registered Client
    def getMac(self):
        return self.detectionData.extraData["beaconMac"]

    def getTxPower(self):
        return self.txPower

    #zero out the BTLE event counters
    def zeroEventRangeCounters(self):
        self.numClientOutRange = 0
        self.numClientInRange = 0

    def logClientEventSend(self,message):
        if self._debugEventManager:
            self.logger.debug("")
            self.logger.debug("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
            self.logger.debug("%%%%%%%%%%%%%%%%%% %s %%%%%%%%%%%%%%%%%%" %message)
            self.logger.debug("    MAC is %s " %self.getMac())
            self.logger.debug("    Beacon ID is %s " %self.beaconId)
            self.logger.debug("    filtered RSSI %i" %self.filter.state)
            self.logger.debug("    RSSI %i" %self.detectionData.extraData['rssi'])
            self.logger.debug("    Major %i" %self.detectionData.extraData['majorNumber'])
            self.logger.debug("    Minor %i" %self.detectionData.extraData['minorNumber'])
            self.logger.debug("    BTLE RSSI client in threshold %i" %self.collectionPointConfig['BtleRssiClientInThreshold'])
            self.logger.debug("    BTLE RSSI client out threshold %i" %self.__clientOutThresholdMin)
            self.logger.debug("    inCount %i : outCount %i" %(self.numClientInRange,self.numClientOutRange))
            self.logger.debug("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
            self.logger.debug("")
        return


    def logClientRange(self,eventType):
        if self.collectionPointConfig['ShowClientRangeDebug']:

            if eventType.upper() == "CLIENTIN":
                self.logger.debug("<<<<<<<<<<<<<<<<< IN RANGE <<<<<<<<<<<<<<<<<")
            else:
                self.logger.debug(">>>>>>>>>>>>>>>>> OUT OF RANGE >>>>>>>>>>>>>>>>>")

            self.logger.debug("    MAC is %s " %self.getMac())
            self.logger.debug("    Beacon ID is %s " %self.beaconId)
            self.logger.debug("    RSSI %i" %self.detectionData.extraData['rssi'])
            self.logger.debug("    Major %i" %self.detectionData.extraData['majorNumber'])
            self.logger.debug("    Minor %i" %self.detectionData.extraData['minorNumber'])
            self.logger.debug("    BTLE RSSI client in threshold %i" %self.collectionPointConfig['BtleRssiClientInThreshold'])
            self.logger.debug("    BTLE RSSI client out threshold %i" %self.__clientOutThresholdMin)
            self.logger.debug("    inCount %i : outCount %i" %(self.numClientInRange,self.numClientOutRange))

            if eventType.upper() == "CLIENTIN":
                self.logger.debug("<<<<<<<<<<<<<<<<< IN RANGE END <<<<<<<<<<<<<<<<<")
            else:
                self.logger.debug(">>>>>>>>>>>>>>>>> OUT OF RANGE END >>>>>>>>>>>>>>>>>")

            self.logger.debug("")
        return

    #part of interface for Registered Client
    def getExtendedDataForEvent(self):
        extraData = {}
        extraData['gatewayType'] = self.collectionPointConfig['GatewayType']
        extraData['lastRegisteredTime'] = self.lastRegisteredTime if self.lastRegisteredTime==None else self.lastRegisteredTime.isoformat() 
        extraData['firstRegisteredTime'] = self.firstRegisteredTime if self.firstRegisteredTime==None else self.firstRegisteredTime.isoformat() 
        extraData['prevClientInMsgTime'] = self.prevClientInMsgTime if self.prevClientInMsgTime==None else self.prevClientInMsgTime.isoformat()
        extraData['prevClientOutMsgTime'] = self.prevClientOutMsgTime if self.prevClientOutMsgTime==None else self.prevClientOutMsgTime.isoformat()
        extraData['timeInCollectionPointInMilliseconds'] = self.timeInCollectionPointInMilliseconds
        extraData['rssi'] = self.detectionData.extraData['rssi']
        extraData['averageRssi'] = self.detectionData.extraData['rssi']
        extraData['filteredRssi'] = self.filter.state
        extraData['txPower'] = self.getTxPower()
        extraData['beaconId'] = self.beaconId
        extraData['beaconMac'] = self.detectionData.extraData["beaconMac"]
        extraData['major'] = self.detectionData.extraData["majorNumber"]
        extraData['minor'] = self.detectionData.extraData["minorNumber"]
        if self.collectionPointConfig['CecData']:
            extraData['industry'] = self.uidMap.get(self.beaconId)

        return extraData
       
    def getExtendedDataForUpdateEvent(self):
        extraData = {}
        extraData['rssi'] = self.detectionData.extraData['rssi']
        extraData['filteredRssi'] = self.filter.state
        extraData['beaconId'] = self.beaconId
        extraData['beaconMac'] = self.detectionData.extraData["beaconMac"]
        extraData['major'] = self.detectionData.extraData["majorNumber"]
        extraData['minor'] = self.detectionData.extraData["minorNumber"]
        if self.collectionPointConfig['CecData']:
            extraData['industry'] = self.uidMap.get(self.beaconId)

        return extraData

    #part of interface for Registered Client
    def setClientInMessageSentToController(self):
        self.logger.debug('set client in message sent')
        self.prevClientInMsgTime = datetime.now()
        self.numClientInRange = 0

    #part of interface for Registered Client
    def setClientOutMessageSentToController(self):
        self.logger.debug('set client out message sent')
        self.prevClientOutMsgTime = datetime.now()
        self.numClientOutRange = 0