コード例 #1
0
ファイル: magicblueshell.py プロジェクト: Betree/magicblue
 def cmd_list_devices(self, *args):
     try:
         self.last_scan = ScanDelegate()
         scanner = Scanner().withDelegate(self.last_scan)
         print('Listing Bluetooth LE devices in range for 5 minutes.'
               'Press CTRL+C to stop searching.')
         print('{: <5} {: <30} {: <12}'.format('ID', 'Name', 'Mac address'))
         print('{: <5} {: <30} {: <12}'.format('--', '----', '-----------'))
         scanner.scan(350)
     except KeyboardInterrupt:
         print('\n')
     except RuntimeError as e:
         logger.error('Problem with the Bluetooth adapter : {}'.format(e))
         return False
コード例 #2
0
ファイル: temp_sensor.py プロジェクト: daviessm/heating
 def find_temp_sensors(sensors):
   TempSensor._scanning_lock.acquire()
   logger.debug('Scanning for devices')
   scanner = Scanner().withDelegate(ScanDelegate())
   try:
     devices = scanner.scan(10.0)
     if sensors is None:
       sensors = {}
     for device in devices:
       if device.addr in sensors:
         continue
       name = ''
       if device.getValueText(9):
         name = device.getValueText(9)
       elif device.getValueText(8):
         name = device.getValueText(8)
       logger.debug('Device name: ' + name)
       if 'SensorTag' in name:
         logger.info('Found SensorTag with address: ' + device.addr)
         sensors[device.addr] = SensorTag(device)
       elif 'MetaWear' in name:
         logger.info('Found MetaWear with address: ' + device.addr)
         sensors[device.addr] = MetaWear(device)
     logger.debug('Finished scanning for devices')
     TempSensor._scanning_lock.release()
     if len(sensors) == 0:
       raise NoTagsFoundException('No sensors found!')
   except BTLEException as e:
     scanner.stop()
     logger.warn('Got exception ' + e.message)
     TempSensor._scanning_lock.release()
   return sensors
コード例 #3
0
ファイル: ganglion.py プロジェクト: OpenBCI/OpenBCI_Python
    def find_port(self):
        """Detects Ganglion board MAC address
        If more than 1 around, will select first. Needs root privilege.
        """

        print("Try to detect Ganglion MAC address. "
              "NB: Turn on bluetooth and run as root for this to work!"
              "Might not work with every BLE dongles.")
        scan_time = 5
        print("Scanning for 5 seconds nearby devices...")

        #   From bluepy example
        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(scan_time)

        nb_devices = len(devices)
        if nb_devices < 1:
            print("No BLE devices found. Check connectivity.")
            return ""
        else:
            print("Found " + str(nb_devices) + ", detecting Ganglion")
            list_mac = []
            list_id = []

            for dev in devices:
                # "Ganglion" should appear inside the "value" associated
                # to "Complete Local Name", e.g. "Ganglion-b2a6"
                for (adtype, desc, value) in dev.getScanData():
                    if desc == "Complete Local Name" and value.startswith("Ganglion"):
                        list_mac.append(dev.addr)
                        list_id.append(value)
                        print("Got Ganglion: " + value +
                              ", with MAC: " + dev.addr)
                        break
        nb_ganglions = len(list_mac)

        if nb_ganglions < 1:
            print("No Ganglion found ;(")
            raise OSError('Cannot find OpenBCI Ganglion MAC address')

        if nb_ganglions > 1:
            print("Found " + str(nb_ganglions) + ", selecting first")

        print("Selecting MAC address " + list_mac[0] + " for " + list_id[0])
        return list_mac[0]
コード例 #4
0
    def getTag(self):
        """Scans for BT LE devices and returns the choosen keywords"""
        self.count = 0
        scanner = Scanner().withDelegate(DefaultDelegate())
        devices = scanner.scan(self.scanTimeout)
        for dev in devices:
            if dev.addr == self.address.lower():
                self.count = 1
			
        if self.count > 0:
            self.count = 0
            return self.found
        else:
            return self.missing
コード例 #5
0
def connect(strip, scanTimeout=2, reconnectAttempts=1, maxAttempts=10):
    # Max attempts reached
    if reconnectAttempts > maxAttempts:
        print("Failed to connect after %d attempts" % maxAttempts)
        return

    try:
        # Scanning for devices
        print("Scanning for devices (%d / %d)" %
              (reconnectAttempts, maxAttempts))
        scanner = Scanner()
        devices = scanner.scan(scanTimeout)

        for device in devices:
            # Only connect to Nuimos
            if device.connectable and device.getValueText(9) == "Nuimo":
                # Init Nuimo class
                nuimo = Nuimo(device.addr)
                nuimo.set_delegate(NuimoDelegate(nuimo, strip))

                # Connect to Nuimo
                print("Trying to connect to %s." % device.addr)

                nuimo.connect()
                nuimo.displayLedMatrix(LedMatrixString().getRaspberry(), 5)

                print("Connected successfully to %s." % device.addr)
                # Reset reconnect attempts on successfull connect
                reconnectAttempts = 0

                while True:
                    nuimo.waitForNotifications()
                return

        # Found no Nuimo
        print("Couldn't find a Nuimo.")
        connect(strip, scanTimeout + 1, reconnectAttempts + 1)
    except BTLEException:
        print("Failed to connect to %s. Make sure to:\n  1. Run program as root (For Scanning and the Strip)\n  2. Disable the Bluetooth device: hciconfig hci0 down\n  3. Enable the Bluetooth device: hciconfig hci0 up\n  4. Enable BLE: btmgmt le on\n" % nuimo.macAddress)
        connect(strip, scanTimeout + 1, reconnectAttempts + 1)
    except KeyboardInterrupt:
        print("Program aborted.")
        return
コード例 #6
0
ファイル: pr_rileylink.py プロジェクト: scudrunner/omnipy
    def _findRileyLink(self):
        scanner = Scanner()
        found = None
        self.logger.debug("Scanning for RileyLink")
        retries = 10
        while found is None and retries > 0:
            retries -= 1
            for result in scanner.scan(1.0):
                if result.getValueText(7) == RILEYLINK_SERVICE_UUID:
                    self.logger.debug("Found RileyLink")
                    found = result.addr
                    try:
                        with open(RILEYLINK_MAC_FILE, "w") as stream:
                            stream.write(result.addr)
                    except IOError:
                        self.logger.warning("Cannot store rileylink mac radio_address for later")
                    break

        if found is None:
            raise PacketRadioError("Could not find RileyLink")

        return found
コード例 #7
0
ファイル: ble_master.py プロジェクト: fridgeresearch/kitchen
    def scan_devs(self):
        func_name = inspect.stack()[0][3]
	logging.debug('%s start BLE scan', func_name)
        adapter = Scanner(0)
        devices = adapter.scan(10.0)
        logging.debug('%s found %d devices', func_name, len(devices))
        for d in devices:
            logging.debug('%s inspecting device %s', func_name, d.addr)
            for (tag, desc, value) in d.getScanData():
                logging.debug('%s tag=%s desc=%s value=%s',
                    func_name, tag, desc, value)
                if tag == 9 and value in self.supported_devs:
                    logging.debug('%s compatible device @%s', func_name, d.addr)
                    if d.addr not in self.devices:
                        self.devices[d.addr] = d
                        logging.info('%s added device @%s to ble_devices', 
                            func_name, d.addr)
                        self.cons[d.addr] = Peripheral(d.addr, 'random')
                        self.sendDevice(d.addr)
                        logging.info('%s connected to device @%s', func_name, d.addr)
        logging.debug('%s devices=%s', func_name, self.devices)
        logging.debug('%s cons=%s', func_name, self.cons)
        logging.debug('%s done BLE scan', func_name)
コード例 #8
0
ファイル: BLE_scan_test2.py プロジェクト: Dyson-t/minirobo
    def __init__(self):
        DefaultDelegate.__init__(self)
        self.lastseq = None
        self.lasttime = datetime.fromtimestamp(0)

    # devにはアドバタイズパケットの情報が詰まっている。ScanEntryクラス
    def handleDiscovery(self, dev, isNewDev, isNewData):
        if dev.addr == '30:ae:a4:0e:4f:12':
            #print('welcome Advertise Data')
            advdata = dev.getScanData()
            #print(advdata)
            for (at, at_desc, ad) in advdata:
                if at == 0xff:  # ESP側でセットしたManifacturer Specific Data
                    mdata = int(ad, 16)  # AD部分には16進文字列が格納されているため数値に変換
                    stick1_lr = (mdata & 0x000000ff00000000) >> 0x20
                    stick1_ud = (mdata & 0x00000000ff000000) >> 0x18
                    stick2_lr = (mdata & 0x0000000000ff0000) >> 0x10
                    stick2_ud = (mdata & 0x000000000000ff00) >> 0x08
            print(stick1_lr, stick1_ud, stick2_lr, stick2_ud)


# Scannerインスタンスを生成するとスキャン開始
# withDelegateでデバイス見つけたときのハンドラーを渡しておくと呼んでくれる。
scanner = Scanner().withDelegate(ScanDelegate())
try:
    while True:
        scanner.scan(0.05)

except KeyboardInterrupt:
    pass
コード例 #9
0
                        if device.get('state') == actions.OFF_STATE:
                            if device.get(
                                    'previous_state') == actions.OFF_STATE:
                                device['state'] = actions.BRIGHTEN_STATE
                            if device.get(
                                    'previous_state') == actions.DARKEN_STATE:
                                device['state'] = actions.BRIGHTEN_STATE
                            if device.get('previous_state'
                                          ) == actions.BRIGHTEN_STATE:
                                device['state'] = actions.DARKEN_STATE
                    else:
                        actions.toggle(device)


scanner = Scanner().withDelegate(ScanDelegate())
while True:
    devices = scanner.scan(1.0)
    if ble_devices.AIRER.get("state") == 1:
        # lets see if its been on for 8 hours and if so turn it off
        lastUpdated = ble_devices.AIRER.get("lastUpdated", datetime)
        timeSinceTurnedOn = datetime.now() - lastUpdated
        if timeSinceTurnedOn.seconds >= (8 * (60 * 60)):
            # turn off
            print("Timer has been on for %d hours and %d minutes" %
                  ((timeSinceTurnedOn.seconds / 60 / 60),
                   ((timeSinceTurnedOn.seconds) / 60) % 60))
            actions.toggle(ble_devices.AIRER)
    if ble_devices.LIVING_ROOM_LIGHTS.get("state") > 0:
        print("lights triggered")
        actions.changeLights(ble_devices.LIVING_ROOM_LIGHTS)
コード例 #10
0
    def scan_devs(self, timeout=8, scan_type='active', sort='rssi'):
        """LE devices scanning

        scan_type  - Indicate the type of LE scan:active, passive, adv or 
                     features.
        """
        if scan_type == 'adv':
            return

        scanner = Scanner(self.devid).withDelegate(LEDelegate())
        #print("[Debug] timeout =", timeout)

        # scan() 返回的 devs 是 dictionary view。
        if scan_type == 'active':  # Active scan 会在 LL 发送 SCAN_REQ PDU
            logger.warning(
                'Before doing an active scan, make sure you spoof your BD_ADDR.'
            )
            logger.info('LE active scanning on %s with timeout %d sec\n' % \
                (blue('hci%d'%self.devid), timeout))
            devs = scanner.scan(timeout)
        elif scan_type == 'passive':
            logger.info('LE passive scanning on %s with timeout %d sec\n' % \
                (blue('hci%d'%self.devid), timeout))
            devs = scanner.scan(timeout, passive=True)
        else:
            logger.error('Unknown LE scan type')
            return

        if sort == 'rssi':
            devs = list(devs)  # 将 dictionary view 转换为 list
            devs.sort(key=lambda d: d.rssi)

        for dev in devs:
            print('Addr:       ', blue(dev.addr.upper()))
            print('Addr type:  ', blue(dev.addrType))
            print('Connectable:',
                  green('True') if dev.connectable else red('False'))
            print("RSSI:        %d dB" % dev.rssi)
            print("General Access Profile:")
            for (adtype, desc, val) in dev.getScanData():
                # 打印当前 remote LE dev 透露的所有 GAP 数据(AD structure)。
                #
                # 如果 bluepy.scan() 执行的是 active scan,那么这些 GAP 数据
                # 可能同时包含 AdvData 与 ScanRspData。其中 AdvData 由 remote LE
                # dev 主动返回,ScanRspData 由 remote BLE dev 响应 SCAN_REQ 返回。
                #
                # 虽然 LL 分开定义了 Advertising PDUs (ADV_IND, ADV_DIRECT_IND...)
                # 和 Scanning PDUs (SCAN_REQ, SCAN_RSP)。但它们分别包含的 AdvData
                # 与 ScanRspData 到了 HCI 层都被放在了 HCI_LE_Advertising_Report
                # event 中。HCI_LE_Advertising_Report 的 Event_Type 标识了这些数
                # 据具体来源于哪个 LL 层的 PDU。另外 ScanRspData 与 AdvData 的格式
                # 完全相同,都是 GAP 协议标准定义的 AD structure。
                #
                # 在 LL 定义的 Advertising PDUs 中 ADV_DIRECT_IND 一定不会包含
                # AdvData。其余的 ADV_IND,ADV_NONCONN_IND 以及 ADV_SCAN_IND 都
                # 可能包含 AdvData。
                #
                # 另外 getScanData() 返回的 desc 还可以通过 ScanEntry.getDescription()
                # 单独获取;val 还可以通过 ScanEntry.getValueText() 单独获取;
                # adtype 表示当前一条 GAP 数据(AD structure)的类型。
                print('\t' + desc + ': ', end='')
                if adtype == COMPLETE_16_BIT_SERVICE_CLS_UUID_LIST:
                    for uuid in val.split(','):
                        print()
                        if len(uuid) == 36:
                            # 这里拿到的是完整的 128-bit uuid,但我们需要 16-bit uuid。
                            print('\t\t' + blue(uuid[4:8]))
                        else:
                            print('\t\t' + blue(uuid))
                    continue
                elif adtype == MANUFACTURER_SPECIFIC_DATA:
                    val = bytes.fromhex(val)
                    if len(val) > 2:
                        print()
                        print(
                            '\t\tCompany ID:', '0x%04x' %
                            int.from_bytes(val[0:2], 'little', signed=False))
                        print('\t\tData:', val[2:])
                    else:
                        print(val)
                    continue
                print(val)
            print("\n")
