Esempio n. 1
0
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
Esempio n. 2
0
def main():
    gc.enable()
    while True:
        WIFI()  #Connect to WiFi
        set_rtc()  #Set RTC time
        mqtt1()  #Connect Heatcheck Client
        mqtt2()  #Conenct BLE Client
        _thread.start_new_thread(heartbeat, ())  #Start HeartBeat loop
        print("Scanning... from: " + MAC)  #Prints device MAC
        print(TOPIC)  #Prints BLE data Topic
        global bt
        bt = Bluetooth()
        if CONFIG.get(
                'btExt') == True:  #If wnating to use external BLE antenna
            Pin('P12', mode=Pin.OUT)(True)
            bt.init(antenna=Bluetooth.EXT_ANT)
            print("Using Ext for Bt")
        bt.start_scan(-1)  #Start Scanning for BLE data indefinitely
        _thread.start_new_thread(scan, ())  #Start BLE decode loop
        print("Scanning....")
        running_check()  #Start wait loop, checks for incoming messages
        machine.reset()  #Should never get this ppoint
Esempio n. 3
0
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!')
Esempio n. 4
0
class RuuviTag:
    def __init__(self, whitelist=None, antenna=None):
        self._whitelist = whitelist
        self._blacklist = []
        self.bluetooth = Bluetooth()
        self.bluetooth.init(antenna=antenna)

    def __repr__(self):
        return "{}(whitelist={!r}, blacklist={!r})".format(
            type(self).__name__, self._whitelist, self._blacklist)

    @property
    def blacklist(self):
        return self._blacklist

    @blacklist.setter
    def blacklist(self, value):
        self._blacklist = value

    def get_tag(self, mac, adv):
        data = self.get_data(adv)

        if data is None:
            self._blacklist.append(mac)
            return None

        data = self.decode_data(*data)

        # Select namedtuple for URL or RAW format
        if data[0] in [2, 4]:
            tag = RuuviTagURL
        else:
            tag = RuuviTagRAW
            if data[0] == 3:
                # Fill missing measurements from RAW 1
                # format with None
                data = data + (None, ) * 3

        return tag(mac.decode("utf-8"), adv.rssi, *data)

    def get_data(self, adv):
        # raw1 and raw2 format
        data = self.get_data_format_raw(adv)
        if data is not None:
            return data

        # deprecated url format
        data = self.get_data_format_2and4(adv)
        if data is not None:
            return (2, data)

    @staticmethod
    def get_data_format_2and4(adv):
        """
        Test if device data is in data format 2 or 4.

        Returns measurement data or None if not in format 2 or 4.
        """
        try:
            data = adv.data.decode("utf-8")
            index = data.find("ruu.vi/#")
            if index > -1:
                return data[(index + 8):]
            else:
                index = data.find("r/")
                if index > -1:
                    return data[(index + 2):]
                return None
        except Exception:
            return None

    def get_data_format_raw(self, adv):
        """Test if device data is in raw format 3 (RAWv1) or 5 (RAWv2).

        Returns decoded measurements from the manufacturer data
        or None if not in format RAWv1, RAWv2 or no data can be extracetd
        from the device.

        The Bluetooth device is necessary to get the manufacturer data.
        """
        raw_data_formats = [3, 5]

        try:
            data = self.bluetooth.resolve_adv_data(
                adv.data, Bluetooth.ADV_MANUFACTURER_DATA)
        except TypeError:
            return None

        if data is None:
            return None

        # Only RuuviTags
        if data[:2] != b"\x99\x04":
            return None

        # Only data format 3 and 5 (raw)
        if data[2] not in raw_data_formats:
            return None

        return (data[2], data)

    def decode_data(self, data_format, data):
        if data_format in (2, 4):
            return decode_data_format_2and4(data)
        elif data_format == 3:
            return decode_data_format_3(data)
        elif data_format == 5:
            return decode_data_format_5(data)
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")
Esempio n. 7
0
class BLEScanner:
    def __init__(self, buffer_size):
        """Store buffer in given storage."""
        self.beaconlist = []
        self.beacontime = []
        self.beaconrssi = []
        self.beaconevents = []
        self.beaconcount = []
        self.timelastdata = time.time()
        self.eventBuffer = RingBuffer(buffer_size)
        self.bluetooth = Bluetooth()

    def new_adv_event(self, event):
        global beaconlist, beaconevents, timelastdata
        if event.events() == Bluetooth.NEW_ADV_EVENT:
            anydata = True
            while anydata:
                adv = self.bluetooth.get_adv()
                if adv != None:
                    timelastdata = time.time()
                    devid = binascii.hexlify(adv[0]).decode('utf-8')
                    rssi = str(adv[3] * -1)
                    if devid not in self.beaconlist:
                        print('new device found {} @ {}'.format(
                            devid, timelastdata))
                        self.beaconlist.append(devid)
                        self.beacontime.append(timelastdata)
                        self.beaconrssi.append(rssi)
                        self.beaconcount.append(0)
                        #if len(beaconevents) > 20:
                        #    beaconevents.pop(0)
                        #beaconevents.append([timelastdata, devid, rssi])
                        self.eventBuffer.add([timelastdata, devid, rssi, 0])

                    else:
                        #find index in array of this beacon and check the timelastdata
                        #update beaconrssi
                        #decide if stuff shoudl be pushed again
                        i = self.beaconlist.index(devid)

                        if self.timelastdata > (self.beacontime[i] + 300):
                            #update it
                            self.beacontime[i] = timelastdata
                            self.beaconrssi[i] = rssi
                            rx_count = self.beaconcount[i]
                            self.beaconcount[i] = self.beaconcount[i] + 1

                            #if len(beaconevents) > 20:
                            #    beaconevents.pop(0)
                            #beaconevents.append([timelastdata, devid, rssi])
                            self.eventBuffer.add(
                                [timelastdata, devid, rssi, rx_count])

                            #print('Updated index {}'.format(i))

                else:
                    anydata = False

    def start_scan(self):
        print('Starting BLE scan')
        #bluetooth =
        self.bluetooth.callback(trigger=Bluetooth.NEW_ADV_EVENT,
                                handler=self.new_adv_event)
        self.bluetooth.init()
        self.bluetooth.start_scan(-1)
