예제 #1
0
class Advertiser(object):
    """Instantiates a BLE beacon advertiser.
    
    Attributes:
        control_file (pathlib.Path): BLE beacon advertiser control file path.
        timeout (float, int): BLE beacon advertiser timeout (s). Must be 
            strictly positive and less than 600.
        uuid (str): BLE beacon advertiser UUID. Must be 32 hexadecimal digits 
            split into 5 groups separated by hyphens. The number of digits in 
            each group from first to last) is {8, 4, 4, 4, 12}.
        major (int): BLE beacon advertiser major value. Must be in [1, 65535].
        minor (int): BLE beacon advertiser minor value. Must be in [1, 65535].
        tx_power (int): BLE beacon advertiser TX power value. Must be in 
            [-40, 4].
        interval (int): BLE beacon advertiser interval (ms) value. Must be in 
            [20, 10000].
    """

    def __init__(self, logger, **kwargs):
        """Instance initialization.

        Args:
            logger (logging.Logger): Configured logger.
            **kwargs: Keyword arguments corresponding to instance attributes. 
                Any unassociated keyword arguments are ignored.
        """
        # Logger
        self.__logger = logger
        # Beacon settings
        for key, value in DEFAULT_CONFIG['advertiser'].items():
            if key in kwargs and kwargs[key]:
                setattr(self, key, kwargs[key])
            else:
                self.__logger.debug("Using default beacon advertiser "
                        f"configuration {key}: {value}.")
                setattr(self, key, value)
        # Create beacon
        self.__service = BeaconService(BLE_DEVICE)
        self.__logger.info("Initialized beacon advertiser.")
        
    def __del__(self):
        """Instance destruction."""
        if self.__control_file_handle is not None:
            self.__control_file_handle.close()
        self.__control_file.unlink()
        
    @property
    def control_file(self):
        """BLE beacon advertiser control file path getter."""
        return self.__control_file
    
    @control_file.setter
    def control_file(self, value):
        """BLE beacon advertiser control file path setter.
        
        Raises:
            TypeError: Beacon advertiser control file must be a string.
        """
        if not isinstance(value, str):
            raise TypeError("Beacon advertiser control file must be a string.")
        else:
            self.__control_file = Path(value).resolve()
            self.__control_file.touch()
            self.__control_file.chmod(0o777)
            with self.__control_file.open(mode='w') as f:
                f.write("0")
            self.__control_file_handle = None
                
    @property
    def timeout(self):
        """BLE beacon advertiser timeout getter."""
        return self.__timeout;
    
    @timeout.setter
    def timeout(self, value):
        """BLE beacon advertiser timeout setter.

        Raises:
            TypeError: Beacon advertiser timeout must be a float, integer, or 
                NoneType.
            ValueError: Beacon advertiser timeout must be strictly positive.
            ValueError: Beacon advertisertimeout cannot exceed maximum 
                allowable timeout.
        """
        if value is not None:
            if not isinstance(value, (float, int)):
                raise TypeError("Beacon advertiser timeout must be a float, "
                        "integer, or NoneType.")
            elif value <= 0:
                raise ValueError("Beacon advertiser timeout must be strictly "
                        "positive.")
            elif value > MAX_TIMEOUT:
                raise ValueError("Beacon advertiser timeout cannot exceed "
                        "maximum allowable timeout.")
        self.__timeout = value
    
    @property
    def uuid(self):
        """BLE beacon advertiser UUID getter."""
        return self.__uuid;

    @uuid.setter
    def uuid(self, value):
        """BLE beacon advertiser UUID setter.

        Raises:
            TypeError: Beacon advertiser UUID must be a string.
        """
        if not isinstance(value, str):
            raise TypeError("Beacon advertiser UUID must be a string.")
        elif not value:
            self.__uuid = str(uuid1())
            self.__logger.debug(f"Beacon advertiser UUID set to {self.__uuid}")
        else:
            self.__uuid = value;

    @property
    def major(self):
        """BLE beacon advertiser major value getter."""
        return self.__major

    @major.setter
    def major(self, value):
        """BLE beacon advertiser major value setter.

        Raises:
            TypeError: Beacon advertiser major value must be an integer.
            ValueError: Beacon advertiser major value must be in [1, 65535].
         """
        if not isinstance(value, int):
            raise TypeError("Beacon advertiser major value must be an integer.")
        elif value < MAJOR_LIMITS[0] or value > MAJOR_LIMITS[1]:
            raise ValueError("Beacon advertiser major value must be in range "
                    f"{MAJOR_LIMITS}.")
        self.__major = value
            
    @property
    def minor(self):
        """BLE beacon advertiser minor value getter."""
        return self.__minor

    @minor.setter
    def minor(self, value):
        """BLE beacon advertiser minor value setter.

        Raises:
            TypeError: Beacon advertiser minor value must be an integer.
            ValueError: Beacon advertiser minor value must be in [1, 65535].
         """
        if not isinstance(value, int):
            raise TypeError("Beacon advertiser minor value must be an integer.")
        elif value < MINOR_LIMITS[0] or value > MINOR_LIMITS[1]:
            raise ValueError("Beacon advertiser minor value must be in range "
                    f"{MINOR_LIMITS}.")
        self.__minor = value

    @property
    def tx_power(self):
        """BLE beacon advertiser TX power value getter."""
        return self.__tx_power

    @tx_power.setter
    def tx_power(self, value):
        """BLE beacon Beacon advertiser TX power setter.

        Raises:
            TypeError: Beacon advertiser TX power must be an integer.
            ValueError: Beacon advertiser TX power must be in [-40, 4].
         """
        if not isinstance(value, int):
            raise TypeError("Beacon advertiser TX power must be an integer.")
        elif value < TX_POWER_LIMITS[0] or value > TX_POWER_LIMITS[1]:
            raise ValueError("Beacon advertiser TX power must be in range "
                    f"{TX_POWER_LIMITS}.")
        self.__tx_power = value

    @property
    def interval(self):
        """BLE beacon advertiser interval getter."""
        return self.__interval

    @interval.setter
    def interval(self, value):
        """BLE beacon advertiser interval setter.

        Raises:
            TypeError: Beacon advertiser interval must be an integer.
            ValueError: Beacon advertiser interval must be in [20, 10000].
         """
        if not isinstance(value, int):
            raise TypeError("Beacon advertiser interval must be an integer.")
        elif value < INTERVAL_LIMITS[0] or value > INTERVAL_LIMITS[1]:
            raise ValueError("Beacon advertiser interval must be in range "
                    f"{INTERVAL_LIMITS}.")
        self.__interval = value
            
    def advertise(self, timeout=0):
        """Execute BLE beacon advertisement.
        
        Args:
            timeout (int, float): Time (s) for which to advertise beacon. If
                specified as None then advertises till user commanded stop via
                control file. Defaults to configuration value.
        """
        # Parse inputs
        if timeout == 0:
            timeout = self.timeout
        # Update control file
        with self.__control_file.open(mode='w') as f:
            f.write("0")
        # Start advertising
        self.__logger.info("Starting beacon advertiser with timeout "
                f"{timeout}.")
        self.__service.start_advertising(self.uuid, self.major, self.minor,
                                         self.tx_power, self.interval)
        # Stop advertising based on either timeout or control file
        start_time = time.monotonic()
        self.__control_file_handle = self.__control_file.open(mode='r+')
        run = True
        while run:
            time.sleep(CONTROL_INTERVAL)
            if timeout is not None:
                if (time.monotonic()-start_time) > timeout:
                    self.__logger.debug("Beacon advertiser timed out.")
                    run = False
            self.__control_file_handle.seek(0)
            control_flag = self.__control_file_handle.read()
            if control_flag != "0":
                self.__logger.debug("Beacon advertiser control flag set to "
                        "stop.")
                run = False
        self.__logger.info("Stopping beacon advertiser.")        
        self.__service.stop_advertising()
        # Cleanup
        self.__control_file_handle.close()
        with self.__control_file.open('w') as f:
            f.write("0")
