You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESP32C3与Sylvania A19智能灯泡BLE连接及写入失败求助

问题分析与解决方案

一、连接失败的核心问题及修复

你的代码存在几个关键的连接逻辑错误,同时服务UUID的获取方式也不准确:

  1. 扫描回调内直接连接的资源冲突
    扫描回调onResult会被频繁触发,在回调内创建BLEClient并发起连接会导致资源竞争,且扫描未停止时连接稳定性极差。应该在找到目标设备后立即停止扫描,再在主线程中执行连接操作。

  2. 缺少连接与服务获取的错误检查
    原代码没有判断connect()是否成功,也没有检查getService()返回的服务是否为空,一旦UUID错误或连接失败,后续代码会直接崩溃。

  3. 依赖广播UUID的局限性
    BLE广播只会携带部分服务UUID,灯泡的完整服务列表需要连接后主动发现,不能直接用广播的getServiceUUID()作为控制服务的UUID。

二、写入无效的问题根源

  1. 写入值格式错误
    writeValue("00 00 00 00 00 00")传递的是带空格的字符串,而BLE特征写入需要的是字节数组,这种字符串会被当作ASCII字符发送,并非你预期的6个0x00字节。

  2. 指令格式不匹配
    Sylvania智能灯泡的BLE控制通常需要符合其私有协议,并非简单的00串或字符串指令,需要找到正确的可写特征后,再匹配对应的指令格式。

三、修改后的代码

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#include <BLEClient.h>
#include <BLEAddress.h>

#define BLE_SCAN_DURATION 5
#define SYLVANIA_SMART_BULB_ADDRESS "你的灯泡MAC地址"

BLEAddress targetBulbAddr(SYLVANIA_SMART_BULB_ADDRESS);
bool bulbFound = false;

class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
public:
    void onResult(BLEAdvertisedDevice advertisedDevice) {
        Serial.printf("发现设备: %s | 广播名称: %s\n", 
                      advertisedDevice.getAddress().toString().c_str(),
                      advertisedDevice.getName().c_str());
        
        // 匹配目标设备
        if (advertisedDevice.getAddress() == targetBulbAddr) {
            Serial.println("找到目标Sylvania灯泡,停止扫描");
            bulbFound = true;
            BLEDevice::getScan()->stop(); // 立即停止扫描
        }
    }
};

// 连接设备并发现所有服务与特征
void connectAndDiscoverServices() {
    BLEClient* pClient = BLEDevice::createClient();
    if (!pClient) {
        Serial.println("创建BLE客户端失败");
        return;
    }

    // 发起连接并检查结果
    if (!pClient->connect(targetBulbAddr)) {
        Serial.println("连接灯泡失败");
        pClient->deleteClient();
        return;
    }
    Serial.println("成功连接灯泡");

    // 发现所有服务
    std::vector<BLERemoteService*> services = pClient->getServices();
    Serial.printf("共发现 %d 个服务:\n", services.size());
    for (auto service : services) {
        Serial.printf("服务UUID: %s\n", service->getUUID().toString().c_str());
        
        // 发现该服务下的所有特征
        std::vector<BLERemoteCharacteristic*> chars = service->getCharacteristics();
        for (auto chr : chars) {
            // 打印特征属性(可写、可读、通知等)
            uint32_t props = chr->getProperties();
            String propStr = "";
            if (props & BLERemoteCharacteristic::PROPERTY_WRITE) propStr += "可写 ";
            if (props & BLERemoteCharacteristic::PROPERTY_READ) propStr += "可读 ";
            if (props & BLERemoteCharacteristic::PROPERTY_NOTIFY) propStr += "通知 ";
            
            Serial.printf("  特征UUID: %s | 属性: %s\n", 
                          chr->getUUID().toString().c_str(),
                          propStr.c_str());
        }
    }

    // 假设你找到正确的可写特征UUID后,替换下面的内容
    // BLERemoteService* pService = pClient->getService("正确的服务UUID");
    // if (pService) {
    //     BLERemoteCharacteristic* pChar = pService->getCharacteristic("正确的特征UUID");
    //     if (pChar && pChar->canWrite()) {
    //         // 发送正确的字节指令,示例:6个0x00字节
    //         uint8_t cmd[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    //         pChar->writeValue(cmd, sizeof(cmd));
    //         Serial.println("已发送控制指令");
    //     }
    // }

    pClient->disconnect();
    pClient->deleteClient();
}

void setup() {
    Serial.begin(115200);
    BLEDevice::init("ESP32C3-BLE-Client");

    // 启动扫描
    BLEScan* pScan = BLEDevice::getScan();
    pScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
    pScan->setActiveScan(true);
    pScan->start(BLE_SCAN_DURATION, false); // 第二个参数false表示扫描结束后不自动删除扫描对象

    // 扫描结束后检查是否找到目标设备
    if (bulbFound) {
        connectAndDiscoverServices();
    } else {
        Serial.println("扫描未找到目标灯泡");
    }
}

void loop() {
    // 如需重复扫描控制,可在此添加逻辑
    delay(5000);
}

四、后续操作步骤

  1. 替换代码中的SYLVANIA_SMART_BULB_ADDRESS为你实际的灯泡MAC地址(格式:AA:BB:CC:DD:EE:FF)。
  2. 上传代码后,打开串口监视器,查看打印的服务与特征列表,找到你手机APP中看到的2个可写特征,记录它们的UUID。
  3. 取消代码中注释的控制逻辑,替换为正确的服务UUID和特征UUID,并根据灯泡的协议调整控制指令(可尝试查找Sylvania BLE控制的公开协议,或通过手机APP抓包分析指令)。

内容的提问来源于stack exchange,提问作者Tyler Yarborough

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 10:52:53