Exemplo n.º 1
0
def COLLECTOR(timeout):
    global runthegame
    global pmdata
    global playermonitor
    global stopmeplease
    scanner = Scanner().withDelegate(ScanDelegate())

    while True:
        if runthegame:  # 0: rawrssi 1:timestamp 2:lastresult 3: ? 4: item counter 5: KalmanRssi 6:KalmanTime
            pmdata = [
                [0, [[], [], 0, 0, 0, [], []]],
                [1, [[], [], 0, 0, 0, [], []]],
                [2, [[], [], 0, 0, 0, [], []]],
                [3, [[], [], 0, 0, 0, [], []]],
                [4, [[], [], 0, 0, 0, [], []]],
            ]
            playermonitor = []
            scanner.clear()
            scanner.start(passive=True)

            while runthegame:
                most = timer()
                scanner.process(0.1)

                if stopmeplease == True:
                    runthegame = False
                    scanner.stop()
        time.sleep(0.01)
Exemplo n.º 2
0
    def run(self):
        while not self.stop_event.wait(2):
            if not self.scanDelegate.identify_queue.empty(): #check for pending identify command
                delegate = self.scanDelegate.identify_queue.get()
                
                time_wait = .25
                cnt = int(delegate.identify_timeout/time_wait)
                logger.debug('identifying: cnt=' + str(cnt) +', timeout = ' + str(delegate.identify_timeout))
                cmd = '{:02x}'.format(tb_protocol.TB_COMMAND_IDENTIFY)
                for i in range(cnt):
                    f, data = btle_sendcmd(delegate.target_mac, cmd)
                    if f:
                        delegate.identified = True
                        delegate.stop_event.set()
                        #logger.debug('identify succeeded ' + data.hex())
                        logger.debug('identify succeeded ')
                        break
                    if delegate.stop_event.wait(time_wait):
                        break
                self.scanDelegate.identify_queue.task_done()

            scanner = Scanner().withDelegate(self.scanDelegate)
            try:
                scanner.clear()
                scanner.start()
                scanner.process(10)
                scanner.stop()
            except Exception as exc:
                logger.debug('Exception > ' + str(exc))
                pass
        logger.debug('ScannerThread: exit')
Exemplo n.º 3
0
    def scan(match=None, duration=5, just_one=False, match_scan_entry=False):
        """This looks through any advertising btle devices for matching ones.

        *** Note you must run this as root ***

        match(scan_data) should return True if scan_data is from the device you're looking for.

            If no match function is provided, it is treated as always returning True (you want
                to see all devices that respond within duration).

            scan_data is a dict mapping description to value, unless match_scan_entry is True
                in which case scan_data is a btle ScanEntry object.

        Duration is how many seconds to scan before returning.

        If just_one is False, scans for the full duration and then
            returns a list of matching ScanEntry objects. (https://ianharvey.github.io/bluepy-doc/scanentry.html)

        If just_one is True, this returns the first match immediately (no list)
            or None after full duration timeout.

        Note (match==None and just_one==True) results in just the first device
            to respond being immediately returned.
        """
        scanner = Scanner().withDelegate(DefaultDelegate())
        scanner.clear()
        scanner.start()
        if not just_one:
            found = []
        try:
            for i in range(max(int(duration * 10),
                               1)):  # Break duration into 10ths
                scanner.process(
                    0.1)  # Handle incoming messages for 1/10th of a second...
                devices = scanner.getDevices()
                for dev in devices:
                    if debug:
                        BtleDevice.dump_scan_entry(dev)
                    if match_scan_entry:
                        params = dev
                    else:
                        params = {
                            name: val
                            for tag, name, val in dev.getScanData()
                        }
                    if match is None or match(params):
                        if just_one:
                            return dev
                        else:
                            found.append(dev)
                scanner.clear()
        finally:
            scanner.stop()

        if just_one:
            return None
        return found
Exemplo n.º 4
0
def status(mac_address):
    print('Looking for switchmate status...')
    sys.stdout.flush()

    scanner = Scanner().withDelegate(ScanDelegate(mac_address))

    scanner.clear()
    scanner.start()
    scanner.process(5)
    scanner.stop()
Exemplo n.º 5
0
 def run(self):
     while True:
         # Do something
         print('Starting Scan Process')
         scanner = Scanner(int(os.environ['SCAN_HCI'])).withDelegate(
             ScanDelegate())
         scanner.clear()
         scanner.start()
         scanner.process(5)
         scanner.stop()
         time.sleep(self.interval)
