Krolyxon
Commit 2586c8d

Branches

Tags

Refs →

orion-rfsrcbluetoothblescanner.cpp

192 lines · 4.9 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],
50 (uint8_t)mData[0]);
51 dev.manufacturer = String(buffer);
52 } else {
53 dev.manufacturer = "unknown";
54 }
55 } else {
56 dev.manufacturer = "unknown";
57 }
58
59 if (advertisedDevice.haveServiceUUID()) {
60 dev.deviceType =
61 advertisedDevice.getServiceUUID().toString().c_str();
62 } else {
63 dev.deviceType = "unknown";
64 }
65
66 devices.push_back(dev);
67 }
68};
69
70// ===== DRAW MENU =====
71void ble_drawMenu() {
72 u8g2.clearBuffer();
73
74 if (devices.empty()) {
75 u8g2.setFont(u8g2_font_6x12_tr);
76 u8g2.drawStr(0, 30, "No devices");
77 u8g2.drawStr(0, 45, "Press BACK");
78 } else {
79 u8g2.setFont(u8g2_font_5x8_tr);
80
81 char counter[20];
82 sprintf(counter, "%d/%d", selectedIndex + 1, (int)devices.size());
83 u8g2.drawStr(0, 8, counter);
84
85 u8g2.setFont(u8g2_font_6x10_tr);
86
87 for (int i = 0; i < 3; i++) {
88 int idx = selectedIndex + i;
89 if (idx >= devices.size())
90 break;
91
92 int y = 22 + i * 14;
93
94 if (i == 0) {
95 u8g2.drawBox(0, y - 10, 128, 12);
96 u8g2.setDrawColor(0);
97 }
98
99 String text = devices[idx].name;
100 if (text.length() > 12)
101 text = text.substring(0, 12) + "..";
102
103 text += " (" + String(devices[idx].rssi) + ")";
104
105 u8g2.drawStr(2, y, text.c_str());
106
107 if (i == 0)
108 u8g2.setDrawColor(1);
109 }
110 }
111
112 u8g2.sendBuffer();
113}
114
115// ===== DEVICE DETAILS =====
116void ble_drawDetails(const BLEDeviceInfo &dev) {
117 u8g2.clearBuffer();
118 u8g2.setFont(u8g2_font_5x8_tr);
119
120 u8g2.drawStr(0, 10, dev.name.c_str());
121 u8g2.drawStr(0, 20, dev.address.c_str());
122
123 char rssiStr[20];
124 sprintf(rssiStr, "RSSI: %d", dev.rssi);
125 u8g2.drawStr(0, 30, rssiStr);
126
127 u8g2.drawStr(0, 40, dev.manufacturer.c_str());
128
129 u8g2.sendBuffer();
130}
131
132// ===== SCAN =====
133void ble_scan() {
134 devices.clear();
135
136 u8g2.clearBuffer();
137 u8g2.drawStr(10, 30, "Scanning...");
138 u8g2.sendBuffer();
139
140 BLEDevice::init("");
141
142 pBLEScan = BLEDevice::getScan();
143 pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks(),
144 false);
145 pBLEScan->setActiveScan(true);
146 pBLEScan->setInterval(100);
147 pBLEScan->setWindow(99);
148
149 pBLEScan->start(5, false);
150
151 // remove duplicates
152 std::vector<BLEDeviceInfo> unique;
153 for (auto &d : devices) {
154 bool exists = false;
155 for (auto &u : unique) {
156 if (u.address == d.address) {
157 exists = true;
158 break;
159 }
160 }
161 if (!exists)
162 unique.push_back(d);
163 }
164
165 devices = unique;
166}
167
168// ===== MAIN LOOP =====
169void ble_loop() {
170 static uint32_t lastPress = 0;
171
172 if (millis() - lastPress < 200)
173 return;
174
175 if (btnDown() && selectedIndex < (int)devices.size() - 1) {
176 selectedIndex++;
177 ble_drawMenu();
178 lastPress = millis();
179 } else if (btnUp() && selectedIndex > 0) {
180 selectedIndex--;
181 ble_drawMenu();
182 lastPress = millis();
183 } else if (btnSelect() && !devices.empty()) {
184 ble_drawDetails(devices[selectedIndex]);
185 delay(3000);
186 ble_drawMenu();
187 lastPress = millis();
188 } else if (btnBack()) {
189 lastPress = millis();
190 return;
191 }
192}