ESP32使用小机云开源项目可以快速使用小机云蓝牙,目前支持arduino,python,idf。ESP32开源仓库
以下以ESP32C3+arduino示例进行说明ESP32如何快速使用小机云蓝牙。python和idf的使用过程类似。
在开始使用前可以先看一下《如何使用小机云蓝牙》一文,可以帮您了解一下小机云蓝牙的工作流程
更建议使用ESP32C3/S3
使用流程概述
- 准备项目信息
- 在代码中填入项目信息
- 获取您ESP32的蓝牙地MAC址。注意,ESP32有蓝牙MAC和WIFI MAC
- 在小机云控制台,选择您的蓝牙项目,在设备列表中,使用您的MAC地址(不要冒号)创建设备
- 查看小程序/APP下发的数据
- 上传您的数据到小程序/APP
开始使用ESP32
1. 准备项目信息
在电脑打开小机云控制台 xsgee.com。创建或选择您的蓝牙项目。在更多中查看项目详情。
我们需要准备三个信息,ProjectId,ProjectSecret,校验内容格式(KEY_CONTENT)

2. 填入项目信息
您只需要根据您的项目类型,把上面拿到的项目信息填入到您的代码中
arduino配置项目信息
c
//ProjectId
#define X_PROJECT_ID "xxxxxx"
//ProjectSecret
#define X_PROJECT_SECRET "xxxxx"
//校验内容格式
#define X_PROJECT_KEY "projectId.mac.myContent.timestamp"python填入项目信息
python
PROJECT_ID = "1013b0e95e00e911"
PROJECT_SECRET = "AF441806D87DB58A17A627101AF33780"
PROJECT_KEY = "projectId.mac.myContent.timestamp"idf填入项目信息
c++
#define CONFIG_PROJECT_ID "1013b0e95e00e911"
#define CONFIG_PROJECT_SECRET "AF441806D87DB58A17A627101AF33780"
#define CONFIG_PROJECT_KEY "projectId.mac.myContent.timestamp"3. 获取您的蓝牙MAC
您可以通过下面方式获取您的蓝牙MAC
arduino打印蓝牙mac地址
c++
uint8_t *mac = BLEDevice::getAddress().getNative()
//注意是倒叙
Serial.printf("%02X%02X%02X%02X%02X%02X\n", mac[5], mac[4], mac[3], mac[2], mac[1], mac[0]);python获取并打印蓝牙mqc
python
ble = bluetooth.BLE()
# 获取 MAC 地址(字节格式)
mac_bytes = ble.config('mac')[1]
# 转换为常见的十六进制显示格式
mac_hex = ubinascii.hexlify(mac_bytes).decode()
# 或者使用 mac_bytes.hex()
print("MAC bytes:", mac_bytes) # b'\xb8:\x1c...'
print("MAC hex:", mac_hex) # "b83a1c..."idf打印蓝牙MAC地址
c
uint8_t mac_addr[6];
// 读取蓝牙 MAC 地址
esp_read_mac(mac_addr, ESP_MAC_BT);
// 打印 MAC 地址
printf("MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
mac_addr[0], mac_addr[1], mac_addr[2],
mac_addr[3], mac_addr[4], mac_addr[5]);4. 创建设备
在您刚才选择的蓝牙项目中,进入项目-->设备列表-->创建设备。输入上面得到的MAC地址,选择任意分组,点击创建即可