Exemplo n.º 6
0
class BadgeBTLE():
    def __init__(self,
                 manufacturer=None,
                 appearance=None,
                 scanTimeout=2,
                 fields=[]):
        """Construct new BadgeBTLE instance.

        Args:
            manufacturer: Bluetooth Manufacturer ID [1] to scan for. Default is no filter.
            appearance: Optional Bluetooth Appearance ID [2] to scan for. If not set, defaults to current or upcoming DEF CON (e.g. 0x26dc).
            scanTimeout: Timeout for Bluetooth scan. Defaults to 2 seconds.

        References:
        [1] https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.manufacturer_name_string.xml
        [2] https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gap.appearance.xml
        """
        self.scanner = Scanner()
        self.scanTimeout = scanTimeout
        self.manufacturer = manufacturer
        self.appearance = appearance if appearance else self.__determineAppearance(
        )

    def __determineAppearance(self):
        year = datetime.now().year
        dcyear = year - 1992  # Calculate DEF CON year
        return "dc" + str(dcyear)

    def scan(self):
        """Perform Bluetooth scan until timeout and return list of nearby BLE devices
        with the specificed (or default) Appearance ID.

        Returns:
            A list of tuples containing these data points: Appearance ID, Manufacturer ID, Local Name, and Signal strength (RSSI).
        """
        devices = self.scanner.scan(self.scanTimeout)
        neighbors = []
        for dev in devices:
            appearance = None
            manufacturer = None
            localName = None
            for (adtype, desc, value) in dev.getScanData():
                if desc.lower() == "appearance":
                    appearance = value.lower()
                if desc.lower() == "manufacturer":
                    manufacturer = value[0:4]
                if desc.lower() == "complete local name":
                    localName = value
                if appearance == self.appearance and manufacturer is not None:
                    neighbors.append(
                        ScanResult(manufacturer, appearance, localName,
                                   dev.rssi, dev.addr))
        self.scanner.clear()
        return neighbors
Exemplo n.º 7
0
    def run(self):
        while True:
            print("Scanning bluetooth devices...")
            scanner = Scanner()
            devices = scanner.scan(self.timeout)
            neighbors = []
            for dev in devices:
                if dev.addr in self.addresses:
                    neighbors.append(Neighbor(dev))

            self.onScan(neighbors)
            scanner.clear()
            sleep(self.delay)
Exemplo n.º 8
0
def main():
    logging.basicConfig(filename='logs/' + __file__ + '.log',
                        level=logging.INFO,
                        format='%(message)s')

    scanner = Scanner(BLE_INTERFACE).withDelegate(ScanDelegate())
    try:
        while True:
            scanner.start()
            scanner.process(timeout=5)
            scanner.stop()
            scanner.clear()
    except KeyboardInterrupt:
        pass
Exemplo n.º 9
0
 def run(self):
     while True:
         # Do something
         print('Starting Scan Process')
         items = set()
         scanner = Scanner(int(os.environ['SCAN_HCI'])).withDelegate(
             ScanDelegate(items))
         scanner.clear()
         scanner.start()
         scanner.process(5)
         scanner.stop()
         for item in items:
             readnewFirmware(item)
         time.sleep(self.interval)
     sys.exit(
     )  #If the loop exists because of an error, let the process go down and have docker restart it.
Exemplo n.º 10
0
 def scan(self):
     """
     Scans for PWS advertisements with the given SSID and returns the first match
     """
     logger.info("Start scanning...")
     scanner = Scanner().withDelegate(self)
     scanner.clear()
     scanner.start(passive=True)
     while self.result is None:
         scanner.process(0.1)
     logger.info(f"SSID match in PWS advertisement from {self.result.addr}")
     scanner.stop()
     # return and clear result
     result = self.result
     self.result = None
     return result
Exemplo n.º 11
0
def main():
        #Scan for Bluetooth devices for 2 seconds
        scanner = Scanner().withDelegate(ScanDelegate())
        scanner.clear()
        scanner.start()
        while(True):
                try:
                    #Open threads to poll data
                    bt_thread = _thread.start_new_thread(scanner.process,(3.0,))
                    us_thread = _thread.start_new_thread(distance,())

                    #Sleep for 4 seconds to ensure both threads safely complete                
                    time.sleep(4)

                    #Transmit data to server for processing
                    sendData(DEVICE_RSSI,DISTANCE_READ)
                    scanner.clear()
                except Exception as e:
                    print(e)
                    return
Exemplo n.º 12
0
class BLEService(Thread):
    def __init__(self, q):
        Thread.__init__(self)
        self.scanner = Scanner()
        self.queue = q
        self.devicesScanned = []

    def run(self):
        print("Starting BLE service...")
        self.scanner.start()
        while True:
            self.devicesScanned.clear()
            self.scanner.clear()
            self.scanner.process(5.0)
            devices = self.scanner.getDevices()
            self.fillQueue(devices)
            #if len(self.queue) > 0:
            #test = self.getFromQueue()
            #for dev in test:
            #    print("DEV: {}".format(dev.getJson()))
            #    print("_________________________")
            print(
                "_____________________Save ble setup, queue size = {}".format(
                    len(self.queue)))
            delay(3)

    def fillQueue(self, devices):
        for d in devices:
            devDto = BLEDeviceDto(d.addr, d.addrType, d.rssi, d.getScanData())
            self.devicesScanned.append(devDto)
        self.queue.append(self.devicesScanned)

    def getFromQueue(self):
        if len(self.queue) is not 0:
            msg = self.queue.popleft()
            return msg
        else:
            return None