コード例 #11
0
from bluepy.btle import Scanner
print "Scan ..."
scanner = Scanner(0)
devices = scanner.scan(3)
for d in devices:
    print str(d.addr) + " - " + str(d.addrType)

print "Done"
コード例 #12
0
# Vulnerability Details
#https://github.com/jasondoyle/Komfy-Switch-Wifi-Password-Disclosure

# Author: Jason Doyle @_jasondoyle
# Komfy Switch with Camera wifi password disclosure exploit script
import re, base64
from bluepy.btle import Scanner
from gattlib import GATTRequester

#lookup table to unscramble
base64Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="  # '=' used for padding
komfy64Alphabet = "qazwersdfxcvbgtyhnmjklpoiu5647382910+/POIKLMJUYTGHNBVFREWSDCXZAQ$"  # '$' used for padding

scanner = Scanner()

devices = scanner.scan(5.0)
bAddr = ""
for dev in devices:
    if "6c:72:20" in dev.addr and dev.getValueText(1) and dev.getValueText(
            7) and dev.getValueText(9):
        bAddr = dev.addr
        print "[+] Komfy switch found: %s (%s), RSSI=%d dB" % (
            dev.addr, dev.addrType, dev.rssi)
if not bAddr:
    print "No Komfy switches found"
    sys.exit(1)

req = GATTRequester(bAddr.encode('ascii', 'ignore'), False, 'hci0')
req.connect(True, 'public', 'none', 0, 78)

#request SSID
コード例 #13
0
import time
from bluepy.btle import UUID, Peripheral
from bluepy.btle import Scanner, DefaultDelegate

class ScanDelegate(DefaultDelegate):
    def __init__(self):
        DefaultDelegate.__init__(self)

    def handleNotification(self, cHandle, data):
        print "inside notification"
        print "Heart rate:", ord(data[1]), "Energy=" ,int(binascii.b2a_hex((data[::-1])[0:2]),16) # This script was tested on ubuntu 14.04
                                                                                                  # To solve the endianess problem reverse the
                                                                                                  # string to find exact value

devices = Scanner()                 # Scanner Object
temp=devices.scan(10)               # Start Scan
try:
    for dev in temp:
        if dev.getScanData()[3][2] == "mr. singh":      # Check for the target BLE device name
            if dev.connectable:
                p = Peripheral(dev.addr, "random")
                p.setDelegate(ScanDelegate())           # Create internal Object of scandelegate class to handle the notifications
except (RuntimeError, TypeError, NameError):
    print "Device not found"
    exit(1)
################### Check for the Services and its characteristics #################
print p.getServices()[0]
print p.getServices()[1]
print p.getServices()[2]
Heart_Rate_Measurement = p.getServiceByUUID(0x180D).getCharacteristics()[0]
Body_Sensor_Location = p.getServiceByUUID(0x180D).getCharacteristics()[1]
コード例 #14
0
def main():
    scanner = Scanner().withDelegate(ScanDelegate())
    devices = scanner.scan(10.0)

    tags = []

    for dev in devices:
        completeLocalName = dev.getValueText(COMPLETE_LOCAL_NAME)
        if completeLocalName == "CC2650 SensorTag":
            print("Connecting to {0} {1} ({2}), RSSI={3} dB".format(
                completeLocalName, dev.addr, dev.addrType, dev.rssi))
            tags.append(sensortag.SensorTag(dev.addr))

    for i in range(0, len(tags)):
        tags[i].magnetometer.enable()

    time.sleep(3.0)
    endTime = time.time() + 10

    data = len(tags) * [[]]
    '''
    while time.time() < endTime:
        #for i in range(0, len(tags)):
        data.append(tags[0].magnetometer.read())
    '''
    print('Calculating Offsets...')
    pos_dict = cali_funcs.parse_input(CALI_FILE)
    pos_m = []
    h = []

    for i in range(CALI_MAG_POSITION):
        for p in range(CALI_POS_SAMPLES):
            pos_m.append(pos_dict['MagPos' + str(i)])
            h.append(pos_dict['MagOrien' + str(i)])
    #print(pos_m)
    while i < CALI_OFFSET_SAMPLES:
        for index in range(len(tags)):
            #data[index].append(tags[index].magnetometer.read())
            data[index].append([20, 20, 20])
        i = i + 1

    offsets = len(tags) * [[0, 0, 0]]
    for i in range(len(tags)):
        offsets[i] = cali_funcs.cali_offset(data[i])

    print('Calibrating...')
    data = []
    for i in range(len(tags)):
        data.append([])
    for pos in range(CALI_MAG_POSITION):

        print('Place Mag at  position ', pos)
        tmp = input('Press Enter to continue')
        for index in range(len(tags)):
            for i in range(CALI_POS_SAMPLES):
                #data[index].append(tags[index].magnetometer.read())
                data[index].append([
                    20 + (index + i) * 10, 20 + (index + i) * 10,
                    20 + 10 * (index + i)
                ])
    cali_para = []
    #print(pos_m)
    for i in range(len(tags)):
        cali_para.append([])
        pos_l = pos_dict['Sensor' + str(i)].copy()
        cali_para[i] = cali_funcs.calibrateSensor(data[i], pos_m, h, pos_l,
                                                  CALI_ITER,
                                                  offsets[i]).copy()

    print('Calibration Finished')
    tmp = input('Press Enter to continue')
    '''
コード例 #15
0
# recupere le numero du controleur
if args.device == "hci0":
    index = 0
elif args.device == "hci1":
    index = 1
elif args.device == "hci2":
    index = 2
elif args.device == "hci3":
    index = 3
else:
    print("device error (hci0 a hci3)")

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

try:
    devices = scanner.scan(int(args.timeout))
except:  # pylint: disable-msg=W0702
    print(
        "Erreur dans le scan le controleur est probablement occupe essayer un autre "
    )
else:
    file_dat = "/tmp/MiFlora_rssi_" + args.antenne + ".dat"
    # print ("file_dat : " + file_dat)
    file_out = open(file_dat, "w")

    for dev in devices:
        #    print ("%s,%s,(%s),%d;" % (args.antenne,dev.addr, dev.addrType, dev.rssi))
        for (adtype, desc, value) in dev.getScanData():
            if desc == "Complete Local Name":
                print("%s;%s;%s;%s;%d;%s," % (args.id, args.antenne, dev.addr, dev.addrType, \
                                              dev.rssi, value))
コード例 #16
0
#!/usr/bin/env python
# import os

import bluepy.btle as ble

from bluepy.btle import Scanner, DefaultDelegate


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())

devs = scanner.scan(2)

for dev in devs:
    if dev.addr == "ac:23:3f:25:a1:06":
        print(dev.addr, "acquired data:")
        print(dev.getScanData())
コード例 #17
0
def main():
        #Scan for Bluetooth devices for 2 seconds
        scanner = Scanner().withDelegate(ScanDelegate())
        scanner.scan(200.0)
コード例 #18
0
ファイル: bucklehunter.py プロジェクト: eybisi/misc
    ▒██░█▀  ▓▓█  ░██░▒▓▓▄ ▄██▒▓██ █▄ ▒██░    ▒▓█  ▄    ░▓█ ░██ ▓▓█  ░██░▓██▒  ▐▌██▒░ ▓██▓ ░ ▒▓█  ▄ ▒██▀▀█▄  
    ░▓█  ▀█▓▒▒█████▓ ▒ ▓███▀ ░▒██▒ █▄░██████▒░▒████▒   ░▓█▒░██▓▒▒█████▓ ▒██░   ▓██░  ▒██▒ ░ ░▒████▒░██▓ ▒██▒
    ░▒▓███▀▒░▒▓▒ ▒ ▒ ░ ░▒ ▒  ░▒ ▒▒ ▓▒░ ▒░▓  ░░░ ▒░ ░    ▒ ░░▒░▒░▒▓▒ ▒ ▒ ░ ▒░   ▒ ▒   ▒ ░░   ░░ ▒░ ░░ ▒▓ ░▒▓░
    ▒░▒   ░ ░░▒░ ░ ░   ░  ▒   ░ ░▒ ▒░░ ░ ▒  ░ ░ ░  ░    ▒ ░▒░ ░░░▒░ ░ ░ ░ ░░   ░ ▒░    ░     ░ ░  ░  ░▒ ░ ▒░
     ░    ░  ░░░ ░ ░ ░        ░ ░░ ░   ░ ░      ░       ░  ░░ ░ ░░░ ░ ░    ░   ░ ░   ░         ░     ░░   ░ 
     ░         ░     ░ ░      ░  ░       ░  ░   ░  ░    ░  ░  ░   ░              ░             ░  ░   ░     
          ░          ░
    '''
    print(a)


print_banner()

scanner = Scanner()
log.info(f"Scannig around for BLE.. Wait for {SCAN_TIME} seconds")
devices = scanner.scan(SCAN_TIME)
log.info(f"Scannig done. Found {len(devices)}")

buckles = []

if len(devices) == 0:
    log.warn("Where are you dude ? :X Maybe increase scan time ?")
    exit()

c = 0
c2 = 0
totallen = len(devices)
with log.progress('Taking closer look to found devices') as progress:
    for dev in devices:
        time.sleep(0.2)
        for (adtype, desc, value) in dev.getScanData():
コード例 #19
0
ファイル: bleexample.py プロジェクト: breitkopf/bluetooth
while True:
    confirm = input("You entered " + device_name +
                    ". Would you like to use this name?")
    if "y" in confirm.lower():
        break
    else:
        device_name = input(
            "Please name your phone (e.g. \"Oncology Attending\".\n\n")

# Initial scan
x = input(
    "I will now scan nearby BLE devices.\n\nMake sure your phone has Bluetooth enabled and near the RPI.\n\nThis will take 10 seconds.\n\nPress ENTER to continue..."
)

scanner = Scanner().withDelegate(ScanDelegate())
devices = scanner.scan(10)

for dev in devices:
    #print("Device %s (%s), RSSI=%d dB" % (dev.addr, dev.addrType, dev.rssi))
    for (adtype, desc, value) in dev.getScanData():
        #print("  %s = %s" % (desc, value))
        first_scan.append(dev.addr)
        if dev.addr not in signal_strength:
            signal_strength[dev.addr] = dev.rssi

x = input(
    "Ready for the second scan. This will take 10 seconds.\n\nTurn off your Bluetooth and press ENTER to continue..."
)

# Second scan, with Bluetooth off
scanner = Scanner().withDelegate(ScanDelegate())
コード例 #20
0
ファイル: test.py プロジェクト: Sail338/ILostMyPhone
        DefaultDelegate.__init__(self)


    def HandleDiscovery(self,dev,new_dev,new_dat):
        if new_dev:
            pass
        if new_dat:
            pass
        
scanner = Scanner().withDelegate(ScanDelegate())

time_diff = 0
first_time = 1
while 1:
    try:
        devices = scanner.scan(0.35)
##        print("Amount of Devices = "+str(len(devices)))
        for ii in devices:
             print(ii.addr)

             print("Device %s, RSSI=%d dB" % (ii.addr,ii.rssi))
             if first_time == 1:
                first_time = 0
                pass
             else:
                time_diff = time.time()-time_prev
                time_prev = time.time()
                rssi_prev = ii.rssi
                continue

    except:
コード例 #21
0
def main():
    # uuid definition
    targetDevice = ""
    targetUUID   = UUID("08590f7e-db05-467e-8757-72f6f66666d4")
    # targetUUID   = UUID(0x2a2b)
    serviceUUID  = UUID("e20a39f4-73f5-4bc4-a12f-17d1ad666661")

    # scanning for Bluetooth LE device
    # P.S. root permission is needed
    print "scanning started..."
    scanner = Scanner().withDelegate(ScanDelegate())
    devices = scanner.scan(5)

    print "\n\nscanning completed...\n found %d device(s)\n" % len(devices)

    for dev in devices:
        print "Device %s (%s), RSSI=%d dB" % (dev.addr, dev.addrType, dev.rssi)
        for (adtype, desc, value) in dev.getScanData():
            print "  %s = %s" % (desc, value)

        try:
            p = Peripheral(dev.addr, "random")
            ch = p.getCharacteristics(uuid=targetUUID)
            if len(ch) > 0:
                print "the desired target found. the address is", dev.addr
                targetDevice = dev.addr
        except:
            # print "Unexpected error:", sys.exc_info()[0]
            print "Unable to connect"
            print " "
        finally:
            p.disconnect()

    # scanning completed, now continue to connect to device
    if targetDevice == "":
        # the target is not found. end.
        print "no target was found."
    else:
        # the target found, continue to subscribe.
        print "\n\nthe target device is ", targetDevice
        print "now try to subscribe..."

        try:
            # try to get the handle first
            p = Peripheral(targetDevice, "random")
            p.setDelegate(NotificationDelegate())
            # svc = p.getServiceByUUID(serviceUUID)
            ch = p.getCharacteristics(uuid=targetUUID)[0] # svc.getCharacteristics(targetUUID)[0]
            handle = ch.getHandle()
            print handle
            ch.write(struct.pack('<bb', 0x01, 0x00))
            # ch.write(bytes('aa', 'utf-8'))
            # p.writeCharacteristic(handle, struct.pack('<bb', 0x01, 0x00), True)

            print

            # Main loop
            while True:
                if p.waitForNotifications(5):
                    # handleNotification() was called
                    continue

                print "Waiting..."
                # Perhaps do something else here
        # except:
        #     print "Unexpected error:", sys.exc_info()[0]
        finally:
            p.disconnect()
