예제 #1
0
    def test_present_log_expired(self):
        """Ensures a log from the present is not expired."""

        logger = BeaconLogger(logfolder, 'test if present log expired')
        present = datetime.now()

        logger._log_datetime = present
        self.assertEqual(logger._log_expired(present.date(), present.hour), False)
예제 #2
0
    def test_future_log_expired(self):
        """Ensures a log from the future does not crash the system."""
        logger = BeaconLogger(logfolder, 'test if future log expired')
        present = datetime.now()
        future = present + timedelta(days=1)

        logger._log_date = future
        self.assertEqual(logger._log_expired(present.date(), present.hour), True)
예제 #3
0
    def test_future_log_expired(self):
        """Ensures a log from the future does not crash the system."""
        logger = BeaconLogger(logfolder, 'test if future log expired')
        present = datetime.now()
        future = present + timedelta(days=1)

        logger._log_date = future
        self.assertEqual(logger._log_expired(present.date(), present.hour),
                         True)
예제 #4
0
    def test_present_log_expired(self):
        """Ensures a log from the present is not expired."""

        logger = BeaconLogger(logfolder, 'test if present log expired')
        present = datetime.now()

        logger._log_datetime = present
        self.assertEqual(logger._log_expired(present.date(), present.hour),
                         False)
예제 #5
0
    def test_make_log_dir(self):
        """Ensure method creates a directory in the primary log folder."""
        logger = BeaconLogger(logfolder, 'test _makedir')
        logger._make_log_dir('floob')

        # make sure the folder was created
        self.assertEqual(os.path.exists('/'.join([logfolder, 'floob'])), True)

        # make sure return value is true if folder already exists
        self.assertEqual(logger._make_log_dir('floob'), None)
예제 #6
0
    def test_make_log_dir(self):
        """Ensure method creates a directory in the primary log folder."""
        logger = BeaconLogger(logfolder, 'test _makedir')
        logger._make_log_dir('floob')

        # make sure the folder was created
        self.assertEqual(os.path.exists('/'.join([logfolder, 'floob'])), True)

        # make sure return value is true if folder already exists
        self.assertEqual(logger._make_log_dir('floob'), None)
예제 #7
0
    def test_constructor_no_preexisting_logfolder(self):
        logger = BeaconLogger(logfolder,
                              'constructor test w/ no preexisting log folder')

        # make sure log file was created
        self.assertEqual(os.path.exists(logfolder), True)

        # make sure log handlers are empty
        self.assertEqual(logger._log.handlers, [])
예제 #8
0
    def test_get_new_log_file(self):
        """Tests the method that returns a new path to the current logging file."""

        logger = BeaconLogger(logfolder, 'test get new log file')
        log_dir = '/'.join([logfolder, str(datetime.now().date())])
        somefile = 'somefile.txt'

        # create non empty non-expired log directory
        os.makedirs(log_dir)
        open(log_dir + '/' + somefile, 'a').close()

        present = datetime.now()
        new_path = logger._get_new_log_file(present.date(), present.hour)
        expected = '/'.join([log_dir, str(present.hour)]) + '.txt'

        # Make sure path is correct, path exists, and the old file is still there
        self.assertEqual(new_path, expected)
        self.assertEqual(os.path.exists(log_dir), True)
        self.assertEqual(os.path.exists(log_dir + '/' + somefile), True)
예제 #9
0
    def test_get_new_log_file(self):
        """Tests the method that returns a new path to the current logging file."""

        logger = BeaconLogger(logfolder, 'test get new log file')
        log_dir = '/'.join([logfolder, str(datetime.now().date())])
        somefile = 'somefile.txt'
        
        # create non empty non-expired log directory
        os.makedirs(log_dir)
        open(log_dir + '/' + somefile, 'a').close()

        present = datetime.now()
        new_path = logger._get_new_log_file(present.date(), present.hour)
        expected = '/'.join([log_dir, str(present.hour)]) + '.txt'

        # Make sure path is correct, path exists, and the old file is still there
        self.assertEqual(new_path, expected)
        self.assertEqual(os.path.exists(log_dir), True)
        self.assertEqual(os.path.exists(log_dir + '/' + somefile), True)
