Welcome to the Pycom forum Forum
    • \[\[global:header.categories\]\]
    • \[\[global:header.recent\]\]
    • \[\[global:header.tags\]\]
    • \[\[global:header.popular\]\]
    • Login

    Explore Pybytes | Official Documentation | Report a Firmware Bug/Issue | GitHub

    Creating an Eddystone beacon?

    Scheduled Pinned Locked Moved WiPy 2&3
    eddystoneibeacon
    17 Posts 7 Posters 5.3k Views 7 Watching
    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.
    • B Offline
      b.veen
      last edited by

      Hi, i have sucessfully implemented an iBeacon using the 'bluetooth.set_advertisement' function with the proper manufacturer_data.

      Now I would like to create an Eddystone beacon, but I am unable to determine the proper parameters.

      Has anyone made an Eddystone beacon using a pycom module?

      B P 3 Replies Last reply Reply Quote 0
      • L Offline
        Lucio Flavio
        last edited by

        This post is deleted!
        1 Reply Last reply Reply Quote 0
        • B Offline
          b.veen @b.veen
          last edited by b.veen

          Hi everybody, I have come a little step closer to my goal.
          By using bluetooth.set_advertisement(service_data=bytes([0xAA, 0xFE,0x10,0xF8,0x00,ord('p'),ord('y'),ord('c'),ord('o'),ord('m'),ord('.'),ord('i'),ord('o')]))
          the WiPy is simulating a 'Physical Web Beacon' with the Eddystone Url http://www.pycom.io

          The framedata looks like this
          LEN, TYPE, VALUE
          2, 0x01, 0x06
          2, 0x0A, 0xEB
          5, 0x12, 0x20004000
          14 ,0x16, 0xAAFE10F8007079636F6D2E696F

          Question is: how to add the field 'Complete 16 bit service UUID list' containing the Eddystone uid (AAFE) ?
          I would expect it should be possible to add this line to the raw data above.
          LEN, TYPE, VALUE
          0x03, 0x03, 0xAAFE

          1 Reply Last reply Reply Quote 0
          • B Offline
            b.veen @b.veen
            last edited by

            I actually managed to get the 16 bit UUID in the frame by using the full 128-bit ID.

            from network import Bluetooth
            b = Bluetooth()
            b.init()
            b.advertise(True)

            uuid = bytes([0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xaa, 0xfe, 0x00, 0x00])
            data = bytes([0xAA, 0xFE, 0x10, 0xF8, 0x00, ord('p'), ord('y'), ord('c'), ord('o'), ord('m'), ord('.'), ord('i'),ord('o')])
            b.set_advertisement(service_uuid=uuid, service_data=data)

            This seems to work to create an Eddystone URL frame.
            But, to be Eddystone compliant you need an UID frame too.

            The frame takes all 32 bytes, so there is no room for extra information.
            The Pycom framework unfortunately adds TX power and beacon interval information. This is hardcoded in modbt.c

            adv_data.set_scan_rsp = false;
            adv_data.include_txpower = true,
            adv_data.min_interval = 0x20;
            adv_data.max_interval = 0x40;

            papasmurphP 1 Reply Last reply Reply Quote 0
            • papasmurphP Offline
              papasmurph @b.veen
              last edited by papasmurph

              @b.veen You don't have to advertise UID as well. TLM is practical though. I got it working too, but from where did you get the UUID?

              B 1 Reply Last reply Reply Quote 0
              • B Offline
                b.veen @papasmurph
                last edited by

                @papasmurph
                For my purposes I do not need TLM so I did not try to get that working.
                My solution was to change the bluetooth.setadvertisement function to include an extra option to enable/disable the TX and interval information.

                I have got the UUID working by providing the full google eddystone UID as registered on the bluetooth website. This resulted in a 'Complete 16 bit service UUD list'.

                The broadcasting of the URL is working too.

                (Since this project I have bought a couple of commercial beacons, it was fun experimenting with the PyCom though).

                papasmurphP 1 Reply Last reply Reply Quote 0
                • papasmurphP Offline
                  papasmurph @b.veen
                  last edited by

                  @b.veen Changing the firmware is not an option for me, considering how much maintenance is still done on it. E.g. continuous Bluetooth scanning (that I need in another project) is still unstable. The UUID insertion seems "magical", as the data is only partly available in the actual packet. I have a slew of dedicated beacons as part of my main offering CliqTags (I even sell beacons, not successfully though). What I'm experimenting with is making a remotely configurable beacon. Especially changing the URL for Eddystone would be interesting, so I've made a converter to the compressed URL format used by Eddystone. What remains is essentially pushing or pulling (more likely the latter, to avoid firewall issues) the URL.

                  1 Reply Last reply Reply Quote 0
                  • P Offline
                    patrick @b.veen
                    last edited by

                    @b-veen You have successfully implemented an iBeacon. I'm doing the same thing but struggling with the bluetooth.set_advertisement method. Can you help? What should I put in the manufacterer_data and what in the service_data? Should I put the complete 31 bytes in the manufacturer_data and in what order...

                    1 Reply Last reply Reply Quote 0
                    • S Offline
                      surly
                      last edited by

                      I tried with data = bytes([0xAA, 0xFE, 0x00,
                      0x29,
                      0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
                      0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
                      0x00,0x00]) , but it doesn't work!

                      papasmurphP 1 Reply Last reply Reply Quote 0
                      • papasmurphP Offline
                        papasmurph @surly
                        last edited by

                        @surly I can help you with Eddystone-URL, if that's interesting, but this seems to be Eddystone-UID.

                        S 1 Reply Last reply Reply Quote 0
                        • S Offline
                          surly @papasmurph
                          last edited by

                          @papasmurph yes, sorry! I mean the Eddystone-URL is ok, but what I really need is the Eddystone-UID ( also the IBeacon version would be usefull ) !

                          papasmurphP 1 Reply Last reply Reply Quote 0
                          • papasmurphP Offline
                            papasmurph @surly
                            last edited by

                            @surly Here's a complete example of iBeacon and Eddystone-URL. I don't have an example of UID or TLD, as I didn't need those.

                            In my iBeacon example, the UUID is encoded in the packet. That's the only UUID I needed (my own), but would be easy to create dynamically from a string.

                            from network import Bluetooth
                            import pycom
                            import time
                            
                            # https://docs.pycom.io/pycom_esp32/library/network.Bluetooth.html
                            # https://support.kontakt.io/hc/en-gb/articles/201492492-iBeacon-advertising-packet-structure
                            # https://github.com/google/eddystone/blob/master/protocol-specification.md
                            # https://github.com/google/eddystone/tree/master/eddystone-url/
                            # https://forum.pycom.io/topic/1120/creating-an-eddystone-beacon
                            # https://www.mkompf.com/tech/eddystoneurl.html
                            
                            MODE_IBEACON = 1
                            MODE_EDDYSTONEURL = 2
                            mode = MODE_IBEACON
                            
                            def twocompl(x):
                                if x < 0:
                                    x += 256
                            
                                return x        
                            
                            timeSleep = 1
                            
                            bluetooth = Bluetooth()
                            bluetooth.init()
                            
                            power1m = -59
                            
                            if mode == MODE_IBEACON:
                                major = 22240
                                minor = 234
                            
                                data = [
                                    0x4c, 0x00, 0x02, 0x15, # Manufacturer data
                                    0xA6, 0xE3, 0xE0, 0x06, 0xBB, 0xC4, 0x4D, 0xD1, 0x9C, 0xA3, 0x3E, 0x86, 0xC4, 0x95, 0x7D, 0xF0, # UUID (CliqTags)
                                    (major >> 8) & 0xFF, major & 0xFF, # Major ID
                                    (minor >> 8) & 0xFF, minor & 0xFF, # Minor ID
                                    twocompl(power1m) # Power
                                ]
                            
                                bluetooth.set_advertisement(name = None, manufacturer_data = bytes(data))
                            elif mode == MODE_EDDYSTONEURL:
                                url = 'https://www.abiro.com'
                            
                                uuid = [0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xaa, 0xfe, 0x00, 0x00]
                            
                                url = url.replace('http://www.', chr(0))
                                url = url.replace('https://www.', chr(1))
                                url = url.replace('http://', chr(2))
                                url = url.replace('https://', chr(3))
                            
                                url = url.replace('.com/', chr(0))
                                url = url.replace('.org/', chr(1))
                                url = url.replace('.edu/', chr(2))
                                url = url.replace('.net/', chr(3))
                                url = url.replace('.info/', chr(4))
                                url = url.replace('.biz/', chr(5))
                                url = url.replace('.gov/', chr(6))
                                url = url.replace('.com', chr(7))
                                url = url.replace('.org', chr(8))
                                url = url.replace('.edu', chr(9))
                                url = url.replace('.net', chr(10))
                                url = url.replace('.info', chr(11))
                                url = url.replace('.biz', chr(12))
                                url = url.replace('.gov', chr(13))
                            
                                data = [
                                    0xAA, 0xFE, # Eddystone ID
                                    0x10, # Eddystone-URL
                                    twocompl(power1m), # Power
                                ]
                            
                                for c in url:
                                    data.append(ord(c))
                            
                                bluetooth.set_advertisement(service_uuid = bytes(uuid), service_data = bytes(data))
                            
                            bluetooth.advertise(True)
                            
                            while True:
                                time.sleep(timeSleep)
                            
                            S Z 2 Replies Last reply Reply Quote 0
                            • S Offline
                              surly @papasmurph
                              last edited by

                              @papasmurph Great! it works! Thank you very much

                              1 Reply Last reply Reply Quote 0
                              • Z Offline
                                zaphodbb @papasmurph
                                last edited by

                                @papasmurph Thanks for doing the work to make the Eddystone beacon. I have your version up and running on WiPy 3.0. The eddystone beacon can send broadcasts the basic url but not a url with a path attached.

                                For example, if the url is https://pycom.io, the physical web app on my iphone gets the url and shows a notification. If the url is https://pycom.io/news, the phone app does not see any beacon.

                                Is this is a limitation of the bluetooth library? If so, is there a fix?

                                J 1 Reply Last reply Reply Quote 0
                                • J Offline
                                  jcaron @zaphodbb
                                  last edited by

                                  @zaphodbb Have you tested with those specific URLs, or with different URLs?

                                  There's a limit on the (compressed) URL length in the Eddystone format which you may hit if your URL is long. The two URLs you gave should fit, but https://forum.pycom.io/topic/1120/creating-an-eddystone-beacon/14 won't, for instance.

                                  If you have longer URLs, you'll need to use an URL-shortener.

                                  Z 1 Reply Last reply Reply Quote 0
                                  • Z Offline
                                    zaphodbb @jcaron
                                    last edited by

                                    @jcaron I used the two urls in my original post. I used the code from @papasmurph and added a print statement to look at the data bytes sent to the Bluetooth function. In both cases the data stream is properly formed.

                                    When transmitting “https://pycom.io” it gets picked up by the physical web app on my phone. When I add the path “/news” and restart the code, the data stream is still properly formed but the app does not see an Eddystone beacon. Removing the path gets the beacon to be seen again.

                                    My conclusion is that there is something happening when a path is added to the url. This is important as any shortened url (ie goo.gl/ads23g) won’t be seen.

                                    J 1 Reply Last reply Reply Quote 0
                                    • J Offline
                                      jcaron @zaphodbb
                                      last edited by

                                      @zaphodbb I think the issue is that the code uses a long (128 bit) UUID instead of the short 16-bit UUID, so there's a very short limitation on the max URL size.

                                      Try replacing the value of uuid with [0xaa, 0xfe] or 0xfeaa, it should give you 14 more bytes for your URL (haven't tried it).

                                      1 Reply Last reply Reply Quote 0

                                      Hello! It looks like you're interested in this conversation, but you don't have an account yet.

                                      Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

                                      With your input, this post could be even better 💗

                                      Register Login
                                      • 1 / 1
                                      • First post
                                        Last post

                                      Pycom on Twitter

                                      Pycom