コード例 #22
0
ファイル: ble_receiver.py プロジェクト: seemoo-lab/BTLEmap
class BLERelay( DefaultDelegate): 

    ########################
    ##  BLE SCANNING
    ########################
    def __init__(self):
        self.packets_sent = 0
        self.scanning = False
        self.scanner = None 
        self.sock = None 
        self.sock_recv_thread = None
        self.current_service_info = None 
        self.connected_peripherals = list()
        self.isConnecting = False
        self.connected_scan_entry: ScanEntry = None 
        self.ble_timeout = 2.0 
        self.autoconnect = True
        self.readable_services = [AssignedNumbers.device_information, AssignedNumbers.generic_access, AssignedNumbers.generic_attribute]
        # List of characteristics UUIDs that hav failed. Created dynamically such that they won't be read a second time 
        self.failing_characteristics: typing.List[UUID] = list()
        DefaultDelegate.__init__(self)

    def handleDiscovery(self, dev, isNewDev, isNewData):
        """
        A BLE signal has been received. The content is part of the dev parameter 
        """
        self.relay_ble_advertisement(dev)
            


    def start_ble_scanning(self): 
        """
        Start the BLE Scanner
        """
        # Setup BLE Scanner 
        
        self.scanner =  Scanner().withDelegate(self)
        self.scanning = True
        t = Thread(target=self.scan_forever,  name="ble_scanning")
        t.start()
        

    def scan_forever(self):
        """
        Scan for BLE signals forever. Uses a short scannning time and a Timer to restart scanning quickly
        """

        while self.scanning:
            try: 
                # Scan for scan_time. Then scan again 
                DBG("Start scanning", logLevel=LogLevel.DEBUG)
                scan_time = 1.0
                devices = self.scanner.scan(scan_time, passive=False)
                connectable_devices = [dev for dev in devices if dev.connectable and not next((d for d in self.connected_peripherals if d == dev.addr), None)]
                DBG("Scan finished. Discovered {} devices".format(len(devices)))

                # Connect on a different thread 
                if self.autoconnect and len(connectable_devices) > 0: 
                    DBG("Connecting to device", logLevel=LogLevel.DEBUG)
                    # Connect to one device and read info before performing a scan again 
                    self.connected_scan_entry = connectable_devices[0]
                    self.read_info_from_ble_device(self.connected_scan_entry)
                elif len(connectable_devices) == 0: 
                    DBG("No connectable devices found", logLevel=LogLevel.DEBUG)
                else: 
                    DBG("Postponing connection. Already connecting", logLevel=LogLevel.DEBUG)

            except Exception as e: 
                DBG("Scan error", logLevel=LogLevel.ERR)
                logging.exception(e)

        DBG("Stopping BLE Scan", logLevel=LogLevel.DEBUG)

            #asyncio.create_task
            #asyncio.run_coroutine_threadsafe(self.connect_to_devices_async(connectable_devices), loop=asyncio.get_event_loop())


    def read_info_from_ble_device(self, dev: ScanEntry): 
        peripheral = self.connect_to_ble_device(dev)
        if peripheral:
            services = self.read_services_from_peripheral(peripheral, dev)
            self.read_characteristics(peripheral, dev, services)
            self.disconnect_from_peripheral(peripheral)
    
    def connect_to_ble_device(self, dev:  ScanEntry) -> Peripheral :
        """
        Connect to a BLE device. 
        This is used to discover services running on this device 
        """

        DBG("Connecting to {}".format(dev.addr), logLevel=LogLevel.DEBUG)

        ## Try connecting 
        try:
            self.connected_peripherals.append(dev.addr) 
            peripheral =  Peripheral(dev, timeout=self.ble_timeout)
            return peripheral
        except Exception as e:
            DBG("Connecting to {} failed".format(dev.addr), logLevel=LogLevel.ERR) 
            logging.exception(e)
            return None 
        
    def reconnect_to_device(self, dev: ScanEntry, old_peripheral: Peripheral) -> Peripheral: 
        try:
            # old_peripheral.disconnect() 
            time.sleep(0.5)
            DBG("Reconnecting to {}".format(dev.addr))
            peripheral =  Peripheral(dev, timeout=3.0)
            return peripheral
        except Exception as e:
            DBG("Reconnecting to {} failed".format(dev.addr), logLevel=LogLevel.ERR) 
            logging.exception(e)
            return None 
        
    def disconnect_from_peripheral(self, peripheral: Peripheral):
        try: 
            if peripheral: 
                peripheral.disconnect(timeout=self.ble_timeout)
        except Exception as e: 
            DBG("Disconnecting failed", logLevel=LogLevel.ERR)
            # DBG(e, logLevel=LogLevel.ERR)

    def read_services_from_peripheral(self, peripheral: Peripheral, dev: ScanEntry) -> typing.List[Service]:
        ## Try getting servicex
        try: 
            services = peripheral.getServices()
            self.relay_discovered_services(peripheral, services)
            return services
        except Exception as e:
            DBG("Getting services from {} failed".format(dev.addr), logLevel=LogLevel.ERR) 
            logging.exception(e)
            services = list() 
            return services
    
    def read_characteristics(self, peripheral: Peripheral, dev: ScanEntry, services:typing.List[Service]): 
        if len(services) > 0: 
            #Discovered services 
            DBG("Discovered services {}".format([s.uuid.getCommonName() for s in services]), logLevel=LogLevel.INFO)

            for s in services:
                try: 
                    DBG("Accessing service: {}".format(s.uuid.getCommonName()))
                    characteristics = s.getCharacteristics()
                    DBG("Discovered characteristics:\n\t{}".format([c.uuid.getCommonName() for c in characteristics]))
                    ## characteristics_info = [(c, b'') for c in characteristics]

                    if s.uuid in self.readable_services: 
                        self.read_value_for_charateristics(characteristics, s, peripheral, dev)     
                    else: 
                        characteristics_info = [(c, b'') for c in characteristics]
                        self.relay_service_information(dev, s, characteristics_info)

                    ## self.relay_service_information(peripheral, s, characteristics_info)
                except Exception as e: 
                    DBG("Accessing service  failed {}".format(s.uuid.getCommonName()), logLevel=LogLevel.ERR)
                    logging.exception(e)

                    # peripheral = self.reconnect_to_device(dev, old_peripheral=peripheral)
                    # if not peripheral:
                    #     break

    def read_value_for_charateristics(self, characteristics: typing.List[Characteristic], service: Service, peripheral: Peripheral, device: ScanEntry):
        characteristics_info = list()

        for c in characteristics: 
            try:
                # Check if Extended properties 
                DBG("Characteristic {} Properties {}".format(c, c.propertiesToString()),  logLevel=LogLevel.DEBUG)
                if c.properties & Characteristic.props["EXTENDED"]: 
                    DBG("Uses extended properties", logLevel=LogLevel.DEBUG)
                    characteristics_info.append((c, b''))
                    continue

                if c.supportsRead() and not c.uuid in self.failing_characteristics: 
                    value = peripheral.readCharacteristic(c.valHandle, timeout=self.ble_timeout)
                    characteristics_info.append((c, value))
                    DBG("Read {} and received {}".format(c.uuid.getCommonName(), value))
                else: 
                    characteristics_info.append((c, b''))
            except Exception as e: 
                DBG("Could not read characteristic {} - {}".format(c.uuid.getCommonName(), c.uuid.binVal), logLevel=LogLevel.DEBUG)
               #  DBG(e.with_traceback(), logLevel=LogLevel.ERR)
                characteristics_info.append((c, b''))
                # peripheral = self.reconnect_to_device(device, old_peripheral=peripheral)
                # if not peripheral:
                #         break
        
        self.relay_service_information(device, service, characteristics_info)
                



    def handleNotification(self, cHandle, data):
        """
        BTLE Peripheral delegate callback 
        """
        DBG("Received notification from cHandle: {} with data {}".format(cHandle, data), logLevel=LogLevel.INFO)


    ########################
    ##  ZEROCONF 
    ########################
    def remove_service(self, zeroconf, type, name): 
        """
        A service has been removed with mDNS/DNS-SD
        """
        if self.current_service_info and self.current_service_info.name == name: 
            # Service removed. Disconnect 
            self.disconnected_from_socket()

        DBG("Service %s removed" % (name,))

    def add_service(self, zeroconf, type, name):
        """
        A service has been resolved with mDNS / DNS-SD
        """
        info = zeroconf.get_service_info(type, name)
        #print("Service %s added, service info: %s" % (name, info))
        # Found service. Connect to it 
        self.connect_to_service(info)
        
    
    def connect_to_service(self, info): 
        """
        Connect to a service that has been detected 
        """
        self.current_service_info = info
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        addr_string = socket.inet_ntop(socket.AF_INET, info.addresses[0])
        #print("Service IP address {}".format(addr_string))
        service_address = (addr_string, info.port)
        DBG("Connecting to {}".format(service_address), logLevel=LogLevel.DEBUG)
        try:
            self.sock.settimeout(5.0)
            self.sock.connect(service_address)
            
            # Start receiving thread 
            t = Thread(target=self.receive_control_commands,  name="sock_receiving")
            t.start()

        except Exception as e: 
            DBG("Socket connection failed", logLevel=LogLevel.ERR)
            logging.exception(e)
            self.disconnected_from_socket()
    


    def disconnected_from_socket(self): 
        """
        Called when the socket disconnected. Clearing up the internal state 
        """
        DBG("Stopping...", logLevel=LogLevel.DEBUG)
        self.sock.close()
        self.scanning = False
        self.sock = None
        DBG("Cleaning up...")
        self.current_service_info = None 
        # Clear the lists for scanned peripherals 
        self.connected_peripherals = list()
            

    def receive_control_commands(self): 
        """
        Loop to receive data from the socket. 
        Run in it's own thread 
        """
        DBG("Waiting for incomming messages", logLevel=LogLevel.DEBUG)
        while self.sock:
            try: 
                header = self.sock.recv(5)
                if header: 
                    DBG("Received incoming message header ", header)
                    # Received header 
                    message_type = header[0]
                    message_length = int.from_bytes(header[1:], byteorder="little")
                    # Read the full message 
                    message = self.sock.recv(message_length)
                    self.control_command_received(message_type, message)
            except Exception as e:
                # Sockets can timeout. No worries to get an exception here
                # DBG("Error occured while receiving from socket", logLevel=LogLevel.ERR)
                # DBG(e, logLevel=LogLevel.ERR)
                continue  
    
    def control_command_received(self, message_type: bytes, message: bytes): 
        """
        The control commands have been received. They will be parsed
        """
        
        DBG("Received message\n type: {}, message: {}".format(message_type,message))

        # 0xfe is the message type for standard control commands 
        if message_type == 0xef: 
            # Decode message to JSON 
            json_message = json.loads(message)
            # {
            #   scanning: true | false, autoconnect: true | false  
            # }
            DBG("Received control command \n{}".format(json_message), logLevel=LogLevel.DEBUG)

            scanning = json_message["scanning"]
            if scanning == True: 
                self.start_ble_scanning()
            elif scanning == False: 
                self.scanning = False
                

            autoconnect = json_message["autoconnect"]
            if autoconnect == True : 
                self.autoconnect = True
            elif autoconnect == False: 
                self.autoconnect = False  


    ########################
    ##  RELAY BLE INFO
    ########################

    ## Sending BLE Packets 
    def relay_ble_advertisement(self, scanEntry:  ScanEntry): 
        """
        Send the BLE packet to the connected service running on iOS 
        """
        ### Message format 
        # 1 byte type - 4 bytes message length - message 
        ###

        name = scanEntry.getValueText( ScanEntry.COMPLETE_LOCAL_NAME)
        if not name: 
            name = scanEntry.getValueText( ScanEntry.SHORT_LOCAL_NAME)
        
        # services_16 = scanEntry.getValueText(ScanEntry.INCOMPLETE_16B_SERVICES)
        # services_32 = scanEntry.getValueText(ScanEntry.INCOMPLETE_32B_SERVICES)
        # services_128 = scanEntry.getValueText(ScanEntry.INCOMPLETE_128B_SERVICES)
        # print("Services 16B: \n\t{}\nServices 32B: \n\t{}\nServices 128B: \n\t{}".format(services_16, services_32 , services_128 ))
        DBG("Raw Data: {}".format(scanEntry.rawData), logLevel=LogLevel.DEBUG)
        raw_data_hex = ""
        if scanEntry.rawData: 
            raw_data_hex = scanEntry.rawData.hex()

        packet_content = {
            "manufacturerDataHex": scanEntry.getValueText(ScanEntry.MANUFACTURER), 
            "macAddress": scanEntry.addr, 
            "rssi": scanEntry.rssi,
            "name": name, 
            "flags": scanEntry.getValueText( ScanEntry.FLAGS), 
            "addressType": scanEntry.addrType,
            "connectable": scanEntry.connectable, 
            "rawData": raw_data_hex, 
            #"scanData": {tag: scanEntry.getValueText(k) for k, tag in scanEntry.dataTags.items()}
        }

        # Check for additional content in this advertisement 

        # Get service UUIDs 
        serviceUUIDs = list()
        if scanEntry.getValueText(ScanEntry.INCOMPLETE_16B_SERVICES):
            serviceUUIDs.append(scanEntry.getValueText(ScanEntry.INCOMPLETE_16B_SERVICES))

        if scanEntry.getValueText(ScanEntry.INCOMPLETE_32B_SERVICES):
            serviceUUIDs.append(scanEntry.getValueText(ScanEntry.INCOMPLETE_32B_SERVICES))
        
        if scanEntry.getValueText(ScanEntry.INCOMPLETE_128B_SERVICES):
            serviceUUIDs.append(scanEntry.getValueText(ScanEntry.INCOMPLETE_128B_SERVICES))

        if scanEntry.getValueText(ScanEntry.COMPLETE_16B_SERVICES):
            serviceUUIDs.append(scanEntry.getValueText(ScanEntry.COMPLETE_16B_SERVICES))

        if scanEntry.getValueText(ScanEntry.COMPLETE_32B_SERVICES):
            serviceUUIDs.append(scanEntry.getValueText(ScanEntry.COMPLETE_32B_SERVICES))

        if scanEntry.getValueText(ScanEntry.COMPLETE_128B_SERVICES):
            serviceUUIDs.append(scanEntry.getValueText(ScanEntry.COMPLETE_128B_SERVICES))

        if len(serviceUUIDs) > 0: 
            packet_content["serviceUUIDs"] = serviceUUIDs 

        # Get service data 
        if scanEntry.getValueText(ScanEntry.SERVICE_DATA_16B): 
            packet_content["serviceData16Bit"] = scanEntry.getValueText(ScanEntry.SERVICE_DATA_16B)
        
        if scanEntry.getValueText(ScanEntry.SERVICE_DATA_32B): 
            packet_content["serviceData32Bit"] = scanEntry.getValueText(ScanEntry.SERVICE_DATA_32B)
        
        if scanEntry.getValueText(ScanEntry.SERVICE_DATA_128B): 
            packet_content["serviceData128Bit"] = scanEntry.getValueText(ScanEntry.SERVICE_DATA_128B)

        
        DBG("Encoding json: ", packet_content)
        json_packet = json.dumps(packet_content).encode() 
        
        # Message type for advertisements is 0
        self.send_packet_over_socket(packet_type=0, packet_data=json_packet)

    def relay_discovered_services(self, device:  Peripheral, services:typing.List[ Service]):
        """
        Relay a packet with all services discovered for a peripheral
        """
        packet_content = {
            "macAddress": device.addr,
            "services": [{
                "uuid": s.uuid.binVal.hex(), 
                "commonName": s.uuid.getCommonName()
            } for s in services]
        }

        json_packet = json.dumps(packet_content).encode() 

        self.send_packet_over_socket(packet_type=1, packet_data=json_packet)

    def relay_service_information(self, device: ScanEntry, service: Service, characteristic_info: typing.List[typing.Tuple[Characteristic, bytes]]):

        packet_content = {
            "macAddress": device.addr, 
            "service": {
                "uuid": service.uuid.binVal.hex(), 
                "commonName": service.uuid.getCommonName() 
            }, 
            "characteristics": [{
                "serviceUUID": service.uuid.binVal.hex(),
                "uuid": c[0].uuid.binVal.hex(), 
                "commonName": c[0].uuid.getCommonName(), 
                "value": c[1].hex()
            } for c in characteristic_info]
        }
        json_packet = json.dumps(packet_content).encode() 

        self.send_packet_over_socket(packet_type=2, packet_data=json_packet)

    def send_packet_over_socket(self, packet_type: int, packet_data: bytes):
        """
        Send information over the connected socket

        Parameters: 
            packet_type (int): The integer representing the packet type that should be sent (e.g. 0 for a BLE advertisment)
            packer_data (bytes): The data for a packet that should be sent 
        """

        message_length = len(packet_data).to_bytes(4, byteorder="little")
        message_type = packet_type.to_bytes(1, byteorder="little")

        sendable_packet = message_type + message_length + packet_data

        DBG("Sending packet with content\n\t{}".format(packet_data.decode()))

        if not self.sock: 
            # No socket available 
            return 

        try: 
            self.packets_sent += 1
            # print("Sending no. {} at: {}".format(self.packets_sent, datetime.datetime.now()))
            self.sock.send(sendable_packet)
        except Exception as e: 
            DBG("Sending over socket failed", logLevel=LogLevel.ERR)
            DBG("Reason: {}".format(e), logLevel=LogLevel.ERR)
            self.disconnected_from_socket()