예제 #10
0
    def test_constructor_with_existing_logfolder(self):

        # Create logfolder and new logger
        os.makedirs(logfolder)
        logger = BeaconLogger(logfolder,
                              'constructor test w/ no preexisting log folder')

        # make sure log folder exists
        self.assertEqual(os.path.exists(logfolder), True)

        # make sure log handlers are empty
        self.assertEqual(logger._log.handlers, [])
예제 #11
0
    def test_log_beacon(self):
        print 'testing log beacon'
        logger = BeaconLogger(logfolder, 'testing log beacon')
        beaconID = 'SOMEBEACONID'
        rssi = 'SOMERSSI'
        logger.log_beacon(beaconID, rssi)

        # Expected log file path
        now = datetime.now()
        log_path = logfolder + '/' + str(now.date()) + '/' + str(now.hour) + '.txt'
        expected_fh_path = os.getcwd() + '/' + log_path

        # Actual logged message
        f = open(log_path, 'r')
        logged_data = f.readline().strip().split('\t')
        f.close()

        # TODO test that the date is accurate
        self.assertEqual(os.path.exists(log_path), True)
        self.assertEqual(logged_data[1], beaconID)
        self.assertEqual(logged_data[2], rssi)
예제 #12
0
    def test_log_beacon(self):
        print 'testing log beacon'
        logger = BeaconLogger(logfolder, 'testing log beacon')
        beaconID = 'SOMEBEACONID'
        rssi = 'SOMERSSI'
        logger.log_beacon(beaconID, rssi)

        # Expected log file path
        now = datetime.now()
        log_path = logfolder + '/' + str(now.date()) + '/' + str(
            now.hour) + '.txt'
        expected_fh_path = os.getcwd() + '/' + log_path

        # Actual logged message
        f = open(log_path, 'r')
        logged_data = f.readline().strip().split('\t')
        f.close()

        # TODO test that the date is accurate
        self.assertEqual(os.path.exists(log_path), True)
        self.assertEqual(logged_data[1], beaconID)
        self.assertEqual(logged_data[2], rssi)
예제 #13
0
    def __init__(self,
                 logpath,
                 debug=False,
                 debug_handler=None,
                 devname='hci0',
                 rssi_threshold=-100):
        """Creates a new Scanner object."""
        # Set up beacon logging
        self._beaconlog = BeaconLogger(logpath, 'beacon_logger')
        self._devname = devname

        # Set up info/debug logging (default output to stdout)
        self._log = logging.getLogger(__name__)
        debug_handler = debug_handler if debug_handler else logging.StreamHandler(
        )
        self._log.addHandler(debug_handler)

        # Info logging will be suppressed if not debugging
        if debug:
            self._log.setLevel(logging.INFO)

        # Set rssi threshold
        self._rssi_threshold = rssi_threshold
예제 #14
0
    def __init__(self, logpath, debug=False, debug_handler=None, devname='hci0', rssi_threshold=-100):
        """Creates a new Scanner object."""
        # Set up beacon logging
        self._beaconlog = BeaconLogger(logpath, 'beacon_logger')
        self._devname = devname

        # Set up info/debug logging (default output to stdout)
        self._log = logging.getLogger(__name__)
        debug_handler = debug_handler if debug_handler else logging.StreamHandler()
        self._log.addHandler(debug_handler)
        
        # Info logging will be suppressed if not debugging
        if debug:
            self._log.setLevel(logging.INFO)

        # Set rssi threshold
        self._rssi_threshold = rssi_threshold
예제 #15
0
    def test_past_log_expired(self):
        """Ensures an old log is expired."""

        logger = BeaconLogger(logfolder, "test past log expired")

        # possible past times (past by a day and hr, just a day, just an hr)
        past = logger._log_datetime
        present = datetime.now()
        past_hr = present - timedelta(hours=1)
        past_day = present - timedelta(days=1)

        logger._log_datetime = past
        self.assertEqual(logger._log_expired(present.date(), present.hour),
                         True)
        logger._log_datetime = past_hr
        self.assertEqual(logger._log_expired(present.date(), present.hour),
                         True)
        logger._log_datetime = past_day
        self.assertEqual(logger._log_expired(present.date(), present.hour),
                         True)
예제 #16
0
    def test_past_log_expired(self):
        """Ensures an old log is expired."""

        logger = BeaconLogger(logfolder, "test past log expired")

        # possible past times (past by a day and hr, just a day, just an hr)
        past = logger._log_datetime
        present = datetime.now()
        past_hr = present - timedelta(hours=1)
        past_day = present - timedelta(days=1)

        logger._log_datetime = past
        self.assertEqual(logger._log_expired(present.date(), present.hour), True)
        logger._log_datetime = past_hr
        self.assertEqual(logger._log_expired(present.date(), present.hour), True)
        logger._log_datetime = past_day
        self.assertEqual(logger._log_expired(present.date(), present.hour), True)