예제 #2
0
#this script that advertises a bluetooth low energy beacon for 15 seconds

import time

from bluetooth.ble import BeaconService  #<--- 3rd party module

#Create an instance of the object from the 3rd party class
service = BeaconService()

service.start_advertising("11111111-2222-3333-4444-555555555555, 1, 1, 1, 200")
time.sleep(15)

service.stop_advertising()

print("DONE")
예제 #3
0
파일: beacon.py 프로젝트: zzma/bleats
#This is a single student implementation of the BLEATS project student initial beacon.


from bluetooth.ble import BeaconService
import time

service = BeaconService()

service.start_advertising("11111111-2222-3333-4444-555555555555",
            1, 1, 1, 200)
time.sleep(15)
service.stop_advertising()

print("Done.")
예제 #4
0
class Advertiser(object):
    """Instantiates a BLE beacon advertiser.
    
    Attributes:
        timeout_a (float, int): BLE beacon advertiser timeout (s). Must be 
            strictly positive and less than 600.
        uuid (str): BLE beacon advertiser UUID. Must be 32 hexadecimal digits 
            split into 5 groups separated by hyphens. The number of digits in 
            each group from first to last) is {8, 4, 4, 4, 12}.
        major (int): BLE beacon advertiser major value. Must be in [1, 65535].
        minor (int): BLE beacon advertiser minor value. Must be in [1, 65535].
        tx_power (int): BLE beacon advertiser TX power value in dbm in range [-70, 4].
        interval (int): BLE beacon advertiser interval (ms) value. Must be in 
            [20, 10000].
    """
    def __init__(self, logger, **kwargs):
        """Instance initialization.

        Args:
            logger (logging.Logger): Configured logger.
            **kwargs: Keyword arguments corresponding to instance attributes. 
                Any unassociated keyword arguments are ignored.
        """
        # Logger
        self.__logger = logger
        # Beacon settings
        for key, value in DEFAULT_CONFIG['advertiser'].items():
            if key in kwargs and kwargs[key]:
                setattr(self, key, kwargs[key])
            else:
                self.__logger.debug("Using default beacon advertiser "
                                    f"configuration {key}: {value}.")
                setattr(self, key, value)
        # Create beacon
        self.__service = BeaconService(BLE_DEVICE)
