WiPy as an iBeacon

  • Have been struggling for a few days now getting the WiPy to advertise an iBeacon frame. I've read on this forum that it should be possible but till now without any luck.

    Does anyone have an example on how to do as the documentation on this is incomplete?

  • @surly
    Have the answers above helped you? if you still have problems let me know please let us know what you're trying to do and where the problem is - I'll help you out

  • @papasmurph
    In those cases the device name is sent in a scan response packet (as a response to a scan request sent by the WiPy), this different from the advertisement.

  • @patrick I've seen beacons that include a name, that BLE scanners pick up, but it's not specified by iBeacon.

  • @patrick
    There isn’t enough bytes in the (standard BLE 4.x) advertisement packet for both a name and beacon data, so if you have a name the extra beacon data is dropped

  • @papasmurph thx, your code works fine. I figured out whats wrong, if you put a name in this line

    bluetooth.set_advertisement(name = None, manufacturer_data = bytes(data))

    then the beacon advertisement doesn't work. I don't know if this is a bug or by design but it is easy to reproduce.

  • @patrick Try this, courtesy of Abiro AB :).

    Also supports Eddystone-URL.

    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 = MODE_IBEACON
    def twocompl(x):
        if x < 0:
            x += 256
        return x        
    timeSleep = 1
    bluetooth = Bluetooth()
    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
    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:
        bluetooth.set_advertisement(service_uuid = bytes(uuid), service_data = bytes(data))
    while True:

  • @patrick I also need a better documentation to continue !

Pycom on Twitter