Krolyxon
Commit 206ed22

Branches

Tags

Refs →

orion-rfsrcbluetoothblescanner.cpp

190 lines · 4.4 KB · C++

1#include <Arduino.h>
2#include <BLEAdvertisedDevice.h>
3#include <BLEDevice.h>
4#include <BLEScan.h>
5#include <vector>
6
7#include "../config.h"
8#include "../utils/buttons.h"
9#include "ui/display.h"
10
11// ===== DEVICE STRUCT =====
12struct BLEDeviceInfo {
13 String name;
14 String address;
15 int rssi;
16 String manufacturer;
17 String deviceType;
18};
19
20static std::vector<BLEDeviceInfo> devices;
21static BLEScan *pBLEScan;
22static int selectedIndex = 0;
23
24// ===== CALLBACK =====
25class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
26 void onResult(BLEAdvertisedDevice advertisedDevice) override {
27 BLEDeviceInfo dev;
28
29 String tempName = advertisedDevice.getName().c_str();
30
31 if (tempName.length() == 0 && advertisedDevice.haveServiceData()) {
32 tempName = advertisedDevice.getServiceData().c_str();
33 }
34
35 if (tempName.length() == 0) {
36 String addr = advertisedDevice.getAddress().toString().c_str();
37 tempName = "BLE_" + addr.substring(addr.length() - 5);
38 }
39
40 dev.name = tempName;
41 dev.address = advertisedDevice.getAddress().toString().c_str();
42 dev.rssi = advertisedDevice.getRSSI();
43
44 if (advertisedDevice.haveManufacturerData()) {
45 String mData = advertisedDevice.getManufacturerData().c_str();
46
47 if (mData.length() >= 2) {
48 char buffer[10];
49 sprintf(buffer, "0x%02X%02X", (uint8_t)mData[1], (uint8_t)mData[0]);
50 dev.manufacturer = String(buffer);
51 } else {
52 dev.manufacturer = "unknown";
53 }
54 } else {
55 dev.manufacturer = "unknown";
56 }
57
58 if (advertisedDevice.haveServiceUUID()) {
59 dev.deviceType = advertisedDevice.getServiceUUID().toString().c_str();
60 } else {
61 dev.deviceType = "unknown";
62 }
63
64 devices.push_back(dev);
65 }
66};
67
68// ===== DRAW MENU =====
69void ble_drawMenu() {
70 u8g2.clearBuffer();
71
72 if (devices.empty()) {
73 u8g2.setFont(u8g2_font_6x12_tr);
74 u8g2.drawStr(0, 30, "No devices");
75 u8g2.drawStr(0, 45, "Press BACK");
76 } else {
77 u8g2.setFont(u8g2_font_5x8_tr);
78
79 char counter[20];
80 sprintf(counter, "%d/%d", selectedIndex + 1, (int)devices.size());
81 u8g2.drawStr(0, 8, counter);
82
83 u8g2.setFont(u8g2_font_6x10_tr);
84
85 for (int i = 0; i < 3; i++) {
86 int idx = selectedIndex + i;
87 if (idx >= devices.size())
88 break;
89
90 int y = 22 + i * 14;
91
92 if (i == 0) {
93 u8g2.drawBox(0, y - 10, 128, 12);
94 u8g2.setDrawColor(0);
95 }
96
97 String text = devices[idx].name;
98 if (text.length() > 12)
99 text = text.substring(0, 12) + "..";
100
101 text += " (" + String(devices[idx].rssi) + ")";
102
103 u8g2.drawStr(2, y, text.c_str());
104
105 if (i == 0)
106 u8g2.setDrawColor(1);
107 }
108 }
109
110 u8g2.sendBuffer();
111}
112
113// ===== DEVICE DETAILS =====
114void ble_drawDetails(const BLEDeviceInfo &dev) {
115 u8g2.clearBuffer();
116 u8g2.setFont(u8g2_font_5x8_tr);
117
118 u8g2.drawStr(0, 10, dev.name.c_str());
119 u8g2.drawStr(0, 20, dev.address.c_str());
120
121 char rssiStr[20];
122 sprintf(rssiStr, "RSSI: %d", dev.rssi);
123 u8g2.drawStr(0, 30, rssiStr);
124
125 u8g2.drawStr(0, 40, dev.manufacturer.c_str());
126
127 u8g2.sendBuffer();
128}
129
130// ===== SCAN =====
131void ble_scan() {
132 devices.clear();
133
134 u8g2.clearBuffer();
135 u8g2.drawStr(10, 30, "Scanning...");
136 u8g2.sendBuffer();
137
138 BLEDevice::init("");
139
140 pBLEScan = BLEDevice::getScan();
141 pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks(),
142 false);
143 pBLEScan->setActiveScan(true);
144 pBLEScan->setInterval(100);
145 pBLEScan->setWindow(99);
146
147 pBLEScan->start(5, false);
148
149 // remove duplicates
150 std::vector<BLEDeviceInfo> unique;
151 for (auto &d : devices) {
152 bool exists = false;
153 for (auto &u : unique) {
154 if (u.address == d.address) {
155 exists = true;
156 break;
157 }
158 }
159 if (!exists)
160 unique.push_back(d);
161 }
162
163 devices = unique;
164}
165
166// ===== MAIN LOOP =====
167void ble_loop() {
168 static uint32_t lastPress = 0;
169
170 if (millis() - lastPress < 200)
171 return;
172
173 if (btnDown() && selectedIndex < (int)devices.size() - 1) {
174 selectedIndex++;
175 ble_drawMenu();
176 lastPress = millis();
177 } else if (btnUp() && selectedIndex > 0) {
178 selectedIndex--;
179 ble_drawMenu();
180 lastPress = millis();
181 } else if (btnSelect() && !devices.empty()) {
182 ble_drawDetails(devices[selectedIndex]);
183 delay(3000);
184 ble_drawMenu();
185 lastPress = millis();
186 } else if (btnBack()) {
187 lastPress = millis();
188 return;
189 }
190}