コード例 #23
0
nomeDoArquivo = raw_input("\nArquivo: ") # sem extensão
nomeDoArquivo = "dados/experimento8 (obstruido)/" + nomeDoArquivo + ".txt"
arquivo = open(nomeDoArquivo, 'w')

rssiList = []
distancias = []

timeout, start_time = time.time() + 600, datetime.now()  

count = 0
while True:
    if (count >= 100): 
        break
    # index is the hci port number of blutooth device, you can consult on terminal with command $ "rfkill"
    # timeout is a timer o scanner on while loop, it works as a delay
    scanner = Scanner(1).withDelegate(ScanDelegate())
    devices = scanner.scan(timeout = 3)
    for dev in devices:
        if (dev.addr == "c8:fd:19:37:2b:0a"):
            count += 1
            imprime(dev.rssi)
            rssiList.append(dev.rssi)
end_time = datetime.now()
arquivo.write(str(rssiList))
arquivo.write('\n')
arquivo.write(str(distancias))
arquivo.write('\n')
arquivo.write('Experiment time: {} '.format(end_time - start_time))
arquivo.close()
print('\n Experiment time: {} '.format(end_time - start_time))
コード例 #24
0
ファイル: main_x_.py プロジェクト: Dyson-t/minirobo
#スキャンしてデバイス見つけたときのハンドラー
class ScanDelegate(DefaultDelegate):
    def __init__(self):
        DefaultDelegate.__init__(self)
        self.lastseq = None
        self.lasttime = datetime.fromtimestamp(0)

    def handleDiscovery(self, dev, isNewDev, isNewData):
        if dev.addr == ADDR_BSTICK:  # ESP32 からだったら
            print("try connect to ", dev.addr)
            con = Connection(ADDR_BSTICK)
            print("connected.")
            con.setDelegate(NotifyDelegate())
            while True:
                if con.waitForNotifications(10.0):
                    continue
                print("wait..")


# Scannerインスタンスを生成するとスキャン開始
# withDelegateでデバイス見つけたときのハンドラーを渡しておくと呼んでくれる。
scanner = Scanner().withDelegate(ScanDelegate())
try:
    while True:
        print("scanning..")
        scanner.scan(1)
        sleep(1)

except KeyboardInterrupt:
    pass
コード例 #25
0
def main():

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

    device_list = scanner.scan(5)  # scan for 5 seconds
    for device in device_list:
        if (device.addr.lower() == DH_ADDRESS.lower()):
            print("Target device host discovered!")
            # RSSI = Received Signal Strength Indicator
            print("Device %s (%s), RSSI=%d dB" %
                  (device.addr, device.addrType, device.rssi))
            scan_data = device.getScanData()
            device_name = scan_data[2][2]
            auth_service_uuid = scan_data[4][2]
            print(device_name)
            print(auth_service_uuid)
            #for (adtype,desc,value) in device.getScanData():
            #    print("\t%s = %s" % (desc, value))

    try:
        device = Peripheral(DH_ADDRESS)
        device.setMTU(520)
        device.setDelegate(PeripheralDelegate())
        print("Successfully connected to device host")
        auth_service = device.getServiceByUUID(auth_service_uuid)
        auth_char = auth_service.getCharacteristics()[0]

        # read authentication characteristic state
        auth_char_val = auth_char.read()
        #print(auth_char_val)
        if (auth_char_val.decode() == '0x15'):  # BLE_CHAR_AUTH_REQ
            print("# Device host ready to receive authentication ticket")
        #auth_ticket = { 'sercret':1, 'public':2 ,'signature':3}
        #auth_ticket = "{'secret': qqqqqqqqqqqqqqaaaaaaaaaaaaaaaaaaaaaaaaaassssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss, 'public': {'dh_id' : uuid, 'dh_addr' : addr, 'owner_id' : gw_id, 'access_rights' : 'Rx', 'ticket_lifetime': 3600},'signature': sig}"
        s_auth_ticket = str(auth_ticket).replace("b\'", "")
        print(s_auth_ticket)

        msg_header = "0x50"
        #msg_payload = str(auth_ticket).encode()
        #msg = msg_header.encode() + msg_payload
        #msg = msg[0:100]
        if ((len(s_auth_ticket) + HEADER_SIZE) > MAX_MSG_SIZE):
            print("Message size exceeds maximum capacity. Fragmenting data...")

            fragments = dataFragment(s_auth_ticket)
            for frag in fragments:
                msg = msg_header.encode() + frag.encode()
                print(msg)
                #print(len(msg))
                auth_char.write(msg)
                time.sleep(0.5)
        else:
            print("Packet does not exceed maximum capacity")
        #auth_char.write(msg)
        #else:
        # catch other responses here
        # such as if device not ready, wait and do authentication later
        # < TODO >
        #    print("# Something went wrong...")
        """
        while True:
            if p.waitForNotifications(1.0):
                # handleNotification() was called
                continue
             print "Waiting..."
            # Perhaps do something else here
        """

    finally:
        device.disconnect()
コード例 #26
0
                print(json.dumps(self.parseData(val)))
                exit()

    def isTemperature(self, addr, sdid, val):
        if sdid != 22:
            return False
        if len(val) != 30:
            return False
        return True

    def parseData(self, val):
        bytes = [int(val[i:i + 2], 16) for i in range(0, len(val), 2)]
        return {
            'timestamp':
            datetime.now().astimezone().replace(microsecond=0).isoformat(),
            'mac':
            ":".join(["{:02X}".format(bytes[i]) for i in range(2, 8)]),
            'temperature': (bytes[8] * 16 + bytes[9]) / 10,
            'humidity':
            bytes[10],
            'battery_percent':
            bytes[11],
            'battery_volt': (bytes[12] * 16 + bytes[13]) / 1000,
            'count':
            bytes[14],
        }


scanner = Scanner().withDelegate(ScanDelegate())
scanner.scan(10.0, passive=True)
コード例 #27
0
client.connect(broker_address, 1883, 60)


# create a delegate class to receive the BLE broadcast packets
class ScanDelegate(DefaultDelegate):
    def __init__(self):
        DefaultDelegate.__init__(self)

    # when this python script discovers a BLE broadcast packet, print a message with the device's MAC address
    def handleDiscovery(self, dev, isNewDev, isNewData):
        if mac == dev.addr:
            client.publish("room_presence/" + place + "/" + dev.addr, dev.rssi)
            print "device", dev.addr, dev.rssi


# create a scanner object that sends BLE broadcast packets to the ScanDelegate
scanner = Scanner().withDelegate(ScanDelegate())

# start the scanner and keep the process running
#scanner.start()
while True:
    print "Still running..."
    devs = scanner.scan(10, passive=True)
    found = 0
    for x in devs:
        if x.addr == mac:
            found = 1
    if found == 0:
        print "reset"
        client.publish("room_presence/" + place + "/" + mac, "-99")
コード例 #28
0
def ble_rescan(tb_gateway):
    # Scan for known devices

    class ScanDelegate(DefaultDelegate):
        def __init__(self):
            DefaultDelegate.__init__(self)

        def handleDiscovery(self, dev, isNewDev, isNewData):
            if isNewDev:
                print("Discovered BT device:", dev.addr)
            elif isNewData:
                print("Received new data from:", dev.addr)

    known_devices_found = False

    # Deactivate and clear existing devices before re-scanning
    for dev, dev_data in known_devices.items():
        for scanned, scanned_data in dev_data["scanned"].items():
            tb_name = scanned_data["tb_name"]

            tb_gateway.gw_connect_device(tb_name)

            tb_gateway.gw_send_attributes(tb_name, {"discovered": False})
            tb_gateway.gw_disconnect_device(tb_name)

        dev_data["scanned"].clear()

    while not known_devices_found:
        try:
            print("Scanning BLE devices...")
            scanner = Scanner().withDelegate(ScanDelegate())
            devices = scanner.scan(15.0)

            for dev in devices:
                print("Device {} ({}), RSSI={} dB".format(
                    dev.addr, dev.addrType, dev.rssi))
                for (adtype, desc, value) in dev.getScanData():
                    print("  {} = {}".format(desc, value))
                    if desc == "Complete Local Name" and value in known_devices:
                        print("    [!] Known device found:", value)

                        tb_name = value + "_" + dev.addr.replace(':',
                                                                 '').upper()

                        known_devices[value]["scanned"][dev.addr] = {
                            "inst": known_devices[value]["extension"](),
                            "periph": Peripheral(),
                            "tb_name": tb_name
                        }

                        # Force TB to create a device
                        tb_gateway.gw_connect_device(tb_name)
                        tb_gateway.gw_send_attributes(
                            tb_name, {
                                "discovered": True,
                                "type": value,
                                "mac_addr": dev.addr,
                                "description":
                                known_devices[value]["desription"]
                            })
                        tb_gateway.gw_disconnect_device(tb_name)

                        known_devices_found = True
        except Exception as e:
            print("Exception caught:", e)
コード例 #29
0
ファイル: scanner.py プロジェクト: peakBreaker/hdahlcontiki
        DefaultDelegate.__init__(self)
        self.scanner = None
        self.timeout = 0

    def handleDiscovery(self, dev, isNewDev, isNewData):
        if dev.addr in sensorTags:
            for (adtype, desc, value) in dev.getScanData():
                print("new sensortag values ::  %s = %s || Adtype: %s" %
                      (desc, value, adtype))
                if adtype == 255:
                    raw_values = bytearray.fromhex(value).decode().split(',')
                    sensor_values = {
                        'x': raw_values[0],
                        'y': raw_values[1],
                        'z': raw_values[2],
                        'id': dev.addr
                    }
                    print("sending to server")
                    print(sensor_values)


scanner = Scanner().withDelegate(ScanDelegate())
scanner.delegate.scanner = scanner  # I know, this makes me cringe too
scanner.timeout = 10
devices = scanner.scan(scanner.timeout, passive=True)