Exemplo n.º 13
0
def main():
    devices = []
    d = ScanDelegate()
    scanner = Scanner().withDelegate(d)
    while True:
        scanner.scan(0.1)
        if d.dev is not None:
            net_device = None
            try:
                net_device = device(d.dev.getValueText(9), d.dev.addr,
                                    d.dev.rssi, d.dev.connectable)
                if True:  # net_device.addr not in devices:
                    SignDevice(net_device)
                    devices.append(net_device.addr)
                    scanner.clear()
                    d.ClearDev()
                else:
                    print("Device %s already signed upon" % net_device.addr)
                    return
            except Exception as e:
                print(
                    "Unable to Connect to Device at address: %s will try again | %s"
                    % (d.dev.addr, d.dev.rssi))
Exemplo n.º 14
0
class CentralManager(DefaultDelegate):

    SCAN_COUNT = 5
    SCAN_INTERVAL = 2.0

    def __init__(self):
        DefaultDelegate.__init__(self)
        self._scanner = Scanner().withDelegate(self)
        self._lamps = []
        self._candidateFound = False
        self.isConnected = False

    def scan(self):
        self.isConnected = False

        # Clear existing connected lamps
        for lamp in self._lamps:
            lamp.disconnect()

        self._lamps = []

        # Scan for new lamps to connect to
        print("Scanning for devices...")

        self._candidateFound = False
        self._scanner.clear()
        self._scanner.start()

        for iter in range(0, CentralManager.SCAN_COUNT):
            self._scanner.process(CentralManager.SCAN_INTERVAL)
            if (self._candidateFound):
                print("Candidate found after {} scan(s). Ending early".format(
                    iter + 1))
                break

        self._scanner.stop()

        scanResult = self._scanner.getDevices()

        # Connect to any lamps found
        for device in scanResult:
            if (Lampi.isLampCandidate(device)):
                lamp = Lampi(device)
                lamp.validate()
                if (lamp.isValid):
                    print("Connected to a lamp with MAC address {}".format(
                        device.addr))
                    self._lamps.append(lamp)
                    self.isConnected = True
                else:
                    lamp.disconnect()

        print("Scan complete")

    def handleDiscovery(self, device, isNew, _):
        if isNew and device.connectable:
            if (Lampi.isLampCandidate(device)):
                self._candidateFound = True
                print(" • Candidate found with MAC address {}".format(
                    device.addr))

    # Discard any lamps that are no longer connected
    def pruneLamps(self):
        for i in range(0, len(self._lamps)):
            lamp = self._lamps[i]
            if (not lamp.isConnected()):
                print("Pruned {}".format(lamp.addr))
                self._lamps.pop(i)
                i -= 1

    def toggleOnOff(self):
        print("Toggling on/off")
        self.pruneLamps()
        for lamp in self._lamps:
            lamp.toggleOnOff()

    def brightnessUp(self):
        print("Sending brightness up")
        self.pruneLamps()
        for lamp in self._lamps:
            lamp.brightnessUp()

    def brightnessDown(self):
        print("Sending brightness down")
        self.pruneLamps()
        for lamp in self._lamps:
            lamp.brightnessDown()

    def preset(self, number):
        print("Starting Preset", str(number))
        self.pruneLamps()
        for lamp in self._lamps:
            lamp.setPreset(number)
Exemplo n.º 15
0
from bluepy.btle import Scanner, DefaultDelegate
import Yeelight
class ScanDelegate(DefaultDelegate): 
    def __init__(self): 
        DefaultDelegate.__init__(self)
    def handleDiscovery(self, dev, isNewDev, isNewData): 
        if isNewDev: 
            print "Discovered device", dev.addr 
        elif isNewData: 
            print "Received new data from", dev.addr
scanner = Scanner()#.withDelegate(ScanDelegate()) 
devices = scanner.scan(10.0)
for dev in devices:
	if (dev.addr == "f0:a0:ee:76:4d:68") :
		print "finded!"
		Yeelight.set_bright(1, 90)
		detection_thread = Thread(target=Yeelight.bulbs_detection_loop)
		detection_thread.start()
		sleep(0.2)

scanner.clear()
		
