0

I just received my ESP32C3 micro controller and only have one smart bulb to learn with. I wrote BLE scan code first and found the bulb. printed both UUIDs and address needed to connect. It wont connect but Im starting to think the service UUIDs are wrong. BLE scanner on my phone show 7 or so services. Only 2 of which allow write. Here is my code. Any help would be much appreciated.

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

// The BLE scan duration in seconds
#define BLE_SCAN_DURATION 5

// The MAC address of the Sylvania Smart+ bulb
#define SYLVANIA_SMART_BULB_ADDRESS "CHANGE ME"

// The service UUID and characteristic UUID of the Sylvania Smart+ bulb
#define SYLVANIA_SMART_BULB_SERVICE_UUID "CHANGE ME"
#define SYLVANIA_SMART_BULB_CHARACTERISTIC_UUID "CHANGE ME"

// Function to handle the BLE scan results
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
public:
  void onResult(BLEAdvertisedDevice advertisedDevice) {
    
      // Print the MAC address, service UUID, and characteristic UUID of the smart bulb
      Serial.printf("Found smart bulb: %s\n", advertisedDevice.getAddress().toString().c_str());
      Serial.printf("Service UUID: %s\n", advertisedDevice.getServiceUUID().toString().c_str());
      Serial.printf("Characteristic UUID: %s\n", advertisedDevice.getServiceDataUUID().toString().c_str());

      // Check if the smart bulb is the Sylvania Smart+ bulb
      if (advertisedDevice.getAddress().toString() == SYLVANIA_SMART_BULB_ADDRESS) {
        // Connect to the Sylvania Smart+ bulb
        BLEClient* pClient = BLEDevice::createClient();
        BLEAddress bulbAddress(SYLVANIA_SMART_BULB_ADDRESS);
        pClient->connect(bulbAddress);

        // Get the service and characteristic of the Sylvania Smart+ bulb
        BLERemoteService* pService = pClient->getService(SYLVANIA_SMART_BULB_SERVICE_UUID);
        BLERemoteCharacteristic* pCharacteristic = pService->getCharacteristic(SYLVANIA_SMART_BULB_CHARACTERISTIC_UUID);

        // Turn off the Sylvania Smart+ bulb
        pCharacteristic->writeValue("00 00 00 00 00 00");

        // Disconnect from the Sylvania Smart+ bulb
        pClient->disconnect();
      }
    }
};

void setup() {
  Serial.begin(115200);

  // Initialize the BLE device
  BLEDevice::init("");

  // Start the BLE scan
  BLEScan* pScan = BLEDevice::getScan();
  pScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pScan->setActiveScan(true);
  pScan->start(BLE_SCAN_DURATION);
}

void loop() {
  // Do nothing in the loop
}

I tried writing \Off \OFF \off 00 00 00 00 00 00 etc.. with my BLE scanner app, still no joy.

I still cant connect anyway so its a 2 step issue.

  • Should you write the string value `"00 00 00 00 00 00"` or a byte array containing 6 zero bytes? – Emil Feb 28 '23 at 07:50
  • Honestly, I have no idea. There are almost 0 docs on its BLE protocols. I posted on reddit and the consensus is to not use BLE devices unless I dev both end points. Just use wifi devices and dev an API that is on my LAN as a control hub. Im guessing these manufacturers do this so people are forced to use their proprietary apps where they can advertise further. Im just confused why that code wont connect at all when a rando BLE scanner app will. That code should connect given the correct addr and UUIDs but it doesn't. – Tyler Yarborough Feb 28 '23 at 19:00
  • Not an actual solution, but running this code you have no idea what it is actually doing, e.g. whether it succeeds in trying to connect or read a service or a characteristic etc. I recommend checking your return values and printing out something if they indicate failure. Do I understand correctly that you have no documentation on the BLE interface for your bulb? You cannot just guess what an API is. It needs documentation or an example. Maybe you can intercept the BLE interactions between the bulb and manufacturers app, or something. Certainly doesn't look like a job for a beginner. – Tarmo Mar 01 '23 at 14:37
  • Beginner or not, doing stuff like this is how you learn. Im not going to look at a task and think to myself and think, "Nah, thats too hard." Especially considering I have a Bachelors in software engineering. I DO know what an API is also considering that Im running a custom one using Flask coded in python. As for the code, I stripped out my threading and WiFi logic that runs async. Your idea about a MiM probe is a great idea though. Ill use bluesnarfer on my Kali box. Not trying to be a D* but approaching people with that "Leave it alone" is why people dont try to learn challenging things. – Tyler Yarborough Mar 01 '23 at 21:08

1 Answers1

0

It seems your command to turn off the bulb is malformed.

pCharacteristic->writeValue("00 00 00 00 00 00");  <--- seems wrong

I looked at the signature for the writeValue() method (as defined in the BLERemoteCharacteristic class) and it seems you shouldn't be sending a string of hex values.

Available signatures are:

void BLERemoteCharacteristic::writeValue(std::string newValue, bool response)
void BLERemoteCharacteristic::writeValue(uint8_t newValue, bool response)
void BLERemoteCharacteristic::writeValue(uint8_t* data, size_t length, bool response)

and the std::string version should be use the actual data as a string.

Assuming you want to send 6 zero bytes to turn it off, you could do

uint8_t data[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
pCharacteristic->writeValue(data, 6, false);

Though I couldn't find any resource detailing what commands the Sylvania Smart+ bulb accepts.

mmixLinus
  • 1,646
  • 2
  • 11
  • 16