|
|
@@ -12,7 +12,6 @@ uint8_t audioBuffer[AUDIO_FRAME_SIZE];
|
|
|
int bufferIndex = 0;
|
|
|
bool readingAudio = false;
|
|
|
|
|
|
-// Simpan data scan: MAC -> RSSI/TX/Name
|
|
|
struct DeviceInfo {
|
|
|
int RSSI;
|
|
|
int TXPower;
|
|
|
@@ -20,13 +19,14 @@ struct DeviceInfo {
|
|
|
};
|
|
|
std::map<String, DeviceInfo> scannedDevices;
|
|
|
|
|
|
-// Simpan device yang connect: connId -> JSON index
|
|
|
std::map<int, int> connIdToIndex;
|
|
|
|
|
|
BLEServer *pServer = nullptr;
|
|
|
BLECharacteristic *pCharacteristic = nullptr;
|
|
|
+BLEScan *pBLEScan;
|
|
|
|
|
|
int connectedClients = 0;
|
|
|
+int lastconnectedClients;
|
|
|
|
|
|
StaticJsonDocument<2048> doc;
|
|
|
JsonArray devices;
|
|
|
@@ -34,34 +34,33 @@ JsonArray devices;
|
|
|
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
|
|
|
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
|
|
|
|
|
|
+// ------------------ CALLBACKS -------------------
|
|
|
class MyServerCallbacks : public BLEServerCallbacks {
|
|
|
void onConnect(BLEServer *pServer, ble_gap_conn_desc *desc) override {
|
|
|
connectedClients++;
|
|
|
-
|
|
|
if (devices.isNull()) devices = doc.createNestedArray("Devices");
|
|
|
|
|
|
JsonObject device = devices.createNestedObject();
|
|
|
int connId = pServer->getConnId();
|
|
|
device["connectedID"] = connId;
|
|
|
device["connInterval"] = desc->conn_itvl;
|
|
|
+ device["mac"] = BLEAddress(desc->peer_ota_addr).toString();
|
|
|
device["latency"] = desc->conn_latency;
|
|
|
device["timeout"] = desc->supervision_timeout;
|
|
|
|
|
|
- // Gunakan MAC dari scannedDevices jika ada RSSI terakhir
|
|
|
- // Biasanya kita tidak punya MAC real connect, bisa pakai RSSI terkuat
|
|
|
- if (!scannedDevices.empty()) {
|
|
|
- auto strongest = scannedDevices.begin();
|
|
|
- for (auto it = scannedDevices.begin(); it != scannedDevices.end(); ++it) {
|
|
|
- if (it->second.RSSI > strongest->second.RSSI) strongest = it;
|
|
|
- }
|
|
|
- device["mac"] = strongest->first;
|
|
|
- device["name"] = strongest->second.name;
|
|
|
- device["RSSI"] = strongest->second.RSSI;
|
|
|
- device["TXPower"] = strongest->second.TXPower;
|
|
|
- } else {
|
|
|
- device["mac"] = "Unknown";
|
|
|
- device["name"] = "Unknown";
|
|
|
- }
|
|
|
+ // if (!scannedDevices.empty()) {
|
|
|
+ // auto strongest = scannedDevices.begin();
|
|
|
+ // for (auto it = scannedDevices.begin(); it != scannedDevices.end(); ++it) {
|
|
|
+ // if (it->second.RSSI > strongest->second.RSSI) strongest = it;
|
|
|
+ // }
|
|
|
+ // device["mac"] = strongest->first;
|
|
|
+ // device["name"] = strongest->second.name;
|
|
|
+ // device["RSSI"] = strongest->second.RSSI;
|
|
|
+ // device["TXPower"] = strongest->second.TXPower;
|
|
|
+ // } else {
|
|
|
+ // device["mac"] = "Unknown";
|
|
|
+ // device["name"] = "Unknown";
|
|
|
+ // }
|
|
|
|
|
|
connIdToIndex[connId] = devices.size() - 1;
|
|
|
|
|
|
@@ -70,6 +69,7 @@ class MyServerCallbacks : public BLEServerCallbacks {
|
|
|
|
|
|
serializeJson(doc, Serial);
|
|
|
Serial.println();
|
|
|
+ BLEDevice::startAdvertising();
|
|
|
}
|
|
|
|
|
|
void onDisconnect(BLEServer *pServer) override {
|
|
|
@@ -107,19 +107,15 @@ class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
|
|
|
void onResult(BLEAdvertisedDevice advertisedDevice) override {
|
|
|
Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
|
|
|
String mac = advertisedDevice.getAddress().toString();
|
|
|
- // String name = advertisedDevice.getName();
|
|
|
String name = advertisedDevice.haveName() ? advertisedDevice.getName() : "Unknown";
|
|
|
int rssi = advertisedDevice.getRSSI();
|
|
|
int txPower = advertisedDevice.getTXPower();
|
|
|
|
|
|
- // Simpan ke scannedDevices
|
|
|
scannedDevices[mac] = { rssi, txPower, name };
|
|
|
|
|
|
for (auto &pair : connIdToIndex) {
|
|
|
int index = pair.second;
|
|
|
JsonObject device = devices[index];
|
|
|
- // Di sini kita tidak bisa cocokkan MAC karena connect MAC random,
|
|
|
- // tapi bisa update semua RSSI terakhir dari scannedDevices
|
|
|
if (scannedDevices.count(mac)) {
|
|
|
device["Name"] = scannedDevices[mac].name;
|
|
|
device["RSSI"] = scannedDevices[mac].RSSI;
|
|
|
@@ -129,22 +125,19 @@ class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-BLEScan *pBLEScan;
|
|
|
-
|
|
|
+// ------------------ SETUP -------------------
|
|
|
void setup() {
|
|
|
Serial.begin(115200);
|
|
|
pinMode(LED_BUILTIN, OUTPUT);
|
|
|
|
|
|
BLEDevice::init("ESP32");
|
|
|
|
|
|
- // Setup scan
|
|
|
pBLEScan = BLEDevice::getScan();
|
|
|
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
|
|
|
pBLEScan->setActiveScan(true);
|
|
|
pBLEScan->setInterval(100);
|
|
|
pBLEScan->setWindow(99);
|
|
|
|
|
|
- // Setup server
|
|
|
pServer = BLEDevice::createServer();
|
|
|
pServer->setCallbacks(new MyServerCallbacks());
|
|
|
|
|
|
@@ -162,25 +155,45 @@ void setup() {
|
|
|
BLEDevice::startAdvertising();
|
|
|
}
|
|
|
|
|
|
-unsigned long lastScanTime = 0;
|
|
|
-const unsigned long scanInterval = 1000; // 1 detik
|
|
|
+// ------------------ LOOP -------------------
|
|
|
+unsigned long lastJsonTime = 0;
|
|
|
+const unsigned long scanInterval = 1000;
|
|
|
|
|
|
void loop() {
|
|
|
digitalWrite(LED_BUILTIN, connectedClients > 0 ? HIGH : LOW);
|
|
|
|
|
|
- // Scan BLE setiap 1 detik
|
|
|
- // if (millis() - lastScanTime > scanInterval) {
|
|
|
- // lastScanTime = millis();
|
|
|
- // pBLEScan->start(0, nullptr, false); // non-blocking scan
|
|
|
+ // kirim update JSON tiap 1 detik
|
|
|
+ // if (millis() - lastJsonTime > scanInterval) {
|
|
|
+ // if (connectedClients == 0) {
|
|
|
+ // doc["Status"] = "NO_CONNECTED";
|
|
|
+ // }
|
|
|
+ // lastJsonTime = millis();
|
|
|
+ // doc["connectedClients"] = connectedClients;
|
|
|
+ // // serializeJsonPretty(doc, Serial);
|
|
|
+ // serializeJson(doc, Serial);
|
|
|
+ // Serial.println();
|
|
|
// }
|
|
|
|
|
|
- pBLEScan->start(2, false); // non-blocking scan
|
|
|
- // Kirim JSON update ke Serial
|
|
|
- static unsigned long lastJsonTime = 0;
|
|
|
- if (millis() - lastJsonTime > scanInterval) {
|
|
|
- lastJsonTime = millis();
|
|
|
- doc["connectedClients"] = connectedClients;
|
|
|
+ if (lastconnectedClients != connectedClients && connectedClients == 0) {
|
|
|
+ doc["Status"] = "NO_CONNECTED";
|
|
|
serializeJson(doc, Serial);
|
|
|
Serial.println();
|
|
|
+ lastconnectedClients = connectedClients;
|
|
|
+ }
|
|
|
+
|
|
|
+ // cek input dari serial untuk disconnect
|
|
|
+ if (Serial.available()) {
|
|
|
+ String input = Serial.readStringUntil('\n');
|
|
|
+ input.trim();
|
|
|
+
|
|
|
+ if (input.startsWith("DISCONNECT")) {
|
|
|
+ int id = input.substring(10).toInt();
|
|
|
+ if (id > 0) {
|
|
|
+ Serial.printf("Disconnecting client %d...\n", id);
|
|
|
+ pServer->disconnect(id);
|
|
|
+ } else {
|
|
|
+ Serial.println("Format salah! Gunakan: DISCONNECT <connId>");
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|