I’ll have to look into this and investigate some ideas 
Hey Ryan (@RWB) I wasn’t exactly diggint into the RSSI question as such but I had an alternative approach in mind where either device can take on the role of the box or the key and hence either one can scan for the other and as such read it’s counterparty’s RSSI (or do other stuff).
(again by hitting the MODE button you can trigger the main action - in this case becoming the BLE central and connecting/disconnecting to/from the peripheral)
#include "Particle.h"
#if (PLATFORM_ID == PLATFORM_XENON)
SYSTEM_MODE(MANUAL)
#endif
SYSTEM_THREAD(ENABLED)
SerialLogHandler logger(LOG_LEVEL_ALL);
const uint16_t vendorBox = 0xFE01;
const BleUuid serviceBoxUuid("0000FE01-0000-1000-8000-00805F9B34FB");
const BleUuid charstxBoxUuid("0000FE02-0000-1000-8000-00805F9B34FB");
const uint16_t charstxBoxNum = 0xFE02;
const uint16_t vendorKey = 0xFE10;
const BleUuid serviceKeyUuid("0000FE10-0000-1000-8000-00805F9B34FB");
BleAdvertisingData advData;
BleAddress peerAddress;
bool peerAddressValid = false;
BlePeerDevice peerDevice;
BleCharacteristic charstxBox;
BleCharacteristic charstxKey;
enum BLE_ROLE { BOX, KEY };
enum BLE_STATE { IDLE, SCAN, SCAN_WAIT, CONNECT, CONNECT_WAIT, READ_DATA, SEND_DATA, DISCONNECT };
BLE_ROLE bleRole = BOX;
BLE_STATE bleState = IDLE;
uint32_t msStateTimeout = 10000;
bool attachPeer(BleAddress addr, BlePeerDevice& peer, int maxCharacteristics = 20);
void setup() {
Serial.begin();
System.on(button_click, clickHandler);
pinMode(D7, OUTPUT);
BLE.onConnected(onConnected, NULL);
BLE.onDisconnected(onDisconnected, NULL);
advData.appendLocalName("BleBox");
advData.appendServiceUUID(serviceBoxUuid);
BLE.advertise(&advData);
}
void loop() {
static uint32_t msStateTime = 0;
switch (bleState) {
case IDLE:
break;
case SCAN:
BLE.stopAdvertising();
peerAddressValid = false;
BLE.scan(scanResultCallback, NULL);
bleState = SCAN_WAIT;
msStateTimeout = 5000;
msStateTime = millis();
break;
case SCAN_WAIT:
if (peerAddressValid)
bleState = CONNECT;
else if (millis() - msStateTime > msStateTimeout) {
Log.warn("timeout at state %d", bleState);
bleState = DISCONNECT;
}
break;
case CONNECT:
if (peerAddressValid) {
attachPeer(peerAddress, peerDevice);
bleState = CONNECT_WAIT;
msStateTimeout = 5000;
msStateTime = millis();
}
else
bleState = DISCONNECT;
break;
case CONNECT_WAIT:
if (peerDevice.connected()) {
Log.info("I'm a Key now");
bleState = READ_DATA;
msStateTimeout = 1000;
msStateTime = millis();
}
else if (millis() - msStateTime > msStateTimeout) {
Log.warn("timeout at state %d", bleState);
bleState = DISCONNECT;
}
break;
case READ_DATA:
if (millis() - msStateTime < msStateTimeout)
break;
if (charstxBox.valid()) {
uint32_t data;
charstxBox.getValue((uint8_t*)&data, sizeof(data));
Log.info("Box timestamp %012lu", data);
charstxBox.setValue(data);
msStateTimeout = 1000;
msStateTime = millis();
}
else {
Log.warn("invalid characteristic");
bleState = DISCONNECT;
}
break;
case SEND_DATA:
if (millis() - msStateTime < msStateTimeout)
break;
if (BLE.connected() && charstxBox.valid()) {
uint32_t data = millis();
charstxBox.setValue(data);
Log.info("my timestamp %012lu", data);
msStateTime = millis();
}
else {
Log.warn("lost connection");
bleState = DISCONNECT;
}
break;
case DISCONNECT:
BLE.disconnectAll();
peerAddressValid = false;
bleRole = BOX;
bleState = IDLE;
BLE.advertise(&advData);
break;
default:
bleState = IDLE;
break;
}
}
void scanResultCallback(const BleScanResult *scanResult, void *context) {
if (BLE.connected())
BLE.disconnectAll();
int countServ = 5; // how many do we expect
BleUuid services[countServ]; // reserve that many service UUIDs
countServ = scanResult->advertisingData.serviceUUID(services, countServ); // request up to countUuid services from advertisingData
Log.info("Found %d UUIDs in advertisingData", countServ);
for (int s = 0; s < countServ; s++) { // iterate over found services
Log.info("%d. UUID: %s (%04X)", s + 1, (const char *)services[s].toString(), services[s].shorted());
if (services[s] == serviceBoxUuid || services[s].shorted() == vendorBox) { // check against expected values
Log.trace("%s: %s ?= %s || %04X ?= %04X"
, (const char*)scanResult->address.toString()
, (const char*)services[s].toString()
, (const char*)serviceBoxUuid.toString()
, services[s].shorted()
, vendorBox);
peerAddress = scanResult->address;
peerAddressValid = true;
BLE.stopScanning();
break;
}
}
}
bool attachPeer(BleAddress addr, BlePeerDevice& peer, int maxCharacteristics) {
charstxBox = BleCharacteristic(); // invalidate characterisics
if (peer.connected())
peer.disconnect();
peer = BLE.connect(addr); // connect to the peer device
if (!peer.connected()) {
Log.warn("Couldn't connect to device");
return false;
}
Log.info("found device and connected to it");
if (!peer.getCharacteristicByUUID(charstxBox, charstxBoxUuid)) {
BleCharacteristic chars[maxCharacteristics];
int foundChar = peer.discoverAllCharacteristics(chars, maxCharacteristics);
Log.info("Found %d of %d characteristics", foundChar, maxCharacteristics);
for (int c = 0; c < foundChar; c++)
{
Log.trace("%s =? %s, %04X ?= %04x", (const char*)chars[c].UUID().toString(), (const char*)charstxBoxUuid.toString(), chars[c].UUID().shorted(), charstxBoxUuid.shorted());
if (chars[c].UUID() == charstxBoxUuid
|| chars[c].UUID().shorted() == charstxBoxUuid.shorted()
|| chars[c].UUID().shorted() == charstxBoxNum
){
charstxBox = chars[c];
break;
}
}
}
return charstxBox.valid();
}
void onConnected(const BlePeerDevice& peer, void* context) {
if (bleRole == BOX) {
charstxBox = BleCharacteristic("box", BleCharacteristicProperty::READ | BleCharacteristicProperty::WRITE_WO_RSP, charstxBoxUuid, serviceBoxUuid, onDataReceived, NULL);
BLE.addCharacteristic(charstxBox);
msStateTimeout = 1000;
bleState = SEND_DATA;
Log.info("connected to %s", (const char*)peer.address().toString());
}
}
void onDisconnected(const BlePeerDevice& peer, void* context) {
Log.info("have been disconnected from %s", (const char*)peer.address().toString());
bleState = DISCONNECT;
}
void onDataReceived(const uint8_t *data, size_t len, const BlePeerDevice &peer, void *context) {
Log.info("Received %d bytes from %s (context: %08x) ", len, (const char *)peer.address().toString(), context);
for (size_t i=0; i < len; i++)
Log.printf("%02x", data[i]);
Log.print("\r\n");
digitalWrite(D7, !digitalRead(D7));
}
void clickHandler(system_event_t event, int param)
{
if (BLE.connected()) {
bleState = DISCONNECT;
}
else {
bleRole = KEY;
bleState = SCAN;
}
}
Alternatively could whichever side had done the scanning inform its counterparty about the found RSSI via charstx.setValue()
.
While this isn’t the solution to your problem it might provide some food for thought.