def main(serial_port): # Create and open the device ble_device = BleDevice(serial_port) ble_device.configure() ble_device.open() # Set up desired security parameters ble_device.client.security.set_security_params(passcode_pairing=False, bond=False, lesc_pairing=False, io_capabilities=IoCapabilities.DISPLAY_ONLY, out_of_band=False) ble_device.client.security.on_pairing_complete.register(on_client_pairing_complete) ble_device.client.security.on_passkey_display_required.register(on_passkey_display) ble_device.client.security.on_passkey_required.register(on_passkey_entry) ble_device.client.security.on_security_level_changed.register(on_security_level_changed) # Create and add the math service service = ble_device.database.add_service(constants.MATH_SERVICE_UUID) # Create and add the hex conversion characteristic to the service hex_conv_char = service.add_characteristic(constants.HEX_CONVERT_CHAR_UUID, constants.HEX_CONVERT_CHAR_PROPERTIES, "Test Data") # Register the callback for when a write occurs and subscription state changes hex_conv_char.on_write.register(on_hex_conversion_characteristic_write) hex_conv_char.on_subscription_change.register(on_gatts_subscription_state_changed) # Create and add the counting characteristic, initializing the data to [0, 0, 0, 0] counting_char = service.add_characteristic(constants.COUNTING_CHAR_UUID, constants.COUNTING_CHAR_PROPERTIES, [0]*4) counting_char.on_subscription_change.register(on_gatts_subscription_state_changed) # Create the thread for the counting characteristic counting_char_thread = CountingCharacteristicThread(counting_char) # Create and add the time service time_service = ble_device.database.add_service(constants.TIME_SERVICE_UUID) # Add the time characteristic and register the callback for when its read time_char = time_service.add_characteristic(constants.TIME_CHAR_UUID, constants.TIME_CHAR_PROPERTIES, "Time") time_char.on_read.register(on_time_char_read) # Initialize the advertising and scan response data adv_data = advertising.AdvertisingData(local_name=constants.PERIPHERAL_NAME, flags=0x06) scan_data = advertising.AdvertisingData(service_uuid128s=constants.TIME_SERVICE_UUID, has_more_uuid128_services=True) ble_device.advertiser.set_advertise_data(adv_data, scan_data) # Start advertising logger.info("Advertising") ble_device.client.on_connect.register(on_connect) ble_device.client.on_disconnect.register(on_disconnect) ble_device.advertiser.start(timeout_sec=0, auto_restart=True) # Create a waitable that will never fire, and wait for some time w = GenericWaitable() w.wait(60*30, exception_on_timeout=False) # Keep device active for 30 mins # Cleanup counting_char_thread.join() logger.info("Done") ble_device.close()
def main(serial_port): # Create and open te device ble_device = BleDevice(serial_port) ble_device.open() # Create and add the Device Info Service to the database dis = device_info.add_device_info_service(ble_device.database) # Set some characteristics in the DIS. The service only contains characteristics which # have values set. The other ones are not present dis.set_software_revision("14.2.1") dis.set_hardware_revision("A") dis.set_firmware_revision("1.0.4") dis.set_serial_number("AB1234") pnp_id = device_info.PnpId(device_info.PnpVendorSource.bluetooth_sig, 0x0058, 0x0002, 0x0013) dis.set_pnp_id(pnp_id) # Initiate the advertising data. Advertise the name and DIS service UUID name = "Peripheral DIS" adv_data = advertising.AdvertisingData(local_name=name, service_uuid16s=device_info.DIS_SERVICE_UUID) ble_device.advertiser.set_advertise_data(adv_data) # Start advertising logger.info("Advertising") ble_device.client.on_connect.register(on_connect) ble_device.client.on_disconnect.register(on_disconnect) ble_device.advertiser.start(timeout_sec=0, auto_restart=True) # Create a waitable that will never fire, and wait for some time w = GenericWaitable() w.wait(60*30, exception_on_timeout=False) # Keep device active for 30 mins # Cleanup logger.info("Done") ble_device.close()
def main(serial_port): # Create and open the device ble_device = BleDevice(serial_port) ble_device.open() # Create and add the current time service to the database. # Tweak the flags below to change how the service is set up current_time_service = current_time.add_current_time_service(ble_device.database, enable_writes=True, enable_local_time_info=True, enable_reference_info=False) # Register handlers for when the characteristics are written to. # These will only be triggered if enable_writes above is true current_time_service.on_current_time_write.register(on_current_time_write) current_time_service.on_local_time_info_write.register(on_local_time_info_write) # Demo of the different ways to manually or automatically control the reported time # Example 1: Automatically reference system time. # All logic is handled within the service and reports the time whenever the characteristic is read # Example 2: Manually report the time 1 day behind using callback method. # Register a user-defined callback to retrieve the current time to report back to the client # Example 3: Manually report the time 1 hour ahead by setting the base time # Set the characteristic's base time to 1 day ahead and allow the service to auto-increment from there example_mode = 1 if example_mode == 1: # configure_automatic() also sets up the Local Time characteristic (if enabled) # to just set the automatic time and leave Local Time unconfigured, use set_time() with no parameters current_time_service.configure_automatic() elif example_mode == 2: def on_time_read(): d = datetime.datetime.now() - datetime.timedelta(days=1) logger.info("Getting time: {}".format(d)) return d current_time_service.set_time(characteristic_read_callback=on_time_read) elif example_mode == 3: base_time = datetime.datetime.now() + datetime.timedelta(hours=1) current_time_service.set_time(base_time) # Register listeners for when the client connects and disconnects ble_device.client.on_connect.register(on_connect) ble_device.client.on_disconnect.register(on_disconnect) # Advertise the Current Time service adv_data = advertising.AdvertisingData(local_name="Current Time", flags=0x06, service_uuid16s=current_time.CURRENT_TIME_SERVICE_UUID) ble_device.advertiser.set_advertise_data(adv_data) logger.info("Advertising") ble_device.advertiser.start(timeout_sec=0, auto_restart=True) # Create a waitable that waits 5 minutes, then exits w = GenericWaitable() w.wait(5 * 60, exception_on_timeout=False) logger.info("Done") ble_device.close()
def main(serial_port): # Create and open the device ble_device = BleDevice(serial_port) ble_device.open() # Create a database to store the readings glucose_database = glucose.BasicGlucoseDatabase() # Add the service to the BLE database, using the glucose database just created, require encryption at the minimum service = glucose.add_glucose_service(ble_device.database, glucose_database, glucose.SecurityLevel.JUST_WORKS) # Set the features of this "glucose sensor" features = glucose.GlucoseFeatures( GlucoseFeatureType.low_battery_detection, GlucoseFeatureType.strip_insertion_error_detection) service.set_features(features) # Add some measurements to the glucose database add_fake_glucose_readings(glucose_database) # Register listeners for when the client connects and disconnects ble_device.client.on_connect.register(on_connect) ble_device.client.on_disconnect.register(on_disconnect) # Set the connection parameters for the client ble_device.client.set_connection_parameters(15, 30, 4000) # Set the function to display the passkey ble_device.client.security.on_passkey_display_required.register( display_passkey) # Set the security parameters for the client ble_device.client.security.set_security_params( passcode_pairing=False, bond=False, io_capabilities=IoCapabilities.DISPLAY_ONLY, out_of_band=False) # Advertise the Glucose service adv_data = advertising.AdvertisingData( local_name="Glucose Test", flags=0x06, service_uuid16s=glucose.GLUCOSE_SERVICE_UUID) ble_device.advertiser.set_advertise_data(adv_data) logger.info("Advertising") ble_device.advertiser.start(timeout_sec=0, auto_restart=True) # Create a waitable that will never fire, and wait for some time w = GenericWaitable() w.wait(60 * 30, exception_on_timeout=False) # Keep device active for 30 mins logger.info("Done") ble_device.close()
def main(serial_port): ble_device = BleDevice(serial_port) # Configure the BLE device to support MTU sizes which allow the max data length extension PDU size # Note this isn't 100% necessary as the default configuration sets the max to this value also ble_device.configure(att_mtu_max_size=MTU_SIZE_FOR_MAX_DLE) ble_device.open() # Create and add the Nordic UART service nus = nordic_uart.add_nordic_uart_service(ble_device.database) nus.on_data_received.register(on_data_rx) nus.on_write_complete.register(on_tx_complete) # Register listeners for when the client connects and disconnects ble_device.client.on_connect.register(on_connect) ble_device.client.on_disconnect.register(on_disconnect) ble_device.client.on_mtu_size_updated.register(on_mtu_size_update) # Configure the client to prefer the max MTU size ble_device.client.preferred_mtu_size = ble_device.max_mtu_size ble_device.client.set_connection_parameters(7.5, 15, 4000) # Advertise the service UUID adv_data = advertising.AdvertisingData(flags=0x06, local_name="Nordic UART Server") scan_data = advertising.AdvertisingData( service_uuid128s=nordic_uart.NORDIC_UART_SERVICE_UUID) ble_device.advertiser.set_advertise_data(adv_data, scan_data) logger.info("Advertising") ble_device.advertiser.start(timeout_sec=0, auto_restart=True) # Create a waitable that waits 5 minutes then exits w = GenericWaitable() try: w.wait(5 * 60, exception_on_timeout=False) except KeyboardInterrupt: pass finally: ble_device.close()
def main(serial_port): # Create and open the device ble_device = BleDevice(serial_port) ble_device.open() # Create and add the battery service to the database battery_service = battery.add_battery_service(ble_device.database, enable_notifications=True) battery_service.set_battery_level(100, False) # Register listeners for when the client connects and disconnects ble_device.client.on_connect.register(on_connect) ble_device.client.on_disconnect.register(on_disconnect) # Leaving security and connection parameters as defaults (don't care) # Advertise the Battery Service adv_data = advertising.AdvertisingData( local_name="Battery Test", flags=0x06, service_uuid16s=battery.BATTERY_SERVICE_UUID) ble_device.advertiser.set_advertise_data(adv_data) logger.info("Advertising") ble_device.advertiser.start(timeout_sec=0, auto_restart=True) battery_level = 100 battery_level_decrement_steps = 1 time_between_steps = 10 # Decrement the battery level until it runs out while battery_level >= 0: time.sleep(time_between_steps) battery_level -= battery_level_decrement_steps logger.info("Updating battery level to {}".format(battery_level)) battery_service.set_battery_level(battery_level) logger.info("Done") ble_device.close()
def main(serial_port): # Create and open the device ble_device = BleDevice(serial_port) ble_device.configure() ble_device.open() # Create the service service = ble_device.database.add_service( constants.DESC_EXAMPLE_SERVICE_UUID) # Create a characteristic and add some descriptors # NOTE: Some descriptors MUST be added during creation: SCCD, User Description, and Presentation Format # CCCD is added automatically based on the characteristic's Notify and Indicate properties # Define the User Description properties and make it writable # The simplest use-case in which the user description is read-only can provide just the first parameter user_desc_props = gatts.GattsUserDescriptionProperties( "UTC Time", write=True, security_level=smp.SecurityLevel.OPEN, max_length=20, variable_length=True) # Define the presentation format. Returning the time in seconds so set exponent to 0 presentation_format = PresentationFormat(fmt=Format.uint32, exponent=0, unit=Units.time_second) # Create the characteristic properties, including the SCCD, User Description, and Presentation Format char_props = gatts.GattsCharacteristicProperties( read=True, write=False, notify=True, max_length=Uint32.byte_count, variable_length=False, sccd=True, user_description=user_desc_props, presentation_format=presentation_format) char = service.add_characteristic(constants.DESC_EXAMPLE_CHAR_UUID, char_props, Uint32.encode(0)) char.on_read.register(on_read) # Add another descriptor to the list char_range_value = Uint32.encode(5555) + Uint32.encode(2**32 - 1000) desc_props = GattsAttributeProperties(read=True, write=False, variable_length=False, max_length=len(char_range_value)) char.add_descriptor(DescriptorUuid.valid_range, desc_props, char_range_value) # Initialize the advertising and scan response data adv_data = advertising.AdvertisingData( local_name=constants.PERIPHERAL_NAME, flags=0x06) scan_data = advertising.AdvertisingData( service_uuid128s=constants.DESC_EXAMPLE_SERVICE_UUID, has_more_uuid128_services=False) ble_device.advertiser.set_advertise_data(adv_data, scan_data) # Start advertising logger.info("Advertising") ble_device.client.on_connect.register(on_connect) ble_device.client.on_disconnect.register(on_disconnect) ble_device.advertiser.start(timeout_sec=0, auto_restart=True) # Create a waitable that will never fire, and wait for some time w = GenericWaitable() w.wait(60 * 30, exception_on_timeout=False) # Keep device active for 30 mins logger.info("Done") ble_device.close()