There are a lot of parts to your question. I would recommend that you break the problem down into a series of smaller problems. Maybe:
- Get advertisement working with hard coded values
- Add reading values from file
- Scanner on ESP32
Get advertisement working with hard coded values
You have mentioned that you want to use the Bluepy library. There are a number of different roles that a Bluetooth device can take. You want your device to be a beacon (broadcaster) which isn't a role that Bluepy supports so you will not be able to use that library.
The extract of code you have appears to be from the example advertisement that is in the BlueZ source code. https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-advertisement. That should work for you. There are other questions that talk about using that code to make a beacon.
Testing broadcast values
Trying to create the code on both ends of the Bluetooth link is a very difficult challenge especially if you are new to Bluetooth. I would recommend that you use some generic tools to help you so that you are only writing code for one end of the Bluetooth link at a time. Once you are confident you have one end working, then move on to the other end.
For scanning, I would recommend using the nRF Connect tool. This will allow you to see if your beacon is broadcasting what you expect.
Use Beacon Simulator to create a beacon that you can practice learning how to read the data from it.
Beacon format
GATT is not used in the creation of a beacon. GATT is when Bluetooth LE devices connect and exchange data.
For a beacon, you are creating the advertising data, which is typically either Service Data or Manufacturer Data.
Looking at your other questions, you appear to know about Eddystone beacon format. That is a good format and I would suggest that is a good one to stick with as you learn because there are examples around. Once you have that working reliably, then you can try creating your own format.
ESP32
You have said that you want an ESP32 device to be in the scanner (Observer) role. It appears there is an example in the ESP32 source code. Test it with the Beacon Simulator and see if it works.
Divide and conquer
It will be easier for people to help you if you bring smaller problems for people to answer questions on. Decide if you want to start coding the scanner or the beacon first. Use a mobile phone app for the opposite role. If things don't work, show your code and what is on the app.
Simple beacon
Your code was close apart from how you entering the UUID. An example that worked for me was:
class TestAdvertisement(Advertisement):
def __init__(self, bus, index):
Advertisement.__init__(self, bus, index, 'peripheral')
company_id = 0x004C
beacon_type = [0x02, 0x15]
beacon_uuid = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16]
major = [0x11, 0x22]
minor = [0x33, 0x44]
tx_power = [0xB3]
manu_data = beacon_type + beacon_uuid + major + minor + tx_power
print('Using data:', manu_data)
self.add_manufacturer_data(company_id, manu_data)
text file
If you are going read data from a text file, using a format that is easy to read might be a good option. For example json is very easy to read in Python.
An example of you data in json might be:
{
"beacon_uuid": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
}
reading text file
Something like the following can be added to the start of the file to put the json data into the data
variable that we can access later
import json
from pathlib import Path
here = Path(__file__).parent
data_file = here.joinpath('beacon_string.json')
with data_file.open() as f:
data = json.load(f)
print('Json data:', data['beacon_uuid'], type(data['beacon_uuid']))
Beacon with data from file
This makes it a small modification to the original class to get the value from data
into the beacon advertisement:
class TestAdvertisement(Advertisement):
def __init__(self, bus, index):
Advertisement.__init__(self, bus, index, 'peripheral')
company_id = 0x004C
beacon_type = [0x02, 0x15]
beacon_uuid = data['beacon_uuid']
major = [0x11, 0x22]
minor = [0x33, 0x44]
tx_power = [0xB3]
manu_data = beacon_type + beacon_uuid + major + minor + tx_power
print('Using data:', manu_data)
self.add_manufacturer_data(company_id, manu_data)
Strings, lists, and bytes
With Bluetooth you can only send octets (bytes that are 8 bits). This means we need to present BlueZ with a list of integers (or a bytearray). If anything isn't a list bytes, it needs to be converted into a list of bytes to be sent. And then at the other end it needs to be converted back to from bytes.
I haven't understood exactly what your original data is so I'll show a few examples that are generally useful when working with Bluetooth and python.
for big_number in [7650, -4321]:
big_number_bytes = big_number.to_bytes(2, byteorder='little', signed=True)
print('big number bytes:', big_number_bytes)
big_number_int = int.from_bytes(big_number_bytes, byteorder='little', signed=True)
print('big number int:', big_number_int)
# big number bytes: [226, 29]
# big number int: 7650
# big number bytes: [31, 239]
# big number int: -4321
hex_str_list = ['32', '36', '33', '34', 'be', 'da']
dec_value_list = []
for hex_str_item in hex_str_list:
dec_value_list.append(int(hex_str_item, 16))
print('list of denary int values:', dec_value_list)
# list of denary int values: [50, 54, 51, 52, 190, 218]
msg_str = 'This is not a test'
byte_list = []
for letter_str in msg_str:
byte_list.append(ord(letter_str))
print('byte list to send:', byte_list)
recv_msg = ''
for letter_byte in byte_list:
recv_msg += chr(letter_byte)
print('Received msg:', recv_msg)
# byte list to send: [84, 104, 105, 115, 32, 105, 115, 32, 110, 111, 116, 32, 97, 32, 116, 101, 115, 116]
# Received msg: This is not a test
read string from a file
andadvertise beacon
are two different unrelated actions ... which one are you having problems with?