def scanForBle(self): ble = BLERadio() #ble._adapter.ble_backend = "bleak" # Forces bleak even if hcitool works. #ble._adapter.ble_backend = "hcitool" # Forces hcitool. Raises exception if unavailable. print("scanning") found = set() self.byteList = [] self.macList = [] self.rssiList = [] self.nameList = [] scan_responses = set() for advertisement in ble.start_scan(ProvideServicesAdvertisement, Advertisement): self.byteList.append(bytes(advertisement)) addr = advertisement.address self.macList.append(addr) self.rssiList.append(advertisement.rssi) self.nameList.append(advertisement.complete_name) print("Complete name: ", advertisement.complete_name) print("mac: ", addr) print("\t" + repr(advertisement)) print("length ", len(advertisement)) print() if advertisement.scan_response and addr not in scan_responses: scan_responses.add(addr) #print("Addr: ", addr) elif not advertisement.scan_response and addr not in found: found.add(addr) found.add(advertisement) else: continue if str(advertisement.address ) == 'Address(string="a5:a5:a5:a5:a5:a5")': print("SUCCESS") #ble.stop_scan() break ble.stop_scan() print()
def scan(self): ble = BLERadio() print("scanning") found = set() scan_responses = set() self.comlist = [] # By providing Advertisement as well we include everything, not just specific advertisements. for advertisement in ble.start_scan(ProvideServicesAdvertisement, Advertisement, timeout=10): addr = advertisement.address if advertisement.scan_response and addr not in scan_responses: scan_responses.add(addr) elif not advertisement.scan_response and addr not in found: found.add(addr) else: continue print(addr, advertisement) #print(advertisement.) self.comlist.append(advertisement) print("\t" + repr(advertisement)) print() print("scan done") connected = [] self.dropdown.clear() for element in self.comlist: if element.complete_name == None: if element.address not in connected: connected.append(element.address) element.address.__str__() #we need to remove out : Address(string=" and ") self.dropdown.addItem(element.address.__str__()[16:-2]) else: if element.complete_name not in connected: connected.append(element.complete_name) self.dropdown.addItem(element.complete_name)
def connect(self): print("Scanning for a PhysBryk Server advertisement...") ble = BLERadio() # pylint: disable=no-member for adv in ble.start_scan(PhysBrykServerAdvertisement, timeout=10): if adv.complete_name and ("PhysBryk" in adv.complete_name): print(f'Found {adv.complete_name}, connecting...') self._connection = ble.connect(adv) self._name = adv.complete_name if self.connected(): self._core_service = self._connection[CoreService] self._services.append(self._core_service) try: #TODO maybe move this checking to the server side self._electrical_service = self._connection[ ElectricalService] self._services.append(self._electrical_service) except NameError: self._electrical_service = None print(f"{self.getName()} connected") else: print(f'unable to connect to {self.getName()}') break # Stop scanning whether or not we are connected. ble.stop_scan()
# Connect to an "eval()" service over BLE UART. from adafruit_ble import BLERadio from adafruit_ble.advertising.standard import ProvideServicesAdvertisement from adafruit_ble.services.nordic import UARTService ble = BLERadio() uart_connection = None while True: if not uart_connection: print("Trying to connect...") for adv in ble.start_scan(ProvideServicesAdvertisement): if UARTService in adv.services: uart_connection = ble.connect(adv) print("Connected") break ble.stop_scan() if uart_connection and uart_connection.connected: uart_service = uart_connection[UARTService] while uart_connection.connected: s = input("Eval: ") uart_service.write(s.encode("utf-8")) uart_service.write(b'\n') print(uart_service.readline().decode("utf-8"))
neopixels.fill(color) print("New color {:06x}".format(color)) advertisement.color = color ble.stop_advertising() ble.start_advertising(advertisement) time.sleep(0.5) ble.stop_advertising() # The second mode listens for color broadcasts and shows the color of the strongest signal. else: closest = None closest_rssi = -80 closest_last_time = 0 print("Scanning for colors") while not slide_switch.value: for entry in ble.start_scan(AdafruitColor, minimum_rssi=-100, timeout=1): if slide_switch.value: break now = time.monotonic() new = False if entry.address == closest: pass elif entry.rssi > closest_rssi or now - closest_last_time > 0.4: closest = entry.address else: continue closest_rssi = entry.rssi closest_last_time = now discrete_strength = min((100 + entry.rssi) // 5, 10) #print(entry.rssi, discrete_strength)
tx_message = RpsAdvertisement() choice = choices[my_choice_idx] tx_message.test_string = choice d_print(2, "TXing RTA", choice) opponent_choice = None ble.start_advertising(tx_message, interval=MIN_AD_INTERVAL) sending_ns = time.monotonic_ns() ### Timeout value is in seconds ### RSSI -100 is probably minimum, -128 would be 8bit signed min ### window and interval are 0.1 by default - same value means ### continuous scanning (sending Advertisement will interrupt this) for adv in ble.start_scan(RpsAdvertisement, minimum_rssi=-90, timeout=MAX_SEND_TIME_S): received_ns = time.monotonic_ns() d_print(2, "RXed RTA", adv.test_string) opponent_choice_bytes = adv.test_string ### Trim trailing NUL chars from bytes idx = 0 while idx < len(opponent_choice_bytes): if opponent_choice_bytes[idx] == 0: break idx += 1 opponent_choice = opponent_choice_bytes[0:idx].decode("utf-8") break ### We have received one message or exceeded MAX_SEND_TIME_S
new_index=possible.pop() ad_by_key[key] = (ad, ad_time_ns, rssi, new_index) ### Scan all element to display the color for key, value in sorted_data[:rows_n]: ad, ad_time_ns, rssi, index_col = value age_ns = then_ns - ad_time_ns pixel_color=gimme_color(age_ns, rssi) strip[index_col]=pixel_color ### Scan unused index to clear the color for index in possible: strip[index]=(0, 0, 0) while True: ### For all the advertisement for ad in ble.start_scan(minimum_rssi=-127, timeout=scan_time_s): ### Take the timestamp now_ns = time.monotonic_ns() ### If this is a contact tracing advertisement if 3 in ad.data_dict: if ad.data_dict[3] == b'o\xfd': ### Found a Contact Tracing advertisement. addr_text = "".join(["{:02x}".format(b) for b in reversed(ad.address.address_bytes)]) if addr_text in last_ad_by_key: ### Updating existing entry with a new timestamp last_ad_by_key[addr_text] = (ad, now_ns, ad.rssi, last_ad_by_key[addr_text][3]) else: ### Creating a new entry, but we don't know what RGB LED to use yet, so NO_IDX last_ad_by_key[addr_text] = (ad, now_ns, ad.rssi, NO_IDX) delete_very_old(rows, last_ad_by_key) hide_old(last_ad_by_key, time.monotonic_ns() - hide_time_ns)
button_b_pressed = False last_switch_state = None uart_connection = None # See if any existing connections are providing UARTService. if ble.connected: for connection in ble.connections: if UARTService in connection: uart_connection = connection break while True: last_switch_state = None if not uart_connection or not uart_connection.connected: # If not connected... print("Scanning...") for adv in ble.start_scan(ProvideServicesAdvertisement, timeout=5): # Scan... if UARTService in adv.services: # If UARTService found... print("Found a UARTService advertisement.") uart_connection = ble.connect( adv) # Create a UART connection... break # Stop scanning whether or not we are connected. ble.stop_scan() # And stop scanning. while uart_connection and uart_connection.connected: # If connected... if cpb.button_a and not button_a_pressed: # If button A pressed... print("Button A pressed.") # Send a LEFT button packet. if not send_packet(uart_connection, ButtonPacket(ButtonPacket.LEFT, pressed=True)): uart_connection = None continue
class PolymathTraining(): """ Core class used for collecting data from the Polymath system.""" def __init__(self, filename="out.csv"): self.filename = filename self.ble = BLERadio() self.uart_connection = None self.config = None self.sample_rate = 0 # In Hz self.samples_per_packet = 0 self.columns = [] self.sequence = 0 self.data = [] pass def connect(self): result = False if not self.uart_connection: for adv in self.ble.start_scan(ProvideServicesAdvertisement): if UARTServiceCustom in adv.services: print("Found a device to connect to: {0}".format(adv)) self.uart_connection = self.ble.connect(adv, timeout=30) print("Connected Successfully") result = True break self.ble.stop_scan() return result def connected(self): return (self.uart_connection and self.uart_connection.connected) def disconnect(self): self.uart_connection.disconnect() def run(self): if self.connected(): uart_service = self.uart_connection[UARTServiceCustom] if (uart_service.in_waiting > 0): line = uart_service.readline().decode() print(line) if ((line is not None) and (len(line) > 0)): if not self.config: # First try getting the configuration for the system. try: read_config = json.loads(line) print(read_config) print("Parsed JSON successfully") # for key in read_config: # print("Key: {0}, Value {1}".format(key, read_config[key])) if ( ("sample_rate" in read_config) and ("samples_per_packet" in read_config) and ("column_location" in read_config)): self.sample_rate = read_config["sample_rate"] self.samples_per_packet = read_config["samples_per_packet"] self.column_locations = [] for i in range(0, self.samples_per_packet): self.column_locations.append("") for key in read_config["column_location"]: self.column_locations[read_config["column_location"][key]] = key self.config = read_config print("Read a valid config. Columns are {0}".format(self.column_locations)) # Initiate a connection uart_service.write("connect".encode()) # Set up the output file with open(self.filename, "w") as f: f.write("sequence,{0}\n".format(','.join(self.column_locations))) else: print("Not all of the expected keys were present.") except ValueError as e: print("Failed to decode JSON due to: {0}".format(e)) pass else: # Collect data. data = line.strip().split(',') packet = [] add_packet = True #Assume if (len(data) == self.samples_per_packet): for sample in data: try: packet.append(int(sample)) except ValueError: add_packet = False break else: add_packet = False if (add_packet): self.data.append(data) with open(self.filename, "a") as f: f.write("{0},{1}\n".format(self.sequence, ','.join(data))) print("Appended {0}".format(data)) self.sequence += 1 pass
choices = ("rock", "paper", "scissors") while True: if button_left(): tx_message = RpsTestAdvertisement() my_choice = choices[random.randrange(len(choices))] tx_message.test_string = my_choice d_print(2, "RTA txing", my_choice) ble.start_advertising(tx_message, interval=0.05) sending_ns = time.monotonic_ns() ##print("ssssssssss") ##message.test32bit = "ssssssss" ##ble.start_advertising(message) ##time.sleep(5) ##ble.stop_advertising() ### timeout in seconds ### -100 is probably minimum for adv in ble.start_scan(RpsTestAdvertisement, minimum_rssi=-127, timeout=15): d_print(2, "RTA rxed", adv.test_string) ble.stop_scan() ble.stop_advertising() print("GAME OVER")
# This example scans for any BLE advertisements and prints one advertisement and one scan response # from every device found. from adafruit_ble import BLERadio ble = BLERadio() print("scanning") found = set() scan_responses = set() for advertisement in ble.start_scan(): addr = advertisement.address if advertisement.scan_response and addr not in scan_responses: scan_responses.add(addr) elif not advertisement.scan_response and addr not in found: found.add(addr) else: continue print(addr, advertisement) print("\t" + repr(advertisement)) print() print("scan done")
wave = WaveFile(file) i2s = I2SOut(TX, RX, D9) i2s.play(wave) while i2s.playing: pass wave.deinit() i2s.deinit() boundary_violations = 0 while True: if reed_switch.value: # Not Docked hits = 0 try: advertisements = ble.start_scan(timeout=3) for advertisement in advertisements: addr = advertisement.address if (advertisement.scan_response and addr.type == addr.RANDOM_STATIC): if advertisement.complete_name == '<Your 1st beacon name here>': hits |= 0b001 elif advertisement.complete_name == '<Your 2nd beacon name here>': hits |= 0b010 elif advertisement.complete_name == '<Your 3rd beacon name here>': hits |= 0b100 except Exception as e: print(repr(e)) hit_count = len([ones for ones in bin(hits) if ones == '1']) solid.color = hit_status[hit_count] solid.animate()
class PestCamera: def __init__(self): self.connection = sqlite3.connect('pest_alert.db') self.cursor = self.connection.cursor() # Define radio for finding deivice self.ble = BLERadio() # set global variable uart_connection, will be replaced with the service once connected self.uart_connection = None # creating the database, this needs to happen before the while loop command1 = """CREATE TABLE IF NOT EXISTS info(picture_path TEXT, humidity FLOAT, temperature FLOAT)""" self.cursor.execute(command1) # on launch, connect to the device and ask for input noCon = True while noCon: # imageName = 'IMAGE00.JPG' # If there is no uart connection yet, connect to an available device with a UART service, # TODO: Make it connect specifically to our project, and not any UART Device, not important if not self.uart_connection: print("Trying to connect...") for adv in self.ble.start_scan(ProvideServicesAdvertisement): if UARTService in adv.services: self.uart_connection = self.ble.connect(adv) print("Connected") break self.ble.stop_scan() # if there is a Uart device connected, ask the user for an input, then call the function corresponding to the input # TODO: Make this refresh automaticaly and with a button press, needed for CDR if self.uart_connection and self.uart_connection.connected: self.uart_service = self.uart_connection[UARTService] noCon = False # add image, temp, and humidity to database once all are recived # commented out for testing, will need to be working for actual project def addToDB(self, textString): vals = textString.split(", ") print(vals) self.cursor.execute("INSERT INTO info VALUES (?, ?, ?)", (vals[0], vals[1], vals[2])) self.connection.commit() self.cursor.execute("SELECT * FROM info") results = self.cursor.fetchall() # render_template('template.html', value=results) print(results) # Testing function to get text from the device, can be removed once we know everything works def getText(self): self.uart_service.write("w".encode("utf-8")) textString = self.uart_service.readline().decode("utf-8") print(textString) self.addToDB(textString) def runAll(self): BUFFSIZE = 4 # bytes received, used to tell if we are getting all of the data byteNum = 0 # send the user input that was passed thru as s, this tells the arduino what we want to do # happens in each run function to ensure command isnt sent before we are ready to get the data self.uart_service.write("r".encode("utf-8")) # wait until the arduino sends an c back, to tell the rpi we are about to get data while (True): val = self.uart_service.read(nbytes=1) if (val == None): continue if (val.decode("utf-8") == 'c'): break # debug statement to know we are getting the name first print("readyForImgName") # read the image name, used to be readLine, but for some reason that broke # When possible use read(nbytes) instead of readline to fix errors if size of data is known # arduino will send a line with the image name, temperature, and humidity seperated by a comma # TODO: textString is sending an unknown number of bytes, should be 19, but for somereason its not imageName = self.uart_service.read(nbytes=12).decode("utf-8") fileName = Path("static/" + imageName) fileName.touch(exist_ok=True) # print the name to make sure its the right one print(imageName) # textString = uart_service.readline().decode("utf-8") # a file with the name of the image that we will save data to f = open(fileName, 'wb+') # get the first 4 bytes, then delay, print statemtns are for debugging val = self.uart_service.read(nbytes=BUFFSIZE) print("delay") time.sleep(.01) print("dd") # Get the data from the uart service, then write them to teh file, 4 bytes at a time for now, seems to be reliable while (val != None): # print(val) f.write(val) val = self.uart_service.read(nbytes=BUFFSIZE) byteNum = byteNum + BUFFSIZE # we need this delay to allow the arduino to send data, if we dont we might read the same data in # time.sleep(.005) # print the number of bytes recived, # close the file f.close()
class Split(Module): '''Enables splitting keyboards wirelessly, or wired''' def __init__( self, split_flip=True, split_side=None, split_type=SplitType.UART, split_target_left=True, uart_interval=20, data_pin=None, data_pin2=None, target_left=True, uart_flip=True, debug_enabled=False, ): self._is_target = True self._uart_buffer = [] self.split_flip = split_flip self.split_side = split_side self.split_type = split_type self.split_target_left = split_target_left self.split_offset = None self.data_pin = data_pin self.data_pin2 = data_pin2 self.target_left = target_left self.uart_flip = uart_flip self._is_target = True self._uart = None self._uart_interval = uart_interval self._debug_enabled = debug_enabled if self.split_type == SplitType.BLE: try: from adafruit_ble import BLERadio from adafruit_ble.advertising.standard import ( ProvideServicesAdvertisement, ) from adafruit_ble.services.nordic import UARTService self.ProvideServicesAdvertisement = ProvideServicesAdvertisement self.UARTService = UARTService except ImportError: print('BLE Import error') return # BLE isn't supported on this platform self._ble = BLERadio() self._ble_last_scan = ticks_ms() - 5000 self._connection_count = 0 self._uart_connection = None self._advertisment = None self._advertising = False self._psave_enable = False def during_bootup(self, keyboard): # Set up name for target side detection and BLE advertisment name = str(getmount('/').label) if self.split_type == SplitType.BLE: self._ble.name = name else: # Try to guess data pins if not supplied if not self.data_pin: self.data_pin = keyboard.data_pin # Detect split side from name if self.split_side is None: if name.endswith('L'): # If name ends in 'L' assume left and strip from name self._is_target = bool(self.split_target_left) self.split_side = SplitSide.LEFT elif name.endswith('R'): # If name ends in 'R' assume right and strip from name self._is_target = not bool(self.split_target_left) self.split_side = SplitSide.RIGHT # if split side was given, find master from split_side. elif self.split_side == SplitSide.LEFT: self._is_target = bool(self.split_target_left) elif self.split_side == SplitSide.RIGHT: self._is_target = not bool(self.split_target_left) # Flips the col pins if PCB is the same but flipped on right if self.split_flip and self.split_side == SplitSide.RIGHT: keyboard.col_pins = list(reversed(keyboard.col_pins)) self.split_offset = len(keyboard.col_pins) if self.split_type == SplitType.UART and self.data_pin is not None: if self._is_target: self._uart = busio.UART( tx=self.data_pin2, rx=self.data_pin, timeout=self._uart_interval ) else: self._uart = busio.UART( tx=self.data_pin, rx=self.data_pin2, timeout=self._uart_interval ) # Attempt to sanely guess a coord_mapping if one is not provided. if not keyboard.coord_mapping: keyboard.coord_mapping = [] rows_to_calc = len(keyboard.row_pins) * 2 cols_to_calc = len(keyboard.col_pins) * 2 for ridx in range(rows_to_calc): for cidx in range(cols_to_calc): keyboard.coord_mapping.append(intify_coordinate(ridx, cidx)) def before_matrix_scan(self, keyboard): if self.split_type == SplitType.BLE: self._check_all_connections() self._receive_ble(keyboard) elif self.split_type == SplitType.UART: if self._is_target or self.data_pin2: self._receive_uart(keyboard) elif self.split_type == SplitType.ONEWIRE: pass # Protocol needs written return def after_matrix_scan(self, keyboard): if keyboard.matrix_update: if self.split_type == SplitType.UART and self._is_target: pass # explicit pass just for dev sanity... elif self.split_type == SplitType.UART and ( self.data_pin2 or not self._is_target ): self._send_uart(keyboard.matrix_update) elif self.split_type == SplitType.BLE: self._send_ble(keyboard.matrix_update) elif self.split_type == SplitType.ONEWIRE: pass # Protocol needs written else: print('Unexpected case in after_matrix_scan') return def before_hid_send(self, keyboard): if not self._is_target: keyboard.hid_pending = False return def after_hid_send(self, keyboard): return def on_powersave_enable(self, keyboard): if self.split_type == SplitType.BLE: if self._uart_connection and not self._psave_enable: self._uart_connection.connection_interval = self._uart_interval self._psave_enable = True def on_powersave_disable(self, keyboard): if self.split_type == SplitType.BLE: if self._uart_connection and self._psave_enable: self._uart_connection.connection_interval = 11.25 self._psave_enable = False def _check_all_connections(self): '''Validates the correct number of BLE connections''' self._connection_count = len(self._ble.connections) if self._is_target and self._connection_count < 2: self._target_advertise() elif not self._is_target and self._connection_count < 1: self._initiator_scan() def _initiator_scan(self): '''Scans for target device''' self._uart = None self._uart_connection = None # See if any existing connections are providing UARTService. self._connection_count = len(self._ble.connections) if self._connection_count > 0 and not self._uart: for connection in self._ble.connections: if self.UARTService in connection: self._uart_connection = connection self._uart_connection.connection_interval = 11.25 self._uart = self._uart_connection[self.UARTService] break if not self._uart: if self._debug_enabled: print('Scanning') self._ble.stop_scan() for adv in self._ble.start_scan( self.ProvideServicesAdvertisement, timeout=20 ): if self._debug_enabled: print('Scanning') if self.UARTService in adv.services and adv.rssi > -70: self._uart_connection = self._ble.connect(adv) self._uart_connection.connection_interval = 11.25 self._uart = self._uart_connection[self.UARTService] self._ble.stop_scan() if self._debug_enabled: print('Scan complete') break self._ble.stop_scan() def _target_advertise(self): '''Advertises the target for the initiator to find''' self._ble.stop_advertising() if self._debug_enabled: print('Advertising') # Uart must not change on this connection if reconnecting if not self._uart: self._uart = self.UARTService() advertisement = self.ProvideServicesAdvertisement(self._uart) self._ble.start_advertising(advertisement) self.ble_time_reset() while not self.ble_rescan_timer(): self._connection_count = len(self._ble.connections) if self._connection_count > 1: self.ble_time_reset() if self._debug_enabled: print('Advertising complete') break self._ble.stop_advertising() def ble_rescan_timer(self): '''If true, the rescan timer is up''' return bool(ticks_diff(ticks_ms(), self._ble_last_scan) > 5000) def ble_time_reset(self): '''Resets the rescan timer''' self._ble_last_scan = ticks_ms() def _send_ble(self, update): if self._uart: try: if not self._is_target: update[1] += self.split_offset self._uart.write(update) except OSError: try: self._uart.disconnect() except: # noqa: E722 if self._debug_enabled: print('UART disconnect failed') if self._debug_enabled: print('Connection error') self._uart_connection = None self._uart = None def _receive_ble(self, keyboard): if self._uart is not None and self._uart.in_waiting > 0 or self._uart_buffer: while self._uart.in_waiting >= 3: self._uart_buffer.append(self._uart.read(3)) if self._uart_buffer: keyboard.secondary_matrix_update = bytearray(self._uart_buffer.pop(0)) return def _send_uart(self, update): # Change offsets depending on where the data is going to match the correct # matrix location of the receiever if self._is_target: if self.split_target_left: update[1] += self.split_offset else: update[1] -= self.split_offset else: if self.split_target_left: update[1] += self.split_offset else: update[1] -= self.split_offset if self._uart is not None: self._uart.write(update) def _receive_uart(self, keyboard): if self._uart is not None and self._uart.in_waiting > 0 or self._uart_buffer: if self._uart.in_waiting >= 60: # This is a dirty hack to prevent crashes in unrealistic cases import microcontroller microcontroller.reset() while self._uart.in_waiting >= 3: self._uart_buffer.append(self._uart.read(3)) if self._uart_buffer: keyboard.secondary_matrix_update = bytearray(self._uart_buffer.pop(0)) return
class Radio: """ Represents a connection through which one can send or receive strings and bytes. The radio can be tuned to a specific channel upon initialisation or via the `configure` method. """ def __init__(self, **args): """ Takes the same configuration arguments as the `configure` method. """ # For BLE related operations. self.ble = BLERadio() # The uid for outgoing message. Incremented by one on each send, up to # 255 when it's reset to 0. self.uid = 0 # Contains timestamped message metadata to mitigate report of # receiving of duplicate messages within AD_DURATION time frame. self.msg_pool = set() # Handle user related configuration. self.configure(**args) def configure(self, channel=42): """ Set configuration values for the radio. :param int channel: The channel (0-255) the radio is listening / broadcasting on. """ if -1 < channel < 256: self._channel = channel else: raise ValueError("Channel must be in range 0-255") def send(self, message): """ Send a message string on the channel to which the radio is broadcasting. :param str message: The message string to broadcast. """ return self.send_bytes(message.encode("utf-8")) def send_bytes(self, message): """ Send bytes on the channel to which the radio is broadcasting. :param bytes message: The bytes to broadcast. """ # Ensure length of message. if len(message) > MAX_LENGTH: raise ValueError( "Message too long (max length = {})".format(MAX_LENGTH)) advertisement = _RadioAdvertisement() # Concatenate the bytes that make up the advertised message. advertisement.msg = struct.pack("<BB", self._channel, self.uid) + message self.uid = (self.uid + 1) % 255 # Advertise (block) for AD_DURATION period of time. self.ble.start_advertising(advertisement) time.sleep(AD_DURATION) self.ble.stop_advertising() def receive(self): """ Returns a message received on the channel on which the radio is listening. :return: A string representation of the received message, or else None. """ msg = self.receive_full() if msg: return msg[0].decode("utf-8").replace("\x00", "") return None def receive_full(self): """ Returns a tuple containing three values representing a message received on the channel on which the radio is listening. If no message was received then `None` is returned. The three values in the tuple represent: * the bytes received. * the RSSI (signal strength: 0 = max, -255 = min). * a microsecond timestamp: the value returned by time.monotonic() when the message was received. :return: A tuple representation of the received message, or else None. """ try: for entry in self.ble.start_scan(_RadioAdvertisement, minimum_rssi=-255, timeout=1, extended=True): # Extract channel and unique message ID bytes. chan, uid = struct.unpack("<BB", entry.msg[:2]) if chan == self._channel: now = time.monotonic() addr = entry.address.address_bytes # Ensure this message isn't a duplicate. Message metadata # is a tuple of (now, chan, uid, addr), to (mostly) # uniquely identify a specific message in a certain time # window. expired_metadata = set() duplicate = False for msg_metadata in self.msg_pool: if msg_metadata[0] < now - AD_DURATION: # Ignore expired entries and mark for removal. expired_metadata.add(msg_metadata) elif (chan, uid, addr) == msg_metadata[1:]: # Ignore matched messages to avoid duplication. duplicate = True # Remove expired entries. self.msg_pool = self.msg_pool - expired_metadata if not duplicate: # Add new message's metadata to the msg_pool and # return it as a result. self.msg_pool.add((now, chan, uid, addr)) msg = entry.msg[2:] return (msg, entry.rssi, now) finally: self.ble.stop_scan() return None
# # BLE scan # from adafruit_ble import BLERadio ble = BLERadio() found = set() scan_responses = set() for advertisement in ble.start_scan(timeout=10): addr = advertisement.address if advertisement.scan_response and addr not in scan_responses: scan_responses.add(addr) elif not advertisement.scan_response and addr not in found: found.add(addr) else: continue print(addr, advertisement) print("\t" + repr(advertisement)) print()
ble = BLERadio() while True: while ble.connected and any(UARTService in connection for connection in ble.connections): for connection in ble.connections: if UARTService not in connection: continue print("RTBobble52 ready...") uart = connection[UARTService] while connection.connected: #get weather info servo = getWeather() #convert the data into a bobble52 command bobble_command = servo + ' s' print(bobble_command) #output the data to the bobble52 uart.write(bobble_command.encode("utf-8")) uart.write(b'\n') print("disconnected, scanning") for advertisement in ble.start_scan(ProvideServicesAdvertisement, timeout=1): if UARTService not in advertisement.services: continue ble.connect(advertisement) print("connected") break ble.stop_scan()
continue sensor_address = group["key"].split("-")[-1] existing_feeds[sensor_address] = [] for feed in group["feeds"]: feed_key = feed["key"].split(".")[-1] existing_feeds[sensor_address].append(feed_key) print(existing_feeds) counter = 0 ble = BLERadio() print("scanning") sequence_numbers = {} # By providing Advertisement as well we include everything, not just specific advertisements. for measurement in ble.start_scan(AdafruitSensorMeasurement): sensor_address = "{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}".format( *measurement.address.address_bytes) print(sensor_address, measurement) if sensor_address not in sequence_numbers: sequence_numbers[ sensor_address] = measurement.sequence_number - 1 % 256 number_missed = measurement.sequence_number - sequence_numbers[ sensor_address] - 1 if number_missed < 0: number_missed += 256 if number_missed != 0: print("missed broadcast!", sequence_numbers[sensor_address], measurement.sequence_number, number_missed) sequence_numbers[sensor_address] = measurement.sequence_number group_key = "bridge-{}-sensor-{}".format(bridge_address, sensor_address)