BLE Write Characteristic Not Working, Peer Device Missing Error

Hi All,

I am trying to make a particle app that can communicate with a Flutter app. I am using both my own built flutter app and the NRF app while developing the particle code. When I try to write a value to my SCharacteristic it seems like my onDataReceived app is not being called. However I do get the following error from the particle serial monitor:

0001066308 [wiring.ble] ERROR: Peer device is missing!

Hoping I have done something stupid and just left something out. Any troubleshooting help would be greatly appreciated.

#include "Particle.h"

SYSTEM_THREAD(ENABLED);

SerialLogHandler logHandler(LOG_LEVEL_INFO);

const unsigned long UPDATE_INTERVAL_MS = 2000;
unsigned long lastUpdate = 0;

const BleUuid serviceUuid("5c1b9a0d-b5be-4a40-8f7a-66b36d0a5176");
BleCharacteristic WeightCharacteristic("Weight", BleCharacteristicProperty::NOTIFY, BleUuid("b8dfe276-54d4-4e5b-8daa-252157d0e1a9"), serviceUuid);
BleCharacteristic SCharacteristic("S", BleCharacteristicProperty::WRITE_WO_RSP, BleUuid("0554102a-5399-4f1c-9e56-6a071dddd4b8"), serviceUuid, onDataReceived, NULL);
float lastValue = 37.0; 

void setup()
{
	(void)logHandler; // Does nothing, just to eliminate the unused variable warning
	BLE.on();
	Serial.begin();
    String id = System.deviceID();
	BLE.addCharacteristic(WeightCharacteristic);
	BLE.addCharacteristic(SCharacteristic);
    SCharacteristic.onDataReceived(onDataReceived, NULL);
	BleAdvertisingData advData;
	advData.appendLocalName(id.c_str()); 
	advData.appendServiceUUID(serviceUuid);
	BLE.advertise(&advData);
	Serial.println("setup complete");
}

void update_ble_characteristic(BleCharacteristic c, float v){
    int32_t newValue = int32_t(v*1000);
    c.setValue(newValue);
}

void loop()
{
	if (millis() - lastUpdate >= UPDATE_INTERVAL_MS){
		lastUpdate = millis();
		if (BLE.connected()){
			float value = lastValue;
			update_ble_characteristic(WeightCharacteristic, value);
			for(int i=0;i<10;i++){
			    delay(5);
			    value += 0.1;
			    update_ble_characteristic(WeightCharacteristic, value);
			}
			
		}
	}
}


void onDataReceived(const uint8_t* data, size_t len, const BlePeerDevice& peer, void* context) {
    Serial.println("Data Incoming");
    for (size_t ii = 0; ii < len; ii++) {
        Serial.write(data[ii]);
    }
}

I fear the device ID plus the service UUID will not fit in your advertising data (unless you use BLE_PHYS_CODED which is not supported by many devices yet).
With a 16 byte UUID in the advertising data your local name should not be longer than 8 characters.

With a slightly altered code which uses a shorter name I get the data just fine.

Testing your peripheral with an app like nRF Connect often helps debugging.
With the long name the device was not discoverable for the app.

SYSTEM_THREAD(ENABLED);

SerialLogHandler logHandler(LOG_LEVEL_ERROR, {{"app", LOG_LEVEL_INFO}});

const unsigned long UPDATE_INTERVAL_MS = 2000;
unsigned long lastUpdate = 0;

const BleUuid srvUuid("5c1b9a0d-b5be-4a40-8f7a-66b36d0a5176");
const BleUuid txUuid("b8dfe276-54d4-4e5b-8daa-252157d0e1a9");
const BleUuid rxUuid("0554102a-5399-4f1c-9e56-6a071dddd4b8");

BleCharacteristic WeightCharacteristic("Weight", BleCharacteristicProperty::NOTIFY, txUuid, srvUuid);
BleCharacteristic SCharacteristic("S", BleCharacteristicProperty::WRITE_WO_RSP, rxUuid, srvUuid, onDataReceived, NULL);

void setup() {
  BLE.on();
  BLE.addCharacteristic(WeightCharacteristic);
  BLE.addCharacteristic(SCharacteristic);
  BleAdvertisingData advData;
  advData.appendLocalName("12345678"); 
  advData.appendServiceUUID(srvUuid);
  BLE.advertise(&advData);
  Log.info("setup complete");
}

void update_ble_characteristic(BleCharacteristic c, float v) {
  int32_t newValue = int32_t(v*1000);
  c.setValue(newValue);
}

void loop() {
  static uint32_t ms = 0;
  if(millis() - ms < UPDATE_INTERVAL_MS) return;
  ms = millis();
  
  if (BLE.connected()) 
    update_ble_characteristic(WeightCharacteristic, random(100) / 10.0);
}

void onDataReceived(const uint8_t* data, size_t len, const BlePeerDevice& peer, void* context) {
  Log.info("Data Incoming");
  for (size_t ii = 0; ii < len; ii++)
    Serial.write(data[ii]);
    
  Serial.println();
}

Interesting point, I do see that my device name is being truncated. However I am still able to detect and read the notifying characteristic. The only problem is the write characteristic. Are you also able to write to the write characteristic?

I will shorten my device name and test on NRF again.

Yes, this is what I meant when I said

I meant I'm getting the data in my serial monitor connected to my Argon.

But in my code I mixed up the names for rx and tx
corrected :blush:

1 Like

So I have tried this code and still can't get the write characteristic to work. I still get the

0001066308 [wiring.ble] ERROR: Peer device is missing!

when I try to write a value to the WRITE characteristic. Seems unlikely this could be a device issue, but will quickly test with a different boron.

Ok so it does seem to be specific to one device. Your sketch works perfectly on one but on the other I get the peer error. Weird!

0001066308 [wiring.ble] ERROR: Peer device is missing!

What device OS version is the stubborn device running?
Can you try building agains 3.2.0-rc.1 and try with that?

1 Like

Good question, overlooked firmware version because I am using web IDE, normally don’t have to worry when I use workbench.

Boron #1 - v1.4.2 - working
Boron #2 - v3.1.0 - not working

After update to v3.2.0-rc.1
Boron #1 - working
Boron #2 - working

Thanks a million, seems like v3.1.0 was the issue.

1 Like

I guess the current default 2.2.0 should also have worked.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.