How To Make a BLE enabled Smart Bulb with STM32 and BleuIO

1. Introduction

2. Connecting the relay

Beware:

3. About the Code

void USBH_CDC_ReceiveCallback(USBH_HandleTypeDef *phost)
{
if(phost == &hUsbHostFS)
{
// Handles the data recived from the USB CDC host, here just printing it out to UART
rx_size = USBH_CDC_GetLastReceivedDataSize(phost);
HAL_UART_Transmit(&huart3, CDC_RX_Buffer, rx_size, HAL_MAX_DELAY);
// Copy buffer to external dongle_response buffer
strcpy((char *)dongle_response, (char *)CDC_RX_Buffer);
memset(CDC_RX_Buffer,0,RX_BUFF_SIZE);
USBH_CDC_Receive(phost, CDC_RX_Buffer, RX_BUFF_SIZE);
}
return;
}
/**
* @brief Simple dongle interpreter
* @retval None
*/
void dongle_interpreter(uint8_t * input)
{
if(strlen((char *)input) != 0)
{
if(strstr((char *)input, "\r\nADVERTISING...") != NULL)
{
isAdvertising = true;
}
if(strstr((char *)input, "\r\nADVERTISING STOPPED.") != NULL)
{
isAdvertising = false;
}
if(strstr((char *)input, "\r\nCONNECTED") != NULL)
{
isConnected = true;
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, GPIO_PIN_SET);
}
if(strstr((char *)input, "\r\nDISCONNECTED") != NULL)
{
isConnected = false;
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, GPIO_PIN_RESET);
}
if(strstr((char *)input, "L=0") != NULL)
{
isLightBulbOn = false;
HAL_GPIO_WritePin(Lightbulb_GPIO_Port, Lightbulb_Pin, GPIO_PIN_RESET);
writeToDongle((uint8_t*)DONGLE_SEND_LIGHT_OFF); uart_buf_len = sprintf(uart_tx_buf, "\r\nLight bulb is %s\r\n", isLightBulbOn ? "on":"off");
HAL_UART_Transmit(&huart3, (uint8_t *)uart_tx_buf, uart_buf_len, HAL_MAX_DELAY);
}
if(strstr((char *)input, "L=1") != NULL)
{
isLightBulbOn = true;
HAL_GPIO_WritePin(Lightbulb_GPIO_Port, Lightbulb_Pin, GPIO_PIN_SET);
writeToDongle((uint8_t*)DONGLE_SEND_LIGHT_ON); uart_buf_len = sprintf(uart_tx_buf, "\r\nLight bulb is %s\r\n", isLightBulbOn ? "on":"off");
HAL_UART_Transmit(&huart3, (uint8_t *)uart_tx_buf, uart_buf_len, HAL_MAX_DELAY);
}
}
memset(&dongle_response, 0, RSP_SIZE);
}
/**
* @brief Simple uart input handler
* @retval None
*/
void handleUartInput(UARTCommandTypeDef cmd)
{
switch(cmd)
{
case UART_RX_0:
{
// 0
uart_buf_len = sprintf(uart_tx_buf, "\r\n(0 pressed)\r\n");
HAL_UART_Transmit(&huart3, (uint8_t *)uart_tx_buf, uart_buf_len, HAL_MAX_DELAY);
if(isBleuIOReady)
{
writeToDongle((uint8_t*)DONGLE_CMD_ATI);
} else
{
uart_buf_len = sprintf(uart_tx_buf, BLEUIO_NOT_READY_MSG);
HAL_UART_Transmit(&huart3, (uint8_t *)uart_tx_buf, uart_buf_len, HAL_MAX_DELAY);
}
uartStatus = UART_RX_NONE;
break;
}
case UART_RX_1:
{
// 1
uart_buf_len = sprintf(uart_tx_buf, "\r\n(1 pressed light bulb on!)\r\n");
HAL_UART_Transmit(&huart3, (uint8_t *)uart_tx_buf, uart_buf_len, HAL_MAX_DELAY);
HAL_GPIO_WritePin(Lightbulb_GPIO_Port, Lightbulb_Pin, GPIO_PIN_SET);
uartStatus = UART_RX_NONE;
break;
}
case UART_RX_2:
{
// 2
uart_buf_len = sprintf(uart_tx_buf, "\r\n(2 pressed light bulb off!)\r\n");
HAL_UART_Transmit(&huart3, (uint8_t *)uart_tx_buf, uart_buf_len, HAL_MAX_DELAY);
HAL_GPIO_WritePin(Lightbulb_GPIO_Port, Lightbulb_Pin, GPIO_PIN_RESET);
uartStatus = UART_RX_NONE;
break;
}
case UART_RX_NONE:
{
break;
}
default:
{
uartStatus = UART_RX_NONE;
break;
}
}
}
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
MX_USB_HOST_Process();
/* USER CODE BEGIN 3 */
// Simple handler for uart input
handleUartInput(uartStatus);
// Inteprets the dongle data
dongle_interpreter(dongle_response);
// Starts advertising as soon as the Dongle is ready.
if(!isAdvertising && !isConnected && isBleuIOReady)
{
HAL_Delay(200);
writeToDongle((uint8_t*)DONGLE_CMD_AT_ADVSTART);
isAdvertising = true;
}
}
/* USER CODE END 3 */

