def isOwnerNearby(self): ''' Logic here checks if a known BLE device is broadcasting nearby. If they are, return true. Else, return false ''' # TODO remove return False bt = Bluetooth() bt.start_scan(ConfigBluetooth.SCAN_ALLOW_TIME) # Scans for 10 seconds while bt.isscanning(): adv = bt.get_adv() if adv and binascii.hexlify(adv.mac) == ConfigBluetooth.MAC_ADDR: try: if self.debug: print("Owner device found: {} Mac addr {}".format( bt.resolve_adv_data(adv.data, Bluetooth.ADV_NAME_CMPL), ConfigBluetooth.MAC_ADDR)) conn = bt.connect(adv.mac) time.sleep(0.05) conn.disconnect() bt.stop_scan() except Exception: bt.stop_scan() return True time.sleep(0.050) return False
def initConnection(address): pycom.rgbled(0xffff00) pycom.heartbeat(False) bluetooth = Bluetooth() bluetooth.start_scan(-1) bluetooth.init() while True: print("starting bluetooth") global connection devices = bluetooth.get_advertisements() try: if devices is not None and len(devices) > 0: for device in devices: uuid = ubinascii.hexlify(device.mac) if (str(uuid) == address): print("foud the arduino") connection = bluetooth.connect(device.mac) print(device) bluetooth.stop_scan() global char char = getBleChar() pycom.rgbled(0x00ff00) return device except: print("arduino refused connection trying again") pycom.heartbeat(True) closeConnection() continue time.sleep(0.05) pycom.rgbled(0xff0000) return None
def isBTDeviceNearby(): bt = Bluetooth() while True: print("Scanning for owner BT device nearby...") bt.start_scan(10) # Scans for 10 seconds while bt.isscanning(): adv = bt.get_adv() if adv and binascii.hexlify(adv.mac) == ConfigBluetooth.MAC_ADDR: try: print("Owner device found: {} Mac addr {}".format( bt.resolve_adv_data(adv.data, Bluetooth.ADV_NAME_CMPL), ConfigBluetooth.MAC_ADDR)) conn = bt.connect(adv.mac) time.sleep(0.05) conn.disconnect() bt.stop_scan() except Exception as e: print("Exception {}".format(e)) bt.stop_scan() break else: time.sleep(0.050)
if adv: print('data %s' % bt.resolve_adv_data(adv.data, bt.ADV_NAME_CMPL)) print('data %s' % bt.resolve_adv_data(adv.data, bt.ADV_NAME_SHORT)) print('data %s' % bt.resolve_adv_data(adv.data, bt.ADV_FLAG)) print('data %s' % bt.resolve_adv_data(adv.data, bt.ADV_16SRV_PART)) print('data %s' % bt.resolve_adv_data(adv.data, bt.ADV_T16SRV_CMPL)) print('data %s' % bt.resolve_adv_data(adv.data, bt.ADV_32SRV_PART)) print('data %s' % bt.resolve_adv_data(adv.data, bt.ADV_32SRV_CMPL)) print('data %s' % bt.resolve_adv_data(adv.data, bt.ADV_128SRV_PART)) print('data %s' % bt.resolve_adv_data(adv.data, bt.ADV_128SRV_CMPL)) print('data %s' % bt.resolve_adv_data(adv.data, bt.ADV_TX_PWR)) time.sleep(4) if adv and bt.resolve_adv_data(adv.data, Bluetooth.ADV_NAME_CMPL) == 'Heart Rate': conn = bt.connect(adv.mac) services = conn.services() for service in services: time.sleep(0.050) if type(service.uuid()) == bytes: print('Reading chars from service = {}'.format(service.uuid())) else: print('Reading chars from service = %x' % service.uuid()) chars = service.characteristics() for char in chars: if (char.properties() & Bluetooth.PROP_READ): print('char {} value = {}'.format(char.uuid(), char.read())) conn.disconnect() break else:
from machine import RTC bluetooth = Bluetooth() bluetooth.set_advertisement(name="lopy2", manufacturer_data="lopy_v2") bluetooth.start_scan( -1) #Change to 10 to have it searching for 10 sec instead if forever #bluetooth.stop_scan() adv = None bluetooth.advertise(True) while True: adv = bluetooth.get_adv() if adv and bluetooth.resolve_adv_data(adv.data, Bluetooth.ADV_NAME_CMPL) == 'lopy1': try: bluetooth.connect(adv.mac) print( bluetooth.resolve_adv_data(adv.data, Bluetooth.ADV_APPEARANCE)) print("Connected to device with addr = {}".format( binascii.hexlify(adv.mac))) #bluetooth.connect(adv.mac) pycom.heartbeat(False) for cycles in range(1): # stop after 1 cycles pycom.rgbled(0x000080) # blue time.sleep(0.5) pycom.rgbled(0x000000) # blue time.sleep(0.5) pycom.rgbled(0x000080) # blue time.sleep(0.5)
def BLEAndLoRaFun(): ###### First, initialize as one LoRa node device ###### # initialize LoRa in LORAWAN mode. # Please pick the region that matches where you are using the device: # Asia = LoRa.AS923 # Australia = LoRa.AU915 # Europe = LoRa.EU868 # United States = LoRa.US915 lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.US915) # create an ABP authentication params dev_addr = struct.unpack(">l", binascii.unhexlify('26021A14'))[0] nwk_swkey = binascii.unhexlify('BB515D851353D2AB5ACCD112F0F2C597') app_swkey = binascii.unhexlify('B74092CB7C5A79CAD681C384ABF925D2') # remove all the channels for channel in range(0, 72): lora.remove_channel(channel) # set all channels to the same frequency (must be before sending the OTAA join request) for channel in range(0, 72): lora.add_channel(channel, frequency=config.LORA_FREQUENCY, dr_min=0, dr_max=3) # join a network using ABP (Activation By Personalization) lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey)) # create a LoRa socket s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) # set the LoRaWAN data rate s.setsockopt(socket.SOL_LORA, socket.SO_DR, 3) # last parameter is 3 # make the socket non-blocking s.setblocking(False) ''' ###### Second, set up BLE server service ###### pycom.heartbeat(False) bluetooth = Bluetooth() #create a bluetooth object bluetooth.set_advertisement(name='LoPyServer'+str(globalvar.device_id), service_uuid=b'3333333333333333') #using callback conn_cb to check client's connection ##Function: conn_cb(callback for bluetooth object events checking) ##Description:check there is any client connected to the service def conn_cb (bt_o): events = bt_o.events()#using events to check if there is any client connected to the service if events & Bluetooth.CLIENT_CONNECTED: print("Client connected") pycom.rgbled(0x007f00) # green elif events & Bluetooth.CLIENT_DISCONNECTED: bt_o.disconnect_client() print("Client disconnected") pycom.rgbled(0x7f0000) # red time.sleep(3) bluetooth.callback(trigger=Bluetooth.CLIENT_CONNECTED | Bluetooth.CLIENT_DISCONNECTED, handler=conn_cb) bluetooth.advertise(True) #set up BLE service srv1 = bluetooth.service(uuid=b'3333333333333333', isprimary=True) #set up service character chr1 = srv1.characteristic(uuid=b'3333333333333333', value=5) #char1_read_counter = 0 def char1_cb_handler(chr): #global char1_read_counter #char1_read_counter += 1 global BLEConnectionCounter events = chr.events() if events & Bluetooth.CHAR_WRITE_EVENT: print("Write request with value = {}".format(chr.value())) else: #modify here to send its device_id to other clients BLEConnectionCounter += 1 return str(globalvar.device_id)+' '+str(BLEConnectionCounter) #using the callback to send the data to other clients char1_cb = chr1.callback(trigger=Bluetooth.CHAR_WRITE_EVENT | Bluetooth.CHAR_READ_EVENT, handler=char1_cb_handler) ''' ###### Third, set up BLE client service ###### bluetooth_client = Bluetooth() #bluetooth_client.init(id=0, mode=Bluetooth.BLE, antenna=None) bluetooth_client.start_scan(10) #server_name1 = bluetooth_client.resolve_adv_data(adv.data, Bluetooth.ADV_NAME_CMPL) counter = 50 #while True: while counter > 0: print(counter) counter -= 1 #Gets an named tuple with the advertisement data received during the scanning. #The structure is (mac, addr_type, adv_type, rssi, data) adv = bluetooth_client.get_adv() #servermac = ''#save the serer mac #use resolve_adv_data to resolve the 31 bytes of the advertisement message #Here is problem: when disconnect from server, then adv will always be null... #if get a valid advertisement from one server if adv: server_name = bluetooth_client.resolve_adv_data( adv.data, Bluetooth.ADV_NAME_CMPL) #print(server_name) if checkValidServer(server_name): try: #Opens a BLE connection with the device specified by the mac_addr argument #This function blocks until the connection succeeds or fails. #print(adv.mac) #global servermac#change servermac to global #servermac = adv.mac #counter += 1 conn = bluetooth_client.connect(adv.mac) #print('connected?',conn.isconnected()) services = conn.services() #print('This is service',services) #print(services) #Yunwei - it seems that only when the type of uuid is bytes then could read the data from server for service in services: time.sleep(0.050) if type(service.uuid()) == bytes: chars = service.characteristics() for char in chars: #check if the character properties is PROP_READ properties = char.properties() print('char properties is ' + str(properties)) if (properties & Bluetooth.PROP_READ): print('char {} value = {}'.format( char.uuid(), char.read())) #Use LoRa to send the data out #s.send(char.read()) time.sleep(2) #10 & Bluetooth.PROP_WRITE #10&Bluetooth.PROP_READ if (properties & Bluetooth.PROP_WRITE): print('write to server!') char.write(b'x02') time.sleep(2) #Yunwei conn.disconnect() #bluetooth_client.deinit() bluetooth_client.stop_scan() time.sleep(3) bluetooth_client.deinit() print('deinit') time.sleep(3) bluetooth_client.init() #if(bluetooth_client.isscanning()): # bluetooth_client.stop_scan() #bluetooth_client.deinit() bluetooth_client.start_scan(10) print('connected?', conn.isconnected()) #break time.sleep(3) gc.collect() #if it's still scan, then need to stop scan first #bluetooth_client.start_scan(-1) ''' if(bluetooth_client.isscanning()): bluetooth_client.stop_scan() #then scan again bluetooth_client.start_scan(-1) ''' except: print( "Error while connecting or reading from the BLE device" ) #break time.sleep(1) if (bluetooth_client.isscanning()): bluetooth_client.stop_scan() bluetooth_client.deinit() time.sleep(1) bluetooth_client.deinit() time.sleep(1) #init again bluetooth_client.init(id=0, mode=Bluetooth.BLE, antenna=None) bluetooth_client.start_scan(10) else: bluetooth_client.deinit() time.sleep(1) bluetooth_client.init() time.sleep(1) bluetooth_client.start_scan(10) print('Scan again') else: print('adv is None!') time.sleep(3) ''' time.sleep(3) #if it's still scan, then need to stop scan first if(bluetooth_client.isscanning()): bluetooth_client.stop_scan() #then scan again bluetooth_client.start_scan(-1) ''' #bluetooth_client.stop_scan() bluetooth_client.stop_scan() bluetooth_client.deinit() print('out of loop!')
def BLEClient(): #Description: check if the BLE server is set up by another LoPy #Note: for convention reason, the LoPy server name will be "LoPyServer"+device_id def checkValidServer(server_name): if (server_name == None): return False else: #check if server_name contains "LoPyServer" if (re.match('LoPyServer*', server_name)): return True else: return False global rec_msg ###### Third, set up BLE client service ###### bluetooth_client = Bluetooth() bluetooth_client.start_scan(10) #server_name1 = bluetooth_client.resolve_adv_data(adv.data, Bluetooth.ADV_NAME_CMPL) counter = 50 #while True: while counter > 0: #Gets an named tuple with the advertisement data received during the scanning. #The structure is (mac, addr_type, adv_type, rssi, data) adv = bluetooth_client.get_adv() #servermac = ''#save the serer mac #use resolve_adv_data to resolve the 31 bytes of the advertisement message #Here is problem: when disconnect from server, then adv will always be null... #if get a valid advertisement from one server if adv: server_name = bluetooth_client.resolve_adv_data( adv.data, Bluetooth.ADV_NAME_CMPL) #print(server_name) if checkValidServer(server_name): try: #Opens a BLE connection with the device specified by the mac_addr argument #This function blocks until the connection succeeds or fails. #print(adv.mac) #global servermac#change servermac to global #servermac = adv.mac #counter += 1 conn = bluetooth_client.connect(adv.mac) #print('connected?',conn.isconnected()) services = conn.services() #print('This is service',services) #print(services) #Yunwei - it seems that only when the type of uuid is bytes then could read the data from server for service in services: time.sleep(0.050) if type(service.uuid()) == bytes: chars = service.characteristics() for char in chars: #check if the character properties is PROP_READ if (char.properties() & Bluetooth.PROP_READ): print('char {} value = {}'.format( char.uuid(), char.read())) #create lora msg rec_msg = str(char.read()) counter -= 1 #Use LoRa to send the data out #s.send(char.read()) time.sleep(5) #Yunwei conn.disconnect() print('connected?', conn.isconnected()) #break time.sleep(3) gc.collect() bluetooth_client.start_scan(10) except: print( "Error while connecting or reading from the BLE device" ) #break time.sleep(1) if (bluetooth_client.isscanning()): bluetooth_client.stop_scan() bluetooth_client.deinit() time.sleep(1) bluetooth_client.init() time.sleep(1) #init again #bluetooth_client.init(id=0, mode=Bluetooth.BLE, antenna=None) bluetooth_client.start_scan(10) else: bluetooth_client.deinit() time.sleep(1) bluetooth_client.init() time.sleep(1) bluetooth_client.start_scan(10) bluetooth_client.stop_scan() bluetooth_client.deinit()
class BluetoothApi: """Many examples integrated from https://microchipdeveloper.com/wireless:ble-gatt-data-organization https://development.pycom.io/firmwareapi/pycom/network/bluetooth/ https://github.com/sandeepmistry/arduino-BLEPeripheral https://github.com/kriswiner/nRF52832DevBoard/blob/master/BMP280_nRF52.ino https://forum.pycom.io/topic/2826/how-to-send-data-to-characteristic-over-ble/17 """ def __init__(self): self.bt = None def start(self): """ """ print('Starting Bluetooth') self.bt = Bluetooth() # Default #self.bt.init(id=0, mode=Bluetooth.BLE, antenna=Bluetooth.INT_ANT, modem_sleep=True) #self.bt.init(id=0, antenna=Bluetooth.INT_ANT, modem_sleep=False) self.bt.init(modem_sleep=False) return print('Entering main loop') while True: print('--- loop ---') adv = self.bt.get_adv() print('adv:', adv) # Give the system some breath. print('machine.idle()') machine.idle() utime.sleep(10.0) continue def scan(self, duration): """ :param duration: """ duration = int(duration) print('Starting Bluetooth scan for {} seconds'.format(duration)) self.bt.start_scan(duration) while self.bt.isscanning(): #print('is-scanning') adv = self.bt.get_adv() if adv: # try to get the complete name name_short = self.bt.resolve_adv_data(adv.data, Bluetooth.ADV_NAME_SHORT) name_complete = self.bt.resolve_adv_data( adv.data, Bluetooth.ADV_NAME_CMPL) print('names:', name_short, name_complete) service_data = self.bt.resolve_adv_data( adv.data, Bluetooth.ADV_SERVICE_DATA) print('service_data:', service_data) mfg_data = self.bt.resolve_adv_data( adv.data, Bluetooth.ADV_MANUFACTURER_DATA) if mfg_data: # try to get the manufacturer data (Apple's iBeacon data is sent here) data = ubinascii.hexlify(mfg_data) print('data:', data) print('Bluetooth scanning stopped') def find_heart_rate(self): """ """ adv = self.bt.get_adv() if adv and self.bt.resolve_adv_data( adv.data, Bluetooth.ADV_NAME_CMPL) == 'Heart Rate': try: conn = self.bt.connect(adv.mac, timeout=5000) services = conn.services() for service in services: utime.sleep(0.050) if type(service.uuid()) == bytes: print('Reading chars from service = {}'.format( service.uuid())) else: print('Reading chars from service = %x' % service.uuid()) chars = service.characteristics() for char in chars: if (char.properties() & Bluetooth.PROP_READ): print('char {} value = {}'.format( char.uuid(), char.read())) conn.disconnect() except: print("Error while connecting or reading from the BLE device") else: utime.sleep(0.050) utime.sleep(10.0) def advertise(self): """https://development.pycom.io/firmwareapi/pycom/network/bluetooth/""" device_name = get_device_name() print('Advertising device {}'.format(device_name)) # TODO: Get from settings self.bt.set_advertisement(name=device_name, service_uuid=b'1234567890123456') def conn_cb(bt_o): """ :param bt_o: """ print("Callback happened") # Returns flags and clear internal registry events = bt_o.events() if events & Bluetooth.CLIENT_CONNECTED: print("Client connected:", events) elif events & Bluetooth.CLIENT_DISCONNECTED: print("Client disconnected") self.bt.callback(trigger=Bluetooth.CLIENT_CONNECTED | Bluetooth.CLIENT_DISCONNECTED, handler=conn_cb) self.bt.advertise(True) def start_service(self): """https://development.pycom.io/firmwareapi/pycom/network/bluetooth/gattsservice/ https://development.pycom.io/firmwareapi/pycom/network/bluetooth/gattscharacteristic/ https://www.bluetooth.com/specifications/gatt/characteristics/ https://docs.python.org/3/library/struct.html The format field determines how a single value contained in the Characteristic Value is formatted. The information contained on this page is referenced in Bluetooth® Core Specification Volume 3, Part G, Section 3.3.3.5.2. https://www.bluetooth.com/specifications/assigned-numbers/format-types/ """ print('Starting service') # A. Battery Service # UUID: 180F # Abstract: The Battery Service exposes the state of a battery within a device # https://github.com/oesmith/gatt-xml/blob/master/org.bluetooth.service.battery_service.xml battery = self.bt.service(uuid=0x180F, isprimary=True, nbr_chars=1, start=True) # Battery Level # UUID: 2A19 # Abstract: The current charge level of a battery. # 100% represents fully charged while 0% represents fully discharged # Format: uint8 # https://github.com/oesmith/gatt-xml/blob/master/org.bluetooth.characteristic.battery_level.xml battery_level = battery.characteristic(uuid=0x2A19, value=78) # B. Environmental Sensing Service (ESS) # https://github.com/oesmith/gatt-xml/blob/master/org.bluetooth.service.environmental_sensing.xml # https://www.bluetooth.com/specifications/assigned-numbers/environmental-sensing-service-characteristics/ # https://github.com/sandeepmistry/arduino-BLEPeripheral/issues/215 # https://github.com/sandeepmistry/arduino-nRF5/issues/248 environment = self.bt.service(uuid=0x181A, isprimary=True, nbr_chars=5, start=True) # Temperature # UUID: 2A6E # InformativeText: Unit is in degrees Celsius with a resolution of 0.01 degrees Celsius # Format: sint16 # https://github.com/oesmith/gatt-xml/blob/master/org.bluetooth.characteristic.temperature.xml # https://github.com/oesmith/gatt-xml/blob/master/org.bluetooth.characteristic.temperature_measurement.xml # https://github.com/oesmith/gatt-xml/blob/master/org.bluetooth.characteristic.temperature_type.xml # https://github.com/ARMmbed/ble/blob/master/ble/services/HealthThermometerService.h # https://github.com/ARMmbed/ble/blob/master/ble/services/EnvironmentalService.h # Temperature Celsius # UUID: 2A1F # Format: sint16 # https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Characteristics/org.bluetooth.characteristic.temperature_celsius.xml self.temp = 42.42 temperature = environment.characteristic(uuid=0x2A1F) def temp_getter(chr): """ :param chr: """ print('Getting characteristic:', chr) value = sint16(self.temp * 10) print('Value:', value) self.temp += 1 return value print('Adding characteristic callback') temperature_callback = temperature.callback( trigger=Bluetooth.CHAR_READ_EVENT, handler=temp_getter) # Temperature Measurement # UUID: 2A1C # Format: Variable length structure # Value Format: FLOAT (IEEE-11073 32-bit FLOAT) # Abstract: The Temperature Measurement characteristic is a variable length structure # containing a Flags field, a Temperature Measurement Value field and, based upon the # contents of the Flags field, optionally a Time Stamp field and/or a Temperature Type field. # https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Characteristics/org.bluetooth.characteristic.temperature_measurement.xml print('Adding Temperature Measurement') temperature_measurement = environment.characteristic( uuid=0x2A1C, value=encode_temperature_2a1c(42.428423)) # Scientific Temperature # UUID: 2A3C # Format: float64 (IEEE-754 64-bit floating point) # https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Characteristics/org.bluetooth.characteristic.scientific_temperature_celsius.xml # http://forum.espruino.com/conversations/306536/ # https://stackoverflow.com/questions/36655172/how-to-read-a-ble-characteristic-float-in-swift # For the 'f', 'd' and 'e' conversion codes, the packed representation uses the IEEE 754 # binary32, binary64 or binary16 format (for 'f', 'd' or 'e' respectively), regardless of # the floating-point format used by the platform. # https://docs.python.org/3/library/struct.html #print('Adding Scientific Measurement') #temperature_sci = environment.characteristic(uuid=0x2A3C, value=float64(42.42)) # Humidity # UUID: 2A6F # InformativeText: Unit is in percent with a resolution of 0.01 percent # Format: uint16 # https://github.com/oesmith/gatt-xml/blob/master/org.bluetooth.characteristic.humidity.xml humidity1 = environment.characteristic(uuid=0x2A6F, value=uint16(86.86 * 100)) humidity2 = environment.characteristic(uuid=0x2A6F, value=uint16(50.55 * 100)) # Pressure # UUID: 2A6D # InformativeText: Unit is in pascals with a resolution of 0.1 Pa # Format: uint32 # https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Characteristics/org.bluetooth.characteristic.pressure.xml # Weight # UUID: 2A98 # InformativeText: Unit is in kilograms with a resolution of 0.005 # Format: uint16 # https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Characteristics/org.bluetooth.characteristic.weight.xml # https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Characteristics/org.bluetooth.characteristic.weight_measurement.xml # https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Characteristics/org.bluetooth.characteristic.weight_scale_feature.xml # https://github.com/oesmith/gatt-xml/blob/master/org.bluetooth.characteristic.weight.xml # https://github.com/oesmith/gatt-xml/blob/master/org.bluetooth.characteristic.weight_measurement.xml # https://github.com/oesmith/gatt-xml/blob/master/org.bluetooth.characteristic.weight_scale_feature.xml weight = environment.characteristic(uuid=0x2A98, value=uint16(25.44 * 2 * 100)) # GPS # https://forum.pycom.io/topic/5012/can-only-see-value-of-first-gatt-characteristic """ lan = bt.service(0x1819, nbr_chars=3) # 0.001 precision lan.characteristic(uuid=0x2AAE, value=int(gps.lat * 1000)) lan.characteristic(uuid=0x2AAF, value=int(gps.lon * 1000)) lan.characteristic(uuid=0x2AB3, value=int(gps.alt * 1000)) """ # Generic Access # UUID: 1800 # Abstract: The generic_access service contains generic information # about the device. All available Characteristics are readonly. # https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Services/org.bluetooth.service.generic_access.xml # Generic Attribute Service # UUID: 1801 # https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Services/org.bluetooth.service.generic_attribute.xml # String Characteristic # UUID: 2A3D # A generic UTF8 string which may be used in Services requiring strings. # https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Characteristics/org.bluetooth.characteristic.string.xml srv1 = self.bt.service(uuid=BluetoothUuid.to_bytes_le( '15ECCA29-0B6E-40B3-9181-BE9509B53200'), isprimary=True, nbr_chars=2, start=True) #generic_attribute = self.bt.service(uuid=0x1800, isprimary=True, nbr_chars=2, start=True) #wifi_ssid = generic_attribute.characteristic(uuid=0x2A3D, properties=Bluetooth.PROP_BROADCAST | Bluetooth.PROP_INDICATE | Bluetooth.PROP_NOTIFY | Bluetooth.PROP_READ | Bluetooth.PROP_WRITE, value="default") #wifi_ssid = generic_attribute.characteristic(uuid=0x2A3D, properties=Bluetooth.PROP_NOTIFY | Bluetooth.PROP_READ | Bluetooth.PROP_WRITE, value="default") wifi_ssid = srv1.characteristic(uuid=0x2A3D) #wifi_password = generic_attribute.characteristic(uuid=0x2A3D, properties=Bluetooth.PROP_READ | Bluetooth.PROP_WRITE) #print('wifi_ssid:', wifi_ssid, dir(wifi_ssid)) #cfg = wifi_ssid.config() #print('cfg:', cfg) #wifi_ssid.config(name='hallodri') print('wifi_ssid:', wifi_ssid) print('wifi_ssid:', dir(wifi_ssid)) def wifi_callback(characteristic): """ :param characteristic: """ print('Characteristic callback:', characteristic) #print('attr_obj:', characteristic.attr_obj) events = characteristic.events() if events & Bluetooth.CHAR_WRITE_EVENT: print("Write request with value = {}".format( characteristic.value())) else: pass value = characteristic.value() print('Reading characteristic:', value) print('Adding characteristic callback') wifi_ssid_callback = wifi_ssid.callback( trigger=Bluetooth.CHAR_READ_EVENT | Bluetooth.CHAR_WRITE_EVENT, handler=wifi_callback) #wifi_password_callback = wifi_password.callback(trigger=Bluetooth.CHAR_READ_EVENT | Bluetooth.CHAR_WRITE_EVENT, handler=wifi_callback) #print('instance:', wifi_ssid.instance()) # Characteristic User Description # UUID: 0x2901,0x2902 print(wifi_ssid_callback) print(dir(wifi_ssid_callback)) srv1.characteristic(uuid=0x2901, value="hello world 1")
class MoveHub(object): def __init__(self, address): self.address = address self.conn = None self.last_color_C = '' self.last_color_D = '' self.last_distance_C = '' self.last_distance_D = '' self.last_brightness_C = 0 self.last_brightness_D = 0 self.last_angle_A = '' self.last_angle_B = '' self.last_angle_C = '' self.last_angle_D = '' self.last_angle_AB = '' self.last_button = '' self.last_hubtilt = 6 self.devicename = '' self.wqueue = [] self.is_subscribe = False def start(self): self.ble = Bluetooth() self.conn = self.ble.connect(self.address) while not self.conn.isconnected(): sleep_ms(100) sleep_ms(2000) self.svcs = self.conn.services() self.chars = self.svcs[2].characteristics() self.devicename = self.svcs[1].characteristics()[0].read().decode( 'utf-8') def stop(self): if self.conn is not None: if self.conn.isconnected(): self.conn.disconnect() self.conn = None def is_connected(self): if self.conn is not None: return self.conn.isconnected() return False def gat_address(self): return self.address def get_name(self): return self.devicename def set_hublight(self, color): command = SET_LED_INI command += bytes([LED_COLORS.index(color)]) self._write(command) def run_motor_for_time(self, motor, time_ms, dutycycle_pct): if motor in MOTORS: if dutycycle_pct in range(-100, 101): command = MOTOR_TIMED_INI command += motor command += MOTOR_TIMED_MID t = bytes((time_ms & 0xff, (time_ms >> 8) & 0xff)) command += t if dutycycle_pct < 0: dutycycle_pct += 255 command += bytes([dutycycle_pct]) command += MOTOR_TIMED_END self._write(command) def run_motors_for_time(self, motor, time_ms, dutycycle_pct_a, dutycycle_pct_b): if motor in MOTOR_PAIRS: if (dutycycle_pct_a in range(-100, 101) and dutycycle_pct_b in range(-100, 101)): command = MOTORS_TIMED_INI command += motor command += MOTORS_TIMED_MID t = bytes((time_ms & 0xff, (time_ms >> 8) & 0xff)) command += t if dutycycle_pct_a < 0: dutycycle_pct_a += 255 command += bytes([dutycycle_pct_a]) if dutycycle_pct_b < 0: dutycycle_pct_b += 255 command += bytes([dutycycle_pct_b]) command += MOTORS_TIMED_END self._write(command) def run_motor_for_angle(self, motor, angle, dutycycle_pct): if motor in MOTORS: if dutycycle_pct in range(-100, 101): command = MOTOR_ANGLE_INI command += motor command += MOTOR_ANGLE_MID ang = bytes((angle & 0xff, (angle >> 8) & 0xff, (angle >> 16) & 0xff, (angle >> 24) & 0xff)) command += ang if dutycycle_pct < 0: dutycycle_pct += 255 command += bytes([dutycycle_pct]) command += MOTOR_ANGLE_END self._write(command) def run_motors_for_angle(self, motor, angle, dutycycle_pct_a, dutycycle_pct_b): if motor in MOTORS: if (dutycycle_pct_a in range(-100, 101) and dutycycle_pct_b in range(-100, 101)): command = MOTORS_ANGLE_INI command += motor command += MOTORS_ANGLE_MID ang = bytes((angle & 0xff, (angle >> 8) & 0xff, (angle >> 16) & 0xff, (angle >> 24) & 0xff)) command += ang if dutycycle_pct_a < 0: dutycycle_pct_a += 255 command += bytes([dutycycle_pct_a]) if dutycycle_pct_b < 0: dutycycle_pct_b += 255 command += bytes([dutycycle_pct_b]) command += MOTORS_ANGLE_END self._write(command) @staticmethod def parse_notifications(self): if len(self.wqueue) > 0: command = self.wqueue.pop(0) self.chars[0].write(command) value = self.chars[0].read() if value is None or len(value) < 5: return #bstr = '' #for i in range(len(value)): # bstr += hex(value[i]) + ' ' #print('value:', bstr) if value[0] == 0x08 and value[1] == 0x00 and value[2] == 0x45: if value[3] == PORT_A: self.last_angle_A = (value[4] + value[5] * 256 + value[6] * 65536 + value[7] * 16777216) if self.last_angle_A > ENCODER_MID: self.last_angle_A = self.last_angle_A - ENCODER_MAX elif value[3] == PORT_B: self.last_angle_B = (value[4] + value[5] * 256 + value[6] * 65536 + value[7] * 16777216) if self.last_angle_B > ENCODER_MID: self.last_angle_B = self.last_angle_B - ENCODER_MAX elif value[3] == PORT_C: if self._port_C_is == TYPE_COLORDISTANCE: if value[4] != 0xFF: self.last_color_C = COLOR_SENSOR_COLORS[value[4]] self.last_brightness_C = value[7] self.last_distance_C = '' else: self.last_color_C = '' self.last_brightness_C = 0 self.last_distance_C = value[5] elif self._port_C_is == TYPE_ENCODERMOTOR: self.last_angle_C = (value[4] + value[5] * 256 + value[6] * 65536 + value[7] * 16777216) if self.last_angle_C > ENCODER_MID: self.last_angle_C = (self.last_angle_C - ENCODER_MAX) elif value[3] == PORT_D: if self._port_D_is == TYPE_COLORDISTANCE: if value[4] != 0xFF: self.last_color_D = COLOR_SENSOR_COLORS[value[4]] self.last_brightness_D = value[7] self.last_distance_D = '' else: self.last_color_D = '' self.last_brightness_D = 0 self.last_distance_D = value[5] elif self._port_D_is == TYPE_ENCODERMOTOR: self.last_angle_D = (value[4] + value[5] * 256 + value[6] * 65536 + value[7] * 16777216) if self.last_angle_D > ENCODER_MID: self.last_angle_D = (self.last_angle_D - ENCODER_MAX) elif value[3] == MOTOR_AB: pass elif (value[0] == 0x06 and value[1] == 0x00 and value[2] == 0x01 and value[3] == 0x02 and value[4] == 0x06): if value[5] == 1: self.last_button = BUTTON_PRESSED elif value[5] == 0: self.last_button = BUTTON_RELEASED else: self.last_button = '' elif (value[0] == 0x05 and value[1] == 0x00 and value[2] == 0x45 and value[3] == 0x3a): if value[4] in range(6): self.last_hubtilt = value[4] else: self.last_hubtilt = 6 print('Tilt: Unknown value') def subscribe_all(self): self.chars[0].callback(Bluetooth.CHAR_NOTIFY_EVENT, MoveHub.parse_notifications, self) self.is_subscribe = True def listen_colordist_sensor(self, port): if port in [PORT_C, PORT_D]: command = LISTEN_INI command += bytes([port]) command += MODE_COLORDIST_SENSOR command += LISTEN_END if port == PORT_C: self._port_C_is = TYPE_COLORDISTANCE else: self._port_D_is = TYPE_COLORDISTANCE self.chars[0].write(command) def listen_angle_sensor(self, port): if port in [PORT_A, PORT_B, PORT_C, PORT_D]: command = LISTEN_INI command += bytes([port]) command += MODE_ENCODER command += LISTEN_END if port == PORT_C: self._port_C_is = TYPE_ENCODERMOTOR elif port == PORT_D: self._port_D_is = TYPE_ENCODERMOTOR self.chars[0].write(command) def listen_button(self): self.chars[0].write(LISTEN_BUTTON) def listen_hubtilt(self, mode): if mode in [MODE_HUBTILT_BASIC, MODE_HUBTILT_FULL]: command = LISTEN_INI command += bytes([PORT_TILT]) command += mode command += LISTEN_END self.chars[0].write(command) def _write(self, command): if self.is_subscribe: self.wqueue.append(command) else: self.chars[0].write(command)
import time bt = Bluetooth() bt.start_scan(-1) while True: adv = bt.get_adv() if adv # try to get the complete name print(bluetooth.resolve_adv_data(adv.data, Bluetooth.ADV_NAME_CMPL)) # try to get the manufacturer data (Apple's iBeacon data is sent here) print(binascii.hexlify(bluetooth.resolve_adv_data(adv.data, Bluetooth.ADV_MANUFACTURER_DATA))) if bt.resolve_adv_data(adv.data, Bluetooth.ADV_NAME_CMPL) == 'Heart Rate': conn = bt.connect(adv.mac) services = conn.services() for service in services: time.sleep(0.050) if type(service.uuid()) == bytes: print('Reading chars from service = {}'.format(service.uuid())) else: print('Reading chars from service = %x' % service.uuid()) chars = service.characteristics() for char in chars: if (char.properties() & Bluetooth.PROP_READ): print('char {} value = {}'.format(char.uuid(), char.read())) conn.disconnect() break else: time.sleep(0.050)
def BlueToothFun(): ''' #Firstly,act as a server pycom.heartbeat(False) bluetooth = Bluetooth() #create a bluetooth object bluetooth.set_advertisement(name='LoPyServer2', service_uuid=b'1234567890123456') #id for this device deviceID = 222 #using callback conn_cb to check client's connection ##Function: conn_cb(callback for bluetooth object events checking) ##Description:check there is any client connected to the service def conn_cb (bt_o): events = bt_o.events()#using events to check if there is any client connected to the service if events & Bluetooth.CLIENT_CONNECTED: print("Client connected") pycom.rgbled(0x007f00) # green elif events & Bluetooth.CLIENT_DISCONNECTED: print("Client disconnected") pycom.rgbled(0x7f0000) # red bluetooth.callback(trigger=Bluetooth.CLIENT_CONNECTED | Bluetooth.CLIENT_DISCONNECTED, handler=conn_cb) # bluetooth.advertise(True) srv1 = bluetooth.service(uuid=b'1234567890123456', isprimary=True) chr1 = srv1.characteristic(uuid=b'ab34567890123456', value=5) #char1_read_counter = 0 def char1_cb_handler(chr): #global char1_read_counter # char1_read_counter += 1 events = chr.events() if events & Bluetooth.CHAR_WRITE_EVENT: print("Write request with value = {}".format(chr.value())) else: #modify here to send message to other clients return str(deviceID) #using the callback to send the data to other clients char1_cb = chr1.callback(trigger=Bluetooth.CHAR_WRITE_EVENT | Bluetooth.CHAR_READ_EVENT, handler=char1_cb_handler) ''' '''srv2 = bluetooth.service(uuid=1234, isprimary=True) chr2 = srv2.characteristic(uuid=4567, value=0x1234) char2_read_counter = 0xF0 def char2_cb_handler(chr): global char2_read_counter char2_read_counter += 1 if char2_read_counter > 0xF1: return char2_read_counter char2_cb = chr2.callback(trigger=Bluetooth.CHAR_READ_EVENT, handler=char2_cb_handler)''' #Secondly, also act as client bt = Bluetooth() bt.start_scan(-1) counter = 0 while True: #Gets an named tuple with the advertisement data received during the scanning. #The structure is (mac, addr_type, adv_type, rssi, data) adv = bt.get_adv() #servermac = ''#save the serer mac #use resolve_adv_data to resolve the 31 bytes of the advertisement message #Here is problem: when disconnect from server, then adv will always be null... if adv and bt.resolve_adv_data( adv.data, Bluetooth.ADV_NAME_CMPL) == 'LoPyServer1': try: #Opens a BLE connection with the device specified by the mac_addr argument #This function blocks until the connection succeeds or fails. #print(adv.mac) #global servermac#change servermac to global #servermac = adv.mac counter += 1 conn = bt.connect(adv.mac) #print('connected?',conn.isconnected()) services = conn.services() #print('This is service',services) #print(services) ''' for service in services: print('This is service uuid',service.uuid()) time.sleep(0.050) if type(service.uuid()) == bytes: print('if bytes:Reading chars from service = {}'.format(service.uuid())) else: print('if not bytes:Reading chars from service = %x' % service.uuid()) chars = service.characteristics() for char in chars: if (char.properties() & Bluetooth.PROP_READ): print('char {} value = {}'.format(char.uuid(), char.read())) ''' #Yunwei - it seems that only when the type of uuid is bytes then could read the data from server for service in services: time.sleep(0.050) if type(service.uuid()) == bytes: chars = service.characteristics() for char in chars: #check if the character properties is PROP_READ if (char.properties() & Bluetooth.PROP_READ): print('char {} value = {}'.format( char.uuid(), char.read()) + str(counter)) #Yunwei conn.disconnect() print('connected?', conn.isconnected()) #break time.sleep(1) bt.start_scan(-1) except: print("Error while connecting or reading from the BLE device") #break time.sleep(1) bt.start_scan(-1) print('Scan again')
import pycom from network import Bluetooth import time import binascii bt = Bluetooth() bt.start_scan(10) conn = bt.connect('08b5d69c1d67') print(conn) services = conn.services() print(services) for service in services: print(service.uuid())
def BLEAndLoRaFun(): #First, initialize as one LoRa node device # initialize LoRa in LORAWAN mode. # Please pick the region that matches where you are using the device: # Asia = LoRa.AS923 # Australia = LoRa.AU915 # Europe = LoRa.EU868 # United States = LoRa.US915 lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.US915) # create an ABP authentication params dev_addr = struct.unpack(">l", binascii.unhexlify('260214B3'))[0] nwk_swkey = binascii.unhexlify('2C2139EEC68B264BF1F0EDCE183CE33F') app_swkey = binascii.unhexlify('C25FB9A263307BF86B659298D86D4A45') # remove all the channels for channel in range(0, 72): lora.remove_channel(channel) # set all channels to the same frequency (must be before sending the OTAA join request) for channel in range(0, 72): lora.add_channel(channel, frequency=config.LORA_FREQUENCY, dr_min=0, dr_max=3) # join a network using ABP (Activation By Personalization) lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey)) # create a LoRa socket s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) # set the LoRaWAN data rate s.setsockopt(socket.SOL_LORA, socket.SO_DR, 3) # last parameter is 3 # make the socket non-blocking s.setblocking(False) #Second, act as BLE client bt = Bluetooth() bt.start_scan(-1) counter = 0 while True: #Gets an named tuple with the advertisement data received during the scanning. #The structure is (mac, addr_type, adv_type, rssi, data) adv = bt.get_adv() #servermac = ''#save the serer mac #use resolve_adv_data to resolve the 31 bytes of the advertisement message #Here is problem: when disconnect from server, then adv will always be null... if adv and bt.resolve_adv_data( adv.data, Bluetooth.ADV_NAME_CMPL) == 'LoPyServer1': try: #Opens a BLE connection with the device specified by the mac_addr argument #This function blocks until the connection succeeds or fails. #print(adv.mac) #global servermac#change servermac to global #servermac = adv.mac counter += 1 conn = bt.connect(adv.mac) #print('connected?',conn.isconnected()) services = conn.services() #print('This is service',services) #print(services) ''' for service in services: print('This is service uuid',service.uuid()) time.sleep(0.050) if type(service.uuid()) == bytes: print('if bytes:Reading chars from service = {}'.format(service.uuid())) else: print('if not bytes:Reading chars from service = %x' % service.uuid()) chars = service.characteristics() for char in chars: if (char.properties() & Bluetooth.PROP_READ): print('char {} value = {}'.format(char.uuid(), char.read())) ''' #Yunwei - it seems that only when the type of uuid is bytes then could read the data from server for service in services: time.sleep(0.050) if type(service.uuid()) == bytes: chars = service.characteristics() for char in chars: #check if the character properties is PROP_READ if (char.properties() & Bluetooth.PROP_READ): print('char {} value = {}'.format( char.uuid(), char.read()) + str(counter)) #Use LoRa to send the data out s.send(char.read()) time.sleep(4) #Yunwei conn.disconnect() print('connected?', conn.isconnected()) #break time.sleep(6) bt.start_scan(-1) except: print("Error while connecting or reading from the BLE device") #break time.sleep(1) bt.start_scan(-1) print('Scan again')
if server_mac is None: print(time.time(), "couldn not find", server_name) pycom.rgbled(0x220000) time.sleep(5) machine.reset() else: #server_adv = Adv[server_mac] print(time.time(), "found", server_name, "at", binascii.hexlify(server_mac)) # , "with", server_adv.rssi) ct = 0 while True: try: pycom.rgbled(0x000022) print(time.time(), ct, "connect to", server_name) conn = bt.connect(server_mac) print(time.time(), "connected successful", ct) break except Exception as e: print(time.time(), "failed", e) bt.disconnect_client() pycom.rgbled(0x220000) time.sleep(1) if ct >= 10: print("reset") machine.reset() ct += 1 pycom.rgbled(0x002200) print(conn.isconnected()) print(conn.get_mtu()) print("Services", len(conn.services()), ":")