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
data_UUID = _TI_UUID(0xAA00) sensor_UUID = _TI_UUID(0xAA01) timestamp_UUID = _TI_UUID(0xAA02) conf_UUID = 0x2902 data_service = p.getServiceByUUID(data_UUID) #print data_service sensor_characteristic = data_service.getCharacteristics(sensor_UUID) #print sensor_characteristic timestamp_characteristic = data_service.getCharacteristics(timestamp_UUID) #print timestamp_characteristic data_descriptor = p.getDescriptors(data_service.hndStart, data_service.hndEnd) timestamp_desc, = [ timestamp_desc for timestamp_desc in data_descriptor if timestamp_desc.uuid == timestamp_UUID ] #print timestamp_desc conf_desc, = [ conf_desc for conf_desc in data_descriptor if conf_desc.uuid == conf_UUID ] #print conf_desc sensor_desc, = [ sensor_desc for sensor_desc in data_descriptor if sensor_desc.uuid == sensor_UUID ]
# print deviceIndex print scanDeviceList[deviceIndex] p = Peripheral(scanDeviceList[deviceIndex], "random") pq = MyDelegate(p) p.setDelegate(pq) #Get UART Service UARTService = p.getServiceByUUID(UART_service_uuid) # Get The UART-Characteristics UARTC = UARTService.getCharacteristics(UART_rx_char_uuid)[0] #Get The handle the UART-Characteristics hUARTC = UARTC.getHandle() # Search and get Get The UART-Characteristics "property" (UUID-0x2902 CCC-Client Characteristic Configuration)) # wich is located in a handle in the range defined by the boundries of the UARTService for desriptor in p.getDescriptors( hUARTC): # The handle range should be read from the services if (desriptor.uuid == 0x2902 ): # but is not done due to a Bluez/BluePy bug :( print( "Trackle UART Client Characteristic Configuration found at handle 0x" + format(desriptor.handle, "02X")) hUARTCCC = desriptor.handle # Turn notifications on by setting bit0 in the CCC more info on: # https://developer.bluetooth.org/gatt/descriptors/Pages/DescriptorViewer.aspx?u=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml p.writeCharacteristic(hUARTCCC, struct.pack('<bb', 0x01, 0x00)) print "Notification is turned on for Trackle sensor" # ++++++++++++++++++++++++++++++ BLE STOP ++++++++++++++++++++++++++++ while True:
read_handle = read_char.getHandle() write_handle = write_char.getHandle() #spp_handle = spp_send_data.getHandle() print("read handle value : 0x" + format(read_handle, "02X")) print("write handle value : 0x" + format(write_handle, "02X")) #spp_send_data.write(str.encode("hi gyutae")) # Search and get the read-Characteristics "property" # (UUID-0x2902 CCC-Client Characteristic Configuration)) # which is located in a handle in the range defined by the boundries of the Service for descriptor in p.getDescriptors( read_handle, 0xFFFF ): # The handle range should be read from the services if (descriptor.uuid == 0x2902 ): # but is not done due to a Bluez/BluePy bug :( print( "Client Characteristic Configuration found at handle 0x" + format(descriptor.handle, "02X")) read_cccd = descriptor.handle #spp_cccd = descriptor.handle p.writeCharacteristic(read_cccd, struct.pack('<bb', 0x01, 0x00)) #p.writeCharacteristic(spp_cccd, struct.pack('<bb', 0x01, 0x00)) #print("pack ", struct.pack('<bb', 0x01, 0x00)) ############################################# # BLE message loop
class Switcher: switcher = None characteristics = None battery_handler = None hashed_share_code_handler = None authority_handler = None time_handler = None switch_handler = None uuids = None share_code = None def __init__(self, mac_address, share_code, debug=False): bluepy.btle.Debugging = debug self.mac_address = mac_address self.share_code = share_code def scan(self): scan_timeout = 10 # seconds scanner = Scanner() retry = True while (retry): try: print('Scanning...') devices = scanner.scan(scan_timeout) for device in devices: name = None for ad_type, description, value in device.getScanData(): if ad_type == 9: name = value if name is None or 'SWITCHER_M' not in name: continue print('A switcher is found: {}({} {})'.format( name, device.addr, device.addrType)) if device.connectable: print('Connectable switcher is found.') self.mac_address = device.addr retry = False break else: print('The switcher is busy') if retry: print('Connectable switcher is not found. Retry...') sleep(2) except Exception as e: print('Error on scanning') traceback.print_exc() self.connect() def connect(self, callback=None): retry = True while retry: try: print('Try to connect to the switcher...') self.switcher = Peripheral(self.mac_address, 'random') retry = False except Exception as e: print('Error on connecting') traceback.print_exc() print('Switcher is connected') if callback: try: callback.on_connected(self) except BTLEException as e: traceback.print_exc() if e.code == BTLEException.DISCONNECTED: print('Switcher disconnected') self.switcher = None # TODO: try re-connect except Exception as e: print('Error on using') traceback.print_exc() finally: if self.switcher: print('Disconnect due to an error') self.switcher.disconnect() def auto_reconnect(func): @functools.wraps(func) def wrap(self, *args, **kargs): if self.switcher is None: self.connect() while (True): try: return func(self, *args, **kargs) except BTLEException as e: if e.code == BTLEException.DISCONNECTED: print('Switcher has gone') else: traceback.print_exc() print('Try reconnect...') self.connect() return wrap def disconnect(self): if self.switcher: self.switcher.disconnect() print('Switcher is disconnected') def to_bytes(self, digits): return bytearray(int(ch) for ch in str(digits)) def show_informations(self): self.load_uuids() self.get_services(True) self.get_characteristics(True) def load_uuids(self): import json with open('uuid.json') as f: self.uuids = {v: k for k, v in json.load(f).items()} def get_uuid_description(self, uuid): try: return self.uuids[uuid] except: return 'Unknown' def get_services(self, print_services=False): print('get_services') services = self.switcher.getServices() if print_services: for service in services: uuid = str(service.uuid) print('UUID: {} ({})'.format(uuid, self.get_uuid_description(uuid))) def get_characteristics(self, print_characteristics=False): print('get_characteristics') if self.characteristics is None: self.characteristics = self.switcher.getCharacteristics() if print_characteristics: for ch in self.characteristics: uuid = str(ch.uuid) print('UUID: {} ({})'.format(uuid, self.get_uuid_description(uuid))) print('Properties: {} ({})'.format(ch.properties, ch.propertiesToString())) print('Handler: 0x{:02x}'.format(ch.getHandle())) print('\n') return self.characteristics def get_descriptors(self): """ Switcher sends no response for this method """ descriptors = self.switcher.getDescriptors() print('descriptors') print(descriptors) def get_handler(self, number_of_handler): characteristics = self.get_characteristics() for ch in characteristics: if ch.getHandle() == number_of_handler: return ch print('There is no handler: {}'.format(number_of_handler)) return None def get_hashed_share_code_handler(self): if not self.hashed_share_code_handler: self.hashed_share_code_handler = self.get_handler(0x1d) return self.hashed_share_code_handler @auto_reconnect def get_battery(self): battery = int.from_bytes(self.switcher.readCharacteristic(0xe), byteorder='big') return battery @auto_reconnect def compare_hashed_share_code(self): hashed_share_code = self.to_bytes('0' + self.share_code) print('Write: {}'.format(hashed_share_code)) result = self.switcher.writeCharacteristic(0x1d, hashed_share_code, True) print(result) @auto_reconnect def get_authority(self): return self.switcher.readCharacteristic(0x1f)[0] def get_day_name(self, day): days = [ 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday' ] return days[day] @auto_reconnect def get_time(self): day, hours, minutes = self.switcher.readCharacteristic(0x2b) return '{} {:02d}:{:02d}'.format(self.get_day_name(day), hours, minutes) @auto_reconnect def manage_switch(self, switch, on=True): """ switch: 1, 2 on: True / False switch 1 on -> 0 switch 1 off -> 1 switch 2 on -> 2 switch 2 off -> 3 """ if switch not in [1, 2]: print('Switch must be 1 or 2') return print('Switch {} {}'.format(switch, 'ON' if on else 'OFF')) param = (switch - 1) * 2 + (0 if on else 1) print(param) result = self.switcher.writeCharacteristic(0x11, bytes([param]), True) print(result) @auto_reconnect def test_switch(self, value): result = self.switcher.writeCharacteristic(0x11, bytes([value]), True) print(result)
import struct from bluepy.btle import Scanner, DefaultDelegate, Peripheral device = Peripheral() device.connect('78:A3:52:00:04:2D') services = device.getServices() characteristics = device.getCharacteristics() descriptors = device.getDescriptors() state = device.getState() #displays all services for service in services: print(service) print("Handle UUID Properties") print("-------------------------------------------------------") for ch in characteristics: print(" 0x"+ format(ch.getHandle(),'02X') +" "+str(ch.uuid) +" " + ch.propertiesToString()) if ch.uuid == '19b10011-e8f2-537e-4f6c-d104768a1214': print(struct.unpack('i', ch.read())[0])
logger.info(log_info) # %% create bluetooth connection, get services and characteristics try: connection = Peripheral(deviceAddr=JDY_MAC) log_info = time.ctime()[4:-5] + " BLE connected." logger.info(log_info) except BTLEDisconnectError: log_info = time.ctime()[4:-5] + " create BLE connection fail. exit" logger.info(log_info) sys.exit() services = connection.getServices() services = list(services) characteristics = connection.getCharacteristics() characteristics = list(characteristics) descriptors = connection.getDescriptors() handles = [] for characteristic in characteristics: # characteristic.handle not equal to characteristic.getHandle() handles.append(characteristic.getHandle()) handle = handles[-1] # %% create serial connections port_names = get_port_devices() for i, item in enumerate(port_names): if 'USB' not in item: del port_names[i] break ports_list = open_ports(port_names[0:len(port_names)]) log_info = time.ctime()[4:-5] + " open two ports success." logger.info(log_info)
class CarControl: scanner = None devices = [] devicetext = "" isConnected = False carAddr = None carName = None carDevice = None carPeripheral = None def __repr__(self): return "devices: {}, address: {}, carName: {}".format( len(self.devices), self.carAddr, self.carName) #return "devices: {}".format(len(self.devices)) def scan(self, timeout=10): foundDevices = 0 self.devices = [] self.devicetext = "" newdevices = [] scansuccess = False try: self.scanner = Scanner() self.scanner.withDelegate(MainDelegate()) newdevices = self.scanner.scan(timeout) scansuccess = True except Exception as e: scansuccess = False if scansuccess: for dev in newdevices: if dev.addrType == btle.ADDR_TYPE_PUBLIC: foundDevices = foundDevices + 1 self.devices.append({ "name": dev.getValueText(9), "addr": dev.addr }) self.devicetext = self.devicetext + "> Device #{} {} ({}), [{}], [{}]\n".format( foundDevices, dev.addr, dev.addrType, dev.getValueText(9), dev.getValueText(8)) # add known cars for k in KNOWN_CARS: foundDevices = foundDevices + 1 self.devices.append({"name": k["name"], "addr": k["addr"]}) self.devicetext = self.devicetext + "> Device #{} {} ({}), [{}]\n".format( foundDevices, k["addr"], "Known Device", k["name"]) return scansuccess def connect(self, carnum): if len(self.devices) == 0: print("connect: Nothing scanned") return if carnum < 0 or carnum > len(self.devices): print("connect: Car number invalid, {}".format(carnum)) return try: self.carAddr = self.devices[carnum]["addr"] self.carName = self.devices[carnum]["name"] self.carPeripheral = Peripheral() self.carPeripheral.withDelegate(MainDelegate()) self.carPeripheral.connect(self.carAddr) self.isConnected = True return True except Exception as e: self.carPeripheral = None print("connect: Error,", e) return False def listdescriptors(self): try: print("listdescriptors: ...") print("listdescriptors: listing descriptors") descriptors = self.carPeripheral.getDescriptors() for desc in descriptors: print(" -- DESCRIPTORS: {}, [{}], Handle: {} (0x{:04x})". format(desc.uuid, UUID(desc.uuid).getCommonName(), desc.handle, desc.handle)) except Exception as e: print("listdescriptors: Error,", e) def listservices(self): try: print("listservices: listing services") services = self.carPeripheral.getServices() for serv in services: print(" -- SERVICE: {} [{}]".format( serv.uuid, UUID(serv.uuid).getCommonName())) characteristics = serv.getCharacteristics() for chara in characteristics: print( " -- --> CHAR: {}, Handle: {} (0x{:04x}) - {} - [{}]" .format(chara.uuid, chara.getHandle(), chara.getHandle(), chara.propertiesToString(), UUID(chara.uuid).getCommonName())) except Exception as e: print("listservices: Error,", e) def disconnectcar(self): self.isConnected = False if self.carPeripheral is None: print("disconnectcar: No car connected") return False try: self.carPeripheral.disconnect() self.carPeripheral = None return True except Exception as e: print("disconnectcar: Error,", e) return False def readcharacteristics(self): try: if self.carPeripheral is None: print("readcharacteristics: No car connected") return print("readcharacteristics: reading the readables") chars = self.carPeripheral.getCharacteristics() for c in chars: if c.supportsRead(): print( " -- READ: {} [{}] (0x{:04x}), {}, Value: {}".format( c.uuid, UUID(c.uuid).getCommonName(), c.getHandle(), c.descs, c.read() if c.supportsRead() else "")) except Exception as e: print("readcharacteristics: Error,", e) def writevalue(self, handle, value, wait=False): try: if self.carPeripheral is None: #print("writevalue: No car connected") return #print("writevalue: writing to handle 0x{:04x} value {}".format(handle, value)) self.carPeripheral.writeCharacteristic(handle, value, wait) except Exception as e: print("writevalue: Error,", e) def readvalue(self, handle): try: if self.carPeripheral is None: print("readvalue: No car connected") return print("readvalue: reading handle 0x{:04x}".format(handle)) value = self.carPeripheral.readCharacteristic(handle) print("readvalue: Handle 0x{:04x} = {}".format(handle, value)) except Exception as e: print("readvalue: Error,", e) def sendhandshake(self): # handshake... for finger in BTCMD_HANDSHAKE: self.writevalue(BTDRIVE_HANDLE, finger, True) def carfiregun(self, intensity=0.5): self.writevalue(BTDRIVE_HANDLE, BTCMD_FIREGUN) def carforward(self, intensity=0.5): if intensity < 0.1 or intensity > 1: return scale = 0x1F actual_intensity = 0x00 + round(scale * intensity) # pull value list tx_list = [BTCMD_DRIVE, actual_intensity, 0x00] tx_data = bytes(tx_list) self.writevalue(BTDRIVE_HANDLE, tx_data, True) def carreverse(self, intensity=0.5): if intensity < 0.1 or intensity > 1: return scale = 0x1F actual_intensity = 0x20 + round(scale * intensity) # pull value list tx_list = [BTCMD_DRIVE, actual_intensity, 0x00] tx_data = bytes(tx_list) self.writevalue(BTDRIVE_HANDLE, tx_data, True) def carright(self, intensity=0.5): if intensity < 0.1 or intensity > 1: return scale = 0x1F actual_intensity = 0x40 + round(scale * intensity) # pull value list tx_list = [BTCMD_DRIVE, 0x00, actual_intensity] tx_data = bytes(tx_list) self.writevalue(BTDRIVE_HANDLE, tx_data, True) def carleft(self, intensity=0.5): if intensity < 0.1 or intensity > 1: return scale = 0x1F actual_intensity = 0x60 + round(scale * intensity) # pull value list tx_list = [BTCMD_DRIVE, 0x00, actual_intensity] tx_data = bytes(tx_list) self.writevalue(BTDRIVE_HANDLE, tx_data, True)
class CSCSensor: """ This class defines a cycling speed and cadence sensor """ def __init__(self): self.peripheral = None self.cscService = None self.cscCharacteristic = None self.cscCharacteristicHandle = None def connect(self, address: str, notification_callback: Callable[[float, float, int], None]): """ Initializes the class :param address: A string with the address of the sensor :param notification_callback: A function that takes two floats (speed, cadence) that will be called for each notification """ self.peripheral = Peripheral(address, "random") delegate = CSCDelegate() delegate.notification_callback = notification_callback self.peripheral.setDelegate(delegate) self.cscService = self.peripheral.getServiceByUUID(CSC_SERVICE_UUID) self.cscCharacteristic = self.cscService.getCharacteristics( CSC_CHAR_UUID)[0] self.cscCharacteristicHandle = self.cscCharacteristic.getHandle() def get_location(self) -> str: """ Returns the location of the sensor :return: an integer representing the location """ location_list = [ "Other", "Top of shoe", "In shoe", "Hip", "Front Wheel", "Left Crank", "Right Crank", "Left Pedal", "Right Pedal", "Front Hub", "Rear Dropout", "Chainstay", "Rear Wheel", "Rear Hub", "Chest", "Spider", "Chain Ring" ] characteristic = self.cscService.getCharacteristics( LOCATION_CHAR_UUID)[0] handle = characteristic.getHandle() location = self.peripheral.readCharacteristic(handle) return location_list[int.from_bytes(location, "little")] def notifications(self, notify: bool) -> None: """ Starts or stops notifications from this sensor :param notify: True to start notifications, False to stop :return: None """ hccc = 0 for descriptor in self.peripheral.getDescriptors( self.cscCharacteristicHandle): if descriptor.uuid == 0x2902: hccc = descriptor.handle break self.peripheral.writeCharacteristic( hccc, struct.pack("<bb", 0x01 & notify, 0x00)) @asyncio.coroutine async def wait_for_notifications(self, wait_time: float) -> bool: """ Wait `wait_time` seconds for a notification :param wait_time: The number of seconds to wait :return: A boolean indicating whether a notification was received """ return self.peripheral.waitForNotifications(wait_time)
import sys from bluepy.btle import UUID, Peripheral if len(sys.argv) != 2: print("Fatal, must pass device address:", sys.argv[0], "<device address=" ">") quit() p = Peripheral(sys.argv[1]) descriptors = p.getDescriptors( 1, 0x00F) #Bug if no limt is specified the function wil hang # (go in a endless loop and not return anything) print("UUID Handle UUID by name") for descriptor in descriptors: print(" " + str(descriptor.uuid) + " 0x" + format(descriptor.handle, "02X") + " " + str(descriptor))
class Switcher: switcher = None characteristics = None battery_handler = None hashed_share_code_handler = None authority_handler = None time_handler = None switch_handler = None uuids = None share_code = None def __init__(self, address, address_type, share_code): self.share_code = share_code retry = True while retry: try: print('Try to connect to the switcher...') self.switcher = Peripheral(address, address_type) print('Switcher is connected') retry = False except Exception as e: print('Error on connecting') print(e) try: # self.retrieve_informations() self.run() finally: print('disconnect from the switcher') self.switcher.disconnect() def to_bytes(self, digits): return bytearray(int(ch) for ch in str(digits)) def retrieve_informations(self): self.load_uuids() self.get_services() self.get_characteristics() def load_uuids(self): import json with open('uuid.json') as f: self.uuids = {v: k for k, v in json.load(f).items()} def get_uuid_description(self, uuid): try: return self.uuids[uuid] except: return 'Unknown' def get_services(self): services = self.switcher.getServices() print('services') for service in services: uuid = str(service.uuid) print('UUID: {} ({})'.format(uuid, self.get_uuid_description(uuid))) def get_characteristics(self): if self.characteristics is None: self.characteristics = self.switcher.getCharacteristics() return self.characteristics ''' print('characteristics') for ch in characteristics: uuid = str(ch.uuid) print('UUID: {} ({})'.format(uuid, self.get_uuid_description(uuid))) print('Properties: {} ({})'.format(ch.properties, ch.propertiesToString())) print('Handler: 0x{:02x}'.format(ch.getHandle())) print('\n') ''' def get_descriptors(self): """ Switcher sends no response for this method """ descriptors = self.switcher.getDescriptors() print('descriptors') print(descriptors) def get_handler(self, number_of_handler): characteristics = self.get_characteristics() for ch in characteristics: if ch.getHandle() == number_of_handler: return ch print('There is no handler: {}'.format(number_of_handler)) return None def get_battery_handler(self): if not self.battery_handler: self.battery_handler = self.get_handler(0xe) return self.battery_handler def get_hashed_share_code_handler(self): if not self.hashed_share_code_handler: self.hashed_share_code_handler = self.get_handler(0x1d) return self.hashed_share_code_handler def get_authority_handler(self): if not self.authority_handler: self.authority_handler = self.get_handler(0x1f) return self.authority_handler def get_time_handler(self): if not self.time_handler: self.time_handler = self.get_handler(0x2b) return self.time_handler def get_switch_handler(self): if not self.switch_handler: self.switch_handler = self.get_handler(0x11) return self.switch_handler def get_battery(self): battery_handler = self.get_battery_handler() battery = int.from_bytes(battery_handler.read(), byteorder='big') return battery def compare_hashed_share_code(self): hashed_share_code_handler = self.get_hashed_share_code_handler() hashed_share_code = self.to_bytes('0' + self.share_code) print('Write: {}'.format(hashed_share_code)) return hashed_share_code_handler.write(hashed_share_code, True) def get_authority(self): authority_handler = self.get_authority_handler() return authority_handler.read()[0] def get_day_name(self, day): days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] return days[day] def get_time(self): time_handler = self.get_time_handler() day, hours, minutes = time_handler.read() return '{} {:02d}:{:02d}'.format(self.get_day_name(day), hours, minutes) def manage_switch(self, switch, on=True): """ switch: 1, 2 on: True / False """ if switch not in [1, 2]: print('Switch must be 1 or 2') return print('Switch {} {}'.format(switch, 'ON' if on else 'OFF')) param = (switch - 1) * 2 + (0 if on else 1) switch = self.get_switch_handler() switch.write(bytes([param])) def run(self): print('Battery Status: {}'.format(self.get_battery())) #print('Shared Hash Code : {}'.format(self.compare_hashed_share_code())) print('Authority : {}'.format(self.get_authority())) print('Time : {}'.format(self.get_time())) while True: switch, status = input().split() self.manage_switch(int(switch), status=='1')
print "Fatal, must pass device address:", sys.argv[ 0], "<device address=" ">" quit() p = Peripheral(sys.argv[1], "random") p.setDelegate(MyDelegate(p)) #Get ButtonService ButtonService = p.getServiceByUUID(button_service_uuid) # Get The Button-Characteristics ButtonC = ButtonService.getCharacteristics(button_char_uuid)[0] #Get The handle tf the Button-Characteristics hButtonC = ButtonC.getHandle() # Search and get Get The Button-Characteristics "property" (UUID-0x2902 CCC-Client Characteristic Configuration)) # wich is located in a handle in the range defined by the boundries of the ButtonService for desriptor in p.getDescriptors( hButtonC, 0x00F): # The handle range should be read from the services 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 # Turn notifications on by setting bit0 in the CCC more info on: # https://developer.bluetooth.org/gatt/descriptors/Pages/DescriptorViewer.aspx?u=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml p.writeCharacteristic(hButtonCCC, struct.pack('<bb', 0x01, 0x00)) print "Notification is turned on for Button1" # Main loop -------- while True: if p.waitForNotifications(1.0):
class Audrey: audrey = None def __init__(self, mac_address, debug=False): bluepy.btle.Debugging = debug self.mac_address = mac_address def scan(self): scan_timeout = 10 # seconds scanner = Scanner() retry = True while (retry): try: print('Scanning...') devices = scanner.scan(scan_timeout) for device in devices: name = None for ad_type, description, value in device.getScanData(): if ad_type == 9: name = value if name is None or 'Audrey' not in name: continue print('Audrey is found: {}({} {})'.format( name, device.addr, device.addrType)) if device.connectable: print('Connectable audrey is found.') self.mac_address = device.addr retry = False break else: print('Audrey is busy') if not self.mac_address: print('Connectable audrey is not found. Retry...') sleep(2) except Exception as e: print('Error on scanning') traceback.print_exc() self.connect() def connect(self, callback=None): retry = True while retry: try: print('Try to connect to Audrey...') self.audrey = Peripheral(self.mac_address, 'public') retry = False except Exception as e: print('Error on connecting') traceback.print_exc() print('Audrey is connected') if callback: try: callback.on_connected(self) except BTLEException as e: traceback.print_exc() if e.code == BTLEException.DISCONNECTED: print('Audrey has gone') self.audrey = None # TODO: try re-connect except Exception as e: print('Error on using') traceback.print_exc() finally: if self.audrey: print('Disconnect due to an error') self.audrey.disconnect() def auto_reconnect(func): @functools.wraps(func) def wrap(self, *args, **kargs): if self.audrey is None: self.connect() while (True): try: return func(self, *args, **kargs) except BTLEException as e: if e.code == BTLEException.DISCONNECTED: print('Audrey has gone') else: traceback.print_exc() print('Try reconnect...') self.connect() return wrap def disconnect(self): if self.audrey: self.audrey.disconnect() print('Audrey is disconnected') def to_bytes(self, digits): return bytearray(int(ch) for ch in str(digits)) @auto_reconnect def send_command(self, command, on_success=None): command += '\r\n' print('Write: {}'.format(command)) result = self.audrey.writeCharacteristic(0x25, command.encode('utf-8'), True) print(result) if on_success: on_success() def load_uuids(self): import json with open('uuid.json') as f: self.uuids = {v: k for k, v in json.load(f).items()} def get_uuid_description(self, uuid): try: return self.uuids[uuid] except: return 'Unknown' def get_services(self, print_services=False): print('get_services') services = self.audrey.getServices() if print_services: for service in services: uuid = str(service.uuid) print('UUID: {} ({})'.format(uuid, self.get_uuid_description(uuid))) def get_characteristics(self, print_characteristics=False): print('get_characteristics') if self.characteristics is None: self.characteristics = self.audrey.getCharacteristics() if print_characteristics: for ch in self.characteristics: uuid = str(ch.uuid) print('UUID: {} ({})'.format(uuid, self.get_uuid_description(uuid))) print('Properties: {} ({})'.format(ch.properties, ch.propertiesToString())) print('Handler: 0x{:02x}'.format(ch.getHandle())) print('\n') return self.characteristics def get_descriptors(self): """ Audrey sends no response for this method """ descriptors = self.audrey.getDescriptors() print('descriptors') print(descriptors)
t_now = 0 # y scale - muscle current m = [] sensor_service = UUID(0x180D) p = Peripheral('DE:5B:BA:87:4C:F7', 'random') SensorService = p.getServiceByUUID(sensor_service) ch = SensorService.getCharacteristics(0x2A37)[0] print(UUID(ch.uuid).getCommonName()) chC = ch.getHandle() for desc in p.getDescriptors(chC, 0x16): if desc.uuid == 0x2902: chC = desc.handle p.writeCharacteristic(chC, struct.pack('<bb', 0x01, 0x00)) class MyDelegate(DefaultDelegate): def __init__(self, params): DefaultDelegate.__init__(self) def handleNotification(self, cHandle, data): plt.ion() plt.figure(1) plt.clf()
class ble_UT363(QObject): CCCD = "00002902-0000-1000-8000-00805f9b34fb" UUID_HEART_RATE_MEASUREMENT = "00002a37-0000-1000-8000-00805f9b34fb" WX_SERVICE_UUID = "0000ff12-0000-1000-8000-00805f9b34fb" WX_CHAR_UUID = "0000FF01-0000-1000-8000-00805f9b34fb" WX_NOTIFICATION_UUID = "0000FF02-0000-1000-8000-00805f9b34fb" wind_sig = pyqtSignal(str, str) temp_sig = pyqtSignal(str, str) disconnect_sig = pyqtSignal() def __init__(self): super().__init__() self.UT363 = None self.udp = None from UDPBeep import find_ip ip, broadcast = find_ip().get_ip() if len(ip) > 0: index = 0 if "192.168.1.251" in ip: index = ip.index("192.168.1.251") print(broadcast[index]) self.udp = udpbeep(broadcast[index], 4445) self.wind_sig.connect(self.send_udpwind) self.timerRx = QtCore.QTimer(self) self.timerRx.timeout.connect(self.writeRxCharacteristic) def disconnect(self): self.timerRx.stop() if self.udp is not None: self.udp.sendData("wind_speed -1 m/s") self.wind_sig.emit(DEFAULT_STRING, DEFAULT_STRING) self.temp_sig.emit(DEFAULT_STRING, DEFAULT_STRING) if self.UT363 is not None: self.UT363.disconnect() self.UT363 = None self.disconnect_sig.emit() def connect(self, address): self.UT363 = Peripheral(address) if self.UT363: self.UT363.setDelegate( MyDelegate(self.UT363, self.temp_sig, self.wind_sig)) self.enableTxNotification() self.timerRx.start(800) def enableTxNotification(self): RxService = self.UT363.getServiceByUUID(self.WX_SERVICE_UUID) if RxService: TxChar = RxService.getCharacteristics(self.WX_NOTIFICATION_UUID)[0] if TxChar: try: TxChar.write(struct.pack('<B', True)) except BTLEException as e: print("BTLE write error : ", type(e).__name__) self.disconnect() def writeRxCharacteristic(self): RxService = self.UT363.getServiceByUUID(self.WX_SERVICE_UUID) if RxService: RxChar = RxService.getCharacteristics(self.WX_CHAR_UUID)[0] if RxChar: try: RxChar.write(struct.pack('<B', 0x5e)) except BTLEException as e: print("BTLE write error : ", type(e).__name__) self.disconnect() def send_udpwind(self, value, unit): if value != DEFAULT_STRING and unit != DEFAULT_STRING: msg = "wind_speed " + value + " " + unit print(msg) if self.udp is not None: self.udp.sendData(msg) def isconnected(self): return self.UT363 is not None def get_device_info(self): services = self.UT363.getServices() for service in services: print(service, "UUID : ", service.uuid) chList = self.UT363.getCharacteristics() print("Handle UUID Properties") print("-------------------------------------------------------") for ch in chList: print(" 0x" + format(ch.getHandle(), '02X') + " " + str(ch.uuid) + " " + ch.propertiesToString()) descriptors = self.UT363.getDescriptors( 1, 0x00F) # Bug if no limt is specified the function wil hang # (go in a endless loop and not return anything) print("UUID Handle UUID by name") for descriptor in descriptors: print(" " + str(descriptor.uuid) + " 0x" + format(descriptor.handle, "02X") + " " + str(descriptor))
sr_service_uuid = UUID(0xFDEE) sr_auth_char_uuid = UUID(0xFD03) sr_tx_uuid = UUID(0xFD05) print('target addr ' + 'ba:03:4c:3a:c3:70') p = Peripheral('ba:03:4c:3a:c3:70', "public") p.setDelegate(MyDelegate(p)) sr_service = p.getServiceByUUID(sr_service_uuid) p.setMTU(36) sr_tx_char = sr_service.getCharacteristics(sr_tx_uuid)[0] sr_tx_char_value_handle = sr_tx_char.getHandle() for desriptor in p.getDescriptors(sr_tx_char_value_handle, 0xFF): if (desriptor.uuid == 0x2902): print("SR_TX CCCD found at handle 0x" + format(desriptor.handle, "02X")) sr_tx_value_cccd_handle = desriptor.handle p.writeCharacteristic(sr_tx_value_cccd_handle, struct.pack('<bb', 0x02, 0x00)) print("Indication is turned on for TX") sr_auth_char = sr_service.getCharacteristics(sr_auth_char_uuid)[0] sr_auth_char_value_handle = sr_auth_char.getHandle() p.writeCharacteristic( sr_auth_char_value_handle, struct.pack('<BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB', 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,