5. 收发数据
arduino收发数据
c++
//xsgee-esp32-ble-arduino.ino
class MyBleCallbacks : public XBleCallbacks {
void onData(uint8_t *data, size_t len) {
String value_str = String((char *)data, len);
XLOGI("Received:%s", value_str.c_str());
}
void onConnected() {
XLOGI("Connected");
}
void onDisconnected() {
XLOGI("Disconnected");
}
void onNotifyState(uint16_t isNotified) {
XLOGI("NotifyStatus: %d" + isNotified);
}
void onAuth(bool isAuthed) {
//蓝牙连接成功后会自动向应用发起校验
XLOGI("AuthStatus: %d" + isAuthed);
//校验成功后同步设备数据
pageDataDriver.uploadData();
delay(100);
//同步设置状态
pageDataDriver.uploadBoardState();
}
void onPageData(KV* pairs, uint8_t len) {
//处理应用发下来的数据是一串字符串协议,例如$X#D#switch:0&57\r\n,提取出switch:0
//这里已经转为key:value格式,pairs里面就是点击页面组件后发下来的key:value
pageDataDriver.handler(pairs, len);
}
};
//PageDataDriver.cpp
void PageDataDriver::handler(KV* pairs, uint8_t len) {
for (uint8_t i = 0; i < len; i++) {
if (pairs[i].key[0] == '\0') {
continue;
}
const char* key = reinterpret_cast<const char*>(pairs[i].key);
const char* value = reinterpret_cast<const char*>(pairs[i].value);
//处理应用发下来的数据,这里开始已经别名为switch,也就是这里说的关键字key
//key后面会带一个value,switch的value是0或1,0表示关,1表示开
if (strncmp(key, "switch", 6) == 0) {
int v = value[0] - '0';
XLOGD("switch value:%d", v);
if (v) {
// 硬件LED控制开
digitalWrite(LED_PIN, HIGH);
m_ledState = 1;
} else {
// 硬件LED控制关
digitalWrite(LED_PIN, LOW);
m_ledState = 0;
}
} else if (strncmp(key, "slider", 6) == 0) {
int v = atoi(value);
XLOGD("slider value:%d", v);
analogWrite(PWM_PIN, v);
m_pwm = v;
}
}
uploadData();
}
void PageDataDriver::uploadData() {
getTemperature();
getButtonState();
char tempValue[16];
snprintf(tempValue, sizeof(tempValue), "%.2f", m_temperature);
//随机颜色,格式为RRGGBB
char colorStr[8];
generateColor(colorStr);
int kv_size = 5;
//读硬件状态,组合成key-value数组
KV kvs[kv_size] = {
KV("switch", std::to_string(m_ledState)),
KV("slider", std::to_string(m_pwm)),
KV("temperature", tempValue),
KV("@IN1", std::to_string(m_buttonState)),
KV("color", colorStr),
};
//sendKvCmd会把kvs数组还原成字条串发送给应用
//注意:kv组合成字符串的长度应小于X_CMD_MAX_LEN - 6
if(xBle.isConnected){
xBle.sendKvCmd("D", kvs, kv_size);
}
}python收发数据
python
# main.py
class MyBleCallbacks(XBleCallbacks):
"""自定义BLE回调类"""
def __init__(self):
super().__init__()
def onConnected(self):
"""连接成功回调"""
print("isConnected!")
def onDisconnected(self):
"""断开连接回调"""
print("isDisconnected!")
def onAuth(self, isAuth):
"""认证结果回调"""
print(f"isAuth: {isAuth}")
driver.uploadData()
time.sleep_ms(50)
driver.uploadBoardState()
def onPageData(self, pairs, length):
"""页面数据回调,已经转成key-value格式,可以参数arduino onPageData的注释"""
# for i, kv in enumerate(pairs):
# print(f" [{i}] {kv.key} = {kv.value}")
driver.handler(pairs)
# pageDataDriver.py
# 处理应用数据,可以参考arduino的注释
def handler(self, pairs):
try:
for kv in pairs:
key = kv.key
value = kv.value
if not key:
continue
if key == "switch" and len(key) >= 6:
v = int(value[0]) if value else 0
print(f"switch value:{v}")
if v:
self.led.value(1) # HIGH
self.m_ledState = 1
else:
self.led.value(0) # LOW
self.m_ledState = 0
elif key == "slider" and len(key) >= 6:
v = int(value) if value else 0
print(f"slider value:{v}")
self.pwm.duty(v * 1023 // 100)
self.m_pwm = v
self.uploadData()
except Exception as e:
print(f"handler error: {e}")
# 上传数据到应用,可以参考arduino的注释
def uploadData(self):
self.getTemperature()
self.getButtonState()
tempValue = f"{self.m_temperature:.2f}"
colorStr = self.generateColor()
kvs = [
KV("switch", str(self.m_ledState)),
KV("slider", str(self.m_pwm)),
KV("temperature", tempValue),
KV("@IN1", str(self.m_buttonState)),
KV("color", colorStr)
]
if self.ble.isConnected():
self.ble.sendKvCmd("D", kvs)如果您遇上无法搜索到设备等问题,可以看一下这篇文章,常见问题
小机云