omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    Using cb library to connect simultaneously multiple TI SensorTag via Bluetooth Low Energy

    Pythonista
    4
    37
    20346
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • ProgrammingGo
      ProgrammingGo last edited by ProgrammingGo

      Hi I am using the Cb lib to use Bluetooth Low Energy with the TI SensorTag.
      I would like to connect more than 1 SensorTag with the Smartphone and I used the example code given here TI SensorTag - Example. I tried to connect several peripherals at the same time but I was not successful. Is there any chance to connect more SensorTags at the same time? WhatI should modify in the code? - I tried to create more than one of delegate = MyCentralManagerDelegate(). It was not successful as well.

      I would be happy to get any information how to solve this problem

      1 Reply Last reply Reply Quote 0
      • JonB
        JonB last edited by

        You may need to store a dict or list of peripherals/services, rather than the single instance variable. You can only have one active Central manager I think, so it needs to be smart enough to keep track of all the different devices

        1 Reply Last reply Reply Quote 0
        • ProgrammingGo
          ProgrammingGo last edited by

          Hi thank you very much, so all peripheral which should be connected to the central needs to be in a list? --->is there may be an example how to implement this? I a newbie in that so small example would be very helpful. But how the central manager can connect to several peripherals using a list or dict?

          1 Reply Last reply Reply Quote 0
          • ccc
            ccc last edited by ccc

            class MultipleDeviceManager(object):
                def __init__(self):
                    self.peripherals = {}  # dict of peripheral names and peripheral objects
            
                def did_discover_peripheral(self, p):
                    if p.name not in self.peripherals:
                        self.peripherals[p.name] = p
                        print(f'Connecting to a new device: {p.name}...')
                        cb.connect_peripheral(p)
            
                def connect_to_device(self, device_name):
                    """May raise a KeyError"""
                    cb.connect_peripheral(self.peripherals[device_name])
            

            I believe that what @JonB is saying above is that your dict may hold information about several different devices but you can only cb.connect_peripheral() to one at a time.

            ProgrammingGo 1 Reply Last reply Reply Quote 0
            • ProgrammingGo
              ProgrammingGo last edited by ProgrammingGo

              Ok thanks I will try it out in these days and will give a feedback here.
              Another question : because I want to read out the same service/characteristic of the sensor value from 3 TI sensortags at the same time , would it be a problem? Or do I need to change the UUID of the sensor Services/Charactersitcs ?

              1 Reply Last reply Reply Quote 0
              • JonB
                JonB last edited by

                it should be possible to connect to multiple devices at once, corebluetooth supports that i believe, but i have not tried.

                im not sure what the service or characteristic uuids look like for the same type of device on different peripherals, so that might be a problem

                1 Reply Last reply Reply Quote 0
                • ProgrammingGo
                  ProgrammingGo last edited by

                  Okay, thank you.yeah the TI SensorTags are using predefined UUID's for the different sensor characteristics /services. Look here [SensorTag(http://processors.wiki.ti.com/index.php/CC2650_SensorTag_User's_Guide#Connecting_to_multiple_SensorTags). So if I want to read out simultaneously the temperature sensor from 2 or 3 SensorTags it could be a problem to differentiate between them.

                  1 Reply Last reply Reply Quote 0
                  • ProgrammingGo
                    ProgrammingGo @ccc last edited by ProgrammingGo

                    @ccc regarding this example so there I only can connect to one device at time?

                    @ccc said in Using cb library to connect simultaneously multiple TI SensorTag via Bluetooth Low Energy:

                    class MultipleDeviceManager(object):
                        def __init__(self):
                            self.peripherals = {}  # dict of peripheral names and peripheral objects
                    
                        def did_discover_peripheral(self, p):
                            if p.name not in self.peripherals:
                                self.peripherals[p.name] = p
                                print(f'Connecting to a new device: {p.name}...')
                                cb.connect_peripheral(p)
                    
                        def connect_to_device(self, device_name):
                            """May raise a KeyError"""
                            cb.connect_peripheral(self.peripherals[device_name])
                    

                    I believe that what @JonB is saying above is that your dict may hold information about several different devices but you can only cb.connect_peripheral() to one at a time.

                    1 Reply Last reply Reply Quote 0
                    • JonB
                      JonB last edited by

                      you might want to just store a list of peripherals. Then examine them, to see if there is anything unique about them, such as name, uuid, etc. Maybe iOS appends a unique integer to the name, not sure.

                      the corebluetooth delegate methods always include the peripheral, thus there is never any ambiguity to whom you would be talking.
                      writing values should be okay, since you provide the perioheral, but getting update notifications might be problematic, since the characteristic doesn't point back to the peripheral object, at least not in the docs, but you might want to check for private attributes.

                      1 Reply Last reply Reply Quote 0
                      • ccc
                        ccc last edited by ccc

                        Do your devices have the same name or do they have different names?

                        If they have the same name then my solution above will not work but a solution that uses unique_name = f'{p.name}-{p.uuid}' would work.

                        Perhaps this discussion would be easier if you could discover a few devices and then print(self.peripherals) so that we can see the names.

                        1 Reply Last reply Reply Quote 0
                        • omz
                          omz last edited by

                          This post is deleted!
                          1 Reply Last reply Reply Quote 0
                          • ProgrammingGo
                            ProgrammingGo last edited by ProgrammingGo

                            The names are the same, but I would have the chance to change it and set an individual device name. Anyway I need to change the names to distinguish each sensor node data. How do you meant that with using unique_name = f'{p.name}-{p.uuid}' ? Is this a combination of name + uuid? --> Should I replace it with the** self.peripherals[p.name] = p**? In the meantime I try to generate an output where a few devices are discovered.

                            1 Reply Last reply Reply Quote 0
                            • ccc
                              ccc last edited by ccc

                              f-strings are described at https://docs.python.org/3/reference/lexical_analysis.html#formatted-string-literals

                              They are new in Python 3.6 so the following are all equivalent:

                              $ python3.6
                              >>> class P():
                              ...     name = 'name'
                              ...     uuid = 'uuid'
                              ...
                              >>> p = P()
                              >>> f'{p.name}-{p.uuid}'
                              'name-uuid'
                              >>> '{}-{}'.format(p.name, p.uuid)
                              'name-uuid'
                              >>> '%s-%s' % (p.name, p.uuid)
                              'name-uuid'
                              >>> '-'.join((p.name, p.uuid))
                              'name-uuid'
                              >>> p.name + '-' + p.uuid
                              'name-uuid'
                              

                              So p.name is not unique and p.uuid is not descriptive but if we put p.name, hyphen, p.uuid together then we have a string that is both descriptive and unique.

                              1 Reply Last reply Reply Quote 0
                              • ccc
                                ccc last edited by

                                Of course in Go, it would be:

                                package main
                                
                                import "fmt"
                                
                                type p_struct struct {
                                	name, uuid string
                                }
                                
                                func main() {
                                	p := p_struct{"name", "uuid"}
                                	fmt.Printf("%v-%v", p.name, p.uuid)
                                }
                                
                                1 Reply Last reply Reply Quote 0
                                • ProgrammingGo
                                  ProgrammingGo last edited by

                                  Thanks a will try it out :).
                                  I have a question regarding the example of the SensorTag which is given in the documentation of cb:

                                     def did_discover_peripheral(self, p):
                                          print('+++ Discovered peripheral: %s (%s)' % (p.name, p.uuid))
                                          if p.name and 'Sensor Tag' in p.name and not self.peripheral:
                                              # Keep a reference to the peripheral, so it doesn't get garbage-collected:
                                              self.peripheral = p
                                              cb.connect_peripheral(self.peripheral)
                                  

                                  This is the function to detect peripherals which are advertising. In the if statement there is something which is a bit unclear. Does it mean that if p.name is available and SensorTag is in P.name is clear, but why not self.peripheral?

                                  1 Reply Last reply Reply Quote 0
                                  • omz
                                    omz last edited by

                                    @ProgrammingGo

                                    In the if statement there is something which is a bit unclear. Does it mean that if p.name is available and SensorTag is in P.name is clear, but why not self.peripheral?

                                    The example connects to just one SensorTag, and that SensorTag is stored in the self.peripheral attribute, so the if not self.peripheral condition means "ignore this if we already found it". As you want to connect to multiple SensorTags, you'd have to handle this differently, of course.

                                    @ccc's code from earlier should be a good starting point. You might just need to use UUIDs instead of names, if all your SensorTags have the same name (not sure if they do generally).

                                    1 Reply Last reply Reply Quote 0
                                    • ProgrammingGo
                                      ProgrammingGo last edited by

                                      Hi,
                                      okay thanks for the explanation. I will try it out. that means the dict {} stores the connected peripherals so that the central does not try to connect to them again. I saw that the dict {} in the code is empty, should this stay like this or can I define the names of the nodes to which I want to have the connection?
                                      Regarding the name I can change the name of the SensorTag so that I could distinguish them

                                      1 Reply Last reply Reply Quote 0
                                      • ccc
                                        ccc last edited by

                                        When you start the dict is empty. Each time that did_discover_peripheral() is run, it will add a new entry in the dict if it is not already there.

                                        1 Reply Last reply Reply Quote 0
                                        • ccc
                                          ccc last edited by

                                          @ProgrammingGo Please run the following with multiple SensorTags turned on and post the output here:

                                          class MultipleDeviceManager(object):
                                              def __init__(self):
                                                  self.by_name = {}  # dict of peripheral names and peripheral objects
                                                  self.by_uuid = {}  # dict of peripheral uuids and peripheral objects
                                          
                                              def did_discover_peripheral(self, p):
                                                  if p.name not in self.by_name:
                                                      self.by_name[p.name] = p
                                                      print(f'Connecting to a new device: {p.name}...')
                                                  if p.uuid not in self.by_uuid :
                                                      self.by_uuid[p.uuid] = p
                                                      print(f'Connecting to a new device: {p.uuid}...')
                                                      cb.connect_peripheral(p)
                                                  print(f'{len(self.by_name)} unique names and {len(self.by_uuid)} unique uuids')
                                          
                                              def connect_to_device(self, device_name):
                                                  """May raise a KeyError"""
                                                  cb.connect_peripheral(self.by_name[device_name])
                                          
                                          ProgrammingGo 1 Reply Last reply Reply Quote 1
                                          • ProgrammingGo
                                            ProgrammingGo @ccc last edited by ProgrammingGo

                                            @ccc I tried it out with two tags ( using the same name for both tags) and I have the following output:

                                            Output:

                                            Connecting to new device: CC2650 SensorTag....
                                            Connecting to new device: <UUID> (too long but was displayed)

                                            1 unique names and 1 unique uuids

                                            Connecting to new device: <UUID> ---> only uuid was displayed because second SensorTag has same name

                                            1 unique names and 2 unique uuids.

                                            So logically I could use the uuid to have multiple sensor connected. I see the problem for the callback functions where I try to read out the sensor values or update it. For services it works, but to read out the same characteristics from both tags it is a problem. I would need to have a reference of the peripheral in the callback function did_discover_services. I wanted to modify the function, is there another way as workaround?

                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post
                                            Powered by NodeBB Forums | Contributors