예제 #17
0
    def test_assign_handler(self):
        """Ensures the correct file handler is assigned."""

        logger = BeaconLogger(logfolder, 'test assign handler')

        # Calculate expected handler path
        now = datetime.now()
        log_path = logfolder + '/' + str(now.date()) + '/' + str(
            now.hour) + '.txt'
        expected_path = os.getcwd() + '/' + log_path

        # Execute method
        logger._assign_handler(now.date(), now.hour)

        self.assertEqual(logger._log.handlers[0].baseFilename, expected_path)

        # check if we can remove and add a filehandler
        logger._log_datetime = logger._log_datetime - timedelta(hours=2)
        logger._assign_handler(now.date(), now.hour)

        self.assertEqual(len(logger._log.handlers), 1)
        self.assertEqual(logger._log.handlers[0].baseFilename, expected_path)
예제 #18
0
    def test_assign_handler(self):
        """Ensures the correct file handler is assigned."""

        logger = BeaconLogger(logfolder, 'test assign handler')

        # Calculate expected handler path
        now = datetime.now()
        log_path = logfolder + '/' + str(now.date()) + '/' + str(now.hour) + '.txt'
        expected_path = os.getcwd() + '/' + log_path

        # Execute method
        logger._assign_handler(now.date(), now.hour)

        self.assertEqual(logger._log.handlers[0].baseFilename, expected_path)

        # check if we can remove and add a filehandler  
        logger._log_datetime = logger._log_datetime - timedelta(hours=2)
        logger._assign_handler(now.date(), now.hour)

        self.assertEqual(len(logger._log.handlers), 1)
        self.assertEqual(logger._log.handlers[0].baseFilename, expected_path)
예제 #19
0
class BeaconScanner():
    def __init__(self,
                 logpath,
                 debug=False,
                 debug_handler=None,
                 devname='hci0',
                 rssi_threshold=-100):
        """Creates a new Scanner object."""
        # Set up beacon logging
        self._beaconlog = BeaconLogger(logpath, 'beacon_logger')
        self._devname = devname

        # Set up info/debug logging (default output to stdout)
        self._log = logging.getLogger(__name__)
        debug_handler = debug_handler if debug_handler else logging.StreamHandler(
        )
        self._log.addHandler(debug_handler)

        # Info logging will be suppressed if not debugging
        if debug:
            self._log.setLevel(logging.INFO)

        # Set rssi threshold
        self._rssi_threshold = rssi_threshold

    def _lescan(self):
        """Executes the hcitool lescan command and checks for expected output."""
        self._log.info('Starting LEscan...')
        command = ['sudo', 'stdbuf', '-oL', 'hcitool', 'lescan']
        lescan = subprocess.Popen(command, stdout=subprocess.PIPE)
        r = lescan.stdout.readline()

        # Check if output is indicative of a successful lescan
        if r != 'LE Scan ...\n':
            # Kill process and return False
            self._log.warn('LEscan command failed.')
            os.system('sudo kill %s' % lescan.pid)
            return False

        return True

    def _toggle_dongle(self):
        """Toggles the Bluetooth dongle: off/on."""
        # Turn Bluetooth dongle off
        self._log.info('Turning off bt dongle')
        command = ['sudo', 'hciconfig', self._devname, 'down']
        p = subprocess.Popen(command, stdout=subprocess.PIPE)
        p.wait()

        # Turn Bluetooth dongle on
        self._log.info('Turning on bt dongle')
        command[3] = 'up'
        p = subprocess.Popen(command, stdout=subprocess.PIPE)
        p.wait()

    def _recover_lescan(self):
        """Attempts to restart the lescan command. Exits if this fails."""
        self._log.warn("LEscan command failed. Attempting to recover.")

        # Toggling on and off the bt dongle historically works
        self._toggle_dongle()

        # Try to start lescan; exit if failure
        if not self._lescan():
            self._log.error("Error: lescan could not recover.")
            exit(1)

    def _hcidump(self):
        """Executes the hcitools hcidump command which outputs all bluetooth activity."""
        self._log.info('Starting hcidump...')
        command = ['sudo', 'stdbuf', '-oL', 'hcidump']
        return subprocess.Popen(command, stdout=subprocess.PIPE)

    def log_beacons(self):
        """Indefinitely logs the ID and RSSI of advertising Bluetooth LE devices."""
        # Execute lescan command: listens for advertising btle devices
        if not self._lescan():
            self._recover_lescan()

        # Execute hcidump command: outputs all
        hcidump = self._hcidump()

        while 1:
            # Read device information
            r = hcidump.stdout.readline()
            info = r.strip().split()

            if info[0] == 'bdaddr':
                beaconID = info[1]

            elif info[0] == 'RSSI:':
                rssi = info[1]

                # Log beacon data if RSSI is above the threshold
                if int(rssi) > self._rssi_threshold:
                    # Log beacon data
                    self._beaconlog.log_beacon(beaconID, rssi)
                    self._log.info('Logging beacon.. ID: %s\tRSSI: %s' %
                                   (beaconID, rssi))