Exemplo n.º 16
0
class InkbirdUpdater(Entity):

    entity_id = "inkbird.updater"

    def __init__(self, hass, inkbird_devices):
        """Initialize the thermometer."""
        Entity.__init__(self)
        self._name = 'Inkbird Updater'
        self._state = None
        self._mac = None
        self.hass = hass
        self.scanner = Scanner()
        self.scanner.clear()
        self.scanner.start()
        self.no_results_counter = 0
        self.inkbird_devices = inkbird_devices

    @property
    def mac(self):
        """Return the mac of the sensor."""
        return self._mac

    @property
    def name(self):
        """Return the name of the sensor."""
        return self._name

    @property
    def state(self):
        """Return the state of the sensor."""
        return self._state

    @property
    def should_poll(self):
        """Return the name of the sensor."""
        _LOGGER.debug("Should_Poll called")
        return True

    def update(self):
        """Get the latest data and use it to update our sensor state."""
        _LOGGER.debug("UPDATE called")
        _LOGGER.debug(f"scanner here is {self.scanner}")

        # The btle on my raspberry pi 4 seems to go MIA
        if self.no_results_counter >= 5:
            _LOGGER.error("Btle went away .. restarting entire btle stack")
            self.scanner = Scanner()
            self.scanner.clear()
            self.scanner.start()
            self.no_results_counter = 0

        try:
            self.scanner.process(timeout=8.0)
        except:
            e = sys.exc_info()[0]
            _LOGGER.error(f" Exception occoured during scanning: {e}")
        results = self.scanner.getDevices()
        _LOGGER.debug(f"got results {results}")
        for dev in results:
            self.handleDiscovery(dev)

        # if we have no results at all, the scanner may have gone MIA.
        # it happens apparently. So, let's count upto 5 and then, if it
        # still happens, restart/refresh the btle stack.
        # any results though will reset the btle 'MIA counter' to 0
        if not any(results):
            self.no_results_counter += 1
        else:
            self.no_results_counter = 0
            self.scanner.clear()

        self._state = []
        return True

    def handleDiscovery(self, dev):
        _LOGGER.debug(f"Discovered device {dev.addr}")
        _LOGGER.debug("Device {} ({}), RSSI={} dB".format(
            dev.addr, dev.addrType, dev.rssi))
        for (adtype, desc, value) in dev.getScanData():
            _LOGGER.debug("[%s]  %s = %s" % (adtype, desc, value))
            if adtype == 255:
                humidity = "%2.2f" % (int(value[6:8] + value[4:6], 16) / 100)
                #temperature = "%2.2f" % (int(value[2:4]+value[:2], 16)/100)
                temperature = int(value[2:4] + value[:2], 16)
                temperature_bits = 16
                if temperature & (1 << (temperature_bits - 1)):
                    temperature -= 1 << temperature_bits
                temperature = "%2.2f" % (temperature / 100)
                battery = int(value[14:16], 16)
                _LOGGER.debug(self.inkbird_devices)
                for device in self.inkbird_devices:
                    _LOGGER.debug(
                        f" dev addr is {dev.addr} and mac is {device.mac}")
                    _LOGGER.debug(
                        f" --> {temperature} - {humidity} - {battery} ")
                    if dev.addr == device.mac:
                        _LOGGER.debug(
                            f" dev addr is {dev.addr} and mac is {device.mac} with parameter of {device.parameter}"
                        )
                        old_state = self.hass.states.get(
                            f"sensor.{device.entity_name}")
                        if old_state:
                            attrs = old_state.attributes
                        else:
                            attrs = None

                        if device.parameter == "temperature":
                            _LOGGER.debug(
                                f" >>>> updating device {device.mac} with {temperature}"
                            )
                            device.temperature = temperature
                            device._state = temperature
                            #self.hass.states.set(f"sensor.{device.entity_name}", temperature, attrs)
                        elif device.parameter == "humidity":
                            _LOGGER.debug(
                                f" >>>> updating device {device.mac} with {humidity}"
                            )
                            device.humidity = humidity
                            device._state = humidity
                            #self.hass.states.set(f"sensor.{device.entity_name}", humidity, attrs)
                        else:
                            _LOGGER.debug(
                                f" >>>> updating device {device.mac} with {battery}"
                            )
                            device.battery = battery
                            device._state = battery
Exemplo n.º 17
0
 def scan(self):
     scanner = Scanner().withDelegate(ScanDelegate())
     devices = scanner.clear()
     devices = scanner.start()
     data = scanner.process(timeout=10)
     devices = scanner.stop()