#        self.__logger.info("Initialized beacon advertiser.")

    def __del__(self):
        """Instance destruction."""
        GPIO.output(16, GPIO.LOW)
        GPIO.output(26, GPIO.LOW)
        GPIO.output(6, GPIO.LOW)

    @property
    def timeout_a(self):
        """BLE beacon advertiser timeout getter."""
        return self.__timeout_a

    @timeout_a.setter
    def timeout_a(self, value):
        """BLE beacon advertiser timeout setter.

        Raises:
            TypeError: Beacon advertiser timeout must be a float, integer, or 
                NoneType.
            ValueError: Beacon advertiser timeout must be strictly positive.
            ValueError: Beacon advertisertimeout cannot exceed maximum 
                allowable timeout.
        """
        if value is not None:
            if not isinstance(value, (float, int)):
                raise TypeError("Beacon advertiser timeout must be a float, "
                                "integer, or NoneType.")
            elif value <= 0:
                raise ValueError("Beacon advertiser timeout must be strictly "
                                 "positive.")
            elif value > MAX_TIMEOUT:
                raise ValueError("Beacon advertiser timeout cannot exceed "
                                 "maximum allowable timeout.")
        self.__timeout_a = value

    @property
    def uuid(self):
        """BLE beacon advertiser UUID getter."""
        return self.__uuid

    @uuid.setter
    def uuid(self, value):
        """BLE beacon advertiser UUID setter.

        Raises:
            TypeError: Beacon advertiser UUID must be a string.
        """
        if not isinstance(value, str):
            raise TypeError("Beacon advertiser UUID must be a string.")
        elif not value:
            self.__uuid = str(uuid1())
            self.__logger.debug(f"Beacon advertiser UUID set to {self.__uuid}")
        else:
            self.__uuid = value

    @property
    def major(self):
        """BLE beacon advertiser major value getter."""
        return self.__major

    @major.setter
    def major(self, value):
        """BLE beacon advertiser major value setter.

        Raises:
            TypeError: Beacon advertiser major value must be an integer.
            ValueError: Beacon advertiser major value must be in [1, 65535].
         """
        if not isinstance(value, int):
            raise TypeError(
                "Beacon advertiser major value must be an integer.")
        elif value < MAJOR_LIMITS[0] or value > MAJOR_LIMITS[1]:
            raise ValueError("Beacon advertiser major value must be in range "
                             f"{MAJOR_LIMITS}.")
        self.__major = value

    @property
    def minor(self):
        """BLE beacon advertiser minor value getter."""
        return self.__minor

    @minor.setter
    def minor(self, value):
        """BLE beacon advertiser minor value setter.

        Raises:
            TypeError: Beacon advertiser minor value must be an integer.
            ValueError: Beacon advertiser minor value must be in [1, 65535].
         """
        if not isinstance(value, int):
            raise TypeError(
                "Beacon advertiser minor value must be an integer.")
        elif value < MINOR_LIMITS[0] or value > MINOR_LIMITS[1]:
            raise ValueError("Beacon advertiser minor value must be in range "
                             f"{MINOR_LIMITS}.")
        self.__minor = value

    @property
    def tx_power(self):
        """BLE beacon advertiser TX power value getter."""
        return self.__tx_power

    @tx_power.setter
    def tx_power(self, value):
        """BLE beacon Beacon advertiser TX power setter.

        Raises:
            TypeError: Beacon advertiser TX power must be an integer.
            ValueError: Beacon advertiser TX power must be in [-70, 4].
         """
        if not isinstance(value, int):
            raise TypeError("Beacon advertiser TX power must be an integer.")
        elif value < TX_POWER_LIMITS[0] or value > TX_POWER_LIMITS[1]:
            raise ValueError("Beacon advertiser TX power must be in range "
                             f"{TX_POWER_LIMITS}.")
        self.__tx_power = value

    @property
    def interval(self):
        """BLE beacon advertiser interval getter."""
        return self.__interval

    @interval.setter
    def interval(self, value):
        """BLE beacon advertiser interval setter.

        Raises:
            TypeError: Beacon advertiser interval must be an integer.
            ValueError: Beacon advertiser interval must be in [20, 10000].
         """
        if not isinstance(value, int):
            raise TypeError("Beacon advertiser interval must be an integer.")
        elif value < INTERVAL_LIMITS[0] or value > INTERVAL_LIMITS[1]:
            raise ValueError("Beacon advertiser interval must be in range "
                             f"{INTERVAL_LIMITS}.")
        self.__interval = value

    def advertise(self, timeout_a=0.5, tx_power=1, interval=500, minor=1):
        """Execute BLE beacon advertisement.
        
        Args:
            timeout_a (int, float): Time (s) for which to advertise beacon. 
                Defaults to configuration value.
            tx_power (int): Beacon advertiser TX power must be an integer in [-70, 4].
            interval (int): BLE beacon advertiser interval (ms) value in [20, 10000].
        """
        # Parse inputs
        if timeout_a == 0:
            timeout_a = self.timeout_a
        if tx_power == 0:
            tx_power = self.tx_power
        # Start advertising
#        GPIO.output(6,GPIO.HIGH);
#        self.__logger.info("Starting beacon advertiser with tx_power "
#                f"{tx_power}.")
        self.__service.start_advertising(self.uuid, self.major, minor,
                                         tx_power, interval)

        time.sleep(timeout_a)
        #        self.__logger.info("Stopping beacon advertiser.")
        self.__service.stop_advertising()