# for dev in devices:
#     print("Device %s (%s), RSSI=%d dB" % (dev.addr, dev.addrType, dev.rssi))
#     for (adtype, desc, value) in dev.getScanData():
#         print("  %s = %s || Adtype: %s" % (desc, value, adtype))
コード例 #30
0
ファイル: c.py プロジェクト: timcoote/btlepython
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)


if __name__=="__main__":

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

    devs = scanner.scan (5.0)

    mac = ''

    for dev in devs:
#        print ("Devices {}, ({}) RSSI {}".format (dev.addr, dev.addrType, dev.rssi))
        mac = dev.addr
#        print (dev.__class__, mac)

    try:
        conn = Peripheral (mac, ADDR_TYPE_PUBLIC)
        conn.getServices ()  # needed to get the services property populated?
    except BTLEException:
        try:
            conn = Peripheral (mac, ADDR_TYPE_RANDOM)
            conn.getServices ()
コード例 #31
0
ファイル: le_scan.py プロジェクト: fO-000/bluescan
    def scan_devs(self, timeout=8, scan_type='active', sort='rssi') -> LeDevicesScanResult:
        """Perform LE Devices scanning and return scan reuslt as LeDevicesScanResult

        scan_type  - 'active' or 'passive'
        """
        if scan_type == 'adv':
            return

        scanner = Scanner(self.devid).withDelegate(LEDelegate())
        #print("[Debug] timeout =", timeout)
        
        spinner = Halo(text="Scanning", spinner={'interval': 200,
                                        'frames': ['', '.', '.'*2, '.'*3]},
                       placement='right')

        # scan() 返回的 devs 是 dictionary view。
        if scan_type == 'active': # Active scan 会在 LL 发送 SCAN_REQ PDU
            logger.warning('Before doing an active scan, make sure you spoof your BD_ADDR.')
            logger.info('LE active scanning on %s with timeout %d sec\n' % \
                (blue('hci%d'%self.devid), timeout))
            spinner.start()
            devs = scanner.scan(timeout)
            spinner.stop()
        elif scan_type == 'passive':
            logger.info('LE passive scanning on %s with timeout %d sec\n' % \
                (blue('hci%d'%self.devid), timeout))
            spinner.start()
            devs = scanner.scan(timeout, passive=True)
            spinner.stop()
        else:
            logger.error('Unknown LE scan type')
            return

        if sort == 'rssi':
            devs = list(devs) # 将 dictionary view 转换为 list
            devs.sort(key=lambda d:d.rssi)
        
        for dev in devs:
            dev_info = LeDeviceInfo(dev.addr.upper(), dev.addrType, dev.connectable, dev.rssi)
            self.devs_scan_result.add_device_info(dev_info)
            
            # print('Addr:       ', blue(dev.addr.upper()))
            # print('Addr type:  ', blue(dev.addrType))
            # print('Connectable:', 
            #     green('True') if dev.connectable else red('False'))
            # print("RSSI:        %d dB" % dev.rssi)
            # print("General Access Profile:")
            for (adtype, desc, val) in dev.getScanData():
                ad_struct = AdStruct(adtype, val)
                dev_info.add_ad_structs(ad_struct)
                # 打印当前 remote LE dev 透露的所有 GAP 数据(AD structure)。
                # 
                # 如果 bluepy.scan() 执行的是 active scan,那么这些 GAP 数据
                # 可能同时包含 AdvData 与 ScanRspData。其中 AdvData 由 remote LE 
                # dev 主动返回,ScanRspData 由 remote BLE dev 响应 SCAN_REQ 返回。
                #
                # 虽然 LL 分开定义了 Advertising PDUs (ADV_IND, ADV_DIRECT_IND...)
                # 和 Scanning PDUs (SCAN_REQ, SCAN_RSP)。但它们分别包含的 AdvData 
                # 与 ScanRspData 到了 HCI 层都被放在了 HCI_LE_Advertising_Report 
                # event 中。HCI_LE_Advertising_Report 的 Event_Type 标识了这些数
                # 据具体来源于哪个 LL 层的 PDU。另外 ScanRspData 与 AdvData 的格式
                # 完全相同,都是 GAP 协议标准定义的 AD structure。
                #
                # 在 LL 定义的 Advertising PDUs 中 ADV_DIRECT_IND 一定不会包含 
                # AdvData。其余的 ADV_IND,ADV_NONCONN_IND 以及 ADV_SCAN_IND 都
                # 可能包含 AdvData。
                #
                # 另外 getScanData() 返回的 desc 还可以通过 ScanEntry.getDescription() 
                # 单独获取;val 还可以通过 ScanEntry.getValueText() 单独获取;
                # adtype 表示当前一条 GAP 数据(AD structure)的类型。
            
        return self.devs_scan_result
コード例 #32
0
def foundLDSdevices(autoconnect=False):
    global _ldsdevices
    global _ndev
    global _devmap
    global _ldevmap
    global _devices
    global _meshname
    global _network
    global DEBUG

    autoconenctID = -1
    # Reset bluetooth adaptor
    _network.registerConnectableDevices(SCANDURATION)
    #    if DEBUG: print("%s Debug: Telink devices found: %s " % (time.strftime('%F %H:%M:%S'), _network.devices))
    telink_scanned_devices = _network.devices

    scanned = False
    scanner = Scanner().withDelegate(ScanDelegate())
    le_scanned_devices = scanner.scan(SCANDURATION)
    scanned = True
    if not scanned:
        print("Fatal error: cannot scan for Bluetooth devices")
        sys.exit(255)
    time.sleep(5)
    count = 0
    maxrssi = MINDISCRSSI
    scanned_devices = []

    # Get intersection of the two scanned records and devmap
    for dev in le_scanned_devices:
        for (adtype, desc, value) in dev.getScanData():
            if ((adtype == 9) and (value == _meshname)):
                for tdev in telink_scanned_devices:
                    #                    print("Matching %s with %s" % (dev.addr, tdev.mac_address))
                    if (tdev.mac_address == dev.addr):
                        dev.seq = count
                        mdata = dev.getValueText(255)
                        sige = mdata.find("0001020304050607")
                        if sige >= 4:
                            sigb = sige - 4
                            sigs = mdata[sigb:sige] + "0000"
                            dev.deviceID = unpack('<i', unhexlify(sigs))[0]
                            if _ldevmap > 0:
                                for details in _devices:
                                    #                                if DEBUG: print("%s DEBUG: Matching ID %d of MAC %s with %s" % (time.strftime('%F %H:%M:%S'), dev.deviceID, dev.addr, toMACString(details['deviceMac'])))
                                    if isBLEMACEqual(
                                            dev.addr,
                                            toMACString(details['deviceMac'])):
                                        dev.attr = details
                                        dev.isBad = False
                                        if DEBUG:
                                            print(
                                                "%s DEBUG: %s has ID %d" %
                                                (time.strftime('%F %H:%M:%S'),
                                                 dev.attr['deviceName'],
                                                 dev.deviceID))
                                        count += 1
                                        _ldsdevices[count] = dev
                                        if dev.rssi > maxrssi:
                                            maxrssi = dev.rssi
                                            autoconenctID = dev.deviceID
                                            if DEBUG:
                                                print(
                                                    "%s DEBUG: [%s] MAC:%s RSSI: %s ID:%s"
                                                    % (time.strftime(
                                                        '%F %H:%M:%S'),
                                                       dev.seq, dev.addr,
                                                       dev.rssi, dev.deviceID))

    _ndev = count
    if _ndev > 0:
        try:
            pickle.dump(_ldsdevices, open("dbcache.p", "wb"))
        except:
            print("%s ERROR: Cannot save presistance dbcache.p" %
                  time.strftime('%F %H:%M:%S'))
        if DEBUG:
            print(
                "%s DEBUG: %s devices found and saved. Will auto connect to device %s"
                % (time.strftime('%F %H:%M:%S'), _ndev, autoconenctID))
    return int(autoconenctID)
コード例 #33
0
# possible to send chat messages, not receive).
#
# To use, run 'pip3 install bluepy', then 'python3 test_client.py'.
# NOTE: This script MUST run as root!

import json
import time
from bluepy.btle import Scanner, Peripheral
from uuid import uuid4
from gatt_constants import SERVICE_UUID, CHARACTERISTIC_UUID

scanner = Scanner()

while True:
    print('Scanning for devices...')
    devices = scanner.scan(10.0)
    for dev in devices:
        print(f'Device {dev.addr} (RSSI: {dev.rssi})')
        for (adtype, desc, value) in dev.getScanData():
            print(f'Adtype: {adtype}, desc: {desc}, value: {value}')
            if adtype == 7 and value == SERVICE_UUID:
                print(
                    '  >> Found the DistributedChat service, finding characteristics...'
                )
                peripheral = Peripheral(dev.addr, dev.addrType, dev.iface)
                characteristics = peripheral.getCharacteristics(
                    uuid=CHARACTERISTIC_UUID)
                if characteristics:
                    my_name = 'Test Client'
                    my_id = str(uuid4())
                    logical_clock = 0
コード例 #34
0
ファイル: nuimo.py プロジェクト: brendonparker/nuimo-py-web
 def start(self, notify):
     scanner = Scanner()
     scanner.withDelegate(ScanDelegate(scanner, notify))
     scanner.scan(10.0)
コード例 #35
0
        if isNewDev:
            pass
            #print ("Discovered device", dev.addr )
            #print(dev)
        elif isNewData:
            pass
            print ("Received new data from", dev.addr)
    def handleNotification(self, cHandle, data):
        # ... perhaps check cHandle
        # ... process 'data'
        pass


print("Scanning for Wallet")
scanner = Scanner().withDelegate(ScanDelegate())
devices = scanner.scan(5.0)
wallet_address = 0
for dev in devices:
    print ("Device %s (%s), RSSI=%d dB" % (dev.addr, dev.addrType, dev.rssi) )
    for (adtype, desc, value) in dev.getScanData():
        print ("  %s = %s" % (desc, value))
        if dev.rssi >  -65 :
                print("Get Wallet address:%s!" % dev.addr)
                wallet_address = dev.addr

if wallet_address == 0:
        print ("No wallet found")
        exit()

p = Peripheral(wallet_address,btle.ADDR_TYPE_PUBLIC)
print(p.setMTU(144+3)) #not actually changing MTU
コード例 #36
0
ファイル: scanner.py プロジェクト: IanHarvey/bluepy
#!/usr/bin/python
from __future__ import print_function

from time import gmtime, strftime, sleep
from bluepy.btle import Scanner, DefaultDelegate, BTLEException
import sys


class ScanDelegate(DefaultDelegate):

    def handleDiscovery(self, dev, isNewDev, isNewData):
        print(strftime("%Y-%m-%d %H:%M:%S", gmtime()), dev.addr, dev.getScanData())
        sys.stdout.flush()

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

# listen for ADV_IND packages for 10s, then exit
scanner.scan(10.0, passive=True)
コード例 #37
0
        #blesensor table is date, time, addr, location, temp, accero
#        cur = conn.cursor()
        dostr = 'INSERT INTO data VALUES (CURRENT_DATE(), NOW(), %s, %s, %s, %s);'
#6        cur.execute (dostr, (addr, loc, temp, accero))
#        conn.commit() 

scanner = Scanner().withDelegate(ScanDelegate()) 
#        myConnection = pymysql.connect (host=hostname, user=username, passwd=password, db=database) 
ManuDataHex = [] 
ReadLoop = True 
RetryCount = 0

try:
        while (ReadLoop):
            devices = scanner.scan(2.0)
            ManuData = ""
            for dev in devices:
                entry = 0
                AcceleroData = 0
                AcceleroType = 0
                TempData = 0
                for saddr in SENSOR_ADDRESS:
                    entry += 1
                if (dev.addr == saddr):
                    print (" ")
                    print ("Device %s (%s), RSSI=%d dB" % (dev.addr, dev.addrType, dev.rssi))
                    CurrentDevAddr = saddr
                    CurrentDevLoc = SENSOR_LOCATION[entry-1]
                    data['RSSI'] = dev.rssi
                    for (adtype, desc, value) in dev.getScanData():
コード例 #38
0
    list_aux = list_aux[1].split('Y')
    datax = list_aux[0]
    list_aux = list_aux[1].split('Z')
    datay = list_aux[0]
    dataz = list_aux[1]
    return;

###############################################
# Scanning Devices
###############################################
os.system("sudo hciconfig hci0 down")
os.system("sudo hciconfig hci0 up")
print " "
print "Scanning devices..."
scanner = Scanner().withDelegate(ScanDelegate())
devices = scanner.scan(8.0)

###############################################
# Connecting Devices
###############################################
print " "
print "Connecting to nodes..."
for dev in devices:
    # Creating Bendsaw Peripheral
    if dev.addr == MAC_DIC['BENDSAW']:
        print " "
        print "Device %s (%s) Bendsaw found, connecting..." %(dev.addr,
                                                              dev.addrType)
        bndsw = Peripheral(dev.addr, dev.addrType)
        nodes['bendsaw'] = bndsw
        for (adtype, desc, value) in dev.getScanData():
コード例 #39
0
ファイル: beepmonster.py プロジェクト: matthewg42/btlefun
    keepScanning = False
        


if __name__ == '__main__':
    import signal
    log.basicConfig(level=logging.DEBUG)
    log.info('OHHAI')

    for sig in [signal.SIGHUP, 
                signal.SIGUSR1, 
                signal.SIGUSR2,
                signal.SIGTERM, 
                signal.SIGQUIT, 
                signal.SIGINT]:
        signal.signal(sig, sighandler)

    bm = BeepManager()
    bm.thread.start()
    while keepScanning:
        try:
            log.info('Starting scan...')
            scanner = Scanner().withDelegate(ScanDelegate())
            scanner.scan(30.0)
        except Exception as e:
            log.error('while scanning: %s: %s' % (type(e), e))
    bm.shutdown()
    bm.thread.join()
    log.info('KTHXBYE')

