class BluetoothManager: def __init__(self, mac=None): if mac is None: mac = '00:00:00:00:00' # ~ Asumiendo la MAC del ESP32 self.uuid = mac self.Open() def __async(self): while True: if self.per.waitForNotifications(1.0): # ~ Deberia ir al delegate continue print("Esperando...") def Open(self): self.per = Peripheral(self.uuid, ADDR_TYPE_RANDOM) # ~ Servicio definido en el ESP32 self.srvc = self.per.getServiceByUUID('') # ~ Caracteristica definida self.esp_char = self.srvc.getCharacteristics('')[0] self.per.setDelegate(DelegateNotification(self.esp_char.getHandle())) def Send(self, trama): self.esp_char.write(trama) def Close(self): self.per.disconnect()
def main(): global blueberry, stream, bby_thread, saveFile if len(sys.argv) < 2: print( "Usage: python3 base_station.py <Blueberry MAC address> <filename of csv>" ) print("MAC args not specified, exiting...") sys.exit() #handle killing of program signal.signal(signal.SIGINT, signal_handler) #MAC address of the device to connect bby_mac = sys.argv[1] #save file name and start saveFile = open("./data/{}".format(sys.argv[2]), "w+") saveFile.write("timestamp, packet_index, hemo_1, hemo_2\n") #connect, setup Blueberry glasses device print("Connecting to Blueberry: {}...".format(bby_mac)) blueberry = Peripheral(bby_mac) peripheral_delegate = PeripheralDelegate(receive_notify) blueberry.setDelegate(peripheral_delegate) setupBlueberry(blueberry) peripheral_delegate.listen = True #start listening loops for Blueberry and muse bby_thread = threading.Thread(target=bby_loop, args=(blueberry, )) bby_thread.start() stream = True #starting pushing out data stream #block here, because we have our two threads running in the background while True: pass
def startPWS(addr, ssid, psk): logger.info(f"Connect to device {addr}") grantorHandler = GrantorHandler(ssid, psk) # Init Peripheral, connect to it an set read delegate peripheral = Peripheral(addr, ADDR_TYPE_RANDOM) peripheral.setDelegate(WPNearbyReadDelegate(grantorHandler)) pwsService = peripheral.getServiceByUUID(PWSGATTServiceUUID) pwsCharacteristic = pwsService.getCharacteristics( forUUID=PWSGATTCharacteristicUUID)[0] logger.debug(f"PWS characteristic: {pwsCharacteristic.getHandle()}") grantorHandler.pwsCharacteristic = pwsCharacteristic time.sleep(0.5) # Subscribe to the PWS characteristics by sending 0x0200 to pwsCharacteristic Handle+1 (Todo clean uo and check if it is always +1) peripheral.writeCharacteristic(pwsCharacteristic.getHandle() + 2, b"\x01\x00", withResponse=True) grantorHandler.sendPWS1() while peripheral.waitForNotifications(2): pass peripheral.disconnect() logger.info("Wi-Fi Password Sharing completed")
def run(self): while True: if not switchqueue.empty(): try: item = switchqueue.get() switch = item['on'] macaddress = self.convertMac(item['macaddress']) auth_key = unhexlify(item['authkey']) notifications = NotificationDelegate() device = Peripheral(macaddress, ADDR_TYPE_RANDOM) device.setDelegate(notifications) device.writeCharacteristic(STATE_NOTIFY_HANDLE, NOTIFY_VALUE, True) device.writeCharacteristic( STATE_HANDLE, sign('\x01' + ('\x00', '\x01')[switch], auth_key)) while True: if device.waitForNotifications(1.0): print('Ending session') break print('Waiting for notification') device.disconnect() except Exception as e: print(e) time.sleep(1)
def run(self): while True: if not switchqueue.empty(): try: item = switchqueue.get() switch = item['on'] if switch: val = '\x01' else: val = '\x00' macaddress = self.convertMac(item['macaddress']) device = Peripheral(macaddress, ADDR_TYPE_RANDOM, int(os.environ['SCAN_HCI'])) if item['newFirmware'] is False: notifications = NotificationDelegate() device.setDelegate(notifications) auth_key = unhexlify(item['authkey']) device.writeCharacteristic(STATE_NOTIFY_HANDLE, NOTIFY_VALUE, True) device.writeCharacteristic( STATE_HANDLE, sign('\x01' + val, auth_key)) while True: if device.waitForNotifications(1.0): device.disconnect() print('Ending session') break print('Waiting for notification. Old Firmware.') else: # new firmware. No notifcation and no auth device.writeCharacteristic(NEW_STATE_HANDLE, val, True) device.disconnect() except Exception as e: print(e) time.sleep(1)
def main(): macs = list() devs = list() delgs = list() with open("./MACs.txt", "r") as f: for line in f: macs.append(line.strip()) #connect and setup two devices... kinda ugly here for now peripheral = Peripheral(macs[0]) devs.append(peripheral) peripheral_delegate = PeripheralDelegate(receive_notify_1) delgs.append(peripheral_delegate) peripheral.setDelegate(peripheral_delegate) peripheral = Peripheral(macs[1]) devs.append(peripheral) peripheral_delegate = PeripheralDelegate(receive_notify_2) delgs.append(peripheral_delegate) peripheral.setDelegate(peripheral_delegate) # start streaming data time.sleep(1) for dev in devs: setupBlueberry(dev) for delg in delgs: delg.listen = True ts = list() for i, dev in enumerate(devs): ts.append(threading.Thread(target=mainLoop, args=[i, dev])) for t in ts: t.start()
def run(self): global devices print "seq%d" % self.seq + " start connecting to " + self.name try: addr = self.dev.addr p = Peripheral(addr) i = 0 p.setDelegate(MyDelegate(self.name, i)) print "seq%d" % self.seq + " connected to " + self.name service = p.getServiceByUUID( "0000ffe0-0000-1000-8000-00805f9b34fb") ch = service.getCharacteristics() for char in ch: if char.uuid == "0000ffe0-0000-1000-8000-00805f9b34fb": break send_lock = threading.Lock() BleSend(send_lock, self.name, char).start() BleReceive(send_lock, self.name, p).start() except: print "seq%d" % self.seq + " error occurred" BTLEException.DISCONNECTED reset() print "exception occurred" info = sys.exc_info() print info[0], ":", info[1], ":", info[2]
class GAmonitor(object): SERVICE_UUIDS = [ UUID('c0be9c58-a717-4e18-828c-a41836f0c7e5'), # Sensors ] CHARACTERISTIC_UUIDS = {'9a067338-1da7-4e0f-8b4a-1e445e1e2df9': 'ACC'} NOTIFICATION_CHARACTERISTIC_UUIDS = [ 'ACC', ] # Notification data NOTIFICATION_ON = struct.pack("BB", 0x01, 0x00) NOTIFICATION_OFF = struct.pack("BB", 0x00, 0x00) def __init__(self, mac_address): self.macAddress = mac_address self.delegate = ScanDelegate() def set_delegate(self, delegate): self.delegate = delegate def connect(self): print('getting peripheral', sys.stderr) self.peripheral = Peripheral(self.macAddress, addrType='public') # Retrieve all characteristics from desired services and map them from their UUID self.peripheral.getServices() svc = self.peripheral.getServiceByUUID( "c0be9c58-a717-4e18-828c-a41836f0c7e5") characteristics = { svcid: svc.getCharacteristics()[i] for svcid, i in zip(self.CHARACTERISTIC_UUIDS, range(2)) } print(characteristics, sys.stderr) # Store each characteristic's value handle for each characteristic name self.characteristicValueHandles = dict( (name, characteristics[uuid].getHandle()) for uuid, name in self.CHARACTERISTIC_UUIDS.items()) # Subscribe for notifications for name in self.NOTIFICATION_CHARACTERISTIC_UUIDS: print('Enabling notification: ', sys.stderr) self.peripheral.writeCharacteristic( self.characteristicValueHandles[name] + 1, self.NOTIFICATION_ON, True) print(name, sys.stderr) print(self.characteristicValueHandles[name] + 1, sys.stderr) self.peripheral.setDelegate(self.delegate) def disconnect(self): self.peripheral.disconnect() def wait_for_notifications(self, timeout): print('calling wait for notifications') return self.peripheral.waitForNotifications(timeout)
def connectToBLE(): # connection to the device bluno = Peripheral("C8:DF:84:24:27:F6", "public") bluno.setDelegate(SensorsDelegate()) svc = bluno.getServiceByUUID("dfb0") ch = svc.getCharacteristics("dfb1")[0] return (bluno, ch)
def subscribe(self): while True: connected = False while connected == False: try: print("connecting to LBE: ", self.device.id) p = Peripheral(self.device.id) except Exception as e: #print (e) sleep(2) else: connected = True p.setDelegate(MyDelegate(self.device)) #Get ButtonService ButtonService = p.getServiceByUUID(button_service_uuid) print("Connected to " + self.device.id) dd = deviceMap[self.device.id] dd.status = Device.Status.CONNECTED # Get The Button-Characteristics # for ch in ButtonService.getCharacteristics(): # print (ch.propertiesToString(), ch.uuid) ButtonC = ButtonService.getCharacteristics( button_chararcteristics_uuid)[0] #Get The handle tf the Button-Characteristics hButtonC = ButtonC.getHandle() # Search and get Get The Button-Characteristics "property" (UUID-0x1124 Human Interface Device (HID))) # wich is located in a handle in the range defined by the boundries of the ButtonService for desriptor in p.getDescriptors( hButtonC, 0xFFFF ): # The handle range should be read from the services #print ("descr", desriptor) # if (desriptor.uuid == 0x2902): # but is not done due to a Bluez/BluePy bug :( #print ("Button1 Client Characteristic Configuration found at handle 0x"+ format(desriptor.handle,"02X")) hButtonCCC = desriptor.handle p.writeCharacteristic(hButtonCCC, struct.pack('<bb', 0x01, 0x00)) print("Notification is turned on for ", self.device) while True: try: if p.waitForNotifications(1.0): continue except BTLEDisconnectError as e: print(e) dd = deviceMap[self.device.id] dd.status = Device.Status.DISCONNECTED break # reconect
def connect(self, callback, address, musePort=None): if address: self.addr = address else: self.addr = self.findMuse() muse = Peripheral(self.addr, iface=self.iface) self.peri = delegate.PeripheralDelegate(callback) muse.setDelegate(self.peri) return muse
class BluepyAdapter(AbstractBleAdapter): STOP_NOTIFY = object() def __init__(self, mac_address): logger.debug("Init Bluepy Adapter") super().__init__(mac_address) self.delegate = BluepyDelegate(self.packet_collector) self.peripheral = Peripheral(self.mac_address, ADDR_TYPE_RANDOM) self.peripheral.setDelegate(self.delegate) self.ch_api_v2 = self._get_characteristic( uuid=SpheroCharacteristic.api_v2.value) # Initial api descriptor # Need for getting response from sphero desc = self._get_descriptor( self.ch_api_v2, GenericCharacteristic.client_characteristic_configuration.value) desc.write(b"\x01\x00", withResponse=True) self._executor.submit(self._receiver) logger.debug("Bluepy Adapter: successful initialization") def close(self): super().close() # ignoring any exception # because it does not matter with contextlib.suppress(Exception): self.peripheral.disconnect() def write(self, packet: Packet, *, timeout: float = 10, raise_api_error: bool = True) -> Optional[Packet]: logger.debug(f"Send {packet}") self.ch_api_v2.write(packet.build(), withResponse=True) return self.packet_collector.get_response(packet, raise_api_error, timeout=timeout) def _receiver(self): logger.debug("Start receiver") sleep = 0.05 while self._running.is_set(): self.peripheral.waitForNotifications(sleep) logger.debug("Stop receiver") def _get_characteristic(self, uuid: int or str) -> Characteristic: return self.peripheral.getCharacteristics(uuid=uuid)[0] def _get_descriptor(self, characteristic: Characteristic, uuid: int or str) -> Descriptor: return characteristic.getDescriptors(forUUID=uuid)[0]
class Nuimo(object): SERVICE_UUIDS = [ UUID('0000180f-0000-1000-8000-00805f9b34fb'), # Battery UUID('f29b1525-cb19-40f3-be5c-7241ecb82fd2'), # Sensors UUID('f29b1523-cb19-40f3-be5c-7241ecb82fd1') # LED Matrix ] CHARACTERISTIC_UUIDS = { UUID('00002a19-0000-1000-8000-00805f9b34fb'): 'BATTERY', UUID('f29b1529-cb19-40f3-be5c-7241ecb82fd2'): 'BUTTON', UUID('f29b1528-cb19-40f3-be5c-7241ecb82fd2'): 'ROTATION', UUID('f29b1527-cb19-40f3-be5c-7241ecb82fd2'): 'SWIPE', UUID('f29b1526-cb19-40f3-be5c-7241ecb82fd2'): 'FLY', UUID('f29b1524-cb19-40f3-be5c-7241ecb82fd1'): 'LED_MATRIX' } NOTIFICATION_CHARACTERISTIC_UUIDS = [ 'BATTERY', # Uncomment only if you are not using the iOS emulator (iOS does't support battery updates without authentication) 'BUTTON', 'ROTATION', 'SWIPE', 'FLY'] # Notification data NOTIFICATION_ON = struct.pack("BB", 0x01, 0x00) NOTIFICATION_OFF = struct.pack("BB", 0x00, 0x00) def __init__(self, mac_address): self.macAddress = mac_address self.delegate=NuimoDelegate(self) def set_delegate(self, delegate): self.delegate = delegate def connect(self): self.peripheral = Peripheral(self.macAddress, addrType='random') # Retrieve all characteristics from desired services and map them from their UUID characteristics = list(itertools.chain(*[self.peripheral.getServiceByUUID(uuid).getCharacteristics() for uuid in Nuimo.SERVICE_UUIDS])) characteristics = dict((c.uuid, c) for c in characteristics) # Store each characteristic's value handle for each characteristic name self.characteristicValueHandles = dict((name, characteristics[uuid].getHandle()) for uuid, name in Nuimo.CHARACTERISTIC_UUIDS.items()) # Subscribe for notifications for name in Nuimo.NOTIFICATION_CHARACTERISTIC_UUIDS: self.peripheral.writeCharacteristic(self.characteristicValueHandles[name] + 1, Nuimo.NOTIFICATION_ON, True) self.peripheral.setDelegate(self.delegate) def wait_for_notifications(self): self.peripheral.wait_for_notifications(1.0) def display_led_matrix(self, matrix, timeout, brightness=1.0): matrix = '{:<81}'.format(matrix[:81]) bites = list(map(lambda leds: reduce(lambda acc, led: acc + (1 << led if leds[led] not in [' ', '0'] else 0), range(0, len(leds)), 0), [matrix[i:i+8] for i in range(0, len(matrix), 8)])) self.peripheral.writeCharacteristic(self.characteristicValueHandles['LED_MATRIX'], struct.pack('BBBBBBBBBBBBB', bites[0], bites[1], bites[2], bites[3], bites[4], bites[5], bites[6], bites[7], bites[8], bites[9], bites[10], max(0, min(255, int(255.0 * brightness))), max(0, min(255, int(timeout * 10.0)))), True)
def unlockKlic(self): print("lockKey: " + self.lockKey) print("lockPwd: " + self.lockPwd) print("mac: " + self.mac) print("") # Convert lockKey to hex self.set_aes_key(self.lockKey) # Connect to klic lock klic = Peripheral(self.mac, "public") klic.setDelegate(KlicDelegate(self.aes_key))
class BLEController: def __init__(self, delegate): # Variables self._delegate = delegate def connect(self, server_mac): self._server_mac = server_mac self._peripheral = Peripheral(self._server_mac) self._peripheral.setDelegate(self._delegate) self._listening = False def disconnect(self): self._peripheral.disconnect() def print_services(self, primary_service_uuid): svcs = self._peripheral.getServices() print("Services:") for s in svcs: print(s) print("Characteristics:") svc = self._peripheral.getServiceByUUID(primary_service_uuid) chs = svc.getCharacteristics() for c in chs: print(str(c) + " handle: " + str(c.getHandle())) def listen(self): if not self._listening: # Are we listening already? self._listening = True while self._listening: if self._peripheral.waitForNotifications( 1.0): # Calls the delegate if true # Delegate was called continue print('BLEController.listen() -> Listening...') def listen_async(self): #raise Exception("Not Implemented") self._listen_thread = _thread.start_new_thread(self.listen, ()) def adjust_light_source(self, value): # value is a tuple of RGB i.e. (255, 255, 255) # BLE characteristic expects a byte array value_bytes = bytes(value) print("BLEController.adjust_light_source -> {}".format(value_bytes)) handle = 49 # The handle value has to be found using e.g. print_services(), bluez, or similar self._peripheral.writeCharacteristic(handle, value_bytes) def stop_listening(self): self._listening = False
class BLEDevice(Thread): def __init__(self, room_batch_queue, room_sub_update_queue, addr, addrType, ble_activity_lock): Thread.__init__(self) print("Created BLE Device: {}".format(addr)) self.room_batch_queue = room_batch_queue self.room_sub_update_queue = room_sub_update_queue self.addr = addr self.addrType = addrType self.ble_activity_lock = ble_activity_lock def ble_listen_loop(self, write_cs, notify_cs): print("writing something so connection stays alive") write_cs.write(b"hey") print("listening to read...") while True: if self.conn.waitForNotifications(1.0): continue print("waiting...") # TODO: Listen for self.room_sub_update_queue updates time.sleep(0.05) def run(self): print("attempting connect to {}".format(self.addr)) self.ble_activity_lock.acquire() self.conn = Peripheral(self.addr, self.addrType) self.ble_activity_lock.release() print("Connected! {}".format(self.addr)) css = self.conn.getCharacteristics() notify_cs = None write_cs = None for cs in css: print(cs.uuid, cs.propertiesToString()) # per.getCharacteristics(uuid='6e400003-b5a3-f393-e0a9-e50e24dcca9e')[0] if cs.propertiesToString() == "NOTIFY ": notify_cs = cs if "WRITE" in cs.propertiesToString(): write_cs = cs if write_cs and notify_cs: self.conn.setDelegate(MyDelegate(self.addr, self.room_batch_queue)) # enable notification setup_data = b"\x01\x00" notify_handle = notify_cs.getHandle() + 1 self.conn.writeCharacteristic(notify_handle, setup_data, withResponse=True) self.ble_listen_loop(write_cs, notify_cs) else: print( "Device {} did not have a write and notify BLE characteristic." .format(self.addr))
def configure_device(scanEntry): logging.info("Connecting to: %s", scanEntry.addr) try: peripheral_device = Peripheral(scanEntry) except: logging.warning("_-_-_ Failed to connect to: %s", scanEntry.addr) else: peripheral_device.setDelegate(ConfigDelegate()) # serviceList = peripheral_device.getServices() # logging.debug(serviceList) # logging.debug(list(serviceList)) # for service in peripheral_device.getServices(): # logging.debug("S: %s", service.uuid) # for characteristic in service.getCharacteristics(): # logging.debug("C: %s", characteristic.uuid) # Read HW ID and apply corresponding configuration hw_id_char = peripheral_device.getCharacteristics(uuid="00001101-0f58-2ba7-72c3-4d8d58fa16de")[0] hw_id = unpack("H", hw_id_char.read())[0] logging.info("HWID:%s", hw_id) if hw_id == HW_ID_CLIMATE: config = climate_configuration elif hw_id == 5: config = conference_configuration else: peripheral_device.disconnect() return uartRxChar = peripheral_device.getCharacteristics(uuid="6e400003-b5a3-f393-e0a9-e50e24dcca9e")[0] uartTxChar = peripheral_device.getCharacteristics(uuid="6e400002-b5a3-f393-e0a9-e50e24dcca9e")[0] # logging.debug(uartRxChar) # logging.debug(uartTxChar) # logging.debug("RX char properties: %s", uartRxChar.propertiesToString()) # logging.debug("TX char properties: %s", uartTxChar.propertiesToString()) logging.debug("Enable notification") uartRxCharDescriptorHandle = uartRxChar.getHandle() + 1 peripheral_device.writeCharacteristic(uartRxCharDescriptorHandle , (1).to_bytes(2, byteorder='little')) # logging.debug(uartRxChar.getHandle()) # logging.debug(uartTxChar.getHandle()) for x in range(0, len(config)): # logging.debug(x) uartTxChar.write(config[x]) if peripheral_device.waitForNotifications(1): pass # logging.debug("Notification received") else: logging.debug("No notification received") peripheral_device.waitForNotifications(1) logging.info("Configuration complete") peripheral_device.disconnect()
def main(): global myMuse, blueberry, stream, muse_thread, bby_thread, eeg_buf, hemo_1_buf, hemo_2_buf, plotter #setup plotting data structures eeg_buf = CircleBuf(0, 256, 2560, name='EEG') hemo_1_buf = CircleBuf(0, 5, 50, name='fNIRS, 880nm') hemo_2_buf = CircleBuf(0, 5, 50, name='fNIRS, 940nm') #setup plot plotter = BufferAnimation(eeg_buf, hemo_1_buf, hemo_2_buf) if len(sys.argv) < 3: print( "Usage: python3 base_station.py <Muse MAC address> <Blueberry MAC address>" ) print("MAC args not specified, exiting...") sys.exit() #handle killing of program signal.signal(signal.SIGINT, signal_handler) #MAC address of the devices to connect muse_mac = sys.argv[1] bby_mac = sys.argv[2] #st myMuse = muselsl.muse.Muse("{}".format(muse_mac), callback_eeg=getMuseData) myMuse.connect() #connect, setup Blueberry glasses device print("Connecting to Blueberry: {}...".format(bby_mac)) blueberry = Peripheral(bby_mac) peripheral_delegate = PeripheralDelegate(receive_notify) blueberry.setDelegate(peripheral_delegate) setupBlueberry(blueberry) peripheral_delegate.listen = True #start listening loops for Blueberry and muse bby_thread = threading.Thread(target=muse_loop, args=(myMuse, )) muse_thread = threading.Thread(target=bby_loop, args=(blueberry, )) bby_thread.start() muse_thread.start() stream = True #starting pushing out data stream time.sleep(3) #block here, because we have our two threads running in the background while True: time.sleep(1) plotter.draw()
def tracker_connect(addr): try: # try to connect dev = Peripheral() dev.connect(addr) print("coneccted") # Once connected enable notification handling and loop through dev.setDelegate(ScanDelegate()) while True: dev.waitForNotifications(10) dev.disconnect() print("Disconnected!") # if fail, go back to scanning, or if diconnects except Exception as e: print(e)
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)) 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 #print(auth_char.valHandle) auth_char_cccd = auth_char.getHandle() + 1 print("CCCD 0x%X" % auth_char_cccd) device.writeCharacteristic(auth_char_cccd, b"\x01\x00") #device.withDelegate(PeripheralDelegate()) auth_char_val = auth_char.read() print(auth_char_val) #if(auth_char_val == 0): ## print("Zero") # wait for server confirmation as a notification message while True: if (device.waitForNotifications(1.0)): print("new notification from server") continue print("Waiting...")
def unlockNoke(self): print '[*] Unlocking Noke Keylock' print '[*] Author: Victor Pasknel (MorphusLabs)\n' # Connect to noke lock mac = "cb:59:c7:03:5d:ef" noke = Peripheral(mac, addrType = 'random') noke.setDelegate(NokeDelegate()) # Sending packets self.firstPacket(noke) self.secondPacket(noke) # Waiting for notification while True: if noke.waitForNotifications(1.0): break # Creating session key self.createSessionKey() # Sending final packet self.thirdPacket(noke)
def main(): global myMuse, blueberry, stream, muse_thread, bby_thread, eegSave, fnirsSave if len(sys.argv) < 3: print( "Usage: python3 base_station.py <Muse MAC address> <Blueberry MAC address>" ) print("MAC args not specified, exiting...") sys.exit() #handle killing of program signal.signal(signal.SIGINT, signal_handler) #MAC address of the devices to connect muse_mac = sys.argv[1] bby_mac = sys.argv[2] #files to save the data fnirsSave = open("./fnirs/{}_fnirs.csv".format(time.time()), "w+") fnirsSave.write("real_time,packet_time,short_path,long_path\n") eegSave = open("./eeg/{}_eeg.csv".format(time.time()), "w+") eegSave.write("real_time,e_num,0,1,2,3,4,5,6,7,8,9,10,11\n") #connect Muse 1.5, 2, or S myMuse = muselsl.muse.Muse("{}".format(muse_mac), callback_eeg=getMuseData) myMuse.connect() #connect, setup Blueberry glasses device print("Connecting to Blueberry: {}...".format(bby_mac)) blueberry = Peripheral(bby_mac) peripheral_delegate = PeripheralDelegate(receive_notify) blueberry.setDelegate(peripheral_delegate) setupBlueberry(blueberry) peripheral_delegate.listen = True #start listening loops for Blueberry and muse bby_thread = threading.Thread(target=muse_loop, args=(myMuse, )) muse_thread = threading.Thread(target=bby_loop, args=(blueberry, )) stream = True #starting pushing out data stream bby_thread.start() muse_thread.start() #block here, because we have our two threads running in the background while True: pass
def start(self): try: device = Peripheral(self.macaddress, ADDR_TYPE_RANDOM, int(os.environ['SCAN_HCI'])) notifications = NotificationDelegate(self.macaddress) device.setDelegate(notifications) device.writeCharacteristic(AUTH_NOTIFY_HANDLE, NOTIFY_VALUE, True) device.writeCharacteristic(AUTH_HANDLE, AUTH_INIT_VALUE, True) print('Press button') statusqueue.put('Press button on Switchmate to get auth key') while True: if device.waitForNotifications(1.0): statusqueue.put('Ending session') break statusqueue.put('Waiting for notification') time.sleep(0) device.disconnect() except Exception as e: print(e)
class BLE_interface(): def __init__(self, addr_str, write_uuid): self.dev = Peripheral(deviceAddr=addr_str) logging.info(f'Connected device {self.dev.addr}') if write_uuid: self.write_uuid = [UUID(write_uuid)] else: self.write_uuid = [UUID(x) for x in ble_chars] logging.debug(f'No write uuid specified, trying {ble_chars}') for c in self.dev.getCharacteristics(): if c.uuid in self.write_uuid: self._write_charac = c self.write_uuid = self._write_charac.uuid logging.debug(f'Found write characteristic {self.write_uuid}') break assert hasattr(self, '_write_charac'), \ "No characteristic with specified UUID found!" assert (self._write_charac.properties & Characteristic.props["WRITE_NO_RESP"]), \ "Specified characteristic is not writable!" ### Status does not work with patches for wr response with threads... # status = self.dev.status() # logging.debug(status) # logging.info(f'Device {addr_str} state change to {status["state"][0]}') def send(self, data: bytes): logging.debug(f'Sending {data}') self._write_charac.write(data, withResponse=False) def set_receiver(self, callback): logging.info('Receiver set up') self.dev.setDelegate(ReceiverDelegate(callback)) def receive_loop(self): assert isinstance( self.dev.delegate, ReceiverDelegate), 'Callback must be set before receive loop!' self.dev.waitForNotifications(3.0) def shutdown(self): self.dev.disconnect() logging.info('BT disconnected')
def preparePeripheral(device): #print(" preparing peripheral:") print(" - address: \t{}".format(device.addr)) print(" - addresstype: \t{}".format(device.addrType)) print(" - interface: \t{}".format(device.iface)) print(" - connectable: \t{}".format(device.connectable)) peripheral = Peripheral(device) #devices[0].addr, devices[0].addrType) #peripheral = Peripheral(device.addr,device.addrType,device.iface) print(" peripheral set") peripheral.setDelegate(MyDelegate(peripheral)) print(" delegate set") Peripheral.availableHandles = { } # Dictionary containing ['UUID' : cccHandle] Peripheral.availabeChararacteristics = [] #peripheral.connect() time.sleep(3) print(" getting services") try: services = peripheral.getServices() except: print("Failed to get services") return 0 print(" displaying services") for ser in services: if ser.uuid in recognizedServices.keys(): print(" Found recognized service: {}".format(ser.uuid)) serChar = ser.getCharacteristics() for char in serChar: #print("Found char: {}".format(char.uuid)) if char.uuid in recognizedServices[str(ser.uuid)]: #handle = char.getHandle() print( " -with recognized charachteristic: {}\t({})".format( char.uuid.getCommonName(), char.uuid)) #print(" -with handle: 0x{:02X}".format(handle)) #cccHandle = getCCCHandle(peripheral, handle) #print (" -CCC handle: 0x{:02X}".format(cccHandle)) #peripheral.availableHandles.append(cccHandle) #peripheral.availableHandles[char.uuid] = cccHandle peripheral.availabeChararacteristics.append(char) return peripheral
class MicaLock(): def __init__(self): self.addr = "" self.key = "" self.apitoken = "" def setAddr(self, addr): self.addr = addr self.p = Peripheral(self.addr, addrType=ADDR_TYPE_PUBLIC) self.p.setDelegate(NotifyDelegate()) def getAddr(self): return self.addr def setKey(self, key): self.key = key self.aes = AES.new(key, AES.MODE_ECB) def getKey(self): return self.key def getApiToken(self): return self.apitoken def setApiToken(self, token): self.apitoken = token def getToken(self): message = binascii.unhexlify('060101017031321c66567559003a0a4d') # Start listening for notification self.p.writeCharacteristic(7, b'\x01\x00') # Send message self.p.writeCharacteristic(3, self.aes.encrypt(message)) self.p.waitForNotifications(1.0) def unlock(self, token): unlockit = binascii.unhexlify('050106303030303030') + self.aes.decrypt( token)[3:7] + binascii.unhexlify('000000') print "Unlocking" self.p.writeCharacteristic(3, self.aes.encrypt(unlockit)) self.p.disconnect()
def initRead(addrs, chars): logs = [] devs = [] for (btAddr, btRead) in zip(addrs, chars): # Creacion de archivos log start, logThis = start_log(btAddr[-2:]) logs.append(logThis) # Conexion a los sensores btDev = Peripheral(btAddr) devs.append(btDev) # Seleccion de las caracteristicas de lectura btCh = btDev.getCharacteristics(uuid=btRead)[0] # Asignacion del "delegate" (tambien se activan las notificaciones) btDev.setDelegate(BtDelegate(btDev, btCh.valHandle, logThis, start)) return logs, devs
class PeripheralResource(): def __init__(self, peripheral, id): self.visible = True self.device = Peripheral(peripheral, random) services = self.device.getServices() self.resources = [] for service in services: try: for char in service.getCharacteristics(): btRes = BluetoothResource(char=char, type=char.propertiesToString()) self.resources.append(btRes) if char.uuid != UUID( 0x2A00) and "WRITE" in char.propertiesToString(): self.led_indicator = char except BTLEException as btexc: if (btexc.code == 2): continue self.device.setDelegate(NotifyDelegate(self.resources, id)) notifyThread = NotifyThread(self) notifyThread.start()
def preparePeripheral(device): #Create the peripheral object from bluetooth device peripheral = Peripheral(device) peripheral.setDelegate(MyDelegate(peripheral)) Peripheral.availableChararacteristics = [] time.sleep(2) #Read all device characteristics and add make a list of recognized characteristics services = peripheral.getServices() for ser in services: if ser.uuid == BLE_SERVICE_ENVIRONMENT: logging.debug(" Found recognized service: {}".format(ser.uuid.getCommonName())) serChar = ser.getCharacteristics() for char in serChar: if char.uuid in recognizedServices[str(ser.uuid)]: logging.debug(" Added characteristics: {}".format(char.uuid.getCommonName())) peripheral.availableChararacteristics.append(char) else: logging.debug(" (Unused characteristics: {})".format(char.uuid.getCommonName())) return peripheral
class ble_7697: def __init__(self): self.my_not = MyDelegate() success = False while (not success): try: self.dev_button = Peripheral("31:ba:00:2b:88:8c", 'public') self.service_button = self.dev_button.getServiceByUUID( "19B10010-E8F2-537E-4F6C-D104768A1214") self.button1 = self.service_button.getCharacteristics()[0] self.button2 = self.service_button.getCharacteristics()[1] self.my_not.button1_handle = self.button1.getHandle() self.my_not.button2_handle = self.button2.getHandle() self.dev_button.setDelegate(self.my_not) except: success = False else: success = True def waitNot(self): while True: if self.dev_button.waitForNotifications(0.1): print("not")
def connect_dev(addr, addrtype): conn_handle = {'conn':None, 'rx_ch':None, 'tx_ch':None, 'ctrl_ch':None, 'nf_handle':None} print('Connecting ' + addr) conn = Peripheral(addr, addrtype) print(addr + ": connected") conn_handle['conn'] = conn nf_handle = {'handle':None, 'data':None} conn.setDelegate(AmdtpDelegate(nf_handle)) conn_handle['nf_handle'] = nf_handle #services_dic = conn.getServices() #for service in services_dic: # print(' service: ' + str(service.uuid)) # charac_dic = service.getCharacteristics() # for charac in charac_dic: # print(' charac: ' + str(charac.uuid)) print(' ---------- Amdtp service below ----------') service = conn.getServiceByUUID('00002760-08c2-11e1-9073-0e8ac72e1011') chs = service.getCharacteristics() for ch in chs: print(' charac: ' + str(ch.uuid)) print(' ' + ch.propertiesToString()) print(' ' + str(ch.getHandle())) # properties: WRITE NO RESPONSE, Handle: 2050 if str(ch.uuid) == '00002760-08c2-11e1-9073-0e8ac72e0011': conn_handle['rx_ch'] = ch # properties: NOTIFY, Handle: 2052 elif str(ch.uuid) == '00002760-08c2-11e1-9073-0e8ac72e0012': conn_handle['tx_ch'] = ch # properties: WRITE NO RESPONSE, Handle: 2055 elif str(ch.uuid) == '00002760-08c2-11e1-9073-0e8ac72e0013': conn_handle['ctrl_ch'] = ch return conn_handle
class OpenBCIGanglion(object): """ Handle a connection to an OpenBCI board. Args: port: MAC address of the Ganglion Board. "None" to attempt auto-detect. aux: enable on not aux channels (i.e. switch to 18bit mode if set) impedance: measures impedance when start streaming timeout: in seconds, if set will try to disconnect / reconnect after a period without new data -- should be high if impedance check max_packets_to_skip: will try to disconnect / reconnect after too many packets are skipped baud, filter_data, daisy: Not used, for compatibility with v3 """ def __init__(self, port=None, baud=0, filter_data=False, scaled_output=True, daisy=False, log=True, aux=False, impedance=False, timeout=2, max_packets_to_skip=20): # unused, for compatibility with Cyton v3 API self.daisy = False # these one are used self.log = log # print_incoming_text needs log self.aux = aux self.streaming = False self.timeout = timeout self.max_packets_to_skip = max_packets_to_skip self.scaling_output = scaled_output self.impedance = impedance # might be handy to know API self.board_type = "ganglion" print("Looking for Ganglion board") if port == None: port = self.find_port() self.port = port # find_port might not return string self.connect() self.streaming = False # number of EEG channels and (optionally) accelerometer channel self.eeg_channels_per_sample = 4 self.aux_channels_per_sample = 3 self.imp_channels_per_sample = 5 self.read_state = 0 self.log_packet_count = 0 self.packets_dropped = 0 self.time_last_packet = 0 # Disconnects from board when terminated atexit.register(self.disconnect) def getBoardType(self): """ Returns the version of the board """ return self.board_type def setImpedance(self, flag): """ Enable/disable impedance measure """ self.impedance = bool(flag) def connect(self): """ Connect to the board and configure it. Note: recreates various objects upon call. """ print("Init BLE connection with MAC: " + self.port) print("NB: if it fails, try with root privileges.") self.gang = Peripheral(self.port, 'random') # ADDR_TYPE_RANDOM print("Get mainservice...") self.service = self.gang.getServiceByUUID(BLE_SERVICE) print("Got:" + str(self.service)) print("Get characteristics...") self.char_read = self.service.getCharacteristics(BLE_CHAR_RECEIVE)[0] print("receive, properties: " + str(self.char_read.propertiesToString()) + ", supports read: " + str(self.char_read.supportsRead())) self.char_write = self.service.getCharacteristics(BLE_CHAR_SEND)[0] print("write, properties: " + str(self.char_write.propertiesToString()) + ", supports read: " + str(self.char_write.supportsRead())) self.char_discon = self.service.getCharacteristics(BLE_CHAR_DISCONNECT)[0] print("disconnect, properties: " + str(self.char_discon.propertiesToString()) + ", supports read: " + str(self.char_discon.supportsRead())) # set delegate to handle incoming data self.delegate = GanglionDelegate(self.scaling_output) self.gang.setDelegate(self.delegate) # enable AUX channel if self.aux: print("Enabling AUX data...") try: self.ser_write(b'n') except Exception as e: print("Something went wrong while enabling aux channels: " + str(e)) print("Turn on notifications") # nead up-to-date bluepy, cf https://github.com/IanHarvey/bluepy/issues/53 self.desc_notify = self.char_read.getDescriptors(forUUID=0x2902)[0] try: self.desc_notify.write(b"\x01") except Exception as e: print("Something went wrong while trying to enable notification: " + str(e)) print("Connection established") def init_streaming(self): """ Tell the board to record like crazy. """ try: if self.impedance: print("Starting with impedance testing") self.ser_write(b'z') else: self.ser_write(b'b') except Exception as e: print("Something went wrong while asking the board to start streaming: " + str(e)) self.streaming = True self.packets_dropped = 0 self.time_last_packet = timeit.default_timer() 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] def ser_write(self, b): """Access serial port object for write""" self.char_write.write(b) def ser_read(self): """Access serial port object for read""" return self.char_read.read() def ser_inWaiting(self): """ Slightly different from Cyton API, return True if ASCII messages are incoming.""" # FIXME: might have a slight problem with thread because of notifications... if self.delegate.receiving_ASCII: # in case the packet indicating the end of the message drops, we use a 1s timeout if timeit.default_timer() - self.delegate.time_last_ASCII > 2: self.delegate.receiving_ASCII = False return self.delegate.receiving_ASCII def getSampleRate(self): return SAMPLE_RATE def getNbEEGChannels(self): """Will not get new data on impedance check.""" return self.eeg_channels_per_sample def getNbAUXChannels(self): """Might not be used depending on the mode.""" return self.aux_channels_per_sample def getNbImpChannels(self): """Might not be used depending on the mode.""" return self.imp_channels_per_sample def start_streaming(self, callback, lapse=-1): """ Start handling streaming data from the board. Call a provided callback for every single sample that is processed Args: callback: A callback function or a list of functions that will receive a single argument of the OpenBCISample object captured. """ if not self.streaming: self.init_streaming() start_time = timeit.default_timer() # Enclose callback funtion in a list if it comes alone if not isinstance(callback, list): callback = [callback] while self.streaming: # should the board get disconnected and we could not wait for notification # anymore, a reco should be attempted through timeout mechanism try: # at most we will get one sample per packet self.waitForNotifications(1. / self.getSampleRate()) except Exception as e: print("Something went wrong while waiting for a new sample: " + str(e)) # retrieve current samples on the stack samples = self.delegate.getSamples() self.packets_dropped = self.delegate.getMaxPacketsDropped() if samples: self.time_last_packet = timeit.default_timer() for call in callback: for sample in samples: call(sample) if (lapse > 0 and timeit.default_timer() - start_time > lapse): self.stop() if self.log: self.log_packet_count = self.log_packet_count + 1 # Checking connection -- timeout and packets dropped self.check_connection() def waitForNotifications(self, delay): """ Allow some time for the board to receive new data. """ self.gang.waitForNotifications(delay) def test_signal(self, signal): """ Enable / disable test signal """ if signal == 0: self.warn("Disabling synthetic square wave") try: self.char_write.write(b']') except Exception as e: print("Something went wrong while setting signal: " + str(e)) elif signal == 1: self.warn("Eisabling synthetic square wave") try: self.char_write.write(b'[') except Exception as e: print("Something went wrong while setting signal: " + str(e)) else: self.warn( "%s is not a known test signal. Valid signal is 0-1" % signal) def set_channel(self, channel, toggle_position): """ Enable / disable channels """ try: # Commands to set toggle to on position if toggle_position == 1: if channel is 1: self.ser.write(b'!') if channel is 2: self.ser.write(b'@') if channel is 3: self.ser.write(b'#') if channel is 4: self.ser.write(b'$') # Commands to set toggle to off position elif toggle_position == 0: if channel is 1: self.ser.write(b'1') if channel is 2: self.ser.write(b'2') if channel is 3: self.ser.write(b'3') if channel is 4: self.ser.write(b'4') except Exception as e: print("Something went wrong while setting channels: " + str(e)) """ Clean Up (atexit) """ def stop(self): print("Stopping streaming...") self.streaming = False # connection might be already down here try: if self.impedance: print("Stopping with impedance testing") self.ser_write(b'Z') else: self.ser_write(b's') except Exception as e: print("Something went wrong while asking the board to stop streaming: " + str(e)) if self.log: logging.warning('sent <s>: stopped streaming') def disconnect(self): if (self.streaming == True): self.stop() print("Closing BLE..") try: self.char_discon.write(b' ') except Exception as e: print("Something went wrong while asking the board to disconnect: " + str(e)) # should not try to read/write anything after that, will crash try: self.gang.disconnect() except Exception as e: print("Something went wrong while shutting down BLE link: " + str(e)) logging.warning('BLE closed') """ SETTINGS AND HELPERS """ def warn(self, text): if self.log: # log how many packets where sent succesfully in between warnings if self.log_packet_count: logging.info('Data packets received:' + str(self.log_packet_count)) self.log_packet_count = 0 logging.warning(text) print("Warning: %s" % text) def check_connection(self): """ Check connection quality in term of lag and number of packets drop. Reinit connection if necessary. FIXME: parameters given to the board will be lost. """ # stop checking when we're no longer streaming if not self.streaming: return # check number of dropped packets and duration without new packets, deco/reco if too large if self.packets_dropped > self.max_packets_to_skip: self.warn("Too many packets dropped, attempt to reconnect") self.reconnect() elif self.timeout > 0 and timeit.default_timer() - self.time_last_packet > self.timeout: self.warn("Too long since got new data, attempt to reconnect") # if error, attempt to reconect self.reconnect() def reconnect(self): """ In case of poor connection, will shut down and relaunch everything. FIXME: parameters given to the board will be lost.""" self.warn('Reconnecting') self.stop() self.disconnect() self.connect() self.init_streaming()
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] Heart_Rate_Control_Point = p.getServiceByUUID(0x180D).getCharacteristics()[2] print Heart_Rate_Measurement , Heart_Rate_Measurement.uuid # Print characteristic and its uuid print Body_Sensor_Location , Body_Sensor_Location.uuid print Heart_Rate_Control_Point , Heart_Rate_Control_Point.uuid ################## Print the Value ###########################
class BtlePeripheral(): def __init__(self, addr, producer, loop, receive_uuid = 0x2221, send_uuid = 0x2222, security = False): self._addr = addr self._producer = producer self._receive_uuid = receive_uuid self._send_uuid = send_uuid self._loop = loop self._security = security self._p = None def start(self): # init btle ElementReader el = BtleNode(self._producer.onBtleData, None, None) em = ElementReader(el) class MyDelegate(DefaultDelegate): def __init__(self): DefaultDelegate.__init__(self) def handleNotification(self, cHandle, data): # TODO: this should handle incorrect format caused by packet losses try: em.onReceivedData(data[2:]) except ValueError as e: print "Decoding value error: " + str(e) # connect ble while not self._p: try: self._p = Peripheral(self._addr, "random") except BTLEException as e: print "Failed to connect: " + str(e) + "; trying again" self._p = None # tell rfduino we are ready for notifications self._p.setDelegate(MyDelegate()) self._p.writeCharacteristic(self._p.getCharacteristics(uuid = self._receive_uuid)[0].valHandle + 1, "\x01\x00") self._loop.create_task(self.btleNotificationListen()) if self._security: # send our public key if configured to do so print "security on, sending our public key" interest = self._producer.makePublicKeyInterest() # write characteristics data = interest.wireEncode().toRawStr() num_fragments = int(math.ceil(float(len(data)) / 18)) print "length of data: " + str(len(data)) + "; number of fragments: " + str(num_fragments) current = 0 for i in range(0, num_fragments - 1): fragment = struct.pack(">B", i) + struct.pack(">B", num_fragments) + data[current:current + 18] current += 18 self._p.writeCharacteristic(self._p.getCharacteristics(uuid = self._send_uuid)[0].valHandle, fragment) print " ".join(x.encode('hex') for x in fragment) fragment = struct.pack(">B", num_fragments - 1) + struct.pack(">B", num_fragments) + data[current:] self._p.writeCharacteristic(self._p.getCharacteristics(uuid = self._send_uuid)[0].valHandle, fragment) print " ".join(x.encode('hex') for x in fragment) @asyncio.coroutine def btleNotificationListen(self): try: while True: if self._p.waitForNotifications(0.2): pass time.sleep(0.01) yield None except BTLEException as e: print("Btle exception: " + str(e) + "; try to restart") self._p = None self.start()
def onBtleData(data): print "got data: " + data.getName().toUri() el = BtleNode(onBtleData, None, None) em = ElementReader(el) class MyDelegate(DefaultDelegate): def __init__(self): DefaultDelegate.__init__(self) def handleNotification(self, cHandle, data): em.onReceivedData(data[2:]) p.setDelegate(MyDelegate()) p.writeCharacteristic(p.getCharacteristics(uuid=my_uuid)[0].valHandle + 1, "\x01\x00") while True: if p.waitForNotifications(1.0): continue """ try: #p.writeCharacteristic(0x2221, bytes(0x01), True) #print p.getCharacteristics() ch = p.getCharacteristics(uuid=my_uuid)[0] if (ch.supportsRead()): while True: val = ch.read() print binascii.hexlify(bytearray(val))
class Yeelight(DefaultDelegate): WRITE_CHAR_UUID = b"aa7d3f34" # -2d4f-41e0-807f-52fbf8cf7443" COMMAND_STX = "43" COMMAND_ETX = "00" AUTH_CMD = "67" AUTH_ON = "02" POWER_CMD = "40" POWER_ON = "01" POWER_OFF = "02" COLOR_CMD = "41" RGB_MODE = "65" BRIGHT_CMD = "42" COLORTEMP_CMD = "43" TEMP_MODE = "65" STATUS_CMD = "44" COLORFLOW_CMD = "4a" SLEEP_CMD = "7f03" def __init__(self, address): DefaultDelegate.__init__(self) self.__address = address self.__connect() # Override def handleNotification(self, handle, data): if handle == 21: format = ( '!xx' # 4345 header 'B' # switch: 01=on 02=off 'B' # mode: 01=rgb 02=warm 'BBBx' # RGB 'B' # Brightness 'H' # temp 2byte 1700 ~ 6500 'xxxxxxx' ) (switch, mode, r, g, b, brightness, temp) = struct.unpack(format, data) if switch != 4: self._switch = switch self._mode = mode self._rgb = '{:02x}{:02x}{:02x}'.format(r, g, b) self._temp = temp self._brightness = brightness def disconnect(self, *args, **kwargs): return self.__peripheral.disconnect(*args, **kwargs) def __connect(self): self.__peripheral = Peripheral(self.__address) self.__peripheral.setDelegate(self) characteristics = self.__peripheral.getCharacteristics() self.__ch = next(iter(filter(lambda x: binascii.b2a_hex(x.uuid.binVal) .startswith(self.WRITE_CHAR_UUID), characteristics))) # Register notification self.__peripheral.writeCharacteristic( 0x16, binascii.a2b_hex('0100')) # Auth self.__write_cmd( self.COMMAND_STX + self.AUTH_CMD + self.AUTH_ON + self.COMMAND_ETX * 15) # Get status self.__request_status() def __write_cmd(self, value): for _ in range(3): try: self.__ch.write(binascii.a2b_hex(value)) self.__peripheral.waitForNotifications(1.0) except BTLEException as e: error = e self.__connect() else: break else: raise error def __request_status(self): self.__write_cmd( self.COMMAND_STX + self.STATUS_CMD + self.COMMAND_ETX * 16 ) @property def switch(self): self.update_status() return self._switch @property def brightness(self): self.update_status() return self._brightness @property def temp(self): self.update_status() return self._temp @property def rgb(self): self.update_status() return self._rgb @property def mode(self): self.update_status() return self._mode def poweron(self): self.__write_cmd( self.COMMAND_STX + self.POWER_CMD + self.POWER_ON + self.COMMAND_ETX * 15) def poweroff(self): self.__write_cmd( self.COMMAND_STX + self.POWER_CMD + self.POWER_OFF + self.COMMAND_ETX * 15) def set_rgb(self, rgb): self.__write_cmd( self.COMMAND_STX + self.COLOR_CMD + rgb + '00' + self.RGB_MODE + self.COMMAND_ETX * 11) def set_brightness(self, value): self.__write_cmd( self.COMMAND_STX + self.BRIGHT_CMD + ('%02x' % value) + self.COMMAND_ETX * 15) # Bypass bug self.__request_status() def set_temp(self, value): if not 1700 <= value <= 6500 and 0.0 <= value <= 1.0: value = int(1700 + value * 4800) self.__write_cmd( self.COMMAND_STX + self.COLORTEMP_CMD + ('%04x' % value) + self.TEMP_MODE + self.COMMAND_ETX * 13) def set_sleep(self, minute): self.__write_cmd( self.COMMAND_STX + self.SLEEP_CMD + ('%02x' % minute) + self.COMMAND_ETX * 14 ) def update_status(self): self.__peripheral.waitForNotifications(0.01)
if len(sys.argv) != 2: print "Fatal, must pass device address:", sys.argv[0], "<device address>" quit() try: print "Info, trying to connect to:", sys.argv[1] p = Peripheral(sys.argv[1]) print "Info, connected and turning notify and sensor on!" ch = p.getCharacteristics(uuid=config_uuid)[0] ch.write(sensorOn, withResponse=True) # With bluepy if you need to read or write a Descriptor you have to # access it using Peripheral readCharacteristic or writeCharacteristic # and the appropriate handle p.setDelegate( MyDelegate("keys") ) p.writeCharacteristic(notifyHnd, notifyOn) while True: try: if p.waitForNotifications(1.0): # handleNotification() was called if keys & 0x01: print "Info, Right Button" if keys & 0x02: print "Info, Left Button" if keys & 0x04: print "Info, Reed Switch" except KeyboardInterrupt: print "exiting..."
class LightBlueBean(DefaultDelegate): # https://github.com/PunchThrough/bean-documentation/blob/master/app_message_types.md MSG_ID_SERIAL_DATA = 0x0000 MSG_ID_BT_SET_ADV = 0x0500 MSG_ID_BT_SET_CONN = 0x0502 MSG_ID_BT_SET_LOCAL_NAME = 0x0504 MSG_ID_BT_SET_PIN = 0x0506 MSG_ID_BT_SET_TX_PWR = 0x0508 MSG_ID_BT_GET_CONFIG = 0x0510 MSG_ID_BT_ADV_ONOFF = 0x0512 MSG_ID_BT_SET_SCRATCH = 0x0514 MSG_ID_BT_GET_SCRATCH = 0x0515 MSG_ID_BT_RESTART = 0x0520 MSG_ID_GATING = 0x0550 MSG_ID_BL_CMD = 0x1000 MSG_ID_BL_FW_BLOCK = 0x1001 MSG_ID_BL_STATUS = 0x1002 MSG_ID_CC_LED_WRITE = 0x2000 MSG_ID_CC_LED_WRITE_ALL = 0x2001 MSG_ID_CC_LED_READ_ALL = 0x2002 MSG_ID_CC_LED_DATA = 0x2082 MSG_ID_CC_ACCEL_READ = 0x2010 MSG_ID_CC_ACCEL_DATA = 0x2090 MSG_ID_CC_TEMP_READ = 0x2011 MSG_ID_CC_TEMP_DATA = 0x2091 MSG_ID_CC_BATT_READ = 0x2015 MSG_ID_CC_BATT_DATA = 0x2095 MSG_ID_AR_SET_POWER = 0x3000 MSG_ID_AR_GET_CONFIG = 0x3006 MSG_ID_DB_LOOPBACK = 0xFE00 MSG_ID_DB_COUNTER = 0xFE01 def __init__(self, mac): self.conn = Peripheral(mac) self.conn.setDelegate(self) self.count = 0 self.buffin = [None]*10 self.got1 = False print('connected') self.service = self.conn.getServiceByUUID(_LBN_UUID(0x10)) self.serial = self.service.getCharacteristics(_LBN_UUID(0x11)) [0] #print(self.serial.propertiesToString()) # Turn on notificiations self.conn.writeCharacteristic(0x2f, '\x01\x00', False) i = 0 while True: #print(self.serial.read()) self.write("a" * 60) #self.write("a" * 5) #self.sendCmd(LightBlueBean.MSG_ID_CC_ACCEL_READ) self.conn.waitForNotifications(1) time.sleep(1) self.conn.disconnect() def write(self, data): self.sendCmd(LightBlueBean.MSG_ID_SERIAL_DATA, data) def sendCmd(self, cmd, data = ""): # https://github.com/PunchThrough/bean-documentation/blob/master/serial_message_protocol.md gst = struct.pack("!BxH", len(data)+2, cmd) + data crc = struct.pack("<H", crc16(gst, 0xFFFF)) gst += crc gt_qty = len(gst)/19 if len(gst) % 19 != 0: gt_qty += 1 #amnt = len(gst) / gt_qty optimal_packet_size = 19 for ch in xrange(0, gt_qty): data = gst[:optimal_packet_size] gst = gst[optimal_packet_size:] gt = 0 if ch == 0: gt = 0x80 gt |= self.count << 5 gt |= gt_qty - ch - 1 gt = struct.pack("B", gt) + data #print("<", hexdump(gt)) self.serial.write(gt) #time.sleep(0.1) self.count = (self.count + 1) % 4 def writeRaw(self, data): self.conn.writeCharacteristic(0x0b, data, False) def handleNotification(self, cHandle, data): #print(">", hexdump(data)) gt = struct.unpack("B", data[0]) [0] #gt_cntr = gt & 0x60 gt_left = gt & 0x1F if gt & 0x80: self.got1 = True self.buffin = self.buffin[:gt_left+1] self.buffin[gt_left] = data[1:] if self.got1 and not self.buffin.count(None): #print("Got ", len(self.buffin), "packets") self.buffin.reverse() self.buffin = ''.join(self.buffin) crc_ = crc16(self.buffin[:-2], 0xFFFF) dlen, cmd = struct.unpack("!BxH", self.buffin[:4]) crc = struct.unpack("<H", self.buffin[-2:]) [0] if crc == crc_: print(self.buffin[4:-2]) else: print("CRC check failure") self.buffin = [None]*10 self.got1 = False
p.writeCharacteristic(handler, struct.pack('<bb', 0x00, 0x00) ,False) #UUID 가져온다. washer_service_uuid = UUID("6e400001-b5a3-f393-e0a9-e50e24dcca9e") battery_service_uuid = UUID("180F") #washer service Characteristics의 센서에서 전송하는 정보이며 Access Permisson은 Notify washerTX_char_uuid = UUID("6e400003-b5a3-f393-e0a9-e50e24dcca9e") battery_level_uuid = UUID("00002a19-0000-1000-8000-00805f9b34fb") #if len(sys.argv) != 2: # print ("Fatal, must pass device address:", sys.argv[0], "<device address="">") # quit() p = Peripheral("c7:74:31:9A:F8:D1","random") p.setDelegate( MyDelegate(p) ) #WasherService, BatteryService를 가져온다. WasherService=p.getServiceByUUID(washer_service_uuid) BatteryService =p.getServiceByUUID(battery_service_uuid) #TX의 Characteristics를 가져온다. WasherTX_C = WasherService.getCharacteristics(washerTX_char_uuid)[0] #battey의 Characteristics를 가져온다. Battery_C = BatteryService.getCharacteristics(battery_level_uuid)[0] # Client Characteristic Descriptor의 handler # 0x13 은 washerTX, 0x0F는 battery # notifications의 비트를 1로 바꿔 활성화한다.
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()