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")
#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")
#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.")
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()