Exemplo n.º 18
0
class BleAdapter:
    def __init__(self,
                 yaml_config: dict,
                 min_rssi: float = -65,
                 ble_device: str = 'hci0'):

        self.devs_in_range = {}  # Stores devices found to be in range
        self.active_connections = {}
        self._chrcs_cache = {}

        self.yaml_config = yaml_config
        self.valid_names = yaml_config['regex']['names']
        self.valid_addrs = yaml_config['regex']['addrs']
        self.chrc_handles = list(yaml_config['characteristics'].keys())

        self.min_rssi = min_rssi
        self.ble_device = ble_device[-1]  # Hacky

        self.scanner = Scanner()

    def update_tracked_devices(self, scan_timeout: float = 3):
        # Refreshes a list of devices that are in range of the bridge
        for conn in self.active_connections.values():
            conn.disconnect()

        time.sleep(1)

        self.active_connections = {}
        self.scanner.clear()

        new_devs = self.scanner.scan(scan_timeout)
        new_devs_in_range = {}

        for dev in new_devs:
            # Exclude devices below a certain rssi
            if dev.rssi < self.min_rssi:
                continue

            # Get mac address and device name from ScanEntry class
            dev_addr = dev.addr.upper()
            dev_name = self._get_dev_name_from_scan_entry(dev)

            # If address is valid, add device
            dev_addr_valid = map(
                lambda x: re.match(x, dev_addr, re.IGNORECASE),
                self.valid_addrs)
            if any(dev_addr_valid):
                new_devs_in_range[dev_addr] = dev
                continue

            # if name is empty, continue
            if not dev_name:
                continue

            # If name is valid, add device
            dev_name_valid = map(lambda x: re.match(x, dev_name),
                                 self.valid_names)
            if any(dev_name_valid):
                new_devs_in_range[dev_addr] = dev
                continue

        self.devs_in_range = new_devs_in_range

        Utils.logger.info(
            f'Valid devices in range: {self.get_tracked_devices_summary()}')

    @timeout(4)
    def create_connection(self, addr: str):
        # Creates a handle to a Peripheral and adds it to active_connections
        try:
            assert addr in self.devs_in_range
            dev_addr = addr.upper()
            dev_addr_type = self.devs_in_range[dev_addr].addrType
            dev_name = self.get_dev_name(dev_addr)

            Utils.logger.info(
                f'Creating connection to {dev_addr_type} address: {dev_addr}')

            dev = Peripheral(dev_addr, dev_addr_type, self.ble_device)

            self.active_connections[dev_name] = dev
            self._chrcs_cache[dev_name] = dev.getCharacteristics()

        except TimeoutError:
            Utils.logger.error(f'Device {addr} not responding.')

        except Exception as e:
            Utils.logger.error(f'An error occurred. {e}')

        except AssertionError:
            Utils.logger.error(f'Device {addr} not in range right now')

    def maintain_connections(self):
        updated_active_connections = {}
        updated_chrc_cache = {}

        # Remove connections that have disconnected
        for dev_name, conn in self.active_connections.items():
            if conn.getState() == 'conn':
                updated_active_connections[dev_name] = conn
                updated_chrc_cache[dev_name] = conn.getCharacteristics()

        self.active_connections = updated_active_connections
        self._chrcs_cache = updated_chrc_cache

        # Reconnect devices in range but are not active
        for addr, scan_entry in self.devs_in_range.items():
            if self.get_dev_name(addr) not in self.active_connections.keys():
                self.create_connection(addr)

    def pull_device_data(self):
        all_device_data = {}

        for dev_name in self.active_connections.keys():
            try:
                all_device_data[dev_name] = self._get_data(dev_name)
            except Exception as e:
                continue

        return all_device_data

    def _get_data(self, dev_name: str):
        Utils.logger.info(f'Loading data from {dev_name}')

        data = {}

        try:
            chrcs = self._chrcs_cache[dev_name]
        except KeyError:
            Utils.logger.error(f'{dev_name} is not an active connection.')
            return

        chrc_handles = [x.replace('-', '') for x in self.chrc_handles]

        for c in chrcs:
            handle = str(c.uuid)
            h = handle.replace('-', '')

            if h not in chrc_handles:
                continue

            # Bottleneck here
            try:
                byte_val = c.read()

            except BTLEDisconnectError:
                Utils.logger.error(f'{dev_name} was disconnected,')
                Utils.logger.error('Will reattempt to connect on next rescan.')

            except Exception as e:
                Utils.logger.error(
                    f'An unknown error occurred trying to read {handle}: {e}')
                raise

            data_type = self.yaml_config['characteristics'][handle]['msg_type']

            if data_type == 'byte':
                data[handle] = str(byte_val)
            elif data_type == 'string':
                data[handle] = byte_val.decode('utf-8')
            elif data_type == 'int':
                data[handle] = int(byte_val.decode('utf-8'))
            elif data_type == 'float':
                data[handle] = float(byte_val.decode('utf-8'))
            elif data_type == 'bool':
                data[handle] = bool(byte_val.decode('utf-8'))
            else:
                Utils.logger.error(f'Invalid msg_type {data_type}')
                raise EnvironmentError

        return data

    def write_data(self, dev_name: str, handle: str, val: str):

        h = handle.replace('-', '')

        try:
            conn = self.active_connections[dev_name]
        except KeyError:
            Utils.logger.error(f'{dev_name} is not an active connection')
            return

        try:
            assert conn.getState() == 'conn'
        except AssertionError:
            Utils.logger.error(f'{dev_name} is disconnected.')

        try:
            chrc = conn.getCharacteristics(uuid=h)[0]
        except BTLEGattError:
            Utils.logger.error(f'Handle {handle} is invalid')
            raise
        except KeyError:
            Utils.logger.error('No characteristic was returned')
            raise

        Utils.logger.info(
            f'Writing value "{val}" to handle "{handle}" on device "{dev_name}"'
        )
        try:
            chrc.write(val)
        except Exception as e:
            Utils.logger.error(e)

    def get_dev_name(self, addr: str):

        dev = self.devs_in_range[addr]

        return self._get_dev_name_from_scan_entry(dev)

    def _get_dev_name_from_scan_entry(self, dev: ScanEntry):
        dev_name = None

        # Attempt to load from Scandata
        for scan_data in dev.getScanData():
            if scan_data[1] == 'Short Local Name':
                dev_name = scan_data[2]

        # Iterate through the dataTags if the above fails
        if dev_name is None:
            try:
                for idx, label in scan_data.dataTags:
                    if label == 'Short Local Name':
                        dev_name = dev.getValueText(idx)
            except AttributeError:
                pass

        # Load using handles if the above fails
        if dev_name is None:
            dev_name = dev.getValueText(8)

        return dev_name

    def get_tracked_devices_summary(self):
        return [(x.addr.upper(), x.getValueText(8))
                for x in self.devs_in_range.values()]

    def get_active_connections_summary(self):
        return list(self.active_connections.keys())
