Holyiot nRF52832 with Custom Python Script

Protonest
3 min readDec 28, 2023

In the rapidly evolving world of the Internet of Things (IoT), the Holyiot nRF52832(Ibeacon) stands out as a versatile and powerful tool. It is capable of providing real-time data on temperature, humidity, and motion, opening up vast possibilities for environmental monitoring and IoT applications. In this article we are helping you to integrate the ibeacon with a Python script, making them accessible to a broad range of developers and enthusiasts.

Components Needed:

  1. Holyiot nRF52832
  2. CR2032 battery

Step 1: Setting Up a Virtual Environment

  • Open Terminal (Mac/Linux) or Command Prompt (Windows)
  • Navigate to your project directory

cd path/to/your/project

  • Create a virtual environment

On macOS and Linux,

python3 -m venv myenv

On Windows,

python -m venv myenv

  • Activate the virtual environment

On macOS and Linux,

source myenv/bin/activate

On Windows,

.\myenv\Scripts\activate

Step 2: Installing Libraries

  • Ensure pip is up-to-date

pip install — upgrade pip

  • Install the ‘bleak’ library

pip install bleak

Step 3: Finding the MAC Address

  • Copy and paste the Python script to find the MAC address(‘find_macaddress.py’)
import asyncio
from bleak import BleakScanner

async def scan_for_devices():
print("Scanning for BLE devices...")
devices = await BleakScanner.discover()

for device in devices:
print(f"Device found: {device.name}, MAC Address: {device.address}")

if not devices:
print("No BLE devices found.")

asyncio.run(scan_for_devices())
  • Run the script

python find_macaddress.py

  • Note the MAC address of your BLE device from the output.

Step 4: Running the Final Code

  • Open the final Python script (e.g., ‘beacon _last.py’)
import asyncio
from bleak import BleakScanner

# Constants for your specific device
TARGET_DEVICE_MAC = "A838554B-CEEE-D90A-A3AB-8499CBA95BAE"

def parse_beacon_data(hex_string):
# Convert hex string to bytes
data_bytes = bytes.fromhex(hex_string)

# Parse UUID, Major, Minor, and Power
uuid = hex_string[4:36]
major = int(hex_string[36:40], 16)
minor = int(hex_string[40:44], 16)
power = int(hex_string[44:46], 16) - 256 if int(hex_string[44:46], 16) > 127 else int(hex_string[44:46], 16)

return {
'UUID': uuid,
'Major': major,
'Minor': minor,
'Power': power
}

def parse_service_data(data_bytes):
temp_parts = [int.from_bytes(data_bytes[i:i+1], byteorder='big', signed=False) for i in range(0, 2)]
humidity_parts = [int.from_bytes(data_bytes[i:i+1], byteorder='big', signed=False) for i in range(2, 4)]

# Concatenate the parts for temperature and humidity
temp_str = ''.join(str(part) for part in temp_parts)
humidity_str = ''.join(str(part) for part in humidity_parts)

# Convert the concatenated string to integer
temperature = int(temp_str)
humidity = int(humidity_str)

# Convert each accelerometer byte to an integer and concatenate
accel_x_parts = [int.from_bytes(data_bytes[i:i+1], byteorder='big', signed=True) for i in range(5, 8)]
accel_y_parts = [int.from_bytes(data_bytes[i:i+1], byteorder='big', signed=True) for i in range(9, 12)]
accel_z_parts = [int.from_bytes(data_bytes[i:i+1], byteorder='big', signed=True) for i in range(13, 16)]

# Concatenate the parts for each axis
accel_x_str = ''.join(str(part) for part in accel_x_parts)
accel_y_str = ''.join(str(part) for part in accel_y_parts)
accel_z_str = ''.join(str(part) for part in accel_z_parts)

# Convert the concatenated string to integer
accel_x = int(accel_x_str)
accel_y = int(accel_y_str)
accel_z = int(accel_z_str)

sign_bytex = data_bytes[4]
sign_bytey = data_bytes[8]
sign_bytez = data_bytes[12]

if sign_bytex == 0:
accel_x = -accel_x
if sign_bytey == 0:
accel_y = -accel_y
if sign_bytez == 0:
accel_z = -accel_z

return {
'Temperature': temperature/100,
'Humidity': humidity/100,
'Accelerometer X': accel_x / 100.0,
'Accelerometer Y': accel_y / 100.0,
'Accelerometer Z': accel_z / 100.0,
}

def detection_callback(device, advertisement_data):
if device.address.lower() == TARGET_DEVICE_MAC.lower():
print(f"Found target device: {device.address}")
# print("Advertisement Data:", advertisement_data)

# Manufacturer Data
manufacturer_data = advertisement_data.manufacturer_data.get(76)
if manufacturer_data:
# print("Raw Manufacturer Data:", manufacturer_data.hex())
decoded_data = parse_beacon_data(manufacturer_data.hex())
if decoded_data:
print("Decoded Manufacturer Data:", decoded_data)

specific_service_data = advertisement_data.service_data.get('00000318-0000-1000-8000-00805f9b34fb')
if specific_service_data:
#print("Specific Service Data (Bytes):", specific_service_data)
decoded_data = parse_service_data(specific_service_data)
print("Decoded Service Data:", decoded_data)


async def main():
scanner = BleakScanner()
scanner.register_detection_callback(detection_callback)

await scanner.start()
await asyncio.sleep(600) # Scan for 20 seconds
await scanner.stop()

asyncio.run(main())
  • Modify the `TARGET_DEVICE_MAC` in your final script to the MAC address you noted earlier.
  • Run your final script

python beacon _last.py

You can compare the readings from the python script with the mobile app of the manufacturer.

Note: If the service ID printed on the terminal is different than 00000318–0000–1000–8000–00805f9b34fb, you need to change it according to your service ID.

Contact Protonest for more details.

Protonest specializes in transforming IoT ideas into reality. We offer prototyping services from concept to completion. Our commitment ensures that your visionary IoT concepts become tangible, innovative, and advanced prototypes.

Our Website: https://www.protonest.co/

If you enjoyed this article and would like to show some support, consider buying me a coffee on Ko-Fi.

Your support not only helps me keep creating content like this but also fuels me! ☕️📚

Thank you for being an amazing reader!

Here’s my Ko-Fi link: https://ko-fi.com/udarakumarasena

Cheers!

--

--