Esempio n. 8
0
File: main.py Progetto: snenyl/Pycom
from network import Bluetooth
import time
import ubinascii
import binascii
import struct

bt = Bluetooth()
bt.start_scan(-1)

bt.init() # This is important for it to work! Put on front fo bt.start?

def acc_recieve_array():
        #x_acc_char.value(b)
    pass

tilt = 0
i = 0
T = []
data_1 = 0
initialWait = 0

while True:
  #time.sleep(3) #Every 3 seconds
  adv = bt.get_adv()
  if adv and bt.resolve_adv_data(adv.data, Bluetooth.ADV_NAME_CMPL) == 'LoPy':
          conn = bt.connect(adv.mac)
          services = conn.services()
          while True:
              for service in services:
                  chars = service.characteristics()
                  for char in chars:
Esempio n. 9
0
class ConfigureBluetooth:
    def __init__(self, data, main):
        self.data = data
        self.main = main
        self.mode = 0
        self.pycom = main.pycom
        self.nodeName = None
        self.connectionFailed = False
        self.bluetoothConnected = False
        self.srv1 = None
        self.chr1 = None
        self.srv2 = None
        self.chr2 = None
        self.chr3 = None
        self.bluetooth = None
        self.char1_cb = None
        self.char2_cb = None
        self.service_uuid = 0x2A6D
        self.service_uuid2 = 0x2A6F
        self.characteristic_uuid = 0x2A6E
        self.characteristic_uuid2 = 0x2B6E
        self.state = 'start'
        self.unlocked = False

        # 1: self.pin_reverb,
        # 2: self.pin_efx1,
        # 3: self.pin_efx2,
        # 4: self.pin_minus,
        # 5: self.pin_plus,
        # 6: self.pin_variation1,
        # 7: self.pin_variation2,
        # 8: self.pin_variation3,
        # 9: self.pin_transpose,
        # 10: self.pin_sound_epiano,
        # 11: self.pin_sound_piano,
        # 12: self.pin_sound_organ
        # 13: self.pin_reserve

    ## start() gets called by main.py in initialisation phase
    ## returns when main state can be started
    def start(self):
        self.setBluetoothAdvertisement(self.mode)

        return True

    def setBluetoothAdvertisement(self, mode):
        if mode == 0:
            print("Bluetooth Basic activated")

            self.nodeName = self.data.get('name')
            print("Advertising on bluetooth with:")
            print(self.nodeName)

            self.bluetooth = Bluetooth()
            self.bluetooth.init()
            ## service_uuid is dummy, is there an existing profile we should use?

            self.bluetooth.set_advertisement(name=self.nodeName,
                                             service_uuid=self.service_uuid)
            self.bluetooth.callback(trigger=Bluetooth.CLIENT_CONNECTED
                                    | Bluetooth.CLIENT_DISCONNECTED,
                                    handler=self.conn_cb)
            self.bluetooth.advertise(True)

            ## Below is dummy code, only for testing purposes, services and characteristics should become classes
            self.srv1 = self.bluetooth.service(uuid=self.service_uuid,
                                               isprimary=True)
            self.chr1 = self.srv1.characteristic(uuid=self.characteristic_uuid,
                                                 value=b'123')
            self.char1_cb = self.chr1.callback(
                trigger=Bluetooth.CHAR_WRITE_EVENT | Bluetooth.CHAR_READ_EVENT,
                handler=self.unlock_handler)

            self.srv1.start()

            self.srv2 = self.bluetooth.service(uuid=self.service_uuid2,
                                               isprimary=True)

            self.chr2 = self.srv2.characteristic(
                uuid=self.characteristic_uuid2, value=b'chr2')
            self.chr3 = self.srv2.characteristic(
                uuid=self.characteristic_uuid2, value=b'chr3')
            self.char2_cb = self.chr2.callback(
                trigger=Bluetooth.CHAR_WRITE_EVENT | Bluetooth.CHAR_READ_EVENT,
                handler=self.interface_handler)

            self.srv2.start()

            self.main.start_main_state()

    def conn_cb(self, bt_o):
        events = bt_o.events()
        if events & Bluetooth.CLIENT_CONNECTED:
            print("Client connected")
            self.bluetoothConnected = True

        elif events & Bluetooth.CLIENT_DISCONNECTED:
            print("Client disconnected")
            self.stop_config_state()

    def unlock_handler(self, chr):
        events = chr.events()
        if events & Bluetooth.CHAR_WRITE_EVENT:
            print("Client has written to UNLOCK characteristic")
            # if written correct passphrase:
            if (chr.value() == b'0123'):
                self.start_config_state()
                self.unlocked = True
            else:
                print('wrong password')
                print("Write request with value = {}".format(chr.value()))
        if events & Bluetooth.CHAR_READ_EVENT:
            print("Client has read characteristic")

    def toggle_method(self, param1, param2):
        # quickly turn on then off = toggle
        self.main.toggle_switch(self.main.pin_array[int(param1) - 1])
        print('Toggled ' + str(self.main.pin_array[int(param1) - 1]))

    def loop_through_options(self):
        # loop through indexes
        self.main.currentIndex += 1
        print(self.main.options)
        if self.main.currentIndex > len(self.main.options) - 1:
            self.main.currentIndex = 0
        print(self.main.currentIndex)
        # # toggle (on-off sequence) and switch (on or off)
        self.main.sequence_method(self.main.options[self.main.currentIndex])

    def switch_method(self, param1, param2=0):
        # switch on or off (controlled by param2)
        if int(param2) == 1:
            self.main.switch_on(self.main.pin_array[int(param1) - 1])
            print('Switched ON ' + str(self.main.pin_array[int(param1) - 1]))
        else:
            self.main.switch_off(self.main.pin_array[int(param1) - 1])
            print('Switched OFF ' + str(self.main.pin_array[int(param1) - 1]))

    def sequence_method(self, param1, param2=0):
        # toggle a sequence of buttons
        # e.g. "11-1-2-3-6"
        self.toggleList = param1.split("-")
        # API: "2,1-2-3,0"
        print(self.toggleList)
        for x in self.toggleList:
            print(x)
            self.main.toggle_switch(self.main.pin_array[int(x) - 1])
            time.sleep(0.1)

    def toggle_setting(self, param1, param2):
        # toggle a sequence of buttons depending on param1 setting int

        self.toggleList = [1, 2, 3]
        print(self.toggleList)
        for x in self.toggleList:
            print(x)
            self.main.toggle_switch(self.main.pin_array[int(x) - 1])
            time.sleep(0.1)

    def transpose_up(self):
        # tranpose up
        # switch 9 to ON (1)
        # toggle 5 (plus)
        self.switch_method(9, 1)
        time.sleep(0.1)
        self.main.toggle_switch(self.main.pin_array[5 - 1])
        time.sleep(0.1)
        self.switch_method(9, 0)

    def transpose_down(self):
        # tranpose down
        # switch 9 to ON (1)
        # toggle 4 (minus)
        self.switch_method(9, 1)
        time.sleep(0.1)
        self.main.toggle_switch(self.main.pin_array[4 - 1])
        time.sleep(0.1)
        self.switch_method(9, 0)

    def octave_up(self):
        # octave up, could be triggered with e.g. PuckJS as BLE client
        self.main.toggle_switch(self.main.pin_array[5 - 1])

    def octave_down(self):
        # octave down
        self.main.toggle_switch(self.main.pin_array[4 - 1])

    def interface_handler(self, chr):
        events = chr.events()
        if events & Bluetooth.CHAR_WRITE_EVENT:
            print("Client has written to characteristic")
            if self.unlocked:
                print("Write request with value = {}".format(chr.value()))
                a = str(chr.value())
                a = a[2:-1].split(",")
                print(a)
                # e.g. STRING="0,00ff00,1"
                # i.e. LED function (0), color, mode (blink / constant / etc.)
                options = {
                    0: self.toggle_method,
                    1: self.switch_method,
                    2: self.sequence_method,
                    3: self.toggle_setting,
                    4: self.transpose_up,
                    5: self.transpose_down,
                    6: self.octave_up,
                    7: self.octave_down,
                    8: self.loop_through_options
                }
                try:
                    if int(a[0]) == 8 or int(a[0]) == 7 or int(
                            a[0]) == 6 or int(a[0]) == 5 or int(a[0]) == 4:
                        options(int(a[0]))()
                    else:
                        options[int(a[0])](a[1], a[2])
                except:
                    print('Error')
                    # self.chr2.value(b'Error')
                # give response back:
                # self.chr2.value(bytearray(a))
                print('OK')
                self.chr2.value(b'OK')

        if events & Bluetooth.CHAR_READ_EVENT:
            print("Client has read characteristic")

    def start_config_state(self):
        self.mode = 1
        self.state = 'start_config_state'
        self.pycom.rgbled(0x0000ff)
        self.chr1.value(b'Welcome')

    def stop_config_state(self):
        self.state = 'stop_config_state'
        self.unlocked = False
        self.pycom.rgbled(0xff0000)
        self.bluetoothConnected = False
        self.mode = 0