Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Beacons with data #243

Open
ukBaz opened this issue Aug 24, 2019 · 3 comments
Open

Beacons with data #243

ukBaz opened this issue Aug 24, 2019 · 3 comments

Comments

@ukBaz
Copy link
Owner

ukBaz commented Aug 24, 2019

It is possible to encode data into the advertising data. With Bluetooth the Manufacturer Data has 23 octets that can be given some structure to send data without connecting.

One barrier to doing this idea might be that manufacturer data uses company identifiers which are unique numbers assigned by the Bluetooth SIG to member companies requesting one.
https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers/

An idea for structure of the data could be:

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
  Version/Type timestamp timestamp timestamp timestamp NodeID NodeID Payload Payload Payload Payload Payload Payload Payload Payload Payload Payload Payload Payload Payload Payload Payload Payload
                len Raw Bytes
Raw Packet 0x10 xx xx xx xx xx xx 15                              
                Number Number   Number  Number                  
Number Packet 0x11 xx xx xx xx xx xx                                
                Number Number Number Number Len String
Value Pakcet 0x12 xx xx xx xx xx xx         11                      
                Len String
String Packet 0x13 xx xx xx xx xx xx 15                              

For switching data to and from bytes in python

int(1).to_bytes(4, byteorder='big', signed=True) 
Out: b'\x00\x00\x00\x01' 

int.from_bytes(b'\xfd', byteorder='big', signed=True)
Out: -3 

An example of an implementation for number packets might be:

import random
import time
from gi.repository import GLib
from bluezero import advertisement
beacon = advertisement.Advertisement(1, 'broadcast')
beacon.manufacturer_data =  {0x0ba2: int(1234).to_bytes(4,
                                                        byteorder='big',
                                                        signed=True)}
ad_manager = advertisement.AdvertisingManager()
ad_manager.register_advertisement(beacon, {})


def send_value(value):
    packet_type = int(0x11).to_bytes(1, byteorder='big')
    time_stamp = int(time.clock_gettime(
        time.CLOCK_BOOTTIME)).to_bytes(4, byteorder='big')
    node_id = int(0).to_bytes(2, byteorder='big')
    v_bytes = int(value).to_bytes(4, byteorder='big', signed=True)
    raw_bytes = (packet_type + time_stamp + node_id + v_bytes)
    return raw_bytes

def update_data():
    ad_manager.unregister_advertisement(beacon)
    # Replace last letter of URL with randomly picked letter
    rand_value = int(random.randrange(-2147483648, 2147483647))
    byte_data = send_value(rand_value)
    beacon.manufacturer_data = {0x0ba2: byte_data}
    print(beacon.manufacturer_data, byte_data)
    ad_manager.register_advertisement(beacon, {})
    return True

GLib.timeout_add_seconds(5, update_data)
beacon.start()

This example is only with integers. An alternative might be to have an exponent also to change to order of magnitude and create decimal numbers.

@mrquincle
Copy link

It makes more sense to encode this in another AD. So, you use the manufacturer AD to have a properly listed manufacturing ID and you use e.g. a service list to encode the payload. It's most convenient to use the 128-bit service uuid list (type 0x07).

@ukBaz
Copy link
Owner Author

ukBaz commented Jan 14, 2025

I'm not sure I understand why I need both manufacturer data and service data. Surely, I can do this with either?

The main point of this issue was to capture 2 things:

  1. how to broadcast data in a compact format
  2. to make the new data available in a BlueZ advertisement, there is a need to unregister_advertisement and register_advertisement

@mrquincle
Copy link

iOS strips it out when in the background, https://stackoverflow.com/questions/63175411/ios-omits-manufacturer-data-from-advertisement-in-background-mode

Reverse engineered the service UUIDs hash towards the bits in the overflow area in the past. https://github.com/crownstone/bluenet-ios-basic-localization/blob/master/BROADCASTING_AS_BEACON.md

I understand that it's just an edge case though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants