ESP32 as reader to Bangle.js

Posted on
  • Hello,
    I have one question: how to read values from bangle.js by device like esp32? I want to use it for my project will external display values from wristband.
    I guess that it will be needed to connect to specified bangle.js and then somehow use data similar way to js.

    BR
    QNerk

  • @Q_NErk, you mean peer to peer BT communication between Bangle.js and ESP32? ...where Bangle.js raises the data and an EPS32 collecting it? ...from one or multiple Bangle.js?

  • It can be peer to peer or it can be brodacasted by bangle.js via BT. Yes, ESP32 will collect data. The best will be from multiple Bangle.js

  • If you're thinking of multiple Bangle.js then make them advertise the data over BLE with NRF.setAdvertising.

    You can then use ESP32 to read that data. If you're using Espruino on it you can do NRF.setScan(...).

    To avoid having to parse un-needed advertising packets it'd better to use manufacturerData so you can filter out the devices.

    So:

    // Bangle
    NRF.setAdvertising({},{
      showName:false,
      manufacturer:0x0590,
      manufacturerData:[1,2,3] // your data here as a series of Bytes
    });
    
    // Scanner
    NRF.setScan(function(device) {
      // data is in  device.manufacturerData
    }, {filters : [{ manufacturerData:{0x0590:{}} }] });
    
  • Hello,
    I passed it this way. I have installed btadv for begining and after this I've tried to set esp32 bluetooth client:

    /**
     * A BLE client example that is rich in capabilities.
     * There is a lot new capabilities implemented.
     * author unknown
     * updated by chegewara
     */
    
    [#include](http://forum.espruino.com/sea­rch/?q=%23include) "BLEDevice.h"
    //#include "BLEScan.h"
    
    // The remote service we wish to connect to.
    static BLEUUID serviceUUID("0000180d-0000-1000-8000-008­05f9b34fb");
    // The characteristic of the remote service we are interested in.
    static BLEUUID    charUUID("0000180d-0000-1000-8000-00805f­9b34fb");
    
    static boolean doConnect = false;
    static boolean connected = false;
    static boolean doScan = false;
    static BLERemoteCharacteristic* pRemoteCharacteristic;
    static BLEAdvertisedDevice* myDevice;
    
    static void notifyCallback(
      BLERemoteCharacteristic* pBLERemoteCharacteristic,
      uint8_t* pData,
      size_t length,
      bool isNotify) {
        Serial.print("Notify callback for characteristic ");
        Serial.print(pBLERemoteCharacteristic->g­etUUID().toString().c_str());
        Serial.print(" of data length ");
        Serial.println(length);
        Serial.print("data: ");
        Serial.println((char*)pData);
    }
    
    class MyClientCallback : public BLEClientCallbacks {
      void onConnect(BLEClient* pclient) {
      }
    
      void onDisconnect(BLEClient* pclient) {
        connected = false;
        Serial.println("onDisconnect");
      }
    };
    
    bool connectToServer() {
        Serial.print("Forming a connection to ");
        Serial.println(myDevice->getAddress().to­String().c_str());
        
        BLEClient*  pClient  = BLEDevice::createClient();
        Serial.println(" - Created client");
    
        pClient->setClientCallbacks(new MyClientCallback());
    
        // Connect to the remove BLE Server.
        pClient->connect(myDevice);  // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
        Serial.println(" - Connected to server");
        pClient->setMTU(517); //set client to request maximum MTU from server (default is 23 otherwise)
      
        // Obtain a reference to the service we are after in the remote BLE server.
        BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
        if (pRemoteService == nullptr) {
          Serial.print("Failed to find our service UUID: ");
          Serial.println(serviceUUID.toString().c_­str());
          pClient->disconnect();
          return false;
        }
        Serial.println(" - Found our service");
    
    
        // Obtain a reference to the characteristic in the service of the remote BLE server.
        pRemoteCharacteristic = pRemoteService->getCharacteristic(charUU­ID);
        if (pRemoteCharacteristic == nullptr) {
          Serial.print("Failed to find our characteristic UUID: ");
          Serial.println(charUUID.toString().c_str­());
          pClient->disconnect();
          return false;
        }
        Serial.println(" - Found our characteristic");
    
        // Read the value of the characteristic.
        if(pRemoteCharacteristic->canRead()) {
          std::string value = pRemoteCharacteristic->readValue();
          Serial.print("The characteristic value was: ");
          Serial.println(value.c_str());
        }
    
        if(pRemoteCharacteristic->canNotify())
          pRemoteCharacteristic->registerForNotify­(notifyCallback);
    
        connected = true;
        return true;
    }
    /**
     * Scan for BLE servers and find the first one that advertises the service we are looking for.
     */
    class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
     /**
       * Called for each advertising BLE server.
       */
      void onResult(BLEAdvertisedDevice advertisedDevice) {
        Serial.print("BLE Advertised Device found: ");
        Serial.println(advertisedDevice.toString­().c_str());
    
        // We have found a device, let us now see if it contains the service we are looking for.
        if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(se­rviceUUID)) {
    
          BLEDevice::getScan()->stop();
          myDevice = new BLEAdvertisedDevice(advertisedDevice);
          doConnect = true;
          doScan = true;
    
        } // Found our server
      } // onResult
    }; // MyAdvertisedDeviceCallbacks
    
    
    void setup() {
      Serial.begin(115200);
      Serial.println("Starting Arduino BLE Client application...");
      BLEDevice::init("");
    
      // Retrieve a Scanner and set the callback we want to use to be informed when we
      // have detected a new device.  Specify that we want active scanning and start the
      // scan to run for 5 seconds.
      BLEScan* pBLEScan = BLEDevice::getScan();
      pBLEScan->setAdvertisedDeviceCallbacks(n­ew MyAdvertisedDeviceCallbacks());
      pBLEScan->setInterval(1349);
      pBLEScan->setWindow(449);
      pBLEScan->setActiveScan(true);
      pBLEScan->start(5, false);
    } // End of setup.
    
    
    // This is the Arduino main loop function.
    void loop() {
    
      // If the flag "doConnect" is true then we have scanned for and found the desired
      // BLE Server with which we wish to connect.  Now we connect to it.  Once we are 
      // connected we set the connected flag to be true.
      if (doConnect == true) {
        if (connectToServer()) {
          Serial.println("We are now connected to the BLE Server.");
        } else {
          Serial.println("We have failed to connect to the server; there is nothin more we will do.");
        }
        doConnect = false;
      }
    
      // If we are connected to a peer BLE Server, update the characteristic each time we are reached
      // with the current time since boot.
      if (connected) {
        String newValue = "Time since boot: " + String(millis()/1000);
        Serial.println("Setting new characteristic value to \"" + newValue + "\"");
        
        // Set the characteristic's value to be the array of bytes that is actually a string.
        pRemoteCharacteristic->writeValue(newVal­ue.c_str(), newValue.length());
      }else if(doScan){
        BLEDevice::getScan()->start(0);  // this is just example to start scan after disconnect, most likely there is better way to do it in arduino
      }
      
      delay(1000); // Delay a second between loops.
    } // End of loop
    

    And I'm receiving:

    BLE Advertised Device found: Name: Bangle.js e4e1, Address: f0:40:5d:1d:e4:e1, serviceUUID: 0000180d-0000-1000-8000-00805f9b34fb, serviceUUID: 0000181a-0000-1000-8000-00805f9b34fb, serviceUUID: 00001819-0000-1000-8000-00805f9b34fb
    Forming a connection to f0:40:5d:1d:e4:e1
     - Created client
     - Connected to server
     - Found our service
    Failed to find our characteristic UUID: 0000180d-0000-1000-8000-00805f9b34fb
    We have failed to connect to the server; there is nothin more we will do.
    onDisconnect
    
    

    What I'm doing wrong?

  • Am I right in thinking that you're not using my example code but are instead trying to connect directly to the Bangle?

    It looks like you're searching for UUID 0000180d-0000-1000-8000-00805f9b34fb which is not something that Bangle.js provides by default as far as I know, so you'd have to add it with NRF.setServices on the Bangle first.

    Or, you could change the characteristics to the ones used for Nordic UART (https://www.espruino.com/Interfacing#blu­etooth-le):

    static BLEUUID serviceUUID("6e400001-b5a3-f393-e0a9-e50­e24dcca9e");
    static BLEUUID    charUUID("6e400002-b5a3-f393-e0a9-e50e24­dcca9e"); // WRITE characteristic
    

    However if you were going to do what I suggested then you could skip connecting, and just read the data from the advertisement you found in MyAdvertisedDeviceCallbacks.

    I should also note that you can just run Espruino on the ESP32 too, and if you do that you don't need any C code - in fact everything you need is in my last answer

  • What I'm doing wrong?

    You picked random Arduino example without understanding what it does (at all)?
    You just paste the example verbatim here and see what happens?
    You talk about "ESP32" or "esp32 bluetooth client" but in fact you mean "Arduino for ESP32"?

    Or maybe you are just some AI bot that did not get the context right? Your post #5 is pretty odd considering previous posts and this being Espruino forum :-)

    Anyway, you don't need to create connection to Bangle to read what it is advertising.
    Whether to use advertising or connection depends how much data it is, how often it is changing, how reliable it should be, how often Bangle moves out of signal range.

    Also you can have only one concurrent connection to the Bangle so if you have phone connected to it already you cannot make second connection from ESP32, that would also mean advertising could be the way. I think in very recent builds Bangle can still advertise while there is something already connected to it.

  • I'm not a bot (I know, all bot can say it :))
    I'm not familiar with JS, that why I'm trying to solve it anyhow by (like You said) c in Arduino envoirment. This is my first tries with BT/BLE.

  • that why I'm trying to solve it anyhow by (like You said) c in Arduino envoirment.

    It is perfectly OK to use any solution. It is just that we cannot help you much here with details of using BLE in Arduino.

    This is my first tries with BT/BLE.

    We can still discuss generic BLE concepts (advertising vs connection) and how to do the Bangle.js side here. For that you already had some suggestions.

    Advertising is short data packet broadcasted periodically containing typically a device name but you can add anything small there (up to 31 bytes total or 2*31bytes - with optional advertising response packet). Then just scanning on the other side and parsing the advertising result should be enough - inside your MyAdvertisedDeviceCallbacks::onResult(BL­EAdvertisedDevice advertisedDevice).

    Currently it checks serviceUUID which can be there too advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(se­rviceUUID) but there can be also other custom data you put there.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

ESP32 as reader to Bangle.js

Posted by Avatar for Q_NErk @Q_NErk

Actions