コード例 #40
0
    def __init__(self):
        DefaultDelegate.__init__(self)

    def handleDiscovery(self, dev, isNewDev, isNewData):
        for (adtype, desc, value) in dev.getScanData():
            if len(value) % 2 == 0:
                ba = bytearray(binascii.unhexlify(value))
                if ba[0] == 0x4C:
                    print('Temp sensor {0}'.format(ba[21]))
                    major = ba[21]
                    rh = 125 * (ba[22] * 256) / 65536 -6
                    temp = 175.72 * (ba[23] * 256) / 65536 - 46.85
                    t = time.localtime()
                    timeStr = time.strftime("%a, %d %b %Y %H:%M:%S", t)
                    outStr = '{0}, {1}, {2}, {3}, {4}'.format(dev.addr, timeStr, time.mktime(t), rh, temp)
                    with open('temp_data.csv', 'a') as csvfile:
                        csvfile.write(outStr)
                        csvfile.write('\n')

os.chdir('/home/pi/projects/ble_beacon')

while True:
        scanner = Scanner().withDelegate(ScanDelegate())
        devices = scanner.scan(100)

for dev in devices:
    print "Device %s (%s), RSSI=%d dB" % (dev.addr, dev.addrType, dev.rssi)
    for (adtype, desc, value) in dev.getScanData():
        print "  %s = %s" % (desc, value)
   
コード例 #41
0
ファイル: main.py プロジェクト: kvantetore/igrill
        "device": "TokenCube 1",
        "addr": "dc:00:62:95:62:67",
        "type": "ambient"
    }
}

INFLUX_SERVER = os.environ.get("INFLUX_SERVER", None) or "raspberrypi.local"
INFLUX_DATABASE = os.environ.get("INFLUX_DB", None) or "sensors"
INFLUX_USER = os.environ.get("INFLUX_USER", None) or "root"
INFLUX_PASSWORD = os.environ.get("INFLUX_PASSWORD", None) or "root"

if __name__ == "__main__":
    print "Creating Scanner"
    delegate = DeviceForwardingDelegate()
    delegate.handlers.append(IGrillHandler(device_settings))
    delegate.handlers.append(TokenCubeHandler(device_settings))

    scanner = Scanner()
    scanner.withDelegate(delegate)

    print "Connecting to InfluxDB server"
    persistence = DataPersistence(INFLUX_SERVER, INFLUX_DATABASE, INFLUX_USER, INFLUX_PASSWORD)

    while True:
        print "Scanning..."
        scanner.scan(30)

        print "Persisting..."
        for handler in delegate.handlers:
            handler.persist_stats(persistence)
コード例 #42
0
class BLEConnector(Connector, Thread):
    def __init__(self, gateway, config, connector_type):
        super().__init__()
        self.__connector_type = connector_type
        self.__default_services = list(range(0x1800, 0x183A))
        self.statistics = {'MessagesReceived': 0, 'MessagesSent': 0}
        self.__gateway = gateway
        self.__config = config
        self.setName(
            self.__config.get(
                "name", 'BLE Connector ' +
                ''.join(choice(ascii_lowercase) for _ in range(5))))

        self._connected = False
        self.__stopped = False
        self.__previous_scan_time = time.time() - 10000
        self.__previous_read_time = time.time() - 10000
        self.__check_interval_seconds = self.__config[
            'checkIntervalSeconds'] if self.__config.get(
                'checkIntervalSeconds') is not None else 10
        self.__rescan_time = self.__config[
            'rescanIntervalSeconds'] if self.__config.get(
                'rescanIntervalSeconds') is not None else 10
        self.__scanner = Scanner().withDelegate(ScanDelegate(self))
        self.__devices_around = {}
        self.__available_converters = []
        self.__notify_delegators = {}
        self.__fill_interest_devices()
        self.daemon = True

    def run(self):
        while True:
            if time.time(
            ) - self.__previous_scan_time >= self.__rescan_time != 0:
                self.__scan_ble()
                self.__previous_scan_time = time.time()

            if time.time(
            ) - self.__previous_read_time >= self.__check_interval_seconds:
                self.__get_services_and_chars()
                self.__previous_read_time = time.time()

            time.sleep(.1)
            if self.__stopped:
                log.debug('STOPPED')
                break

    def close(self):
        self.__stopped = True
        for device in self.__devices_around:
            try:
                if self.__devices_around[device].get('peripheral') is not None:
                    self.__devices_around[device]['peripheral'].disconnect()
            except Exception as e:
                log.exception(e)
                raise e

    def get_name(self):
        return self.name

    def on_attributes_update(self, content):
        log.debug(content)
        for device in self.__devices_around:
            if self.__devices_around[device]['device_config'].get(
                    'name') == content['device']:
                for requests in self.__devices_around[device]['device_config'][
                        "attributeUpdates"]:
                    for service in self.__devices_around[device]['services']:
                        if requests[
                                'characteristicUUID'] in self.__devices_around[
                                    device]['services'][service]:
                            characteristic = self.__devices_around[device][
                                'services'][service][requests[
                                    'characteristicUUID']]['characteristic']
                            if 'WRITE' in characteristic.propertiesToString():
                                if content['data'].get(
                                        requests['attributeOnThingsBoard']
                                ) is not None:
                                    try:
                                        self.__check_and_reconnect(device)
                                        content_to_write = content['data'][
                                            requests[
                                                'attributeOnThingsBoard']].encode(
                                                    'UTF-8')
                                        characteristic.write(
                                            content_to_write, True)
                                    except BTLEDisconnectError:
                                        self.__check_and_reconnect(device)
                                        content_to_write = content['data'][
                                            requests[
                                                'attributeOnThingsBoard']].encode(
                                                    'UTF-8')
                                        characteristic.write(
                                            content_to_write, True)
                                    except Exception as e:
                                        log.exception(e)
                            else:
                                log.error(
                                    'Cannot process attribute update request for device: %s with data: %s and config: %s',
                                    device, content,
                                    self.__devices_around[device]
                                    ['device_config']["attributeUpdates"])

    def server_side_rpc_handler(self, content):
        log.debug(content)
        try:
            for device in self.__devices_around:
                if self.__devices_around[device]['device_config'].get(
                        'name') == content['device']:
                    for requests in self.__devices_around[device][
                            'device_config']["serverSideRpc"]:
                        for service in self.__devices_around[device][
                                'services']:
                            if requests[
                                    'characteristicUUID'] in self.__devices_around[
                                        device]['services'][service]:
                                characteristic = self.__devices_around[device][
                                    'services'][service][
                                        requests['characteristicUUID']][
                                            'characteristic']
                                if requests.get(
                                        'methodProcessing'
                                ) and requests['methodProcessing'].upper(
                                ) in characteristic.propertiesToString():
                                    if content['data']['method'] == requests[
                                            'methodRPC']:
                                        response = None
                                        if requests['methodProcessing'].upper(
                                        ) == 'WRITE':
                                            try:
                                                self.__check_and_reconnect(
                                                    device)
                                                response = characteristic.write(
                                                    content['data'].get(
                                                        'params',
                                                        '').encode('UTF-8'),
                                                    requests.get(
                                                        'withResponse', False))
                                            except BTLEDisconnectError:
                                                self.__check_and_reconnect(
                                                    device)
                                                response = characteristic.write(
                                                    content['data'].get(
                                                        'params',
                                                        '').encode('UTF-8'),
                                                    requests.get(
                                                        'withResponse', False))
                                        elif requests[
                                                'methodProcessing'].upper(
                                                ) == 'READ':
                                            try:
                                                self.__check_and_reconnect(
                                                    device)
                                                response = characteristic.read(
                                                )
                                            except BTLEDisconnectError:
                                                self.__check_and_reconnect(
                                                    device)
                                                response = characteristic.read(
                                                )
                                        elif requests[
                                                'methodProcessing'].upper(
                                                ) == 'NOTIFY':
                                            try:
                                                self.__check_and_reconnect(
                                                    device)
                                                delegate = self.__notify_handler(
                                                    self.
                                                    __devices_around[device],
                                                    characteristic.handle)
                                                response = delegate.data
                                            except BTLEDisconnectError:
                                                self.__check_and_reconnect(
                                                    device)
                                                delegate = self.__notify_handler(
                                                    self.
                                                    __devices_around[device],
                                                    characteristic.handle)
                                                response = delegate.data
                                        if response is not None:
                                            log.debug(
                                                'Response from device: %s',
                                                response)
                                            if requests['withResponse']:
                                                response = 'success'
                                            self.__gateway.send_rpc_reply(
                                                content['device'],
                                                content['data']['id'],
                                                str(response))
                                else:
                                    log.error(
                                        'Method for rpc request - not supported by characteristic or not found in the config.\nDevice: %s with data: %s and config: %s',
                                        device, content,
                                        self.__devices_around[device]
                                        ['device_config']["serverSideRpc"])
        except Exception as e:
            log.exception(e)

    def is_connected(self):
        return self._connected

    def open(self):
        self.__stopped = False
        self.start()

    def device_add(self, device):
        for interested_device in self.__devices_around:
            if device.addr.upper(
            ) == interested_device and self.__devices_around[
                    interested_device].get('scanned_device') is None:
                self.__devices_around[interested_device][
                    'scanned_device'] = device
                self.__devices_around[interested_device][
                    'is_new_device'] = True
            log.debug('Device with address: %s - found.', device.addr.upper())

    def __get_services_and_chars(self):
        for device in self.__devices_around:
            try:
                if self.__devices_around.get(
                        device) is not None and self.__devices_around[
                            device].get('scanned_device') is not None:
                    log.debug('Connecting to device: %s', device)
                    if self.__devices_around[device].get('peripheral') is None:
                        address_type = self.__devices_around[device][
                            'device_config'].get('addrType', "public")
                        peripheral = Peripheral(
                            self.__devices_around[device]['scanned_device'],
                            address_type)
                        self.__devices_around[device][
                            'peripheral'] = peripheral
                    else:
                        peripheral = self.__devices_around[device][
                            'peripheral']
                    try:
                        log.info(peripheral.getState())
                    except BTLEInternalError:
                        peripheral.connect(
                            self.__devices_around[device]['scanned_device'])
                    try:
                        services = peripheral.getServices()
                    except BTLEDisconnectError:
                        self.__check_and_reconnect(device)
                        services = peripheral.getServices()
                    for service in services:
                        if self.__devices_around[device].get(
                                'services') is None:
                            log.debug(
                                'Building device %s map, it may take a time, please wait...',
                                device)
                            self.__devices_around[device]['services'] = {}
                        service_uuid = str(service.uuid).upper()
                        if self.__devices_around[device]['services'].get(
                                service_uuid) is None:
                            self.__devices_around[device]['services'][
                                service_uuid] = {}

                            try:
                                characteristics = service.getCharacteristics()
                            except BTLEDisconnectError:
                                self.__check_and_reconnect(device)
                                characteristics = service.getCharacteristics()

                            if self.__config.get('buildDevicesMap', False):
                                for characteristic in characteristics:
                                    descriptors = []
                                    self.__check_and_reconnect(device)
                                    try:
                                        descriptors = characteristic.getDescriptors(
                                        )
                                    except BTLEDisconnectError:
                                        self.__check_and_reconnect(device)
                                        descriptors = characteristic.getDescriptors(
                                        )
                                    except BTLEGattError as e:
                                        log.debug(e)
                                    except Exception as e:
                                        log.exception(e)
                                    characteristic_uuid = str(
                                        characteristic.uuid).upper()
                                    if self.__devices_around[device][
                                            'services'][service_uuid].get(
                                                characteristic_uuid) is None:
                                        self.__check_and_reconnect(device)
                                        self.__devices_around[device][
                                            'services'][service_uuid][
                                                characteristic_uuid] = {
                                                    'characteristic':
                                                    characteristic,
                                                    'handle':
                                                    characteristic.handle,
                                                    'descriptors': {}
                                                }
                                    for descriptor in descriptors:
                                        log.debug(descriptor.handle)
                                        log.debug(str(descriptor.uuid))
                                        log.debug(str(descriptor))
                                        self.__devices_around[device][
                                            'services'][service_uuid][
                                                characteristic_uuid][
                                                    'descriptors'][
                                                        descriptor.
                                                        handle] = descriptor
                            else:
                                for characteristic in characteristics:
                                    characteristic_uuid = str(
                                        characteristic.uuid).upper()
                                    self.__devices_around[device]['services'][
                                        service_uuid][characteristic_uuid] = {
                                            'characteristic': characteristic,
                                            'handle': characteristic.handle
                                        }

                    if self.__devices_around[device]['is_new_device']:
                        log.debug('New device %s - processing.', device)
                        self.__devices_around[device]['is_new_device'] = False
                        self.__new_device_processing(device)
                    for interest_char in self.__devices_around[device][
                            'interest_uuid']:
                        for section in self.__devices_around[device][
                                'interest_uuid'][interest_char]:
                            data = self.__service_processing(
                                device, section['section_config'])
                            converter = section['converter']
                            converted_data = converter.convert(section, data)
                            self.statistics[
                                'MessagesReceived'] = self.statistics[
                                    'MessagesReceived'] + 1
                            log.debug(data)
                            log.debug(converted_data)
                            self.__gateway.send_to_storage(
                                self.get_name(), converted_data)
                            self.statistics['MessagesSent'] = self.statistics[
                                'MessagesSent'] + 1
            except BTLEDisconnectError:
                log.debug('Connection lost. Device %s', device)
                continue
            except Exception as e:
                log.exception(e)

    def __new_device_processing(self, device):
        default_services_on_device = [
            service
            for service in self.__devices_around[device]['services'].keys()
            if int(service.split('-')[0], 16) in self.__default_services
        ]
        log.debug('Default services found on device %s :%s', device,
                  default_services_on_device)
        converter = BytesBLEUplinkConverter(
            self.__devices_around[device]['device_config'])
        converted_data = None
        for service in default_services_on_device:
            characteristics = [
                char for char in self.__devices_around[device]['services']
                [service].keys() if self.__devices_around[device]['services']
                [service][char]['characteristic'].supportsRead()
            ]
            for char in characteristics:
                read_config = {
                    'characteristicUUID': char,
                    'method': 'READ',
                }
                try:
                    self.__check_and_reconnect(device)
                    data = self.__service_processing(device, read_config)
                    attribute = capitaliseName(UUID(char).getCommonName())
                    read_config['key'] = attribute
                    read_config['byteFrom'] = 0
                    read_config['byteTo'] = -1
                    converter_config = [{
                        "type": "attributes",
                        "clean": False,
                        "section_config": read_config
                    }]
                    for interest_information in converter_config:
                        try:
                            converted_data = converter.convert(
                                interest_information, data)
                            self.statistics[
                                'MessagesReceived'] = self.statistics[
                                    'MessagesReceived'] + 1
                            log.debug(converted_data)
                        except Exception as e:
                            log.debug(e)
                except Exception as e:
                    log.debug('Cannot process %s', e)
                    continue
        if converted_data is not None:
            # self.__gateway.add_device(converted_data["deviceName"], {"connector": self})
            self.__gateway.send_to_storage(self.get_name(), converted_data)
            self.statistics[
                'MessagesSent'] = self.statistics['MessagesSent'] + 1

    def __check_and_reconnect(self, device):
        # pylint: disable=protected-access
        while self.__devices_around[device]['peripheral']._helper is None:
            log.debug("Connecting to %s...", device)
            self.__devices_around[device]['peripheral'].connect(
                self.__devices_around[device]['scanned_device'])

    def __notify_handler(self, device, notify_handle, delegate=None):
        class NotifyDelegate(DefaultDelegate):
            def __init__(self):
                DefaultDelegate.__init__(self)
                self.device = device
                self.data = {}

            def handleNotification(self, handle, data):
                self.data = data
                log.debug(
                    'Notification received from device %s handle: %i, data: %s',
                    self.device, handle, data)

        if delegate is None:
            delegate = NotifyDelegate()
        device['peripheral'].withDelegate(delegate)
        device['peripheral'].writeCharacteristic(notify_handle, b'\x01\x00',
                                                 True)
        if device['peripheral'].waitForNotifications(1):
            log.debug("Data received: %s", delegate.data)
        return delegate

    def __service_processing(self, device, characteristic_processing_conf):
        for service in self.__devices_around[device]['services']:
            characteristic_uuid_from_config = characteristic_processing_conf.get(
                'characteristicUUID')
            if characteristic_uuid_from_config is None:
                log.error('Characteristic not found in config: %s',
                          pformat(characteristic_processing_conf))
                return None
            if self.__devices_around[device]['services'][service].get(
                    characteristic_uuid_from_config) is None:
                continue
            characteristic = self.__devices_around[device]['services'][
                service][characteristic_uuid_from_config]['characteristic']
            self.__check_and_reconnect(device)
            data = None
            if characteristic_processing_conf.get(
                    'method', '_').upper().split()[0] == "READ":
                if characteristic.supportsRead():
                    self.__check_and_reconnect(device)
                    data = characteristic.read()
                    log.debug(data)
                else:
                    log.error(
                        'This characteristic doesn\'t support "READ" method.')
            if characteristic_processing_conf.get(
                    'method', '_').upper().split()[0] == "NOTIFY":
                self.__check_and_reconnect(device)
                descriptor = characteristic.getDescriptors(forUUID=0x2902)[0]
                handle = descriptor.handle
                if self.__notify_delegators.get(device) is None:
                    self.__notify_delegators[device] = {}
                if self.__notify_delegators[device].get(handle) is None:
                    self.__notify_delegators[device][handle] = {
                        'function':
                        self.__notify_handler,
                        'args': (self.__devices_around[device], handle,
                                 self.__notify_delegators[device].get(handle)),
                        'delegate':
                        None
                    }
                    self.__notify_delegators[device][handle][
                        'delegate'] = self.__notify_delegators[device][handle][
                            'function'](*self.__notify_delegators[device]
                                        [handle]['args'])
                    data = self.__notify_delegators[device][handle][
                        'delegate'].data
                else:
                    self.__notify_delegators[device][handle]['args'] = (
                        self.__devices_around[device], handle,
                        self.__notify_delegators[device][handle]['delegate'])
                    self.__notify_delegators[device][handle][
                        'delegate'] = self.__notify_delegators[device][handle][
                            'function'](*self.__notify_delegators[device]
                                        [handle]['args'])
                    data = self.__notify_delegators[device][handle][
                        'delegate'].data
            if data is None:
                log.error('Cannot process characteristic: %s with config:\n%s',
                          str(characteristic.uuid).upper(),
                          pformat(characteristic_processing_conf))
            else:
                log.debug('data: %s', data)
            return data

    def __scan_ble(self):
        log.debug("Scanning for devices...")
        try:
            self.__scanner.scan(self.__config.get('scanTimeSeconds', 5),
                                passive=self.__config.get(
                                    'passiveScanMode', False))
        except BTLEManagementError as e:
            log.error('BLE working only with root user.')
            log.error(
                'Or you can try this command:\nsudo setcap '
                '\'cap_net_raw,cap_net_admin+eip\' %s'
                '\n====== Attention! ====== '
                '\nCommand above - provided access to ble devices to any user.'
                '\n========================',
                str(bluepy_path[0] + '/bluepy-helper'))
            self._connected = False
            raise e
        except Exception as e:
            log.exception(e)
            time.sleep(10)

    def __fill_interest_devices(self):
        if self.__config.get('devices') is None:
            log.error(
                'Devices not found in configuration file. BLE Connector stopped.'
            )
            self._connected = False
            return None
        for interest_device in self.__config.get('devices'):
            keys_in_config = ['attributes', 'telemetry']
            if interest_device.get('MACAddress') is not None:
                default_converter = BytesBLEUplinkConverter(interest_device)
                interest_uuid = {}
                for key_type in keys_in_config:
                    for type_section in interest_device.get(key_type):
                        if type_section.get("characteristicUUID") is not None:
                            converter = None
                            if type_section.get('converter') is not None:
                                try:
                                    module = TBUtility.check_and_import(
                                        self.__connector_type,
                                        type_section['converter'])
                                    if module is not None:
                                        log.debug(
                                            'Custom converter for device %s - found!',
                                            interest_device['MACAddress'])
                                        converter = module(interest_device)
                                    else:
                                        log.error(
                                            "\n\nCannot find extension module for device %s .\nPlease check your configuration.\n",
                                            interest_device['MACAddress'])
                                except Exception as e:
                                    log.exception(e)
                            else:
                                converter = default_converter
                            if converter is not None:
                                if interest_uuid.get(
                                        type_section["characteristicUUID"].
                                        upper()) is None:
                                    interest_uuid[type_section[
                                        "characteristicUUID"].upper()] = [{
                                            'section_config':
                                            type_section,
                                            'type':
                                            key_type,
                                            'converter':
                                            converter
                                        }]
                                else:
                                    interest_uuid[type_section[
                                        "characteristicUUID"].upper()].append({
                                            'section_config':
                                            type_section,
                                            'type':
                                            key_type,
                                            'converter':
                                            converter
                                        })
                        else:
                            log.error(
                                "No characteristicUUID found in configuration section for %s:\n%s\n",
                                key_type, pformat(type_section))
                if self.__devices_around.get(
                        interest_device['MACAddress'].upper()) is None:
                    self.__devices_around[
                        interest_device['MACAddress'].upper()] = {}
                self.__devices_around[interest_device['MACAddress'].upper(
                )]['device_config'] = interest_device
                self.__devices_around[interest_device['MACAddress'].upper(
                )]['interest_uuid'] = interest_uuid
            else:
                log.error(
                    "Device address not found, please check your settings.")