Exemplo n.º 19
0
def init_scanner():
    scanner = Scanner()
    scanner.clear()
    scanner.start()
    return scanner
Exemplo n.º 20
0
class InkbirdUpdater(Entity):

    entity_id = "inkbird.updater"

    def __init__(self, hass, inkbird_devices):
        """Initialize the thermometer."""
        Entity.__init__(self)
        self._name = 'Inkbird Updater'
        self._state = None
        self._mac = None
        self.hass = hass
        self.scanner = Scanner()
        self.scanner.clear()
        self.scanner.start()
        self.inkbird_devices = inkbird_devices

    @property
    def mac(self):
        """Return the mac of the sensor."""
        return self._mac

    @property
    def name(self):
        """Return the name of the sensor."""
        return self._name

    @property
    def state(self):
        """Return the state of the sensor."""
        return self._state

    @property
    def should_poll(self):
        """Return the name of the sensor."""
        _LOGGER.debug("Should_Poll called")
        return True

    def update(self):
        # added
        global pid
        ##
        """Get the latest data and use it to update our sensor state."""
        _LOGGER.debug("UPDATE called")
        _LOGGER.debug(f"scanner here is {self.scanner}")

        try:
            self.scanner.process(timeout=8.0)
        except:
            e = sys.exc_info()[0]
            _LOGGER.error(f" Exception occoured during scanning: {e}")
        results = self.scanner.getDevices()
        _LOGGER.debug(f"got results {results}")

        # The btle on my raspberry pi 4 seems to go MIA
        # if we have no results at all, the scanner may have gone MIA.
        # it happens apparently. So, let's count upto 5 and then, if it
        # still happens, restart/refresh the btle stack.
        # Seems to go MIA more frequently on RPi3B: removed counter and restart immediately if no results obtained
        # May generate 10 s update timeout errors
        if not any(results):
            _LOGGER.error("Btle went away .. restarting entire btle stack")
            ## Kill the bluepy-helper process
            # There is a memory leak: new instance of bluepy-helper is created with Scanner(), without terminating running instance
            # https://github.com/IanHarvey/bluepy/issues/267#issuecomment-657183840
            # adapted from: https://github.com/JsBergbau/MiTemperature2/blob/master/LYWSD03MMC.py
            del self.scanner  #probably not needed?
            bluepypid = 0
            pstree = os.popen("pstree -p " + str(pid)).read(
            )  #we want to kill only bluepy from our own process tree, because other python scripts have there own bluepy-helper process
            _LOGGER.debug("PSTree: " + pstree)
            try:
                bluepypid = re.findall(
                    r'bluepy-helper\((.*)\)',
                    pstree)[0]  #Store the bluepypid, to kill it later
            except IndexError:  #Should not happen since we're now connected
                _LOGGER.debug("Couldn't find pid of bluepy-helper")
            if bluepypid is not 0:
                os.system("kill " + bluepypid)
                _LOGGER.debug("Killed bluepy with pid: " + str(bluepypid))


# Kill bluepy-helper systemwide anyways...not good if there are other scripts using bluepy
#            else:
#                os.system('pkill bluepy-helper')
#                _LOGGER.debug("Killed bluepy-helper")
##
            self.scanner = Scanner()
            self.scanner.clear()
            self.scanner.start()
            try:
                self.scanner.process(timeout=8.0)
            except:
                e = sys.exc_info()[0]
                _LOGGER.error(f" Exception occoured during scanning: {e}")
            results = self.scanner.getDevices()
            _LOGGER.debug(f"Got new results {results}")

        for dev in results:
            if dev.addr in devicemacs:
                self.handleDiscovery(dev)

        self.scanner.clear()
        self._state = []
        return True

    def handleDiscovery(self, dev):
        #        _LOGGER.debug(f"Discovered device {dev.addr}")
        _LOGGER.debug("Discovered device {} ({}), RSSI={} dB".format(
            dev.addr, dev.addrType, dev.rssi))
        for (adtype, desc, value) in dev.getScanData():
            _LOGGER.debug("[%s]  %s = %s" % (adtype, desc, value))
            if adtype == 255:
                _LOGGER.debug(
                    f"{dev.addr} is in devicemacs list and now gets parameters!"
                )
                humidity = "%2.2f" % (int(value[6:8] + value[4:6], 16) / 100)
                #temperature = "%2.2f" % (int(value[2:4]+value[:2], 16)/100)
                temperature = int(value[2:4] + value[:2], 16)
                temperature_bits = 16
                if temperature & (1 << (temperature_bits - 1)):
                    temperature -= 1 << temperature_bits
                temperature = "%2.2f" % (temperature / 100)
                battery = int(value[14:16], 16)
                _LOGGER.debug(self.inkbird_devices)
                for device in self.inkbird_devices:
                    _LOGGER.debug(
                        f" dev addr is {dev.addr} and mac is {device.mac}")
                    #                    _LOGGER.debug(f" --> {temperature} - {humidity} - {battery} ")
                    if dev.addr == device.mac:
                        _LOGGER.debug(
                            f" dev addr is {dev.addr} and mac is {device.mac} with parameter of {device.parameter}"
                        )
                        # What does this do? Removed
                        #                        old_state = self.hass.states.get(f"sensor.{device.entity_name}")
                        #                        if old_state:
                        #                            attrs = old_state.attributes
                        #                        else:
                        #                            attrs = None
                        if device.parameter == "temperature":
                            _LOGGER.debug(
                                f" >>>> updating device {device.mac} with {temperature}"
                            )
                            device.temperature = temperature
                            device._state = temperature
                            #self.hass.states.set(f"sensor.{device.entity_name}", temperature, attrs)
                        elif device.parameter == "humidity":
                            _LOGGER.debug(
                                f" >>>> updating device {device.mac} with {humidity}"
                            )
                            device.humidity = humidity
                            device._state = humidity
                            #self.hass.states.set(f"sensor.{device.entity_name}", humidity, attrs)
                        else:
                            _LOGGER.debug(
                                f" >>>> updating device {device.mac} with {battery}"
                            )
                            device.battery = battery
                            device._state = battery
                            #self.hass.states.set(f"sensor.{device.entity_name}", battery, attrs)
        _LOGGER.debug(f" Done with handleDiscovery")
