Text Editor
Adafruit recommends using the Mu editor for editing your CircuitPython code. You can get more info in this guide.
Alternatively, you can use any text editor that saves simple text files.
Download the Project Bundle
Your project will use a specific set of CircuitPython libraries and the code.py file. To get everything you need, click on the Download Project Bundle link below, and uncompress the .zip file.
Drag the contents of the uncompressed bundle directory onto your board's CIRCUITPY drive, replacing any existing files or directories with the same names, and adding any new ones that are necessary.
# SPDX-FileCopyrightText: 2024 johnpark for Adafruit Industries
#
# SPDX-License-Identifier: MIT
'''
BLE BBQ Thermometer to WiFi to Adafruit IO Dashboard
Feather ESP32-S3 8MB No PSRAM
'''
import os
import time
import adafruit_connection_manager
import wifi
import adafruit_minimqtt.adafruit_minimqtt as MQTT
import adafruit_ble
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble_ibbq import IBBQService
aio_username = os.getenv("aio_username")
aio_key = os.getenv("aio_key")
print(f"Connecting to {os.getenv('CIRCUITPY_WIFI_SSID')}")
wifi.radio.connect(
os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD")
)
print(f"Connected to {os.getenv('CIRCUITPY_WIFI_SSID')}")
### Feeds ###
feeds = [aio_username + f"/feeds/bbq{i}" for i in range(1, 7)]
battery_feed = aio_username + "/feeds/bbq_battery"
# Define callback methods which are called when events occur
# pylint: disable=unused-argument, redefined-outer-name
def connected(client, userdata, flags, rc):
print("Connected to Adafruit IO")
def disconnected(client, userdata, rc):
print("Disconnected from Adafruit IO")
# Create a socket pool
pool = adafruit_connection_manager.get_radio_socketpool(wifi.radio)
ssl_context = adafruit_connection_manager.get_radio_ssl_context(wifi.radio)
connection_manager = adafruit_connection_manager.get_connection_manager(pool)
# Set up a MiniMQTT Client
mqtt_client = MQTT.MQTT(
broker="io.adafruit.com",
port=1883,
username=aio_username,
password=aio_key,
socket_pool=pool,
ssl_context=ssl_context,
)
# Setup the callback methods above
mqtt_client.on_connect = connected
mqtt_client.on_disconnect = disconnected
# Connect the client to the MQTT broker.
print("Connecting to Adafruit IO...")
mqtt_client.connect()
# PyLint can't find BLERadio for some reason so special case it here.
ble = adafruit_ble.BLERadio() # pylint: disable=no-member
ibbq_connection = None
battery_percentage = 100
def c_to_f(temp_c):
return (temp_c * 9/5) + 32
def volt_to_percent(voltage, max_voltage):
return (voltage / max_voltage) * 100
def probe_check(temp): # if value is wildly high no probe is connected
return temp if temp <= 11000 else 0
battery_val = 3.3
while True:
print("Scanning...")
for adv in ble.start_scan(ProvideServicesAdvertisement, timeout=5):
if IBBQService in adv.services:
print("found an IBBq advertisement")
ibbq_connection = ble.connect(adv)
print("Connected")
break
# Stop scanning whether or not we are connected.
ble.stop_scan()
if ibbq_connection and ibbq_connection.connected:
ibbq_service = ibbq_connection[IBBQService]
ibbq_service.init()
while ibbq_connection.connected:
print(
"Temperatures:",
ibbq_service.temperatures,
"; Battery:",
ibbq_service.battery_level,
)
grill_vals = [probe_check(c_to_f(temp)) for temp in ibbq_service.temperatures]
battery_val, battery_max = ibbq_service.battery_level
battery_percentage = (volt_to_percent(battery_val, 3.3))
mqtt_client.loop(timeout=1)
for feed, val in zip(feeds, grill_vals):
print(f"Sending grill value: {val} to {feed}...")
mqtt_client.publish(feed, val)
mqtt_client.publish(battery_feed, battery_percentage)
print("Sent")
time.sleep(5)
How It Works
The code does two key things -- connect to a Bluetooth iBBQ device to receive data and connect to the Internet via WiFi to send data via MQTT to AIO feeds.
Libraries
Import necessary libraries for WiFi connection, BLE communication, and MQTT for data transfer.
import os import time import adafruit_connection_manager import wifi import adafruit_minimqtt.adafruit_minimqtt as MQTT import adafruit_ble from adafruit_ble.advertising.standard import ProvideServicesAdvertisement from adafruit_ble_ibbq import IBBQService
Environment Variables for Adafruit IO
Retrieve Adafruit IO username and key from environment variables from the settings.toml file.
aio_username = os.getenv("aio_username")
aio_key = os.getenv("aio_key")
print(f"Connecting to {os.getenv('CIRCUITPY_WIFI_SSID')}")
wifi.radio.connect(os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD"))
print(f"Connected to {os.getenv('CIRCUITPY_WIFI_SSID')}")
Setup MQTT Feeds
Define functions to handle connection and disconnection events with the MQTT broker.
feeds = [aio_username + f"/feeds/bbq{i}" for i in range(1, 7)]
battery_feed = aio_username + "/feeds/bbq_battery"
MQTT Callback Functions
Define functions to handle connection and disconnection events with the MQTT broker.
def connected(client, userdata, flags, rc):
print("Connected to Adafruit IO")
def disconnected(client, userdata, rc):
print("Disconnected from Adafruit IO")
Create Socket Pool and SSL Context
Set up the socket pool and SSL context for secure MQTT communication.
pool = adafruit_connection_manager.get_radio_socketpool(wifi.radio) ssl_context = adafruit_connection_manager.get_radio_ssl_context(wifi.radio) connection_manager = adafruit_connection_manager.get_connection_manager(pool)
mqtt_client = MQTT.MQTT(
broker="io.adafruit.com",
port=1883,
username=aio_username,
password=aio_key,
socket_pool=pool,
ssl_context=ssl_context,
)
mqtt_client.on_connect = connected
mqtt_client.on_disconnect = disconnected
print("Connecting to Adafruit IO...")
mqtt_client.connect()
ble = adafruit_ble.BLERadio()
Helper Functions
There are three functions created here. One to convert Celsius to Fahrenheit, another to convert voltage to percentage, and one to check if a temperature probe is connected.
def c_to_f(temp_c):
return (temp_c * 9/5) + 32
def volt_to_percent(voltage, max_voltage):
return (voltage / max_voltage) * 100
def probe_check(temp):
return temp if temp <= 11000 else 0
Main Loop
The main loop first scans for the BBQ thermometer, and then connects to it.
Next, it reads temperature and battery data, converts them to Farenheit and Voltage, respectively.
Then, it sends this data to Adafruit IO using MQTT, and repeats the process in a loop every five seconds.
while True:
print("Scanning...")
for adv in ble.start_scan(ProvideServicesAdvertisement, timeout=5):
if IBBQService in adv.services:
print("found an IBBq advertisement")
ibbq_connection = ble.connect(adv)
print("Connected")
break
ble.stop_scan()
if ibbq_connection and ibbq_connection.connected:
ibbq_service = ibbq_connection[IBBQService]
ibbq_service.init()
while ibbq_connection.connected:
print("Temperatures:", ibbq_service.temperatures, "; Battery:", ibbq_service.battery_level)
grill_vals = [probe_check(c_to_f(temp)) for temp in ibbq_service.temperatures]
battery_val, battery_max = ibbq_service.battery_level
battery_percentage = volt_to_percent(battery_val, 3.3)
mqtt_client.loop(timeout=1)
for feed, val in zip(feeds, grill_vals):
print(f"Sending grill value: {val} to {feed}...")
mqtt_client.publish(feed, val)
mqtt_client.publish(battery_feed, battery_percentage)
print("Sent")
time.sleep(5)
On the next page follow the MQTT in CircuitPython guide to get your Adafruit IO account and feed set up.
Page last edited January 21, 2025
Text editor powered by tinymce.