コード例 #43
0
class SmartGadgetService(Service):
    def __init__(self, cls, interface=None):
        """Base class for a Smart Gadget :class:`~msl.network.service.Service`.

        Parameters
        ----------
        cls
            A :class:`~smartgadget.sht3x.SHT3XService` or a
            :class:`~smartgadget.shtc1.SHTC1Service` class type.
        interface : :class:`int`, optional
            The Bluetooth interface to use for the connection. For example, 0 or :data:`None`
            means ``/dev/hci0``, 1 means ``/dev/hci1``.
        """
        super(SmartGadgetService, self).__init__(name=cls.DEVICE_NAME)
        self._device_name = cls.DEVICE_NAME
        self._cls = cls
        self._interface = interface
        self._max_attempts = 5
        self._retries_remaining = 0
        self._scanner = Scanner()
        self._gadgets_available = {}
        self._gadgets_connected = {}
        # only add a MAC address in here if the connection request was made explicitly
        self._requested_connections = set()

    def max_attempts(self) -> int:
        """Returns the maximum number of times to try to connect or read/write data from/to a Smart Gadget.

        Returns
        -------
        :class:`int`
            The maximum number of times to retry.
        """
        return self._max_attempts

    def set_max_attempts(self, max_attempts):
        """Set the maximum number of times to try to connect or read/write data from/to a Smart Gadget.

        Since a Bluetooth connection can drop unexpectedly, this provides the opportunity
        to automatically re-connect or re-send a request to a Smart Gadget.

        Parameters
        ----------
        max_attempts : :class:`int`
            The maximum number of times to try to connect or read/write data from/to a Smart Gadget.
            Increasing the number of attempts will decrease the occurrence of getting a
            ``BTLEDisconnectError`` or a :exc:`BrokenPipeError` when sending requests, but may make
            sending a request take a long time while the connection automatically tries to be
            re-established.
        """
        self._max_attempts = max(1, int(max_attempts))
        logger.debug('The maximum number attempts has been set to {}'.format(
            self._max_attempts))

    def scan(self, timeout=10, passive=False) -> List[str]:
        """Scan for Smart Gadgets that are within Bluetooth range.

        Parameters
        ----------
        timeout : :class:`float`, optional
            The number of seconds to scan for Smart Gadgets.
        passive : :class:`bool`, optional
            Use active (to obtain more information when connecting) or passive scanning.

        Returns
        -------
        :class:`list` of :class:`str`
            A list of MAC addresses of the Smart Gadgets that are available for this
            particular SHTxx class.
        """
        self._gadgets_available.clear()
        logger.info('Scanning for {!r}...'.format(self._device_name))
        for d in self._scanner.scan(timeout=timeout, passive=passive):
            if d.getValueText(d.COMPLETE_LOCAL_NAME) == self._device_name:
                self._gadgets_available[d.addr] = d
        logger.info('Found {} Smart Gadgets'.format(
            len(self._gadgets_available)))
        return list(self._gadgets_available)

    def connect_gadget(self, mac_address, strict=True) -> bool:
        """Connect to the specified Smart Gadget.

        It is not necessary to call this method to connect to a Smart Gadget via Bluetooth
        before fetching data from it. The Bluetooth connection will automatically be
        created and destroyed when requesting information from the Smart Gadget if the
        Bluetooth connection does not already exist.

        Establishing a Bluetooth connection to a Smart Gadget takes approximately 7 seconds.
        If you are only requesting data from a couple of Smart Gadgets then connecting to each
        Smart Gadget at the beginning of your script and then fetching data in a loop would
        be more efficient if you want to fetch data as quickly as possible. However, there are
        hardware limits to how many Smart Gadgets can simultaneously have a Bluetooth connection
        with the Raspberry Pi. So, there is a compromise between how quickly your program can
        fetch data and how many Smart Gadgets you want to fetch data from.

        Parameters
        ----------
        mac_address : :class:`str`
            The MAC address of the Smart Gadget to connect to.
        strict : :class:`bool`, optional
            Whether to raise an error if the Smart Gadget could not be connected to.

        Returns
        -------
        :class:`bool`
            Whether the connection was successful.
        """
        failed = self.connect_gadgets([mac_address], strict=strict)[1]
        return len(failed) == 0

    def connect_gadgets(self, mac_addresses, strict=True) -> Tuple[list, list]:
        """Connect to the specified Smart Gadgets.

        See :meth:`.connect_gadget` for more details.

        Parameters
        ----------
        mac_addresses : :class:`list` of :class:`str`
            A list of MAC addresses of the Smart Gadgets to connect to.
        strict : :class:`bool`, optional
            Whether to raise an error if a Smart Gadget could not be connected to.

        Returns
        -------
        :class:`tuple` of :class:`list`
            A list of MAC addresses of the Smart Gadgets that were successfully connected to
            and the MAC addresses of the Smart Gadgets that could not be connected to.
        """
        failed_connections = []
        for mac_address in mac_addresses:
            self._retries_remaining = self._max_attempts
            try:
                self._connect(mac_address)
                self._requested_connections.add(mac_address)
            except BTLEDisconnectError as e:
                if strict:
                    logger.error(e)
                    raise
                else:
                    logger.warning(
                        'Could not connect to {!r}'.format(mac_address))
                    failed_connections.append(mac_address)
        return list(self._gadgets_connected), failed_connections

    def connected_gadgets(self) -> List[str]:
        """Returns the MAC addresses of the Smart Gadgets that are currently connected.

        Returns
        -------
        :class:`list` of :class:`str`
            The MAC addresses of the currently-connected Smart Gadgets.
        """
        return list(self._gadgets_connected)

    def disconnect_gadget(self, mac_address):
        """Disconnect the Smart Gadget with the specified MAC address.

        Parameters
        ----------
        mac_address : :class:`str`
            The MAC address of the Smart Gadget to disconnect from.
        """
        gadget = self._gadgets_connected.pop(mac_address, None)
        if gadget:
            try:
                logger.info('Disconnecting from {!r}...'.format(mac_address))
                gadget.disconnect()
            except:
                pass
        try:
            self._requested_connections.remove(mac_address)
        except:
            pass

    def disconnect_gadgets(self):
        """Disconnect from all Smart Gadgets."""
        for mac_address, gadget in self._gadgets_connected.items():
            try:
                gadget.disconnect()
            except:
                pass
            try:
                self._requested_connections.remove(mac_address)
            except:
                pass
        self._gadgets_connected.clear()
        logger.info('Disconnected from all Smart Gadgets')

    def temperature(self, mac_address) -> float:
        """Returns the current temperature for the specified MAC address.

        Parameters
        ----------
        mac_address : :class:`str`
            The MAC address of the Smart Gadget.

        Returns
        -------
        :class:`float`
            The temperature [degree C].
        """
        return self._process('temperature', mac_address)

    def humidity(self, mac_address) -> float:
        """Returns the current humidity for the specified MAC address.

        Parameters
        ----------
        mac_address : :class:`str`
            The MAC address of the Smart Gadget.

        Returns
        -------
        :class:`float`
            The humidity [%RH].
        """
        return self._process('humidity', mac_address)

    def dewpoint(self, mac_address, temperature=None, humidity=None) -> float:
        """Returns the dew point for the specified MAC address.

        Parameters
        ----------
        mac_address : :class:`str`
            The MAC address of the Smart Gadget.
        temperature : :class:`float`, optional
            The temperature [degree C]. If :data:`None` then reads the current
            temperature value from the Smart Gadget.
        humidity : :class:`float`, optional
            The humidity [%RH]. If :data:`None` then reads the current
            humidity value from the Smart Gadget.

        Returns
        -------
        :class:`float`
            The dew point [degree C].
        """
        return self._process('dewpoint',
                             mac_address,
                             temperature=temperature,
                             humidity=humidity)

    def temperature_humidity(self, mac_address) -> Tuple[float, float]:
        """Returns the current temperature and humidity for the specified MAC address.

        Parameters
        ----------
        mac_address : :class:`str`
            The MAC address of the Smart Gadget.

        Returns
        -------
        :class:`float`
            The temperature [degree C].
        :class:`float`
            The humidity [%RH].
        """
        return self._process('temperature_humidity', mac_address)

    def temperature_humidity_dewpoint(
            self, mac_address) -> Tuple[float, float, float]:
        """Returns the current temperature, humidity and dew point for the specified MAC address.

        Parameters
        ----------
        mac_address : :class:`str`
            The MAC address of the Smart Gadget.

        Returns
        -------
        :class:`float`
            The temperature [degree C].
        :class:`float`
            The humidity [%RH].
        :class:`float`
            The dew point [degree C].
        """
        return self._process('temperature_humidity_dewpoint', mac_address)

    def battery(self, mac_address) -> int:
        """Returns the battery level for the specified MAC address.

        Parameters
        ----------
        mac_address : :class:`str`
            The MAC address of the Smart Gadget.

        Returns
        -------
        :class:`int`
            The battery level [%].
        """
        return self._process('battery', mac_address)

    def rssi(self, mac_address) -> int:
        """Returns the Received Signal Strength Indication (RSSI) for the last received broadcast from the device.

        This is an integer value measured in dB, where 0 dB is the maximum (theoretical) signal
        strength, and more negative numbers indicate a weaker signal.

        Parameters
        ----------
        mac_address : :class:`str`
            The MAC address of the Smart Gadget.

        Returns
        -------
        :class:`int` or :data:`None`
            The RSSI value if the :class:`~smartgadget.smart_gadget.SmartGadget` was
            initialized with a :ref:`ScanEntry <scanentry>` object. Otherwise returns
            :data:`None`.
        """
        return self._process('rssi', mac_address)

    def info(self, mac_address) -> dict:
        """Returns all available information from the Smart Gadget.

        Parameters
        ----------
        mac_address : :class:`str`
            The MAC address of the Smart Gadget.

        Returns
        -------
        :class:`dict`
            Includes information such as the firmware, hardware and software version numbers,
            the battery level, the temperature, humidity and dew point values and the timing
            information about the data logger (if the Smart Gadgets supports logging).
        """
        return self._process('info', mac_address)

    def shutdown_service(self):
        """Shutdown the Smart Gadget :class:`~msl.network.service.Service` and
        the Network :class:`~msl.network.manager.Manager`."""
        self.disconnect_gadgets()

    def restart_bluetooth(self):
        """Restart the Bluetooth driver on the Raspberry Pi.

        This can fix scanning issues or connection timeouts.

        .. attention::

           Calling this method will disconnect all Smart Gadgets that are currently connected
           to the Raspberry Pi.
        """
        logger.debug('Restarting bluetooth...')
        self.disconnect_gadgets()
        subprocess.run(['sudo', 'systemctl', 'restart', 'bluetooth'],
                       check=True)

    @staticmethod
    def rpi_date() -> str:
        """Returns the current date of the Raspberry Pi.

        Returns
        -------
        :class:`str`
            The current date of the Raspberry Pi in the ISO-8601 format.
        """
        return datetime.now().isoformat(sep=' ')

    @staticmethod
    def set_rpi_date(date):
        """Set the date of the Raspberry Pi.

        This is useful if the Raspberry Pi does not have internet access on startup
        to sync with an online NTP server. Does not set the time zone.

        Parameters
        ----------
        date
            Can be a :class:`~datetime.datetime` object, an ISO-8601
            formatted :class:`str`, a :class:`float` in seconds, or an
            :class:`int` in milliseconds.
        """
        date = milliseconds_to_datetime(timestamp_to_milliseconds(date))
        logger.debug("Setting Raspberry Pi date to '{}'".format(date))
        subprocess.run(
            ['sudo', 'date', '-s',
             date.strftime('%a %d %b %Y %I:%M:%S %p')],
            check=True)

    def _connect(self, mac_address):
        """Connect to a Smart Gadget."""
        gadget = self._gadgets_connected.get(mac_address)
        if gadget is None:
            device = self._gadgets_available.get(mac_address) or mac_address
            while gadget is None:
                try:
                    self._retries_remaining -= 1
                    if mac_address in self._requested_connections:
                        logger.info(
                            'Re-connecting to {!r}...'.format(mac_address))
                    else:
                        logger.info(
                            'Connecting to {!r}...'.format(mac_address))
                    gadget = self._cls(device, interface=self._interface)
                    self._gadgets_connected[mac_address] = gadget
                except BTLEDisconnectError as e:
                    if self._retries_remaining < 1:
                        logger.error(e)
                        raise
                    text = 'retry remains' if self._retries_remaining == 1 else 'retries remaining'
                    logger.warning('{} -- {} {}'.format(
                        e, self._retries_remaining, text))
        return gadget

    def _process(self, method_name, mac_address, **kwargs):
        """All Smart Gadget services call this method to process the request."""
        self._retries_remaining = self._max_attempts
        while True:
            gadget = self._connect(mac_address)
            try:
                logger.info('Processing {!r} from {!r} -- kwargs={}'.format(
                    method_name, mac_address, kwargs))
                out = getattr(gadget, method_name)(**kwargs)
                if mac_address not in self._requested_connections:
                    self.disconnect_gadget(mac_address)
                return out
            except (BrokenPipeError, BTLEDisconnectError) as e:
                if self._retries_remaining < 1:
                    logger.error(e)
                    raise
                self._gadgets_connected.pop(mac_address, None)
                text = 'retry remains' if self._retries_remaining == 1 else 'retries remaining'
                logger.warning('{} -- {} {}'.format(e, self._retries_remaining,
                                                    text))
