-
-
Notifications
You must be signed in to change notification settings - Fork 80
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!
Metadata
Metadata
Assignees
Labels
No labels