Exemplo n.º 21
0
def scan(callback,
         devices=None,
         raw=False,
         iface=0,
         reset_timeout=30,
         reset_deadtime=300):
    """Listen for BLE advertising packets from Ruuvitags.

    Args:
        callback: Function which will be called for each received
            Ruuvitag packet.
        devices: List of BT address strings in format "fe:ed:de:ad:be:ef"
            for whitelisting devices. If None, no address filtering is made.
        raw: If False, callback is called with a dictionary with decoded
            values from advertising message, plus "time" and "rssi" keys
            which have the packet arrival time and rssi as values.
            If True, callback is called with a tuple (value, addr, rssi)
            with the value being the raw BLE packet data, addr the BT address
            of the sending device and rssi the received signal strength
            indicator from the BT stack.
        iface: The number part of the BT interface device (0 for
            /dev/hci0 etc.)
        reset_timeout: Time in seconds, after which a reset of the BT
            adapter is made, if no packets are received.
        reset_deadtime: Time in seconds. If a BT reset is made and packets
            are still not arriving, the next reset attempt is made after
            this time has passed.
    """
    if devices:
        dev = [s.lower() for s in devices]
        devices = dev

    recv_event = threading.Event()

    reset_thread = threading.Thread(target=idlereset,
                                    args=(recv_event, reset_timeout,
                                          reset_deadtime))
    reset_thread.daemon = True
    reset_thread.start()

    # Start scanning
    scanner = Scanner(iface).withDelegate(
        ScanDelegate(recv_event, callback, devices, raw))
    scanner.clear()
    scanner.start(passive=True)
    try:
        while True:
            try:
                scanner.process(0)
            except BTLEException:
                try:
                    scanner.stop()
                except BTLEException:
                    scanner._stopHelper()
                    reset_btadapter()
                scanner.clear()
                scanner.start(passive=True)
    except (KeyboardInterrupt, SystemExit):
        pass

    log.info("Stopping scan.")
    scanner.stop()
Exemplo n.º 22
0
class _StoppableScanner(threading.Thread):
    """Scanner class which can be started and stopped asynchronously.

    Non-thread-safe.

    It is implemented as a thread which checks regularly for the stop
    condition within the :meth:`run()` method; it can be stopped by calling the
    :meth:`stop()` method.
    """

    def __init__(self, show_warnings=False, *args, **kwargs):
        """Constructor.

        Args:
            show_warnings (bool, optional): If True shows warnings, if any, when
            discovering devices not respecting the BlueSTSDK's advertising
            data format, nothing otherwise.
        """
        try:
            super(_StoppableScanner, self).__init__(*args, **kwargs)
            self._stop_called = threading.Event()
            self._process_done = threading.Event()
            with lock(self):
                self._scanner = Scanner().withDelegate(_ScannerDelegate(show_warnings))
        except BTLEException as e:
            # Save details of the exception raised but don't re-raise, just
            # complete the function.
            import sys
            self._exc = sys.exc_info()

    def run(self):
        """Run the thread."""
        self._stop_called.clear()
        self._process_done.clear()
        try:
            with lock(self):
                self._scanner.clear()
                self._exc = None
                self._scanner.start(passive=False)
                while True:
                    #print('.')
                    self._scanner.process(_ScannerDelegate._SCANNING_TIME_PROCESS_s)
                    if self._stop_called.isSet():
                        self._process_done.set()
                        break
 
        except BTLEException as e:
            # Save details of the exception raised but don't re-raise, just
            # complete the function.
            import sys
            self._exc = sys.exc_info()

    def stop(self):
        """Stop the thread."""
        self._stop_called.set()
        while not (self._process_done.isSet() or self._exc):
            pass
        try:
            self._exc = None
            with lock(self):
                self._scanner.stop()
        except BTLEException as e:
            # Save details of the exception raised but don't re-raise, just
            # complete the function.
            import sys
            self._exc = sys.exc_info()

    def join(self):
        """Join the thread.
        
        Raises:
            :exc:`blue_st_sdk.utils.blue_st_exceptions.BlueSTInvalidOperationException`
            is raised if this method is not run as root.
        """
        super(_StoppableScanner, self).join()
        if self._exc:
            msg = '\nBluetooth scanning requires root privilege, ' \
                  'so please run the script with \"sudo\".'
            raise BlueSTInvalidOperationException(msg)