コード例 #44
0
ファイル: light.py プロジェクト: mattiasjonsson/ha-plejd
def connect(pi):
    from bluepy.btle import Scanner, DefaultDelegate, Peripheral, ADDR_TYPE_RANDOM, UUID, BTLEException
    device = None
    addr = None

    _LOGGER.debug("Starting plejd connection")

    disconnect(pi)

    scanner = Scanner()

    for i in range(1, 10):
        devs = sorted(list(scanner.scan(1)), key=lambda d: d.rssi)[::-1]

        for d in devs:
            for (adtype, desc, value) in d.getScanData():
                if (adtype == 8 and value == "P mesh"):
                    try:
                        dev = Peripheral(d, addrType=ADDR_TYPE_RANDOM)
                        if dev.getServiceByUUID(UUID(PLEJD_SERVICE)):
                            device = dev
                        else:
                            dev.disconnect()

                        break
                    except BTLEException as e:
                        _LOGGER.warning(
                            "failed connecting to device '%s' : '%s'" %
                            (d.addr, e))
            if device:
                break

        if device is None:
            _LOGGER.warning("no device found on iteration %d" % (i))
        else:
            break

    if device == None:
        _LOGGER.warning("Failed to find a Plejd device to connect to")
        return

    _LOGGER.debug("Connected to Plejd device '%s'" % (device.addr))

    pi["device"] = device
    pi["address"] = binascii.a2b_hex(device.addr.replace(':', ''))[::-1]
    pi["handles"] = {}
    pi["handles"]["last_data"] = pi["device"].getCharacteristics(
        uuid=UUID(LAST_DATA_UUID))[0].getHandle()
    pi["handles"]["auth"] = pi["device"].getCharacteristics(
        uuid=UUID(AUTH_UUID))[0].getHandle()
    pi["handles"]["ping"] = pi["device"].getCharacteristics(
        uuid=UUID(PING_UUID))[0].getHandle()
    pi["handles"]["data"] = pi["device"].getCharacteristics(
        uuid=UUID(DATA_UUID))[0].getHandle()

    class PlejdDelegate(DefaultDelegate):
        def handleNotification(self, handle, value):
            if handle == pi["handles"]["last_data"]:
                dec = plejd_enc_dec(pi["key"], pi["address"], value)
                # check if this is a device we care about
                if dec[0] in PLEJD_DEVICES:
                    device = PLEJD_DEVICES[dec[0]]
                else:
                    _LOGGER.debug("no match for device '%d' (%s)" %
                                  (dec[0], binascii.b2a_hex(dec)))
                    return
                dim = 0xffff
                state = None
                if dec[3:5] == b'\x00\xc8' or dec[3:5] == b'\x00\x98':
                    # 00c8 and 0098 both mean state+dim
                    state = dec[5]
                    dim = int.from_bytes(dec[6:8], 'little')
                elif dec[3:5] == b'\x00\x97':
                    # 0097 is state only
                    state = dec[5]
                else:
                    _LOGGER.debug("no match for command '%s' (%s)" %
                                  (binascii.b2a_hex(dec[3:5], dec)))
                    return
                if (state == 0):
                    state = False
                else:
                    state = True

                device.update_state(state, dim)

    class PlejdNotificationThread(Thread):
        def __init__(self):
            Thread.__init__(self)
            self.stopped = True
            _LOGGER.debug("setting up notification thread")

        def stop(self):
            _LOGGER.debug("stopping notification thread")
            self.stopped = True

        import time

        def run(self):
            from bluepy.btle import BTLEInternalError
            _LOGGER.debug("starting notification thread")
            self.stopped = False
            while True:
                try:
                    pi["device"].waitForNotifications(1)
                except BTLEInternalError as e:
                    _LOGGER.warning("Encountered bluepy internal error: '%s'" %
                                    (e))
                if self.stopped:
                    break

            _LOGGER.debug("exiting notification thread")

    authenticate(pi)
    # the notification handle is last_data + 2
    pi["device"].writeCharacteristic(pi["handles"]["last_data"] + 2,
                                     b'\x02\x00')
    pi["device"].withDelegate(PlejdDelegate())
    pi["thread"] = PlejdNotificationThread()
    pi["thread"].start()

    _LOGGER.debug("all plejd setup completed")
コード例 #45
0
		print(scanentry.getScanData())
		print(scanentry.getValueText(9))
		print(scanentry.getValueText(22))
		

#scanner = Scanner().withDelegate(BTThermometerDelegate("C4:B3:61:94:78:38"))
#while True:
#devices = scanner.scan()


from bluepy.btle import Scanner, DefaultDelegate

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:
    print "Device %s (%s), RSSI=%d dB" % (dev.addr, dev.addrType, dev.rssi)
    for (adtype, desc, value) in dev.getScanData():
        print "  %s = %s" % (desc, value)

コード例 #46
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
コード例 #47
0
ファイル: ScanDelegate.py プロジェクト: uname/blepi
#-*- coding: utf-8 -*-
from bluepy.btle import Scanner, DefaultDelegate
from SigObject import sigObject
from log import logger
import signals

class ScanDelegate(DefaultDelegate):
    
    def __init__(self):
        DefaultDelegate.__init__(self)
        
    def handleDiscovery(self, dev, isNewDev, isNewData):
        #logger.debug("%s[%d]" % (dev.addr, dev.rssi))
        sigObject.emit(signals.BLE_INFO_UPDATE, dev.addr, dev.rssi)

if __name__ == "__main__":
    from bluepy.btle import Scanner
    scanner = Scanner().withDelegate(ScanDelegate())
    scanner.scan(4)
コード例 #48
0
###############################################
def split_accel_data(data):
    global datax, datay, dataz
    list_aux = data.split('X')
    list_aux = list_aux[1].split('Y')
    datax = list_aux[0]
    list_aux = list_aux[1].split('Z')
    datay = list_aux[0]
    dataz = list_aux[1]
    return;

###############################################
# Scanning Devices
###############################################
scanner = Scanner().withDelegate(ScanDelegate())
devices = scanner.scan(6.0)

###############################################
# Connecting Devices
###############################################
print " "
print "Connecting to nodes..."
print " "
for dev in devices:
    if dev.addr == BNDSW_MAC_ADDR:
	print "Device %s (%s) Bendsaw found, connecting..." %(dev.addr, dev.addrType)
	bndsw = Peripheral(dev.addr, dev.addrType)
	for (adtype, desc, value) in dev.getScanData():
	    print "    %s = %s" % (desc, value)
	print " "
    if dev.addr == SPIRO_MAC_ADDR: