Esempio n. 1
0
    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()
Esempio n. 2
0
    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)
Esempio n. 3
0
    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"))
Esempio n. 5
0
             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)
Esempio n. 6
0
        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)
Esempio n. 8
0
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
Esempio n. 9
0
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")
Esempio n. 12
0
        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()
Esempio n. 13
0
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()
Esempio n. 14
0
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
Esempio n. 15
0
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()
Esempio n. 17
0
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)