예제 #20
0
class BeaconScanner():
    def __init__(self, logpath, debug=False, debug_handler=None, devname='hci0', rssi_threshold=-100):
        """Creates a new Scanner object."""
        # Set up beacon logging
        self._beaconlog = BeaconLogger(logpath, 'beacon_logger')
        self._devname = devname

        # Set up info/debug logging (default output to stdout)
        self._log = logging.getLogger(__name__)
        debug_handler = debug_handler if debug_handler else logging.StreamHandler()
        self._log.addHandler(debug_handler)
        
        # Info logging will be suppressed if not debugging
        if debug:
            self._log.setLevel(logging.INFO)

        # Set rssi threshold
        self._rssi_threshold = rssi_threshold

    def _lescan(self):
        """Executes the hcitool lescan command and checks for expected output."""
        self._log.info('Starting LEscan...')
        command = ['sudo', 'stdbuf', '-oL', 'hcitool', 'lescan', '--duplicates']
        lescan = subprocess.Popen(command, stdout=subprocess.PIPE)
        r = lescan.stdout.readline()

        # Check if output is indicative of a successful lescan
        if r != 'LE Scan ...\n':
            # Kill process and return False
            self._log.warn('LEscan command failed.')
            os.system('sudo kill %s' % lescan.pid)
            return False

        return True

    def _toggle_dongle(self):
        """Toggles the Bluetooth dongle: off/on."""
        # Turn Bluetooth dongle off
        self._log.info('Turning off bt dongle')
        command = ['sudo', 'hciconfig', self._devname, 'down']
        p = subprocess.Popen(command, stdout=subprocess.PIPE)
        p.wait()

        # Turn Bluetooth dongle on
        self._log.info('Turning on bt dongle')
        command[3] = 'up'
        p = subprocess.Popen(command, stdout=subprocess.PIPE)
        p.wait()

    def _recover_lescan(self):
        """Attempts to restart the lescan command. Exits if this fails."""
        self._log.warn("LEscan command failed. Attempting to recover.")
        
        # Toggling on and off the bt dongle historically works
        self._toggle_dongle()

        # Try to start lescan; exit if failure
        if not self._lescan():
            self._log.error("Error: lescan could not recover.")
            exit(1)

    def _hcidump(self):
        """Executes the hcitools hcidump command which outputs all bluetooth activity."""
        self._log.info('Starting hcidump...')
        command = ['sudo', 'stdbuf', '-oL', 'hcidump']
        return subprocess.Popen(command, stdout=subprocess.PIPE)

    def log_beacons(self):
        """Indefinitely logs the ID and RSSI of advertising Bluetooth LE devices."""
        # Execute lescan command: listens for advertising btle devices
        if not self._lescan():
            self._recover_lescan()

        # Execute hcidump command: outputs all 
        hcidump = self._hcidump()

        while 1:
            # Read device information
            r = hcidump.stdout.readline()
            info = r.strip().split()

            if info[0] == 'bdaddr':
                beaconID =  info[1]

            elif info[0] == 'RSSI:':
                rssi = info[1]

		# Log beacon data if RSSI is above the threshold
	        if int(rssi) > self._rssi_threshold:
                    # Log beacon data
                    self._beaconlog.log_beacon(beaconID, rssi)
                    self._log.info('Logging beacon.. ID: %s\tRSSI: %s' % (beaconID, rssi))