main.ino 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #include <BLEDevice.h>
  2. #include <BLEServer.h>
  3. #include <BLEUtils.h>
  4. #include <BLEScan.h>
  5. #include <BLEAdvertisedDevice.h>
  6. #include <BLE2902.h>
  7. #include <ArduinoJson.h>
  8. #include <map>
  9. #define AUDIO_FRAME_SIZE 60
  10. uint8_t audioBuffer[AUDIO_FRAME_SIZE];
  11. int bufferIndex = 0;
  12. bool readingAudio = false;
  13. // Simpan data scan: MAC -> RSSI/TX/Name
  14. struct DeviceInfo {
  15. int RSSI;
  16. int TXPower;
  17. String name;
  18. };
  19. std::map<String, DeviceInfo> scannedDevices;
  20. // Simpan device yang connect: connId -> JSON index
  21. std::map<int, int> connIdToIndex;
  22. BLEServer *pServer = nullptr;
  23. BLECharacteristic *pCharacteristic = nullptr;
  24. int connectedClients = 0;
  25. StaticJsonDocument<2048> doc;
  26. JsonArray devices;
  27. #define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
  28. #define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
  29. class MyServerCallbacks : public BLEServerCallbacks {
  30. void onConnect(BLEServer *pServer, ble_gap_conn_desc *desc) override {
  31. connectedClients++;
  32. if (devices.isNull()) devices = doc.createNestedArray("Devices");
  33. JsonObject device = devices.createNestedObject();
  34. int connId = pServer->getConnId();
  35. device["connectedID"] = connId;
  36. device["connInterval"] = desc->conn_itvl;
  37. device["latency"] = desc->conn_latency;
  38. device["timeout"] = desc->supervision_timeout;
  39. // Gunakan MAC dari scannedDevices jika ada RSSI terakhir
  40. // Biasanya kita tidak punya MAC real connect, bisa pakai RSSI terkuat
  41. if (!scannedDevices.empty()) {
  42. auto strongest = scannedDevices.begin();
  43. for (auto it = scannedDevices.begin(); it != scannedDevices.end(); ++it) {
  44. if (it->second.RSSI > strongest->second.RSSI) strongest = it;
  45. }
  46. device["mac"] = strongest->first;
  47. device["name"] = strongest->second.name;
  48. device["RSSI"] = strongest->second.RSSI;
  49. device["TXPower"] = strongest->second.TXPower;
  50. } else {
  51. device["mac"] = "Unknown";
  52. device["name"] = "Unknown";
  53. }
  54. connIdToIndex[connId] = devices.size() - 1;
  55. doc["Status"] = "NEW_CONNECT";
  56. doc["connectedClients"] = connectedClients;
  57. serializeJson(doc, Serial);
  58. Serial.println();
  59. }
  60. void onDisconnect(BLEServer *pServer) override {
  61. connectedClients--;
  62. doc["Status"] = "DEVICE_DISCONNECTED";
  63. doc["connectedClients"] = connectedClients;
  64. int connId = pServer->getConnId();
  65. if (connIdToIndex.count(connId)) {
  66. int index = connIdToIndex[connId];
  67. JsonArray newDevices = doc.createNestedArray("Devices");
  68. for (int i = 0; i < devices.size(); i++) {
  69. if (i == index) continue;
  70. JsonObject oldDevice = devices[i];
  71. JsonObject newDevice = newDevices.createNestedObject();
  72. newDevice["connectedID"] = oldDevice["connectedID"];
  73. newDevice["connInterval"] = oldDevice["connInterval"];
  74. newDevice["latency"] = oldDevice["latency"];
  75. newDevice["timeout"] = oldDevice["timeout"];
  76. if (oldDevice.containsKey("RSSI")) newDevice["RSSI"] = oldDevice["RSSI"];
  77. if (oldDevice.containsKey("TXPower")) newDevice["TXPower"] = oldDevice["TXPower"];
  78. if (oldDevice.containsKey("mac")) newDevice["mac"] = oldDevice["mac"];
  79. if (oldDevice.containsKey("name")) newDevice["name"] = oldDevice["name"];
  80. }
  81. devices = newDevices;
  82. connIdToIndex.erase(connId);
  83. }
  84. serializeJson(doc, Serial);
  85. Serial.println();
  86. }
  87. };
  88. class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
  89. void onResult(BLEAdvertisedDevice advertisedDevice) override {
  90. Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
  91. String mac = advertisedDevice.getAddress().toString();
  92. // String name = advertisedDevice.getName();
  93. String name = advertisedDevice.haveName() ? advertisedDevice.getName() : "Unknown";
  94. int rssi = advertisedDevice.getRSSI();
  95. int txPower = advertisedDevice.getTXPower();
  96. // Simpan ke scannedDevices
  97. scannedDevices[mac] = { rssi, txPower, name };
  98. for (auto &pair : connIdToIndex) {
  99. int index = pair.second;
  100. JsonObject device = devices[index];
  101. // Di sini kita tidak bisa cocokkan MAC karena connect MAC random,
  102. // tapi bisa update semua RSSI terakhir dari scannedDevices
  103. if (scannedDevices.count(mac)) {
  104. device["Name"] = scannedDevices[mac].name;
  105. device["RSSI"] = scannedDevices[mac].RSSI;
  106. device["TXPower"] = scannedDevices[mac].TXPower;
  107. }
  108. }
  109. }
  110. };
  111. BLEScan *pBLEScan;
  112. void setup() {
  113. Serial.begin(115200);
  114. pinMode(LED_BUILTIN, OUTPUT);
  115. BLEDevice::init("ESP32");
  116. // Setup scan
  117. pBLEScan = BLEDevice::getScan();
  118. pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  119. pBLEScan->setActiveScan(true);
  120. pBLEScan->setInterval(100);
  121. pBLEScan->setWindow(99);
  122. // Setup server
  123. pServer = BLEDevice::createServer();
  124. pServer->setCallbacks(new MyServerCallbacks());
  125. BLEService *pService = pServer->createService(SERVICE_UUID);
  126. pCharacteristic = pService->createCharacteristic(
  127. CHARACTERISTIC_UUID,
  128. BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_INDICATE);
  129. pCharacteristic->addDescriptor(new BLE2902());
  130. pService->start();
  131. BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  132. pAdvertising->addServiceUUID(SERVICE_UUID);
  133. pAdvertising->setScanResponse(false);
  134. pAdvertising->setMinPreferred(0x0);
  135. BLEDevice::startAdvertising();
  136. }
  137. unsigned long lastScanTime = 0;
  138. const unsigned long scanInterval = 1000; // 1 detik
  139. void loop() {
  140. digitalWrite(LED_BUILTIN, connectedClients > 0 ? HIGH : LOW);
  141. // Scan BLE setiap 1 detik
  142. // if (millis() - lastScanTime > scanInterval) {
  143. // lastScanTime = millis();
  144. // pBLEScan->start(0, nullptr, false); // non-blocking scan
  145. // }
  146. pBLEScan->start(2, false); // non-blocking scan
  147. // Kirim JSON update ke Serial
  148. static unsigned long lastJsonTime = 0;
  149. if (millis() - lastJsonTime > scanInterval) {
  150. lastJsonTime = millis();
  151. doc["connectedClients"] = connectedClients;
  152. serializeJson(doc, Serial);
  153. Serial.println();
  154. }
  155. }