Exemplo n.º 23
0
	while i < padding_size:
		padding = padding+"0"
		i+=1
	new_package = package+padding 
	try_until_success(output.write, msg="Failed to send to player 1", args=[new_package,True])

handler1 = BTEventHandler(1)
handler2 = BTEventHandler(2)

with open("mac.txt") as f:
	macAddresses = f.readlines()
macAddresses = [m.strip() for m in macAddresses]

# Create a scanner with the handler as delegate
scanner1 = Scanner().withDelegate(handler1)
scanner1.clear()
while True:
	while True:
		# Start scanning. While scanning, handleDiscovery will be called whenever a new device or new data is found
		devs = scanner1.scan(3)

		# Get HEXIWEAR's address
		devices = [dev for dev in devs if dev.getValueText(0x8) == 'HEXIWEAR']
		hexi_addr = []
		for dev in devices:
			print dev.addr
			if dev.addr in macAddresses:
				hexi_addr.append(dev.addr)
		print hexi_addr
		if len(hexi_addr) >= 2:
			player1 = hexi_addr[0]
Exemplo n.º 24
0
class BLEScan():
 bledev = 0
 timeout = 5.0
 scanner = None
 devices = []
 devrssi = []
 lastscan = 0

 def __init__(self,devnum=0,timeout=5.0):
  self.bledev = int(devnum)
  self.timeout = float(timeout)
  self.scanner = None
  self.devices = []
  self.devrssi = []
  self.lastscan = 0
  self._scanning = False
  self.scantime = 10
  self.minsleep = 15
  self.maxsleep = 40

 def stop(self):
    try:
     if self.scanner is not None:
      self.scanner.stop()
    except:
     pass
    self._scanning = False

 def scan(self):
    result = False
    devices = []
    self._scanning = True
    try:
     self.scanner = Scanner(self.bledev)
     devices = self.scanner.scan(self.timeout)
     result = True
     self.lastscan = time.time()
    except Exception as e:
     print("BLE error: ",e)
     self.devices = []
     self.devrssi = []
    self._scanning = False
    tempdev = []
    temprssi = []
    for dev in devices:
      try:
       if self.bledev == int(dev.iface):
        temprssi.append(dev.rssi)
        tempdev.append(str(dev.addr).lower().strip())
      except:
        pass
    self.devices = tempdev
    self.devrrsi = temprssi
    return result

 def isdevonline(self,devaddress):
  return (self.getdevrssi(devaddress) != -100)

 def getdevrssi(self,devaddress):
   try:
    for d in range(len(self.devices)):
     if str(devaddress).lower().strip()==str(self.devices[d]).lower().strip():
      return self.devrrsi[d]
    return -100
   except Exception as e:
    return -100

 def getage(self):
  if self.lastscan==0:
   return -1
  try:
   result = time.time()-self.lastscan
  except:
   result = -1
  return result

 def sniff(self, callback,startwait=0,scantime=10,minsleep=15,maxsleep=40):
    self._scanning = True
    self.scantime = scantime
    self.minsleep = minsleep
    self.maxsleep = maxsleep
    _blestatus = BLEHelper.BLEStatus[self.bledev]
    time.sleep(startwait)
    try:
     if self.timeout==0:
      while self._scanning:
       while _blestatus.norequesters()==False or _blestatus.nodataflows()==False or _blestatus.isscaninprogress():
        time.sleep(0.5)
#       print("scan start")#debug
       _blestatus.reportscan(1)
       try:
        self.scanner = Scanner(self.bledev).withDelegate(SniffDelegate(callback))
       except:
        pass
       self.scanner.clear()
       self.scanner.start(passive=True)
       self.scanner.process(scantime)
       self.scanner.stop()
       _blestatus.reportscan(0)
#       print("scan pause")#debug
       time.sleep(uniform(minsleep,maxsleep))
     else:
      while _blestatus.norequesters()==False or _blestatus.nodataflows()==False or _blestatus.isscaninprogress():
        time.sleep(0.5)
      _blestatus.reportscan(1)
      self.scanner = Scanner(self.bledev).withDelegate(SniffDelegate(callback))
      self.scanner.scan(self.timeout,passive=True)
      _blestatus.reportscan(0)
     self.lastscan = time.time()
    except Exception as e:
     _blestatus.reportscan(0)
    self._scanning = False