4. Using the example project

4.1 What you will need

5. How to setup project

5.1 Downloading the project from GitHub

5.2 Importing as an Existing Project

6. Running the example

7. Controlling the light from a web browser

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
crossorigin="anonymous"
/>
<title>Control Light using Bleutooth Low Energy</title>
</head>
<body class="mt-5">
<div class="container mt-5">
<h1 class="mb-5">Control Light using Bleutooth Low Energy</h1>
<button class="btn btn-success" id="connect">Connect</button>
<button class="btn btn-warning" id="lightOn" disabled>Turn On</button>
<button class="btn btn-danger" id="lightOf" disabled>Turn Off</button>
</div>
<div class="container mt-5">
<img id="light" src="light_off.png" alt="" />
</div>
<script src="script.js"></script>
</body>
</html>
import * as my_dongle from "bleuio";
const dongleToConnect = "[0]40:48:FD:E5:35:A5";
import lightOnImg from "./light_on.png";
import lightOfImg from "./light_off.png";
document.getElementById("connect").addEventListener("click", function () {
my_dongle.at_connect();
document.getElementById("lightOn").disabled = false;
document.getElementById("lightOf").disabled = false;
document.getElementById("connect").disabled = true;
});
document.getElementById("lightOn").addEventListener("click", function () {
my_dongle
.ati()
.then((data) => {
//make central if not
if (JSON.stringify(data).includes("Peripheral")) {
console.log("peripheral");
my_dongle.at_central().then((x) => {
console.log("central now");
});
}
})
.then(() => {
// connect to dongle
my_dongle
.at_getconn()
.then((y) => {
if (JSON.stringify(y).includes(dongleToConnect)) {
console.log("already connected");
} else {
my_dongle.at_gapconnect(dongleToConnect).then(() => {
console.log("connected successfully");
});
}
})
.then(() => {
// send command to control light
my_dongle.at_spssend("L=1").then(() => {
console.log("Turned on");
document.getElementById("light").src = lightOnImg;
});
});
});
});
document.getElementById("lightOf").addEventListener("click", function () {
my_dongle
.ati()
.then((data) => {
//make central if not
if (JSON.stringify(data).includes("Peripheral")) {
console.log("peripheral");
my_dongle.at_central().then((x) => {
console.log("central now");
});
}
})
.then(() => {
// connect to dongle
my_dongle
.at_getconn()
.then((y) => {
if (JSON.stringify(y).includes(dongleToConnect)) {
console.log("already connected");
} else {
my_dongle.at_gapconnect(dongleToConnect).then(() => {
console.log("connected successfully");
});
}
})
.then(() => {
// send command to control light
my_dongle.at_spssend("L=0").then(() => {
console.log("Turned off");
document.getElementById("light").src = lightOfImg;
});
});
});
});
- Open this site https://bleuio.com/web_terminal.html and click connect to dongle.
- Select the appropriate port to connect.
- Once it says connected, type **"ATI"**. This will show dongle information and current status.
- If the dongle is on peripheral role, set it to central by typing **"AT+CENTRAL"**
- Now do a gap scan by typing **"AT+GAPSCAN"**
- Once you see your dongle on the list ,stop the scan by pressing control+c
- Copy the ID and paste it into the script (script.js) line #2

--

--

--

The BleuIO is Bluetooth low energy solution that can be used to create new BLE 5.0 applications in the fastest and easiest way.

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Exploring the API-First Design Pattern

Nametag: Moving Forward

Day 13: Variables! — The Building Blocks of Programming

Dates in JavaScript, design tips, Typescript, NFTs, and more

Do You Hate How Slow Python Is? This Is How You Can Make It Run Faster!

That One Thing That Made Me Stumbled Onto Programming

The 4-Step Plan To Make Yourself Invaluable at Work

A group of three engineers working with a fourth person to help him out.

ServiceNow bi-directional integration

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
bleuio

bleuio

The BleuIO is Bluetooth low energy solution that can be used to create new BLE 5.0 applications in the fastest and easiest way.

More from Medium

THM Extending Your Network

Set up Dynamic DNS for Dynamic IP Addresses at Home (FREE) + WireGuard Configuration

Simple Bot To Book your Practical Driving Test

(How to) Secure your e-mail and prevent most cyberattacks