-
-
Notifications
You must be signed in to change notification settings - Fork 79
Service Not Found Error when Writing Commands to ESP32 in NativeScript BLE App #280
Open
Description
I’m currently building a NativeScript app that uses BLE to connect to an ESP32 microcontroller. The microcontroller initializes a BLE server with a name, a service UUID, and characteristic UUIDs, as shown in the code snippet below. My NativeScript app successfully connects to the BLE service, but when I attempt to write commands to the characteristic, I consistently receive a service_not_found error.
#include <Arduino.h> #include <BLEDevice.h> #include <BLEServer.h> #include <BLEUtils.h> #include <BLE2902.h> #include <ESP32Servo.h> #include <string> #define LOCKER_MAIN_SERVICE_UUID "3e64e8c5-6b16-4b5d-b244-5bfa29c64aa6" #define CHARACTERISTIC_SERVO_COMMANDS_UUID "c18c2e14-0b84-4b1e-8c9e-2195c62ee5e2" Servo myServo; int servoPin = 5; // Pin for servo signal BLECharacteristic *pCharacteristic; bool deviceConnected = false; class LockerServerCallbacks : public BLEServerCallbacks { void onConnect(BLEServer* pServer) { deviceConnected = true; Serial.println("Device connected"); } void onDisconnect(BLEServer* pServer) { deviceConnected = false; Serial.println("Device disconnected"); // Restart advertising pServer->startAdvertising(); Serial.println("Advertising restarted"); } }; class ServoCharacteristicsCallbacks : public BLECharacteristicCallbacks { void onWrite(BLECharacteristic *pCharacteristic) { // Use Arduino's String class to get the value String rxValue = pCharacteristic->getValue().c_str(); // Get the value as a String if (rxValue.length() > 0) { // Convert the received string to an integer (assuming single-digit commands) int command = rxValue[0] - '0'; // Convert ASCII character to integer Serial.print("Received: "); Serial.println(command); // Print the received command // Move the servo based on the command moveServo(command); } } void moveServo(int command) { //moving the servo code... } }; void setup() { Serial.begin(115200); // Attach the servo to the pin myServo.attach(servoPin); myServo.write(90); // Center the servo delay(1000); // Wait for 2 seconds for the servo to stabilize // BLE setup BLEDevice::init("MyESP32Locker"); Serial.println("Initializing MyESP32Locker"); // Create BLE Server BLEServer *pServer = BLEDevice::createServer(); pServer->setCallbacks(new LockerServerCallbacks()); // Create BLE service BLEService *pService = pServer->createService(LOCKER_MAIN_SERVICE_UUID); // Create a BLE characteristic pCharacteristic = pService->createCharacteristic( CHARACTERISTIC_SERVO_COMMANDS_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE ); pCharacteristic->setCallbacks(new ServoCharacteristicsCallbacks()); // Start the service pService->start(); Serial.println("BLE service started!"); // Start advertising BLEAdvertising *pAdvertising = BLEDevice::getAdvertising(); // Enable scan response pAdvertising->setScanResponse(true); pAdvertising->setMinPreferred(0x06); // Functions that help with iPhone connections pAdvertising->setMinPreferred(0x12); Serial.println("Starting BLE advertising..."); // BLEDevice::startAdvertising(); // pAdvertising->start(); pServer->startAdvertising(); Serial.println("BLE advertising started, Waiting for a client connection to notify..."); } void loop() { // Do nothing here }``` Native script code: ```javascript const Bluetooth = require("@nativescript-community/ble").Bluetooth; const { fromObject } = require("@nativescript/core"); const createViewModel = require("@/view-models/loading-view-model").createViewModel; const Permissions = require("nativescript-permissions"); // Correctly import the permissions module // UUIDs for your ESP32 BLE service and characteristic (replace with actual ones) const LOCKER_MAIN_SERVICE_UUID = "3e64e8c5-6b16-4b5d-b244-5bfa29c64aa6"; // Change this to a unique UUID const CHARACTERISTIC_SERVO_COMMANDS_UUID = "c18c2e14-0b84-4b1e-8c9e-2195c62ee5e2"; // Change this to a uniq // Create and export the ViewModel const viewModel = createViewModel(); const bluetooth = new Bluetooth(); let connectedPeripheral; // Function to check and request Bluetooth permissions function doRequestPermissions() { return Permissions.requestPermissions([ android.Manifest.permission.BLUETOOTH, android.Manifest.permission.BLUETOOTH_ADMIN, android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION, ]); } async function onNavigatingTo(args) { const page = args.object; page.bindingContext = viewModel; // Set the binding context to the view model // TODO Check if Bluetooth on the device is enabled?! // Request permissions try { await doRequestPermissions(); console.log("All permissions granted"); // Start scanning for devices after permissions are granted scanAndConnect(); } catch (error) { console.error("Error while requesting permissions: ", error); } }; async function scanAndConnect() { try { viewModel.isConnecting = true; viewModel.connectionStatus = `Scanning for Locker device with service UUID ${LOCKER_MAIN_SERVICE_UUID}`; console.log(`Scanning for Locker device with service UUID ${LOCKER_MAIN_SERVICE_UUID}`); // Scan for devices with the matching SERVICE_UUID await bluetooth.startScanning({ serviceUUIDs: [LOCKER_MAIN_SERVICE_UUID], seconds: 20, onDiscovered: (peripheral) => { if (peripheral.name && peripheral.name.startsWith("MyESP32Locker")) { console.log("Discovered Locker device"); viewModel.connectionStatus = "Discovered Locker. Now Connecting..."; console.log("Peripheral object attributes:") console.dir(peripheral) connectedPeripheral = peripheral; bluetooth.stopScanning(); connectToLocker(peripheral); } }, onError:(error)=> { console.error("Error during BLE scan: ", error); viewModel.connectionStatus = "Could not find the device. Try again."; viewModel.isConnecting = false; bluetooth.stopScanning(); } }); } catch (error) { console.error("Error during BLE scan: ", error); viewModel.connectionStatus = "Error scanning for devices."; viewModel.isConnecting = false; } } // Function to connect to the Locker device async function connectToLocker(peripheral) { try { console.log("Connecting to peripheral") viewModel.connectionStatus = "Connecting to Locker..."; await bluetooth.connect({ UUID: peripheral.UUID, onConnected: (peripheral) => { console.log("Connected successfuly to "+ peripheral.name) console.log("Periperhal connected with name: " + peripheral.name); // // the peripheral object now has a list of available services: // peripheral.services.forEach(function(service) { // console.log("service found: " + JSON.stringify(service)); // });< viewModel.connectionStatus = "Connected to " + peripheral.name; viewModel.isConnecting = false; }, onDisconnected: () => { console.log("Disconnected successfuly to "+ peripheral.name) viewModel.connectionStatus = "Disconnected from " + peripheral.name; } }); } catch (error) { console.error("Error connecting to peripheral: ", error); viewModel.connectionStatus = "Connection failed."; viewModel.isConnecting = false; } } // Functions to send commands to the ESP32 async function sendCommand(command) { try { if (connectedPeripheral) { console.log("Sending command:") console.log("connectedPeripheral.UUID "+connectedPeripheral.UUID) console.log("LOCKER_MAIN_SERVICE_UUID "+LOCKER_MAIN_SERVICE_UUID) console.log("CHARACTERISTIC_SERVO_COMMANDS_UUID "+CHARACTERISTIC_SERVO_COMMANDS_UUID) console.log("[command] "+command) console.log("[command as Uint8Array] "+new Uint8Array([command]) ) // Use Uint8Array directly await bluetooth.write({ peripheralUUID: connectedPeripheral.UUID, // Use peripheralUUID instead of UUID serviceUUID: LOCKER_MAIN_SERVICE_UUID, characteristicUUID: CHARACTERISTIC_SERVO_COMMANDS_UUID, value: [0] }); console.log(`Command ${command} sent to Locker.`); } else { console.warn("No device connected."); } } catch (error) { console.error("Error sending command: ", error); } } // Export functions for button taps exports.onNavigatingTo = onNavigatingTo; exports.onScanAndConnectTap = ()=> scanAndConnect(); exports.onOpenButtonTap = () => sendCommand(0); // Send 0 to open exports.onCloseButtonTap = () => sendCommand(180); // Send 180 to close
Error I receive:
Sending command:
Error sending command: [BluetoothError]:service_not_found,arguments: {"peripheralUUID":"08:B6:1F:28:62:86","serviceUUID":"180e","characteristicUUID":"c18c2e14-0b84-4b1e-8c9e-2195c62ee5e2","value":[0]}Additional Notes:
- I have verified that the characteristic and service UUIDs are correct.
- I have used the nRF Connect application on my Android phone, and it can successfully communicate with my ESP32, sending commands to the device's service with that UUID
I would greatly appreciate any help or suggestions on how to resolve this issue. Thank you in advance!
Activity
Metadata
Metadata
Assignees
Labels
No labels