├── .github
└── workflows
│ └── PioBuild.yaml
├── .gitignore
├── .vscode
└── extensions.json
├── CMakeLists.txt
├── doc
├── HomeAssistantSnippets.md
└── screenshots
│ ├── bt_monitor_page.png
│ ├── main_menu.jpg
│ └── parameter_page.jpg
├── include
├── BluetoothParameter.h
├── BluetoothScanner.h
├── CallbackHelper.h
├── NestedStruct.h
├── TelnetSerial.h
├── WiFiComponent.h
├── led.h
├── mqtt.h
├── parameter.h
└── stackDbgHelper.h
├── partitions_custom.csv
├── platformio.ini
├── readme.md
├── sdkconfig.defaults
└── src
├── BluetoothScanner.cpp
├── CMakeLists.txt
├── TelnetSerial.cpp
├── WiFiComponent.cpp
├── main.cpp
├── mqtt.cpp
└── parameter.cpp
/.github/workflows/PioBuild.yaml:
--------------------------------------------------------------------------------
1 | name: Build PlatformIO Project
2 |
3 | on:
4 | push:
5 | branches:
6 | - '**'
7 | workflow_dispatch:
8 |
9 |
10 | jobs:
11 | build:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Checkout
15 | uses: actions/checkout@v3
16 | - name: Cache pip
17 | uses: actions/cache@v2
18 | with:
19 | path: ~/.cache/pip
20 | key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
21 | restore-keys: |
22 | ${{ runner.os }}-pip-
23 | - name: Cache PlatformIO
24 | uses: actions/cache@v2
25 | with:
26 | path: ~/.platformio
27 | key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
28 | - name: Set up Python
29 | uses: actions/setup-python@v4
30 | with:
31 | python-version: '3.8'
32 | - name: Install PlatformIO
33 | run: |
34 | python -m pip install --upgrade pip
35 | pip install --upgrade platformio
36 |
37 |
38 | - name: Run PlatformIO
39 | run: pio run -e wemos_d1_mini32
40 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # These are some examples of commonly ignored file patterns.
2 | # You should customize this list as applicable to your project.
3 | # Learn more about .gitignore:
4 | # https://www.atlassian.com/git/tutorials/saving-changes/gitignore
5 |
6 |
7 | .pio
8 |
9 | # Node artifact files
10 | node_modules/
11 | dist/
12 |
13 | # Compiled Java class files
14 | *.class
15 |
16 | # Compiled Python bytecode
17 | *.py[cod]
18 |
19 | # Log files
20 | *.log
21 |
22 | # Package files
23 | *.jar
24 |
25 | # Maven
26 | target/
27 | dist/
28 |
29 | # JetBrains IDE
30 | .idea/
31 |
32 | # Unit test reports
33 | TEST*.xml
34 |
35 | # Generated by MacOS
36 | .DS_Store
37 |
38 | # Generated by Windows
39 | Thumbs.db
40 |
41 | # Applications
42 | *.app
43 | *.exe
44 | *.war
45 |
46 | # Large media files
47 | *.mp4
48 | *.tiff
49 | *.avi
50 | *.flv
51 | *.mov
52 | *.wmv
53 |
54 | /.vscode/launch.json
55 | /.vscode/c_cpp_properties.json
56 | .vscode/settings.json
57 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // See http://go.microsoft.com/fwlink/?LinkId=827846
3 | // for the documentation about the extensions.json format
4 | "recommendations": [
5 | "platformio.platformio-ide"
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # The following lines of boilerplate have to be in your project's CMakeLists
2 | # in this exact order for cmake to work correctly
3 | cmake_minimum_required(VERSION 3.16.0)
4 |
5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake)
6 | project(Esp32_bluetoothClassicScan)
7 |
--------------------------------------------------------------------------------
/doc/HomeAssistantSnippets.md:
--------------------------------------------------------------------------------
1 |
2 | I use the ESP32 bluetooth presence scans to provide presence information to HomeAssistant.
3 |
4 | Here's an example of a Bluetooth presence sensor for a _ESP32-MQTT-Bluetooth-Monitor_ device with Identity ```ESP32-bluetooth-monitor```.
5 | The device that the confidence is reported for has alias ```s10```. When the Bluetooth scanner node goes down, this is also reflected in the presence sensor.
6 | This snippet belongs in the ```sensor:``` section of the HomeAssistant configuration.
7 | ```yaml
8 | - platform: mqtt
9 | state_topic: 'monitor/ESP32-bluetooth-monitor/s10'
10 | value_template: '{{ value_json.confidence }}'
11 | unit_of_measurement: '%'
12 | availability:
13 | - topic: "monitor/ESP32-bluetooth-monitor/status"
14 | payload_available: "online"
15 | payload_not_available: "offline"
16 | name: 'ESP32 S10 bluetooth presence confidence'
17 | ```
18 |
19 |
20 | The following snippet is an automation used to trigger _Arrival_ / _Departure_ scans based on door open / close triggers.
21 | For my household where 4 devices are in the Known Devices list, precense is generally detected within about __2.5 seconds__ of the door being opened!
22 |
23 | ```yaml
24 | - id: 'bt_presence_scan_on_door_open_close'
25 | alias: Bluetooth Presence scan on Door open/close
26 | description: Scan for bluetooth arrival / departure on door open / close events
27 | trigger:
28 | # Any door sensor to trigger the scan for:
29 | - platform: state
30 | entity_id: binary_sensor.voordeur_contact
31 | - platform: state
32 | entity_id: binary_sensor.achterdeur_contact
33 | condition: []
34 | action:
35 | # Either scan for departure or arrivals
36 | - choose:
37 | - conditions:
38 | - condition: template
39 | value_template: "{{ trigger.to_state.state == 'off' }}"
40 | # Door close: delayed scan for departing devices
41 | sequence:
42 | - delay: 00:02:00
43 | - service: mqtt.publish
44 | data:
45 | topic: monitor/scan/DEPART
46 | # Door open: scan for new devices
47 | default:
48 | - service: mqtt.publish
49 | data:
50 | topic: monitor/scan/ARRIVE
51 | mode: parallel
52 | max: 3
53 | max_exceeded: silent
54 | ```
55 |
56 | I've newly added passive ble iBeacon scan support which will also support rssi value reporting. Below is an example to get to that data using an MQTT sensor in HomeAssistant. This example uses an _ESP32-MQTT-Bluetooth-Monitor_ device with Identity ```ESP32-bluetooth-monitor```.
57 | The device that the confidence is reported for has alias ```s10-iBeacon```.
58 | This snippet belongs in the ```sensor:``` section of the HomeAssistant configuration.
59 | ```yaml
60 | - platform: mqtt
61 | state_topic: 'monitor/ESP32-bluetooth-monitor/s10-iBeacon'
62 | value_template: '{{ value_json.rssi }}'
63 | unit_of_measurement: 'dBm'
64 | availability:
65 | - topic: "monitor/ESP32-bluetooth-monitor/status"
66 | payload_available: "online"
67 | payload_not_available: "offline"
68 | name: 'ESP32 S10 iBeacon RSSI'
69 | ```
70 |
71 |
--------------------------------------------------------------------------------
/doc/screenshots/bt_monitor_page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RoboMagus/ESP32-MQTT-Bluetooth-Monitor/a1b736af58aa088100e51a006ae3a8a09ac60d31/doc/screenshots/bt_monitor_page.png
--------------------------------------------------------------------------------
/doc/screenshots/main_menu.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RoboMagus/ESP32-MQTT-Bluetooth-Monitor/a1b736af58aa088100e51a006ae3a8a09ac60d31/doc/screenshots/main_menu.jpg
--------------------------------------------------------------------------------
/doc/screenshots/parameter_page.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RoboMagus/ESP32-MQTT-Bluetooth-Monitor/a1b736af58aa088100e51a006ae3a8a09ac60d31/doc/screenshots/parameter_page.jpg
--------------------------------------------------------------------------------
/include/BluetoothParameter.h:
--------------------------------------------------------------------------------
1 | #ifndef BLUETOOTH_PARAMETER_H
2 | #define BLUETOOTH_PARAMETER_H
3 |
4 | #include "WString.h"
5 | #include "parameter.h"
6 |
7 |
8 | static const char MAC_ADDR[] PROGMEM = "MAC address / iBeacon UUID";
9 | static const char ALIAS [] PROGMEM = "Alias";
10 |
11 |
12 | class BluetoothParameter {
13 | public:
14 | BluetoothParameter(uint8_t index) :
15 | bm_mac_addr (alias_id+1, MAC_ADDR, "", 40),
16 | bm_mac_alias (alias_id , ALIAS , "", 20),
17 | bm_mac_sep (PSTR("
"))
18 | {
19 | // Write the required ID's to retrieve preference data.
20 | sprintf (alias_id, "abm%02d", index);
21 | // Alias starts at 'a', mac addr starts with 'bm'. This way the same buffer can be used for both!!
22 | }
23 |
24 | const char *getMacAddress() {
25 | return bm_mac_addr.getValue();
26 | }
27 |
28 | void setMacAddress(const char * val) {
29 | bm_mac_addr.setValue(val);
30 | }
31 |
32 | const char *getAlias() {
33 | return bm_mac_alias.getValue();
34 | }
35 |
36 | void setAlias(const char * val) {
37 | bm_mac_alias.setValue(val);
38 | }
39 |
40 | private:
41 | /*const*/ char alias_id[8];
42 |
43 | Parameter bm_mac_addr;
44 | Parameter bm_mac_alias;
45 | Parameter bm_mac_sep;
46 | };
47 |
48 | #endif // BLUETOOTH_PARAMETER_H
--------------------------------------------------------------------------------
/include/BluetoothScanner.h:
--------------------------------------------------------------------------------
1 | #ifndef BLUETOOTH_SCANNER_H
2 | #define BLUETOOTH_SCANNER_H
3 |
4 | // Basic headers
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include // std::sort
11 | #include
12 | #include
13 | #include
14 |
15 | // IDF headers
16 | #include
17 | #include
18 | #include
19 | #include "nvs.h"
20 | #include "nvs_flash.h"
21 | #include "esp_system.h"
22 | #include "esp_log.h"
23 | #include "esp32-hal-bt.h"
24 | #include "esp_bt.h"
25 | #include "esp_bt_main.h"
26 | #include "esp_bt_device.h"
27 | #include "esp_gap_bt_api.h"
28 |
29 | // Tweaked SDK configuration
30 | #include "sdkconfig.h"
31 | #include
32 |
33 | #include
34 | #include
35 | #include
36 | #include
37 | #include "BLEEddystoneURL.h"
38 | #include "BLEEddystoneTLM.h"
39 | #include "BLEBeacon.h"
40 |
41 | // monitor/setup/ADD STATIC DEVICE
42 | // monitor/setup/add known device
43 | // monitor/setup/delete known device
44 |
45 | char *bda2str(const esp_bd_addr_t bda, char *str, size_t size);
46 | bool str2bda(const char* str, esp_bd_addr_t& mac);
47 |
48 | enum class ScanType{
49 | None,
50 | Arrival,
51 | Departure,
52 | Either
53 | };
54 |
55 | class BluetoothScanner : public BLEAdvertisedDeviceCallbacks
56 | {
57 | public:
58 | BluetoothScanner(Stream& serialStream) : mSerial(serialStream) {
59 | }
60 | virtual ~BluetoothScanner() {
61 |
62 | }
63 |
64 | void init();
65 |
66 | void setup();
67 |
68 | void loop();
69 |
70 | void stop();
71 |
72 | void setNumArrivalScans (uint8_t val );
73 | void setNumDepartureScans (uint8_t val );
74 | void setSecondsBetweenScanIters (unsigned long val );
75 | void setBeaconExpiration (uint32_t val );
76 | void setMinTimeBetweenScans (uint32_t val );
77 | void setPeriodicScanInterval (uint32_t val );
78 | void setScanDurationTimeout (uint32_t val );
79 | void setMqttTopic (const std::string& topic );
80 | void setScannerIdentity (const char* identity);
81 | void setRetainFlag (bool flag );
82 |
83 | void startBluetoothScan(ScanType scanType);
84 |
85 | void addKnownDevice (const std::string& input);
86 | void addKnownDevice (const esp_bd_addr_t mac, const char* alias);
87 | void deleteKnownDevice(const std::string& mac);
88 | void deleteKnownDevice(const esp_bd_addr_t mac);
89 | void clearKnownDevices();
90 |
91 | void addKnownIBeacon (const std::string& input);
92 | void addKnownIBeacon (const BLEUUID uuid, const char* alias);
93 | void deleteKnownIBeacon(const BLEUUID uuid);
94 |
95 | // BLE advertisement results:
96 | void onResult(BLEAdvertisedDevice advertisedDevice);
97 | // BLE scan done callback:
98 | void bleScanCompleted(BLEScanResults);
99 |
100 | void HandleBleAdvertisementResult(BLEAdvertisedDevice& bleAdvertisedDeviceResult);
101 |
102 | private:
103 | void removeFromBtDevices(const esp_bd_addr_t mac);
104 |
105 | uint8_t getNumScans(ScanType scanType);
106 | unsigned long getLastScanTime(ScanType scanType);
107 | void setLastScanTime(ScanType scanType, unsigned long time);
108 |
109 | bool scanForNextDevice();
110 |
111 | void SetReadRemoteNameResult(const esp_bt_gap_cb_param_t::read_rmt_name_param& remoteNameParam);
112 | void HandleReadRemoteNameResult(esp_bt_gap_cb_param_t::read_rmt_name_param& remoteNameParam);
113 |
114 | void gap_init();
115 | void startupGap();
116 | void gap_callback(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param);
117 |
118 | void update_device_info(esp_bt_gap_cb_param_t *param);
119 |
120 | struct btDeviceId_t {
121 | esp_bd_addr_t mac;
122 | String name;
123 | uint8_t confidence;
124 | uint8_t state;
125 | uint8_t scansLeft;
126 |
127 | btDeviceId_t(const esp_bd_addr_t MAC, String Name) : name(std::move(Name)), confidence(0), state(0)
128 | {
129 | memcpy(mac, MAC, sizeof(esp_bd_addr_t));
130 | }
131 | };
132 |
133 | struct iBeaconDeviceId_t {
134 | iBeaconDeviceId_t(const BLEUUID uuid, String Name) : uuid(uuid), name(std::move(Name)), power(0), lastSentRssi(0), confidence(0), state(0), last_update_millis(0)
135 | {
136 |
137 | }
138 |
139 | bool isVirgin () {
140 | return !filled_once;
141 | }
142 |
143 | void reset() {
144 | power = 0;
145 | confidence = 0;
146 | state = 0;
147 | memset(rssi_array, 0, sizeof(rssi_array));
148 | filled_once=false;
149 | }
150 |
151 | void addRSSI(int rssi) {
152 | if(!filled_once && rssi_idx == 0) {
153 | memset(rssi_array, rssi, sizeof(rssi_array)); // Fill all with first value to get immediate 'find'
154 | }
155 | rssi_array[rssi_idx] = rssi;
156 | rssi_idx = (rssi_idx + 1)%rssi_array_size;
157 | if (!filled_once && rssi_idx == 0) {
158 | filled_once = true;
159 | }
160 | }
161 |
162 | int getFilteredRSSI() {
163 | if(!filled_once) {
164 | return 0;
165 | }
166 | else {
167 | int copy[rssi_array_size];
168 | std::copy(std::begin(rssi_array), std::end(rssi_array), std::begin(copy));
169 | std::sort(copy, copy + rssi_array_size);
170 | return copy[2];
171 | }
172 | }
173 |
174 | BLEUUID uuid;
175 | String name;
176 | int power;
177 | int lastSentRssi;
178 |
179 | uint8_t confidence;
180 | uint8_t state;
181 |
182 | unsigned long last_update_millis;
183 |
184 | private:
185 | static const int rssi_array_size = 5;
186 | int rssi_array[rssi_array_size];
187 | int rssi_idx = 0;
188 | bool filled_once = false;
189 | };
190 | public:
191 | const std::vector& getBtDeviceStates();
192 |
193 | private:
194 |
195 | Stream& mSerial;
196 |
197 | typedef enum {
198 | APP_GAP_STATE_IDLE = 0,
199 | APP_GAP_STATE_DEVICE_DISCOVERING,
200 | APP_GAP_STATE_DEVICE_DISCOVER_COMPLETE,
201 | APP_GAP_STATE_SERVICE_DISCOVERING,
202 | APP_GAP_STATE_SERVICE_DISCOVER_COMPLETE,
203 | } app_gap_state_t;
204 |
205 | typedef struct {
206 | bool dev_found;
207 | uint8_t bdname_len;
208 | uint8_t eir_len;
209 | uint8_t rssi;
210 | uint32_t cod;
211 | uint8_t eir[ESP_BT_GAP_EIR_DATA_LEN];
212 | uint8_t bdname[ESP_BT_GAP_MAX_BDNAME_LEN + 1];
213 | esp_bd_addr_t bda;
214 | app_gap_state_t state;
215 | } app_gap_cb_t;
216 |
217 | app_gap_cb_t m_dev_info;
218 | std::vector btDevices;
219 | std::mutex btDevicesMutex;
220 |
221 | std::vector iBeaconDevices;
222 | std::mutex iBeaconDevicesMutex;
223 |
224 | volatile uint8_t scanInProgress = 0;
225 | int scanIndex = -1; // loops over devices
226 | int iterationScansLeft = -1; // Loops over iterations
227 | ScanType scanMode;
228 |
229 |
230 | int scanTime = 4; //1; //In seconds
231 | BLEScan *pBLEScan = nullptr;
232 | bool bleScan_shouldStart = false;
233 | uint8_t scanContinueCount = 0;
234 | const uint8_t scanContinueWraparound = 4;
235 | const size_t maxBleProcessPerIteration = 3;
236 |
237 | std::queue readRemoteNameResultQueue;
238 |
239 | std::queue bleAdvertisedDeviceResultQueue;
240 |
241 | // Scanner parameters from storage:
242 | uint8_t num_arrival_scans;
243 | uint8_t num_departure_scans;
244 | unsigned long scan_iter_interval;
245 | uint32_t beacon_expiration_seconds;
246 | uint32_t min_seconds_between_scans;
247 | uint32_t periodic_scan_interval;
248 | uint32_t scan_duration_timeout;
249 | std::string m_mqtt_topic;
250 | const char* m_scanner_identity;
251 | bool m_retain = false;
252 |
253 | unsigned long last_arrival_scan_time = 0;
254 | unsigned long last_departure_scan_time = 0;
255 |
256 | unsigned long last_scan_iter_millis = 0;
257 | };
258 |
259 | #endif // BLUETOOTH_SCANNER_H
260 |
--------------------------------------------------------------------------------
/include/CallbackHelper.h:
--------------------------------------------------------------------------------
1 | #ifndef CALLBACK_HELPER_H
2 | #define CALLBACK_HELPER_H
3 |
4 | // Callback helper class / definitions based on the bounce implementation by embeddedartistry:
5 | // https://github.com/embeddedartistry/embedded-resources/blob/master/examples/cpp/bounce.cpp
6 | //
7 | // Better lead:
8 | //https://stackoverflow.com/questions/1000663/using-a-c-class-member-function-as-a-c-callback-function
9 |
10 | #include
11 |
12 |
13 | template
14 | struct Callback;
15 |
16 | template
17 | struct Callback {
18 | template
19 | static Ret callback(Args... args) {
20 | return func(args...);
21 | }
22 | static std::function func;
23 | };
24 |
25 | template
26 | std::function Callback::func;
27 |
28 |
29 |
30 | #endif // CALLBACK_HELPER_H
31 |
--------------------------------------------------------------------------------
/include/NestedStruct.h:
--------------------------------------------------------------------------------
1 | #ifndef NESTED_STRUCT_H
2 | #define NESTED_STRUCT_H
3 |
4 | template
5 | struct NestedStruct
6 | {
7 | NestedStruct contained;
8 | T t;
9 | // Constructor
10 | NestedStruct() : t(N) {}
11 | };
12 |
13 | template
14 | struct NestedStruct
15 | {
16 | T t;
17 | // Constructor
18 | NestedStruct() : t(0) {}
19 | };
20 |
21 | template
22 | class NestWrapper
23 | {
24 | public:
25 | T (&data)[N] = reinterpret_cast(nest);
26 | static const int size = N;
27 | private:
28 | NestedStruct nest;
29 | };
30 |
31 | #endif // NESTED_STRUCT_H
--------------------------------------------------------------------------------
/include/TelnetSerial.h:
--------------------------------------------------------------------------------
1 | /*
2 | TelnetSerial.h - Arduino like serial library for printing over Telnet for ESP8266 & ESP32
3 | */
4 |
5 | #ifndef TelnetSerial_h
6 | #define TelnetSerial_h
7 |
8 | #include
9 | #include <../include/time.h> // See issue #6714
10 | #include "Stream.h"
11 | #include "WiFiServer.h"
12 | #include "WiFiClient.h"
13 |
14 | #include "stackDbgHelper.h"
15 |
16 | #define MAX_TELNET_CLIENTS 2
17 |
18 | class Telnet: public Stream
19 | {
20 | public:
21 | Telnet(uint16_t port = 23);
22 | virtual ~Telnet() {}
23 |
24 | void begin();
25 |
26 | void end();
27 |
28 | void handleConnections();
29 |
30 | int getConnectionCount();
31 |
32 | int available(void) override;
33 |
34 | void flush(void) override;
35 |
36 | int peek(void) override
37 | {
38 | int return_value = -1;
39 | for(uint8_t i = 0; i < MAX_TELNET_CLIENTS; i++){
40 | if (serverClients[i] && serverClients[i].connected()){
41 | return_value = serverClients[i].peek();
42 | if (return_value >= 0) {
43 | break;
44 | }
45 | }
46 | }
47 | return return_value;
48 | }
49 |
50 | int read(void) override
51 | {
52 | int return_value = -1;
53 | for(uint8_t i = 0; i < MAX_TELNET_CLIENTS; i++){
54 | if (serverClients[i] && serverClients[i].connected()){
55 | return_value = serverClients[i].read();
56 | if (return_value >= 0) {
57 | break;
58 | }
59 | }
60 | }
61 | return return_value;
62 | }
63 |
64 | size_t read(char* buffer, size_t size)
65 | {
66 | size_t return_value = 0;
67 | for(uint8_t i = 0; i < MAX_TELNET_CLIENTS; i++){
68 | if (serverClients[i] && serverClients[i].connected()){
69 | return_value = serverClients[i].read((uint8_t*)buffer, size);
70 | if (return_value > 0) {
71 | break;
72 | }
73 | }
74 | }
75 | return return_value;
76 | }
77 | size_t readBytes(char* buffer, size_t size) override
78 | {
79 | size_t return_value = 0;
80 | for(uint8_t i = 0; i < MAX_TELNET_CLIENTS; i++){
81 | if (serverClients[i] && serverClients[i].connected()){
82 | return_value = serverClients[i].read((uint8_t*)buffer, size);
83 | if (return_value > 0) {
84 | break;
85 | }
86 | }
87 | }
88 | return return_value;
89 | }
90 | size_t readBytes(uint8_t* buffer, size_t size) override
91 | {
92 | size_t return_value = 0;
93 | for(uint8_t i = 0; i < MAX_TELNET_CLIENTS; i++){
94 | if (serverClients[i] && serverClients[i].connected()){
95 | return_value = serverClients[i].read(buffer, size);
96 | if (return_value > 0) {
97 | break;
98 | }
99 | }
100 | }
101 | return return_value;
102 | }
103 |
104 | size_t write(uint8_t c) override
105 | {
106 | size_t last_return_value = 0;
107 | //push UART data to all connected telnet clients
108 | for(uint8_t i = 0; i < MAX_TELNET_CLIENTS; i++) {
109 | if (serverClients[i] && serverClients[i].connected()){
110 | last_return_value = serverClients[i].write(c);
111 | feedLoopWDT(); // Must be done <= 360 mS
112 | auto _millis = millis();
113 | if(_millis > _last_yield_ms + _yield_timeout) {
114 | //yield();
115 | delay(10);
116 | _last_yield_ms=_millis;
117 | }
118 | }
119 | }
120 | return last_return_value;
121 | }
122 | size_t write(const uint8_t *buffer, size_t size) override
123 | {
124 | size_t last_return_value = 0;
125 | //push UART data to all connected telnet clients
126 | for(uint8_t i = 0; i < MAX_TELNET_CLIENTS; i++){
127 | if (serverClients[i] && serverClients[i].connected()){
128 | last_return_value = serverClients[i].write(buffer, size);
129 | feedLoopWDT(); // Must be done <= 360 mS
130 | auto _millis = millis();
131 | if(_millis > _last_yield_ms + _yield_timeout) {
132 | //yield();
133 | delay(10);
134 | _last_yield_ms=_millis;
135 | }
136 | }
137 | }
138 | return last_return_value;
139 | }
140 | using Print::write; // Import other write() methods to support things like write(0) properly
141 |
142 | protected:
143 | WiFiServer server;
144 | WiFiClient serverClients[MAX_TELNET_CLIENTS];
145 | size_t _rx_size;
146 | unsigned long _last_yield_ms;
147 | const unsigned long _yield_timeout = 500;
148 | };
149 |
150 | class TelnetSerial: public Stream
151 | {
152 | public:
153 | TelnetSerial(uint16_t telnetPort = 23) : _telnet(telnetPort) {
154 |
155 | }
156 | virtual ~TelnetSerial() {}
157 |
158 | void begin() {
159 | _telnet.begin();
160 | _begun = true;
161 | }
162 |
163 | void end() {
164 | _telnet.end();
165 | _begun = false;
166 | }
167 |
168 | void loop() {
169 | SCOPED_STACK_ENTRY;
170 | _telnet.handleConnections();
171 | }
172 |
173 | int getConnectionCount() {
174 | return _telnet.getConnectionCount();
175 | }
176 |
177 | int available(void)
178 | {
179 | int last_return_value = 0;
180 | last_return_value = Serial.available();
181 | if(_begun && !last_return_value) {
182 | last_return_value = _telnet.available();
183 | }
184 | return last_return_value;
185 | }
186 |
187 | void flush(void)
188 | {
189 | Serial.flush();
190 | if(_begun) {
191 | _telnet.flush();
192 | }
193 | }
194 |
195 | int peek(void) override
196 | {
197 | int last_return_value = -1;
198 | last_return_value = Serial.peek();
199 | if(_begun && last_return_value < 0) {
200 | last_return_value = _telnet.peek();
201 | }
202 | return last_return_value;
203 | }
204 |
205 | int read(void) override
206 | {
207 | int last_return_value = -1;
208 | last_return_value = Serial.read();
209 | if(_begun && last_return_value < 0) {
210 | last_return_value = _telnet.read();
211 | }
212 | return last_return_value;
213 | }
214 |
215 | size_t read(char* buffer, size_t size)
216 | {
217 | size_t last_return_value = 0;
218 | last_return_value = Serial.read(buffer, size);
219 | if(_begun && !last_return_value) {
220 | last_return_value = _telnet.read(buffer, size);
221 | }
222 | return last_return_value;
223 | }
224 | size_t readBytes(char* buffer, size_t size) override
225 | {
226 | size_t last_return_value = 0;
227 | last_return_value = Serial.read(buffer, size);
228 | if(_begun && !last_return_value) {
229 | last_return_value = _telnet.read(buffer, size);
230 | }
231 | return last_return_value;
232 | }
233 |
234 | size_t write(uint8_t c) override
235 | {
236 | size_t last_return_value = 0;
237 | //. Test if using single char writing...
238 | //if(_begun) {
239 | // last_return_value = _telnet.write(c);
240 | //}
241 | last_return_value = Serial.write(c);
242 | return last_return_value;
243 | }
244 |
245 | size_t write(const uint8_t *buffer, size_t size) override
246 | {
247 | size_t last_return_value = 0;
248 | if(_begun) {
249 | last_return_value = _telnet.write(buffer, size);
250 | }
251 | last_return_value = Serial.write(buffer, size);
252 | return last_return_value;
253 | }
254 |
255 | using Print::write; // Import other write() methods to support things like write(0) properly
256 |
257 | protected:
258 | Telnet _telnet;
259 | bool _begun = false;
260 |
261 | public:
262 | Telnet& TelNet = _telnet;
263 | };
264 |
265 |
266 | #endif
267 |
--------------------------------------------------------------------------------
/include/WiFiComponent.h:
--------------------------------------------------------------------------------
1 | #ifndef WIFICOMPONENT_h
2 | #define WIFICOMPONENT_h
3 |
4 | // Basic headers
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | // Tweaked SDK configuration
12 | #include "sdkconfig.h"
13 |
14 | // Arduino includes
15 | #include
16 | #include
17 | #include // https://github.com/tzapu/WiFiManager
18 |
19 | // Configuration access point password:
20 | #ifndef AP_PASSWD
21 | #define AP_PASSWD "abc45678"
22 | #endif
23 |
24 | // Config portal httpd auth:
25 | #ifndef HTTPD_USER
26 | #define HTTPD_USER "admin"
27 | #endif
28 | #ifndef HTTPD_PASSWD
29 | #define HTTPD_PASSWD "1234"
30 | #endif
31 |
32 | class WiFiComponent {
33 | public:
34 | typedef std::function customHtmlHandler_t;
35 |
36 | WiFiComponent(Stream& serialStream) : mSerial(serialStream)
37 | {
38 | // Nothing
39 | }
40 |
41 | void setup();
42 | void loop();
43 |
44 | void registerOtaStartCallback(std::function callback);
45 |
46 | void registerParamSaveCallback(std::function callback);
47 |
48 | // Note: This must be called before 'setup()'!!
49 | void addCustomHtmlPage(const char* path, customHtmlHandler_t handler);
50 |
51 | private:
52 | void wifiInfo();
53 |
54 | // Setup functions
55 | void setupArduinoOTA();
56 | void setupConfigPortal();
57 |
58 | void stopArduinoOTA();
59 |
60 | // Parameter handling functions
61 | void loadParams();
62 | void storeParams();
63 |
64 | // Callbacks
65 | void saveWifiCallback();
66 | void configModeCallback (WiFiManager *myWiFiManager);
67 | void saveParamCallback();
68 | void handleRoute();
69 | void bindServerCallback();
70 |
71 | Stream& mSerial;
72 |
73 | uint8_t otaBusy = 0;
74 | std::vector> ota_callback_functions;
75 |
76 | std::vector> paramSaved_callback_functions;
77 |
78 | struct customPage_t {
79 | const char* path;
80 | customHtmlHandler_t handler;
81 |
82 | customPage_t(const char* Path, customHtmlHandler_t Handler) : path(Path), handler(Handler) {
83 | }
84 | };
85 | std::vector custom_html_page_handlers;
86 | String _hostname;
87 | };
88 |
89 | #endif // WIFICOMPONENT_h
--------------------------------------------------------------------------------
/include/led.h:
--------------------------------------------------------------------------------
1 | #ifndef LED_H
2 | #define LED_H
3 |
4 | #include
5 |
6 | #define BLINK_GPIO (gpio_num_t)CONFIG_BLINK_GPIO
7 |
8 | #define ON 255
9 | #define OFF 0
10 |
11 | class LED {
12 | public:
13 | LED(const gpio_num_t pin = BLINK_GPIO) : _pin(pin){
14 |
15 | }
16 |
17 | void setup(){
18 | gpio_reset_pin(_pin);
19 | /* Set the GPIO as a push/pull output */
20 | gpio_set_direction(_pin, GPIO_MODE_OUTPUT);
21 |
22 | ledcAttachPin(_pin, 0); // Assign ledpin to PWM channel
23 | // Initialize channels
24 | // channels 0-15, resolution 1-16 bits, freq limits depend on resolution
25 | // ledcSetup(uint8_t channel, uint32_t freq, uint8_t resolution_bits);
26 | ledcSetup(0, 4000, 8); // 12 kHz PWM, 8-bit resolution
27 | }
28 |
29 | // void blink_task(void *pvParameter)
30 | // {
31 | // // Configure the IOMUX register for pad BLINK_GPIO (some pads are
32 | // // muxed to GPIO on reset already, but some default to other
33 | // // functions and need to be switched to GPIO. Consult the
34 | // // Technical Reference for a list of pads and their default
35 | // // functions.)
36 | // //
37 | // gpio_pad_select_gpio(BLINK_GPIO);
38 | // // Set the GPIO as a push/pull output
39 | // gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
40 | // while(1) {
41 | // // Blink off (output low)
42 | // gpio_set_level(BLINK_GPIO, 0);
43 | // vTaskDelay(1000 / portTICK_PERIOD_MS);
44 | // // Blink on (output high)
45 | // gpio_set_level(BLINK_GPIO, 1);
46 | // vTaskDelay(1000 / portTICK_PERIOD_MS);
47 | // }
48 | // }
49 |
50 | void toggle() {
51 | // Toggle the LED state
52 | _led_state = (_led_state ? 0 : 255);
53 |
54 | ledcWrite(0, _led_state); // set the brightness of the LED
55 | }
56 |
57 | void set(uint8_t level) {
58 | //gpio_set_level(_pin, level);
59 |
60 | ledcWrite(0, level); // set the brightness of the LED
61 | _led_state = level;
62 | }
63 |
64 | private:
65 | uint8_t _led_state = 0;
66 | const gpio_num_t _pin;
67 | };
68 |
69 | extern LED led;
70 |
71 | #endif // LED_H
--------------------------------------------------------------------------------
/include/mqtt.h:
--------------------------------------------------------------------------------
1 | #ifndef MQTT_H
2 | #define MQTT_H
3 |
4 | // Basic headers
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | // Arduino headers
12 | #include
13 | #include
14 | #include "WiFiClient.h"
15 | #include "Stream.h"
16 |
17 |
18 | class MQTT {
19 | public:
20 | typedef std::function CallbackFunction_t;
21 |
22 | MQTT(Stream& serialStream) : mSerial(serialStream), mqtt_client(espClient)
23 | {
24 | // Nothing..
25 | }
26 |
27 | void setup(
28 | const char* mqtt_server,
29 | const char* mqtt_port,
30 | const char* mqtt_username,
31 | const char* mqtt_password,
32 | const char* mqtt_client_id);
33 | void loop();
34 |
35 | void setStateTopic(std::string state_topic);
36 | void setIpTopic(std::string ip_topic);
37 | static std::string trimWildcards(const char* topic);
38 |
39 | void send_message(const char *topic, const char *payload, bool retain = false);
40 |
41 | void add_callback(const char* topic, CallbackFunction_t callbackFunction);
42 | void clear_callbacks();
43 |
44 | void add_subscription_topic(String topic);
45 | void remove_subscription_topic(String topic);
46 | void clear_subscription_topics();
47 |
48 | private:
49 |
50 | void mqtt_callback(char* topic, byte* payload, unsigned int length);
51 | bool reconnect();
52 |
53 | Stream& mSerial;
54 | WiFiClient espClient;
55 | PubSubClient mqtt_client;
56 |
57 | // Stored MQTT parameters
58 | const char* _mqtt_server = nullptr;
59 | const char* _mqtt_port = nullptr;
60 | const char* _mqtt_username = nullptr;
61 | const char* _mqtt_password = nullptr;
62 | const char* _mqtt_clientId = nullptr;
63 |
64 | uint32_t _mqtt_reconnect_retries = 0;
65 |
66 | std::string _mqtt_state_topic_str = "";
67 | std::string _mqtt_ip_topic_str = "";
68 |
69 | // MQTT Last reconnection counter
70 | unsigned long last_reconnect_attempt = 0;
71 |
72 | std::vector> callback_functions;
73 | std::vector subscription_topics;
74 |
75 | static const uint8_t mqtt_max_reconnect_tries = 10;
76 | };
77 |
78 |
79 | extern MQTT mqtt;
80 |
81 | #endif // MQTT_H
82 |
--------------------------------------------------------------------------------
/include/parameter.h:
--------------------------------------------------------------------------------
1 | #ifndef Parameter_h
2 | #define Parameter_h
3 |
4 | // Basic headers
5 | #include
6 | #include
7 | #include
8 |
9 | // Tweaked SDK configuration
10 | #include "sdkconfig.h"
11 |
12 | #include // https://github.com/tzapu/WiFiManager
13 |
14 |
15 | #define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
16 | #define MAX(a ,b) ((a) > (b) ? (a) : (b))
17 |
18 |
19 | class Parameter : public WiFiManagerParameter{
20 | public:
21 | // Constructors for different Parameter types:
22 | Parameter(const char *custom);
23 | Parameter(const char *id, const char *label, const char* defaultValue = "", int length = 0, const char *custom = nullptr, int labelPlacement = WFM_LABEL_BEFORE);
24 |
25 | void initialize();
26 | void storeValue();
27 |
28 | void setValue(const char *value);
29 |
30 | private:
31 | bool _initialized = false;
32 | };
33 |
34 | bool param2bool(const Parameter& param);
35 |
36 | template::value, int>::type* = nullptr>
37 | constexpr int maxNumDigits(const T maxVal) {
38 | return MAX(6, static_cast(log10(abs(maxVal))) + 2);
39 | }
40 |
41 | template::value, int>::type* = nullptr>
42 | constexpr int maxNumDigits(const T maxVal) {
43 | return 12;
44 | }
45 |
46 | // Numeric parameter:
47 | template::value, T>::type>
48 | class NumericParameter : public Parameter
49 | {
50 | public:
51 | NumericParameter(const char *id, const char *label, T defaultValue, T minValue = std::numeric_limits::min(), T maxValue = std::numeric_limits::max(), int labelPlacement = WFM_LABEL_BEFORE) :
52 | Parameter(id, label, nullptr, maxNumDigits(std::numeric_limits::max()), nullptr, labelPlacement), m_min(minValue), m_max(maxValue)
53 | {
54 | std::string strVal = std::to_string(defaultValue);
55 | WiFiManagerParameter::setValue(strVal.c_str());
56 | }
57 |
58 | void setValue(const T value) {
59 | std::string strVal = std::to_string(value);
60 | Parameter::setValue(strVal.c_str());
61 | }
62 |
63 | template
64 | const typename std::enable_if::value, T>::type getValue() {
65 | T val = atof(Parameter::getValue());
66 | T cVal = CLAMP(val, m_min, m_max);
67 | if (cVal != val) {
68 | setValue(cVal);
69 | }
70 | return cVal;
71 | }
72 |
73 | template
74 | const typename std::enable_if::value, T>::type getValue() {
75 | long long val = atoll(Parameter::getValue());
76 | T tVal = CLAMP(val, m_min, m_max);
77 | if (tVal != val) {
78 | setValue(tVal);
79 | }
80 | return tVal;
81 | }
82 |
83 | operator T() {
84 | return getValue();
85 | }
86 |
87 | T& operator=(T value) {
88 | setValue(value);
89 | return value;
90 | }
91 |
92 | private:
93 | const T m_min;
94 | const T m_max;
95 | };
96 |
97 | typedef NumericParameter BoolParameter;
98 | typedef NumericParameter U8Parameter;
99 | typedef NumericParameter< int8_t> I8Parameter;
100 | typedef NumericParameter U16Parameter;
101 | typedef NumericParameter< int16_t> I16Parameter;
102 | typedef NumericParameter U32Parameter;
103 | typedef NumericParameter< int32_t> I32Parameter;
104 | typedef NumericParameter IntParameter;
105 | typedef NumericParameter LongParameter;
106 | typedef NumericParameter ULongParameter;
107 | typedef NumericParameter FloatParameter;
108 |
109 | #endif // Parameter_h
110 |
--------------------------------------------------------------------------------
/include/stackDbgHelper.h:
--------------------------------------------------------------------------------
1 | #ifndef StackDbgHelper_h
2 | #define StackDbgHelper_h
3 |
4 | // Basic headers
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | // Tweaked SDK configuration
11 | #include "sdkconfig.h"
12 |
13 | // Arduino includes
14 | #include
15 |
16 | struct stack_entry {
17 | uint32_t pc;
18 | const char* func;
19 | uint32_t line;
20 |
21 | stack_entry(uint32_t _pc, const char* f, uint32_t l) : pc(_pc), func(f), line(l) {
22 |
23 | }
24 | };
25 |
26 | extern std::stack _stack;
27 |
28 | class scopedStackEntry {
29 | public:
30 | scopedStackEntry(uint32_t val, const char* f, uint32_t line) : _entry(val, f, line) {
31 | _stack.push(_entry);
32 | }
33 |
34 | ~scopedStackEntry() {
35 | _stack.pop();
36 | }
37 |
38 | private:
39 | stack_entry _entry;
40 | };
41 |
42 | #define SCOPED_STACK_ENTRY scopedStackEntry _s(_stack.size(), __PRETTY_FUNCTION__, __LINE__);
43 |
44 |
45 | #endif // StackDbgHelper_h
46 |
--------------------------------------------------------------------------------
/partitions_custom.csv:
--------------------------------------------------------------------------------
1 | # Name, Type, SubType, Offset, Size, Flags
2 | nvs, data, nvs, 0x009000, 0x005000,
3 | otadata, data, ota, 0x00e000, 0x002000,
4 | app0, app, ota_0, 0x010000, 0x1F0000,
5 | app1, app, ota_1, 0x200000, 0x1F0000,
6 | eeprom0, data, 0x99, 0x3F0000, 0x002000,
7 | spiffs, data, spiffs, 0x3F2000, 0x00E000,
--------------------------------------------------------------------------------
/platformio.ini:
--------------------------------------------------------------------------------
1 | ; PlatformIO Project Configuration File
2 | ;
3 | ; Build options: build flags, source filter
4 | ; Upload options: custom upload port, speed and extra flags
5 | ; Library options: dependencies, extra library storages
6 | ; Advanced options: extra scripting
7 | ;
8 | ; Please visit documentation for the other options and examples
9 | ; https://docs.platformio.org/page/projectconf.html
10 |
11 | [env]
12 | # Use Tasmota platform: It refers to Arduino + Esp-IDF frameworks that work well together!!
13 | platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.4.1/platform-espressif32-2.0.4.1.zip
14 | framework = arduino, espidf
15 | platform_packages =
16 |
17 | lib_deps =
18 | ropg/ezTime @ 0.8.3
19 | https://github.com/RoboMagus/WiFiManager.git#customizations
20 | https://github.com/knolleary/PubSubClient#v2.8
21 |
22 | build_flags =
23 | ; Do Not Modify:
24 | -DARDUINO_STACK_SIZE=4096
25 | -DCORE_DEBUG_LEVEL=3
26 | ; -DCORE_DEBUG_LEVEL=4
27 | -DCONFIG_BLINK_GPIO=2
28 | -DESP32=1
29 | -DMQTT_MAX_PACKET_SIZE=512
30 | -DWM_MDNS=1
31 | -DWM_ERASE_NVS=1
32 | -DWM_DEBUG_LEVEL=DEBUG_NOTIFY
33 | -Wno-missing-field-initializers
34 | -Wno-unused-variable
35 | ; Can Modify:
36 | -DAP_PASSWD=\"abc45678\"
37 | -DHTTPD_USER=\"admin\"
38 | -DHTTPD_PASSWD=\"1234\"
39 | -DMAX_NUM_STORED_BLUETOOTH_DEVICES=8
40 | -DDUMPTIMEMEMINTERVAL=10
41 | ; -DNO_USE_TELNET_SERIAL
42 |
43 | monitor_filters = esp32_exception_decoder
44 | monitor_speed = 115200
45 |
46 | ; >>>>>>>>>>>
47 | ; For OTA update and remote debugging
48 | ;
49 | ; monitor_port = socket://192.168.1.200:23
50 | ; upload_protocol = espota
51 | ; upload_port = 192.168.1.200
52 | ; upload_flags =
53 | ; --port=3232
54 | ; --auth=admin
55 | ; <<<<<<<<<<<
56 |
57 | [env:wemos_d1_mini32]
58 | board = wemos_d1_mini32
59 | board_build.partitions = partitions_custom.csv
60 | board_upload.maximum_size = 2031616
61 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 | 
4 |
5 | # ESP32 BT Monitor
6 |  
7 | 
8 |
9 | __What is it?__
10 |
11 | This is a (at the moment __partial__) port of [andrewjfreyer/monitor](https://github.com/andrewjfreyer/monitor) for the popular and super cheap ESP32 boards. For a more detailed explanation of how it works, visit the link above. But as a short summary: this software allows you to scan for known Bluetooth devices by MAC address on demand, by requesting their name. The beauty of it is that you don't need any special software running on the devices you'd like to track!
12 |
13 | __iBeacon support:__
14 |
15 | Currently, support for ble iBeacon devices is also being implemented!
16 | The ESP32 will in the background continually listen passively to broadcasts of iBeacon devices. If a found ble __UUID__ matches one of the configured __UUID__'s then an MQTT message will be broadcast that includes the _RSSI_ of the found service.
17 | _Note_ that this feature is currently still subject to change!!
18 |
19 |
20 | ## Building the project from source
21 | ### Prerequisites
22 | In order to build this project, you need to have __Visual Studio Code__ installed, with the __C/C++__ and __PlatformIO IDE__ extensions.
23 |
24 | ### Libraries
25 | This project relies on the following libraries:
26 | - [ropg/ezTime](https://github.com/ropg/ezTime)
27 | - [knolleary/PubSubClient](https://github.com/knolleary/PubSubClient#v2.8)
28 | - [RoboMagus/WiFiManager](https://github.com/RoboMagus/WiFiManager) (Modified from [tzapu/WiFiManager](https://github.com/tzapu/WiFiManager))
29 |
30 | ### Build it
31 | 1. Clone this repository
32 | 2. Open the local repository directory in VSCode
33 | 3. Open the PIO _Projects & Configuration_ tab and create an existing project.
34 | 4. Open this project from the PIO interface
35 | 5. In the sidebar, open up the PIO Tab and under _PROJECT TASKS_ / _Default_ hit _Build_
36 | Note: The first time opening this project, PlatformIO will take some time to fetch all the required modules before the list under _PROJECT TASKS_ shows up!!
37 | 6. Once the build succeeds you can flash your ESP32 with the '_Monitor_' compatible Bluetooth scanner.
38 |
39 | __Modifications:__
40 | When building the project from sources, there are some things you may want to customize in ```platformio.ini```.
41 | - ```AP_PASSWD```: The AccessPoint password for when the ESP32 is not yet configured to connect to your home WiFi network.
42 | - ```HTTPD_USER```: Username for authorization on the config portal when the ESP32 is connected to your home WiFi network.
43 | - ```HTTPD_PASSWD```: Password for authorization on the config portal when the ESP32 is connected to your home WiFi network.
44 | - ```MAX_NUM_STORED_BLUETOOTH_DEVICES```: Maximum number of _known bluetooth devices_ that can be stored on the ESP32
45 |
46 | By default PlatformIO is set up for flashing devices that are connected to your computer. If you wish to perform remote debugging or over the air updates using ```espota``` you'll need to uncomment the following section and fill in your device-ip:
47 | ```
48 | monitor_port = socket://[device-ip]:23
49 | upload_protocol = espota
50 | upload_port = [device-ip]
51 | upload_flags =
52 | --port=3232
53 | --auth=admin
54 | ```
55 |
56 |
57 | ## Configuration
58 | After flasing your ESP32 some initial configuration is required. To begin, connect your phone to the ESP32's WiFi hotspot. This will have a name starting with ```ESP32_bt```, followed by unique characters based on the devices MAC address. The default firmware configuration requires the following credentials in order to connect to the AP: ```abc45678```. When connected navigate with your browser of choice to ```192.168.4.1``` to open the configuration menu.
59 |
60 |
61 |
62 | Now it's best to first enter the __settings__ menu to start configuration there. Performing the WiFi configuration first will cause the device to restart and connect to your home network. You can still configure the device after this, it just requires some more steps to navigate to it's new IP again!
63 | The settings menu contains all settings related to the BT monitor application as shown below. The scan settings and BT devices can be skipped and configured later on. The important bits for now are the MQTT parameters to make sure the application can communicate.
64 |
65 |
66 |
67 | In case you need to revisit the configuration pages you can do so by navigating to the ESP32's IP address on your home network. To prevent others from tinkering with your device any access to it's webpage once it's connected to your WiFi network is password protected! To log on, use username ```admin``` and password ```1234```.
68 |
69 | ## Usage
70 | ### web control
71 | The ESP32 bluetooth scan status can be seen through the devices webpage by following the __BT Monitor__ link in the main menu. This page will show you all configured devices by name and MAC address, as well as their away / present state. From this page you can also trigger various scans and update the page to load the new scan results.
72 |
73 |
74 |
75 | ### Home assistant
76 | Find some examples for sensors and automations in HomeAssistant [here](doc/HomeAssistantSnippets.md).
77 |
78 | ## Features
79 | ### Implemented:
80 | - [andrewjfreyer/monitor](https://github.com/andrewjfreyer/monitor) compatible MQTT scan reporting
81 | - Arrival / Departure scan triggered by ```monitor/scan/arrive``` and ```monitor/scan/depart```
82 | - 'Any' scan (scan for departure on present devices and arrival for away devices) triggered by ```monitor/scan/any```
83 | - Periodic scanning
84 | - Setup known bluetooth devices through MQTT using ```monitor/setup/add known device``` and ```monitor/setup/delete known device```
85 | - Send only MAC when deleting a device
86 | - Send MAC followed by its alias when adding devices
87 | - Over the air update
88 | - through web interface
89 | - Using ```espota```
90 | - Setup through [modified](https://github.com/RoboMagus/WiFiManager) [WiFiManager](https://github.com/tzapu/WiFiManager)
91 | - Password protected web interface once connected to your home WiFi network
92 | - Bluetooth Scan status + scan controls webpage
93 | - Logging over serial and telnet
94 | - Monitor settings:
95 | - #Arrival scans
96 | - #Departure scans
97 | - seconds between scans within set
98 | - minimal time between scan sets
99 | - periodic scanning interval
100 |
101 | ### ToDo
102 | - [ ] Add passive scanning as is available in [monitor](https://github.com/andrewjfreyer/monitor)
103 | - [ ] Expand configuration options
104 | - [ ] Add BLE iBeacon scanning support for room by room presence detection
105 | - [x] Initial support __(This is subject to change!!)__
106 | - [ ] Add support for interacting with ble keyfinders
107 | - [ ] Strip away the core BT monitor logic to expose as a library
108 | - [ ] Make an ESPHome component for it
109 | - **Work In Progress**
110 |
111 |
--------------------------------------------------------------------------------
/sdkconfig.defaults:
--------------------------------------------------------------------------------
1 | #
2 | # Automatically generated file. DO NOT EDIT.
3 | # Espressif IoT Development Framework (ESP-IDF) Project Configuration
4 | #
5 | CONFIG_IDF_CMAKE=y
6 | CONFIG_IDF_TARGET="esp32"
7 | CONFIG_IDF_TARGET_ESP32=y
8 | CONFIG_IDF_FIRMWARE_CHIP_ID=0x0000
9 |
10 | #
11 | # SDK tool configuration
12 | #
13 | CONFIG_SDK_TOOLPREFIX="xtensa-esp32-elf-"
14 | # CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS is not set
15 | # end of SDK tool configuration
16 |
17 | #
18 | # Build type
19 | #
20 | CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y
21 | # CONFIG_APP_BUILD_TYPE_ELF_RAM is not set
22 | CONFIG_APP_BUILD_GENERATE_BINARIES=y
23 | CONFIG_APP_BUILD_BOOTLOADER=y
24 | CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y
25 | # end of Build type
26 |
27 | #
28 | # Application manager
29 | #
30 | CONFIG_APP_COMPILE_TIME_DATE=y
31 | # CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set
32 | # CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set
33 | # CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set
34 | CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16
35 | # end of Application manager
36 |
37 | #
38 | # Bootloader config
39 | #
40 | CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
41 | # CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set
42 | # CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set
43 | # CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set
44 | # CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set
45 | # CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set
46 | # CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set
47 | CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y
48 | # CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set
49 | # CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set
50 | CONFIG_BOOTLOADER_LOG_LEVEL=3
51 | # CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_8V is not set
52 | CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y
53 | # CONFIG_BOOTLOADER_FACTORY_RESET is not set
54 | # CONFIG_BOOTLOADER_APP_TEST is not set
55 | CONFIG_BOOTLOADER_WDT_ENABLE=y
56 | # CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set
57 | CONFIG_BOOTLOADER_WDT_TIME_MS=9000
58 | # CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set
59 | # CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set
60 | CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0
61 | # CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set
62 | # end of Bootloader config
63 |
64 | #
65 | # Security features
66 | #
67 | # CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set
68 | # CONFIG_SECURE_BOOT is not set
69 | # CONFIG_SECURE_FLASH_ENC_ENABLED is not set
70 | # end of Security features
71 |
72 | #
73 | # Serial flasher config
74 | #
75 | CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200
76 | CONFIG_ESPTOOLPY_WITH_STUB=y
77 | # CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set
78 | # CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set
79 | CONFIG_ESPTOOLPY_FLASHMODE_DIO=y
80 | # CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set
81 | CONFIG_ESPTOOLPY_FLASHMODE="dio"
82 | # CONFIG_ESPTOOLPY_FLASHFREQ_80M is not set
83 | CONFIG_ESPTOOLPY_FLASHFREQ_40M=y
84 | # CONFIG_ESPTOOLPY_FLASHFREQ_26M is not set
85 | # CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set
86 | CONFIG_ESPTOOLPY_FLASHFREQ="40m"
87 | # CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set
88 | # CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set
89 | CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
90 | # CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set
91 | # CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set
92 | CONFIG_ESPTOOLPY_FLASHSIZE="4MB"
93 | CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y
94 | CONFIG_ESPTOOLPY_BEFORE_RESET=y
95 | # CONFIG_ESPTOOLPY_BEFORE_NORESET is not set
96 | CONFIG_ESPTOOLPY_BEFORE="default_reset"
97 | CONFIG_ESPTOOLPY_AFTER_RESET=y
98 | # CONFIG_ESPTOOLPY_AFTER_NORESET is not set
99 | CONFIG_ESPTOOLPY_AFTER="hard_reset"
100 | # CONFIG_ESPTOOLPY_MONITOR_BAUD_9600B is not set
101 | # CONFIG_ESPTOOLPY_MONITOR_BAUD_57600B is not set
102 | CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y
103 | # CONFIG_ESPTOOLPY_MONITOR_BAUD_230400B is not set
104 | # CONFIG_ESPTOOLPY_MONITOR_BAUD_921600B is not set
105 | # CONFIG_ESPTOOLPY_MONITOR_BAUD_2MB is not set
106 | # CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER is not set
107 | CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL=115200
108 | CONFIG_ESPTOOLPY_MONITOR_BAUD=115200
109 | # end of Serial flasher config
110 |
111 | #
112 | # Partition Table
113 | #
114 | # CONFIG_PARTITION_TABLE_SINGLE_APP is not set
115 | # CONFIG_PARTITION_TABLE_TWO_OTA is not set
116 | CONFIG_PARTITION_TABLE_CUSTOM=y
117 | CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
118 | CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
119 | CONFIG_PARTITION_TABLE_OFFSET=0x8000
120 | CONFIG_PARTITION_TABLE_MD5=y
121 | # end of Partition Table
122 |
123 | #
124 | # Arduino Configuration
125 | #
126 | CONFIG_ENABLE_ARDUINO_DEPENDS=y
127 | CONFIG_AUTOSTART_ARDUINO=y
128 | # CONFIG_ARDUINO_RUN_CORE0 is not set
129 | CONFIG_ARDUINO_RUN_CORE1=y
130 | # CONFIG_ARDUINO_RUN_NO_AFFINITY is not set
131 | CONFIG_ARDUINO_RUNNING_CORE=1
132 | # CONFIG_ARDUINO_EVENT_RUN_CORE0 is not set
133 | CONFIG_ARDUINO_EVENT_RUN_CORE1=y
134 | # CONFIG_ARDUINO_EVENT_RUN_NO_AFFINITY is not set
135 | CONFIG_ARDUINO_EVENT_RUNNING_CORE=1
136 | # CONFIG_ARDUINO_UDP_RUN_CORE0 is not set
137 | CONFIG_ARDUINO_UDP_RUN_CORE1=y
138 | # CONFIG_ARDUINO_UDP_RUN_NO_AFFINITY is not set
139 | CONFIG_ARDUINO_UDP_TASK_PRIORITY=3
140 | CONFIG_ARDUINO_UDP_RUNNING_CORE=1
141 | # CONFIG_ARDUINO_ISR_IRAM is not set
142 | CONFIG_DISABLE_HAL_LOCKS=y
143 |
144 | #
145 | # Debug Log Configuration
146 | #
147 | # CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_NONE is not set
148 | # CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_ERROR is not set
149 | CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_WARN=y
150 | # CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_INFO is not set
151 | # CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_DEBUG is not set
152 | # CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_VERBOSE is not set
153 | CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL=2
154 | # CONFIG_ARDUHAL_LOG_COLORS is not set
155 | # CONFIG_ARDUHAL_ESP_LOG is not set
156 | # end of Debug Log Configuration
157 |
158 | CONFIG_ARDUHAL_PARTITION_SCHEME_DEFAULT=y
159 | # CONFIG_ARDUHAL_PARTITION_SCHEME_MINIMAL is not set
160 | # CONFIG_ARDUHAL_PARTITION_SCHEME_NO_OTA is not set
161 | # CONFIG_ARDUHAL_PARTITION_SCHEME_HUGE_APP is not set
162 | # CONFIG_ARDUHAL_PARTITION_SCHEME_MIN_SPIFFS is not set
163 | CONFIG_ARDUHAL_PARTITION_SCHEME="default"
164 | CONFIG_AUTOCONNECT_WIFI=y
165 | # CONFIG_ARDUINO_SELECTIVE_COMPILATION is not set
166 | CONFIG_ARDUINO_SELECTIVE_WiFi=y
167 | # end of Arduino Configuration
168 |
169 | #
170 | # Compiler options
171 | #
172 | # CONFIG_COMPILER_OPTIMIZATION_DEFAULT is not set
173 | CONFIG_COMPILER_OPTIMIZATION_SIZE=y
174 | # CONFIG_COMPILER_OPTIMIZATION_PERF is not set
175 | # CONFIG_COMPILER_OPTIMIZATION_NONE is not set
176 | # CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE is not set
177 | # CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set
178 | CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE=y
179 | # CONFIG_COMPILER_CXX_EXCEPTIONS is not set
180 | # CONFIG_COMPILER_CXX_RTTI is not set
181 | # CONFIG_COMPILER_STACK_CHECK_MODE_NONE is not set
182 | CONFIG_COMPILER_STACK_CHECK_MODE_NORM=y
183 | # CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set
184 | # CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set
185 | CONFIG_COMPILER_STACK_CHECK=y
186 | # CONFIG_COMPILER_WARN_WRITE_STRINGS is not set
187 | # CONFIG_COMPILER_DISABLE_GCC8_WARNINGS is not set
188 | # end of Compiler options
189 |
190 | #
191 | # Component config
192 | #
193 |
194 | #
195 | # Application Level Tracing
196 | #
197 | CONFIG_APPTRACE_DEST_TRAX=y
198 | # CONFIG_APPTRACE_DEST_NONE is not set
199 | CONFIG_APPTRACE_ENABLE=y
200 | CONFIG_APPTRACE_LOCK_ENABLE=y
201 | CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO=-1
202 | CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH=0
203 | CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX=0
204 |
205 | #
206 | # FreeRTOS SystemView Tracing
207 | #
208 | # CONFIG_SYSVIEW_ENABLE is not set
209 | # end of FreeRTOS SystemView Tracing
210 |
211 | # CONFIG_APPTRACE_GCOV_ENABLE is not set
212 | # end of Application Level Tracing
213 |
214 | #
215 | # Bluetooth
216 | #
217 | CONFIG_BT_ENABLED=y
218 |
219 | #
220 | # Bluetooth controller
221 | #
222 | # CONFIG_BTDM_CTRL_MODE_BLE_ONLY is not set
223 | # CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY is not set
224 | CONFIG_BTDM_CTRL_MODE_BTDM=y
225 | CONFIG_BTDM_CTRL_BLE_MAX_CONN=2
226 | CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN=2
227 | CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN=1
228 | # CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_HCI is not set
229 | CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_PCM=y
230 | CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=1
231 | CONFIG_BTDM_CTRL_PCM_ROLE_EDGE_CONFIG=y
232 | CONFIG_BTDM_CTRL_PCM_ROLE_MASTER=y
233 | # CONFIG_BTDM_CTRL_PCM_ROLE_SLAVE is not set
234 | CONFIG_BTDM_CTRL_PCM_POLAR_FALLING_EDGE=y
235 | # CONFIG_BTDM_CTRL_PCM_POLAR_RISING_EDGE is not set
236 | CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0
237 | CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0
238 | CONFIG_BTDM_CTRL_AUTO_LATENCY=y
239 | CONFIG_BTDM_CTRL_AUTO_LATENCY_EFF=y
240 | CONFIG_BTDM_CTRL_LEGACY_AUTH_VENDOR_EVT=y
241 | CONFIG_BTDM_CTRL_LEGACY_AUTH_VENDOR_EVT_EFF=y
242 | CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF=2
243 | CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF=2
244 | CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF=1
245 | CONFIG_BTDM_CTRL_PINNED_TO_CORE_0=y
246 | # CONFIG_BTDM_CTRL_PINNED_TO_CORE_1 is not set
247 | CONFIG_BTDM_CTRL_PINNED_TO_CORE=0
248 | CONFIG_BTDM_CTRL_HCI_MODE_VHCI=y
249 | # CONFIG_BTDM_CTRL_HCI_MODE_UART_H4 is not set
250 |
251 | #
252 | # MODEM SLEEP Options
253 | #
254 | CONFIG_BTDM_MODEM_SLEEP=y
255 | CONFIG_BTDM_MODEM_SLEEP_MODE_ORIG=y
256 | # CONFIG_BTDM_MODEM_SLEEP_MODE_EVED is not set
257 | CONFIG_BTDM_LPCLK_SEL_MAIN_XTAL=y
258 | # end of MODEM SLEEP Options
259 |
260 | CONFIG_BTDM_BLE_DEFAULT_SCA_250PPM=y
261 | CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF=1
262 | # CONFIG_BTDM_BLE_SCAN_DUPL is not set
263 | CONFIG_BTDM_CTRL_FULL_SCAN_SUPPORTED=y
264 | CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y
265 | CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100
266 | CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20
267 | CONFIG_BTDM_COEX_BT_OPTIONS=y
268 | CONFIG_BTDM_COEX_BLE_ADV_HIGH_PRIORITY=y
269 | # end of Bluetooth controller
270 |
271 | CONFIG_BT_BLUEDROID_ENABLED=y
272 | # CONFIG_BT_NIMBLE_ENABLED is not set
273 | # CONFIG_BT_CONTROLLER_ONLY is not set
274 |
275 | #
276 | # Bluedroid Options
277 | #
278 | CONFIG_BT_BTC_TASK_STACK_SIZE=2048
279 | CONFIG_BT_BLUEDROID_PINNED_TO_CORE_0=y
280 | # CONFIG_BT_BLUEDROID_PINNED_TO_CORE_1 is not set
281 | CONFIG_BT_BLUEDROID_PINNED_TO_CORE=0
282 | CONFIG_BT_BTU_TASK_STACK_SIZE=2048
283 | # CONFIG_BT_BLUEDROID_MEM_DEBUG is not set
284 | CONFIG_BT_CLASSIC_ENABLED=y
285 | # CONFIG_BT_A2DP_ENABLE is not set
286 | # CONFIG_BT_SPP_ENABLED is not set
287 | # CONFIG_BT_HFP_ENABLE is not set
288 | # CONFIG_BT_HID_HOST_ENABLED is not set
289 | CONFIG_BT_SSP_ENABLED=y
290 | CONFIG_BT_BLE_ENABLED=y
291 | CONFIG_BT_GATTS_ENABLE=y
292 | # CONFIG_BT_GATTS_PPCP_CHAR_GAP is not set
293 | # CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL is not set
294 | CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_AUTO=y
295 | CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MODE=0
296 | CONFIG_BT_GATTC_ENABLE=y
297 | CONFIG_BT_GATTC_CACHE_NVS_FLASH=y
298 | CONFIG_BT_BLE_SMP_ENABLE=y
299 | # CONFIG_BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE is not set
300 | CONFIG_BT_STACK_NO_LOG=y
301 | CONFIG_BT_ACL_CONNECTIONS=2
302 | # CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST is not set
303 | CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY=y
304 | # CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK is not set
305 | CONFIG_BT_SMP_ENABLE=y
306 | # CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set
307 | CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30
308 | CONFIG_BT_RESERVE_DRAM=0xdb5c
309 | # end of Bluedroid Options
310 | # end of Bluetooth
311 |
312 | # CONFIG_BLE_MESH is not set
313 |
314 | #
315 | # CoAP Configuration
316 | #
317 | CONFIG_COAP_MBEDTLS_PSK=y
318 | # CONFIG_COAP_MBEDTLS_PKI is not set
319 | # CONFIG_COAP_MBEDTLS_DEBUG is not set
320 | CONFIG_COAP_LOG_DEFAULT_LEVEL=0
321 | # end of CoAP Configuration
322 |
323 | #
324 | # Driver configurations
325 | #
326 |
327 | #
328 | # ADC configuration
329 | #
330 | # CONFIG_ADC_FORCE_XPD_FSM is not set
331 | CONFIG_ADC_DISABLE_DAC=y
332 | # end of ADC configuration
333 |
334 | #
335 | # SPI configuration
336 | #
337 | # CONFIG_SPI_MASTER_IN_IRAM is not set
338 | CONFIG_SPI_MASTER_ISR_IN_IRAM=y
339 | # CONFIG_SPI_SLAVE_IN_IRAM is not set
340 | CONFIG_SPI_SLAVE_ISR_IN_IRAM=y
341 | # end of SPI configuration
342 |
343 | #
344 | # UART configuration
345 | #
346 | # CONFIG_UART_ISR_IN_IRAM is not set
347 | # end of UART configuration
348 |
349 | #
350 | # RTCIO configuration
351 | #
352 | # CONFIG_RTCIO_SUPPORT_RTC_GPIO_DESC is not set
353 | # end of RTCIO configuration
354 | # end of Driver configurations
355 |
356 | #
357 | # eFuse Bit Manager
358 | #
359 | # CONFIG_EFUSE_CUSTOM_TABLE is not set
360 | # CONFIG_EFUSE_VIRTUAL is not set
361 | # CONFIG_EFUSE_CODE_SCHEME_COMPAT_NONE is not set
362 | CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4=y
363 | # CONFIG_EFUSE_CODE_SCHEME_COMPAT_REPEAT is not set
364 | CONFIG_EFUSE_MAX_BLK_LEN=192
365 | # end of eFuse Bit Manager
366 |
367 | #
368 | # ESP-TLS
369 | #
370 | CONFIG_ESP_TLS_USING_MBEDTLS=y
371 | # CONFIG_ESP_TLS_USE_SECURE_ELEMENT is not set
372 | # CONFIG_ESP_TLS_SERVER is not set
373 | # CONFIG_ESP_TLS_PSK_VERIFICATION is not set
374 | # end of ESP-TLS
375 |
376 | #
377 | # ESP32-specific
378 | #
379 | CONFIG_ESP32_REV_MIN_0=y
380 | # CONFIG_ESP32_REV_MIN_1 is not set
381 | # CONFIG_ESP32_REV_MIN_2 is not set
382 | # CONFIG_ESP32_REV_MIN_3 is not set
383 | CONFIG_ESP32_REV_MIN=0
384 | CONFIG_ESP32_DPORT_WORKAROUND=y
385 | # CONFIG_ESP32_DEFAULT_CPU_FREQ_80 is not set
386 | # CONFIG_ESP32_DEFAULT_CPU_FREQ_160 is not set
387 | CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
388 | CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240
389 | # CONFIG_ESP32_SPIRAM_SUPPORT is not set
390 | CONFIG_ESP32_MEMMAP_TRACEMEM=y
391 | CONFIG_ESP32_MEMMAP_TRACEMEM_TWOBANKS=y
392 | # CONFIG_ESP32_TRAX is not set
393 | CONFIG_ESP32_TRACEMEM_RESERVE_DRAM=0x8000
394 | # CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_TWO is not set
395 | CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR=y
396 | CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES=4
397 | # CONFIG_ESP32_ULP_COPROC_ENABLED is not set
398 | CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=0
399 | CONFIG_ESP32_DEBUG_OCDAWARE=y
400 | CONFIG_ESP32_BROWNOUT_DET=y
401 | CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0=y
402 | # CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_1 is not set
403 | # CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_2 is not set
404 | # CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_3 is not set
405 | # CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_4 is not set
406 | # CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_5 is not set
407 | # CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_6 is not set
408 | # CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_7 is not set
409 | CONFIG_ESP32_BROWNOUT_DET_LVL=0
410 | CONFIG_ESP32_REDUCE_PHY_TX_POWER=y
411 | CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y
412 | # CONFIG_ESP32_TIME_SYSCALL_USE_RTC is not set
413 | # CONFIG_ESP32_TIME_SYSCALL_USE_FRC1 is not set
414 | # CONFIG_ESP32_TIME_SYSCALL_USE_NONE is not set
415 | CONFIG_ESP32_RTC_CLK_SRC_INT_RC=y
416 | # CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS is not set
417 | # CONFIG_ESP32_RTC_CLK_SRC_EXT_OSC is not set
418 | # CONFIG_ESP32_RTC_CLK_SRC_INT_8MD256 is not set
419 | CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024
420 | CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000
421 | CONFIG_ESP32_XTAL_FREQ_40=y
422 | # CONFIG_ESP32_XTAL_FREQ_26 is not set
423 | # CONFIG_ESP32_XTAL_FREQ_AUTO is not set
424 | CONFIG_ESP32_XTAL_FREQ=40
425 | # CONFIG_ESP32_DISABLE_BASIC_ROM_CONSOLE is not set
426 | # CONFIG_ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set
427 | # CONFIG_ESP32_USE_FIXED_STATIC_RAM_SIZE is not set
428 | CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL=5
429 | # end of ESP32-specific
430 |
431 | #
432 | # Power Management
433 | #
434 | # CONFIG_PM_ENABLE is not set
435 | # end of Power Management
436 |
437 | #
438 | # ADC-Calibration
439 | #
440 | CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y
441 | CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y
442 | CONFIG_ADC_CAL_LUT_ENABLE=y
443 | # end of ADC-Calibration
444 |
445 | #
446 | # Common ESP-related
447 | #
448 | CONFIG_ESP_ERR_TO_NAME_LOOKUP=y
449 | CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=24
450 | CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=1792
451 | CONFIG_ESP_MAIN_TASK_STACK_SIZE=2048
452 | CONFIG_ESP_IPC_TASK_STACK_SIZE=2048
453 | CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y
454 | CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=1536
455 | CONFIG_ESP_CONSOLE_UART_DEFAULT=y
456 | # CONFIG_ESP_CONSOLE_UART_CUSTOM is not set
457 | # CONFIG_ESP_CONSOLE_UART_NONE is not set
458 | CONFIG_ESP_CONSOLE_UART_NUM=0
459 | CONFIG_ESP_CONSOLE_UART_TX_GPIO=1
460 | CONFIG_ESP_CONSOLE_UART_RX_GPIO=3
461 | CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200
462 | CONFIG_ESP_INT_WDT=y
463 | CONFIG_ESP_INT_WDT_TIMEOUT_MS=500
464 | CONFIG_ESP_INT_WDT_CHECK_CPU1=y
465 | CONFIG_ESP_TASK_WDT=y
466 | # CONFIG_ESP_TASK_WDT_PANIC is not set
467 | CONFIG_ESP_TASK_WDT_TIMEOUT_S=8
468 | CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y
469 | CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y
470 | # CONFIG_ESP_PANIC_HANDLER_IRAM is not set
471 | CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y
472 | CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y
473 | CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y
474 | CONFIG_ESP_MAC_ADDR_UNIVERSE_BT_OFFSET=2
475 | CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y
476 | # end of Common ESP-related
477 |
478 | #
479 | # Ethernet
480 | #
481 | CONFIG_ETH_ENABLED=y
482 | CONFIG_ETH_USE_ESP32_EMAC=y
483 | CONFIG_ETH_PHY_INTERFACE_RMII=y
484 | # CONFIG_ETH_PHY_INTERFACE_MII is not set
485 | CONFIG_ETH_RMII_CLK_INPUT=y
486 | # CONFIG_ETH_RMII_CLK_OUTPUT is not set
487 | CONFIG_ETH_RMII_CLK_IN_GPIO=0
488 | CONFIG_ETH_DMA_BUFFER_SIZE=512
489 | CONFIG_ETH_DMA_RX_BUFFER_NUM=5
490 | CONFIG_ETH_DMA_TX_BUFFER_NUM=5
491 | CONFIG_ETH_USE_SPI_ETHERNET=y
492 | # CONFIG_ETH_SPI_ETHERNET_DM9051 is not set
493 | # CONFIG_ETH_USE_OPENETH is not set
494 | # end of Ethernet
495 |
496 | #
497 | # Event Loop Library
498 | #
499 | # CONFIG_ESP_EVENT_LOOP_PROFILING is not set
500 | CONFIG_ESP_EVENT_POST_FROM_ISR=y
501 | CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y
502 | # end of Event Loop Library
503 |
504 | #
505 | # GDB Stub
506 | #
507 | # end of GDB Stub
508 |
509 | #
510 | # ESP HTTP client
511 | #
512 | CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y
513 | CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH=y
514 | # end of ESP HTTP client
515 |
516 | #
517 | # HTTP Server
518 | #
519 | CONFIG_HTTPD_MAX_REQ_HDR_LEN=512
520 | CONFIG_HTTPD_MAX_URI_LEN=512
521 | CONFIG_HTTPD_ERR_RESP_NO_DELAY=y
522 | CONFIG_HTTPD_PURGE_BUF_LEN=32
523 | # CONFIG_HTTPD_LOG_PURGE_DATA is not set
524 | CONFIG_HTTPD_WS_SUPPORT=y
525 | # end of HTTP Server
526 |
527 | #
528 | # ESP HTTPS OTA
529 | #
530 | # CONFIG_OTA_ALLOW_HTTP is not set
531 | # end of ESP HTTPS OTA
532 |
533 | #
534 | # ESP HTTPS server
535 | #
536 | # CONFIG_ESP_HTTPS_SERVER_ENABLE is not set
537 | # end of ESP HTTPS server
538 |
539 | #
540 | # ESP NETIF Adapter
541 | #
542 | CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120
543 | CONFIG_ESP_NETIF_TCPIP_LWIP=y
544 | # CONFIG_ESP_NETIF_LOOPBACK is not set
545 | CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=y
546 | # end of ESP NETIF Adapter
547 |
548 | #
549 | # ESP System Settings
550 | #
551 | # CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set
552 | CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y
553 | # CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set
554 | # CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set
555 | # end of ESP System Settings
556 |
557 | #
558 | # High resolution timer (esp_timer)
559 | #
560 | # CONFIG_ESP_TIMER_PROFILING is not set
561 | CONFIG_ESP_TIMER_TASK_STACK_SIZE=2048
562 | # CONFIG_ESP_TIMER_IMPL_FRC2 is not set
563 | CONFIG_ESP_TIMER_IMPL_TG0_LAC=y
564 | # end of High resolution timer (esp_timer)
565 |
566 | #
567 | # Wi-Fi
568 | #
569 | CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE=y
570 | CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10
571 | CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=24
572 | # CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set
573 | CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y
574 | CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1
575 | CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=24
576 | # CONFIG_ESP32_WIFI_CSI_ENABLED is not set
577 | CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y
578 | CONFIG_ESP32_WIFI_TX_BA_WIN=6
579 | CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y
580 | CONFIG_ESP32_WIFI_RX_BA_WIN=6
581 | CONFIG_ESP32_WIFI_NVS_ENABLED=y
582 | CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y
583 | # CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set
584 | CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752
585 | CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32
586 | # CONFIG_ESP32_WIFI_DEBUG_LOG_ENABLE is not set
587 | CONFIG_ESP32_WIFI_IRAM_OPT=y
588 | CONFIG_ESP32_WIFI_RX_IRAM_OPT=y
589 | # CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE is not set
590 | # end of Wi-Fi
591 |
592 | #
593 | # PHY
594 | #
595 | CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y
596 | # CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set
597 | CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20
598 | CONFIG_ESP32_PHY_MAX_TX_POWER=20
599 | # end of PHY
600 |
601 | #
602 | # Core dump
603 | #
604 | # CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set
605 | # CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set
606 | CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y
607 | # end of Core dump
608 |
609 | #
610 | # FAT Filesystem support
611 | #
612 | # CONFIG_FATFS_CODEPAGE_DYNAMIC is not set
613 | CONFIG_FATFS_CODEPAGE_437=y
614 | # CONFIG_FATFS_CODEPAGE_720 is not set
615 | # CONFIG_FATFS_CODEPAGE_737 is not set
616 | # CONFIG_FATFS_CODEPAGE_771 is not set
617 | # CONFIG_FATFS_CODEPAGE_775 is not set
618 | # CONFIG_FATFS_CODEPAGE_850 is not set
619 | # CONFIG_FATFS_CODEPAGE_852 is not set
620 | # CONFIG_FATFS_CODEPAGE_855 is not set
621 | # CONFIG_FATFS_CODEPAGE_857 is not set
622 | # CONFIG_FATFS_CODEPAGE_860 is not set
623 | # CONFIG_FATFS_CODEPAGE_861 is not set
624 | # CONFIG_FATFS_CODEPAGE_862 is not set
625 | # CONFIG_FATFS_CODEPAGE_863 is not set
626 | # CONFIG_FATFS_CODEPAGE_864 is not set
627 | # CONFIG_FATFS_CODEPAGE_865 is not set
628 | # CONFIG_FATFS_CODEPAGE_866 is not set
629 | # CONFIG_FATFS_CODEPAGE_869 is not set
630 | # CONFIG_FATFS_CODEPAGE_932 is not set
631 | # CONFIG_FATFS_CODEPAGE_936 is not set
632 | # CONFIG_FATFS_CODEPAGE_949 is not set
633 | # CONFIG_FATFS_CODEPAGE_950 is not set
634 | CONFIG_FATFS_CODEPAGE=437
635 | CONFIG_FATFS_LFN_NONE=y
636 | # CONFIG_FATFS_LFN_HEAP is not set
637 | # CONFIG_FATFS_LFN_STACK is not set
638 | CONFIG_FATFS_FS_LOCK=0
639 | CONFIG_FATFS_TIMEOUT_MS=10000
640 | CONFIG_FATFS_PER_FILE_CACHE=y
641 | # end of FAT Filesystem support
642 |
643 | #
644 | # Modbus configuration
645 | #
646 | CONFIG_FMB_COMM_MODE_RTU_EN=y
647 | CONFIG_FMB_COMM_MODE_ASCII_EN=y
648 | CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=150
649 | CONFIG_FMB_MASTER_DELAY_MS_CONVERT=200
650 | CONFIG_FMB_QUEUE_LENGTH=20
651 | CONFIG_FMB_SERIAL_TASK_STACK_SIZE=2048
652 | CONFIG_FMB_SERIAL_BUF_SIZE=256
653 | CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB=8
654 | CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS=1000
655 | CONFIG_FMB_SERIAL_TASK_PRIO=10
656 | # CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT is not set
657 | CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT=20
658 | CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE=20
659 | CONFIG_FMB_CONTROLLER_STACK_SIZE=4096
660 | CONFIG_FMB_EVENT_QUEUE_TIMEOUT=20
661 | CONFIG_FMB_TIMER_PORT_ENABLED=y
662 | CONFIG_FMB_TIMER_GROUP=0
663 | CONFIG_FMB_TIMER_INDEX=0
664 | # CONFIG_FMB_TIMER_ISR_IN_IRAM is not set
665 | # end of Modbus configuration
666 |
667 | #
668 | # FreeRTOS
669 | #
670 | # CONFIG_FREERTOS_UNICORE is not set
671 | CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF
672 | CONFIG_FREERTOS_CORETIMER_0=y
673 | # CONFIG_FREERTOS_CORETIMER_1 is not set
674 | CONFIG_FREERTOS_HZ=200
675 | CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y
676 | # CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set
677 | # CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set
678 | CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y
679 | CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y
680 | CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y
681 | CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=5
682 | CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y
683 | # CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE is not set
684 | # CONFIG_FREERTOS_ASSERT_DISABLE is not set
685 | CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=768
686 | CONFIG_FREERTOS_ISR_STACKSIZE=1792
687 | # CONFIG_FREERTOS_LEGACY_HOOKS is not set
688 | CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16
689 | # CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION is not set
690 | CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1
691 | CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=1536
692 | CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10
693 | CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0
694 | CONFIG_FREERTOS_USE_TRACE_FACILITY=y
695 | CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y
696 | # CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID is not set
697 | CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y
698 | CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER=y
699 | # CONFIG_FREERTOS_RUN_TIME_STATS_USING_CPU_CLK is not set
700 | CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y
701 | # CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set
702 | CONFIG_FREERTOS_DEBUG_OCDAWARE=y
703 | # CONFIG_FREERTOS_FPU_IN_ISR is not set
704 | # end of FreeRTOS
705 |
706 | #
707 | # Heap memory debugging
708 | #
709 | # CONFIG_HEAP_POISONING_DISABLED is not set
710 | CONFIG_HEAP_POISONING_LIGHT=y
711 | # CONFIG_HEAP_POISONING_COMPREHENSIVE is not set
712 | CONFIG_HEAP_TRACING_OFF=y
713 | # CONFIG_HEAP_TRACING_STANDALONE is not set
714 | # CONFIG_HEAP_TRACING_TOHOST is not set
715 | CONFIG_HEAP_TASK_TRACKING=y
716 | # CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set
717 | # end of Heap memory debugging
718 |
719 | #
720 | # jsmn
721 | #
722 | # CONFIG_JSMN_PARENT_LINKS is not set
723 | # CONFIG_JSMN_STRICT is not set
724 | # end of jsmn
725 |
726 | #
727 | # libsodium
728 | #
729 | # end of libsodium
730 |
731 | #
732 | # Log output
733 | #
734 | # CONFIG_LOG_DEFAULT_LEVEL_NONE is not set
735 | # CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set
736 | # CONFIG_LOG_DEFAULT_LEVEL_WARN is not set
737 | CONFIG_LOG_DEFAULT_LEVEL_INFO=y
738 | # CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set
739 | # CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set
740 | CONFIG_LOG_DEFAULT_LEVEL=3
741 | CONFIG_LOG_COLORS=y
742 | CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y
743 | # CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set
744 | # end of Log output
745 |
746 | #
747 | # LWIP
748 | #
749 | CONFIG_LWIP_LOCAL_HOSTNAME="espressif"
750 | CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y
751 | # CONFIG_LWIP_L2_TO_L3_COPY is not set
752 | # CONFIG_LWIP_IRAM_OPTIMIZATION is not set
753 | CONFIG_LWIP_TIMERS_ONDEMAND=y
754 | CONFIG_LWIP_MAX_SOCKETS=12
755 | # CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set
756 | # CONFIG_LWIP_SO_LINGER is not set
757 | CONFIG_LWIP_SO_REUSE=y
758 | CONFIG_LWIP_SO_REUSE_RXTOALL=y
759 | CONFIG_LWIP_SO_RCVBUF=y
760 | # CONFIG_LWIP_NETBUF_RECVINFO is not set
761 | CONFIG_LWIP_IP4_FRAG=y
762 | CONFIG_LWIP_IP6_FRAG=y
763 | # CONFIG_LWIP_IP4_REASSEMBLY is not set
764 | # CONFIG_LWIP_IP6_REASSEMBLY is not set
765 | # CONFIG_LWIP_IP_FORWARD is not set
766 | # CONFIG_LWIP_STATS is not set
767 | # CONFIG_LWIP_ETHARP_TRUST_IP_MAC is not set
768 | CONFIG_LWIP_ESP_GRATUITOUS_ARP=y
769 | CONFIG_LWIP_GARP_TMR_INTERVAL=60
770 | CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=24
771 | CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y
772 | # CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set
773 |
774 | #
775 | # DHCP server
776 | #
777 | CONFIG_LWIP_DHCPS_LEASE_UNIT=60
778 | CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8
779 | # end of DHCP server
780 |
781 | # CONFIG_LWIP_AUTOIP is not set
782 | # CONFIG_LWIP_IPV6_AUTOCONFIG is not set
783 | CONFIG_LWIP_NETIF_LOOPBACK=y
784 | CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8
785 |
786 | #
787 | # TCP
788 | #
789 | CONFIG_LWIP_MAX_ACTIVE_TCP=16
790 | CONFIG_LWIP_MAX_LISTENING_TCP=16
791 | CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y
792 | CONFIG_LWIP_TCP_MAXRTX=12
793 | CONFIG_LWIP_TCP_SYNMAXRTX=6
794 | CONFIG_LWIP_TCP_MSS=1440
795 | CONFIG_LWIP_TCP_TMR_INTERVAL=250
796 | CONFIG_LWIP_TCP_MSL=60000
797 | CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744
798 | CONFIG_LWIP_TCP_WND_DEFAULT=5744
799 | CONFIG_LWIP_TCP_RECVMBOX_SIZE=6
800 | CONFIG_LWIP_TCP_QUEUE_OOSEQ=y
801 | # CONFIG_LWIP_TCP_SACK_OUT is not set
802 | # CONFIG_LWIP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set
803 | # CONFIG_LWIP_TCP_OVERSIZE_MSS is not set
804 | CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS=y
805 | # CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set
806 | CONFIG_LWIP_TCP_RTO_TIME=1500
807 | # end of TCP
808 |
809 | #
810 | # UDP
811 | #
812 | CONFIG_LWIP_MAX_UDP_PCBS=16
813 | CONFIG_LWIP_UDP_RECVMBOX_SIZE=6
814 | # end of UDP
815 |
816 | CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=2048
817 | # CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY is not set
818 | CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0=y
819 | # CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU1 is not set
820 | CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x0
821 | # CONFIG_LWIP_PPP_SUPPORT is not set
822 | CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3
823 | CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5
824 |
825 | #
826 | # ICMP
827 | #
828 | # CONFIG_LWIP_MULTICAST_PING is not set
829 | # CONFIG_LWIP_BROADCAST_PING is not set
830 | # end of ICMP
831 |
832 | #
833 | # LWIP RAW API
834 | #
835 | CONFIG_LWIP_MAX_RAW_PCBS=16
836 | # end of LWIP RAW API
837 |
838 | #
839 | # SNTP
840 | #
841 | CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1
842 | CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000
843 | # end of SNTP
844 |
845 | CONFIG_LWIP_ESP_LWIP_ASSERT=y
846 | # end of LWIP
847 |
848 | #
849 | # mbedTLS
850 | #
851 | CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
852 | # CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set
853 | # CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set
854 | CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y
855 | CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384
856 | CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096
857 | # CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set
858 | # CONFIG_MBEDTLS_DEBUG is not set
859 |
860 | #
861 | # Certificate Bundle
862 | #
863 | CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y
864 | CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y
865 | # CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set
866 | # CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set
867 | # CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set
868 | # end of Certificate Bundle
869 |
870 | # CONFIG_MBEDTLS_ECP_RESTARTABLE is not set
871 | # CONFIG_MBEDTLS_CMAC_C is not set
872 | CONFIG_MBEDTLS_HARDWARE_AES=y
873 | # CONFIG_MBEDTLS_HARDWARE_MPI is not set
874 | CONFIG_MBEDTLS_HARDWARE_SHA=y
875 | # CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set
876 | # CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set
877 | CONFIG_MBEDTLS_HAVE_TIME=y
878 | # CONFIG_MBEDTLS_HAVE_TIME_DATE is not set
879 | CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y
880 | CONFIG_MBEDTLS_SHA512_C=y
881 | CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y
882 | # CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set
883 | # CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set
884 | # CONFIG_MBEDTLS_TLS_DISABLED is not set
885 | CONFIG_MBEDTLS_TLS_SERVER=y
886 | CONFIG_MBEDTLS_TLS_CLIENT=y
887 | CONFIG_MBEDTLS_TLS_ENABLED=y
888 |
889 | #
890 | # TLS Key Exchange Methods
891 | #
892 | CONFIG_MBEDTLS_PSK_MODES=y
893 | CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y
894 | CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK=y
895 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK=y
896 | CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK=y
897 | CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y
898 | CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y
899 | CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y
900 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y
901 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y
902 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y
903 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y
904 | # end of TLS Key Exchange Methods
905 |
906 | CONFIG_MBEDTLS_SSL_RENEGOTIATION=y
907 | # CONFIG_MBEDTLS_SSL_PROTO_SSL3 is not set
908 | CONFIG_MBEDTLS_SSL_PROTO_TLS1=y
909 | CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y
910 | CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y
911 | # CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set
912 | CONFIG_MBEDTLS_SSL_ALPN=y
913 | CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y
914 | CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y
915 |
916 | #
917 | # Symmetric Ciphers
918 | #
919 | CONFIG_MBEDTLS_AES_C=y
920 | # CONFIG_MBEDTLS_CAMELLIA_C is not set
921 | # CONFIG_MBEDTLS_DES_C is not set
922 | CONFIG_MBEDTLS_RC4_DISABLED=y
923 | # CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT is not set
924 | # CONFIG_MBEDTLS_RC4_ENABLED is not set
925 | # CONFIG_MBEDTLS_BLOWFISH_C is not set
926 | # CONFIG_MBEDTLS_XTEA_C is not set
927 | CONFIG_MBEDTLS_CCM_C=y
928 | CONFIG_MBEDTLS_GCM_C=y
929 | # end of Symmetric Ciphers
930 |
931 | # CONFIG_MBEDTLS_RIPEMD160_C is not set
932 |
933 | #
934 | # Certificates
935 | #
936 | CONFIG_MBEDTLS_PEM_PARSE_C=y
937 | CONFIG_MBEDTLS_PEM_WRITE_C=y
938 | CONFIG_MBEDTLS_X509_CRL_PARSE_C=y
939 | CONFIG_MBEDTLS_X509_CSR_PARSE_C=y
940 | # end of Certificates
941 |
942 | CONFIG_MBEDTLS_ECP_C=y
943 | CONFIG_MBEDTLS_ECDH_C=y
944 | CONFIG_MBEDTLS_ECDSA_C=y
945 | # CONFIG_MBEDTLS_ECJPAKE_C is not set
946 | CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y
947 | CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y
948 | CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y
949 | CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y
950 | CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y
951 | CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y
952 | CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y
953 | CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y
954 | CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y
955 | CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y
956 | CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y
957 | CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y
958 | CONFIG_MBEDTLS_ECP_NIST_OPTIM=y
959 | # CONFIG_MBEDTLS_POLY1305_C is not set
960 | # CONFIG_MBEDTLS_CHACHA20_C is not set
961 | # CONFIG_MBEDTLS_HKDF_C is not set
962 | # CONFIG_MBEDTLS_THREADING_C is not set
963 | # CONFIG_MBEDTLS_SECURITY_RISKS is not set
964 | # end of mbedTLS
965 |
966 | #
967 | # mDNS
968 | #
969 | CONFIG_MDNS_MAX_SERVICES=10
970 | CONFIG_MDNS_TASK_PRIORITY=1
971 | CONFIG_MDNS_TASK_STACK_SIZE=2560
972 | # CONFIG_MDNS_TASK_AFFINITY_NO_AFFINITY is not set
973 | CONFIG_MDNS_TASK_AFFINITY_CPU0=y
974 | # CONFIG_MDNS_TASK_AFFINITY_CPU1 is not set
975 | CONFIG_MDNS_TASK_AFFINITY=0x0
976 | CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS=2000
977 | CONFIG_MDNS_TIMER_PERIOD_MS=100
978 | # end of mDNS
979 |
980 | #
981 | # ESP-MQTT Configurations
982 | #
983 | CONFIG_MQTT_PROTOCOL_311=y
984 | # CONFIG_MQTT_TRANSPORT_SSL is not set
985 | CONFIG_MQTT_TRANSPORT_WEBSOCKET=y
986 | # CONFIG_MQTT_USE_CUSTOM_CONFIG is not set
987 | # CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set
988 | # CONFIG_MQTT_CUSTOM_OUTBOX is not set
989 | # end of ESP-MQTT Configurations
990 |
991 | #
992 | # Newlib
993 | #
994 | CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y
995 | # CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set
996 | # CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set
997 | # CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set
998 | # CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set
999 | CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y
1000 | # CONFIG_NEWLIB_NANO_FORMAT is not set
1001 | # end of Newlib
1002 |
1003 | #
1004 | # NVS
1005 | #
1006 | # end of NVS
1007 |
1008 | #
1009 | # OpenSSL
1010 | #
1011 | # CONFIG_OPENSSL_DEBUG is not set
1012 | CONFIG_OPENSSL_ASSERT_DO_NOTHING=y
1013 | # CONFIG_OPENSSL_ASSERT_EXIT is not set
1014 | # end of OpenSSL
1015 |
1016 | #
1017 | # PThreads
1018 | #
1019 | CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5
1020 | CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=2048
1021 | CONFIG_PTHREAD_STACK_MIN=768
1022 | CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y
1023 | # CONFIG_PTHREAD_DEFAULT_CORE_0 is not set
1024 | # CONFIG_PTHREAD_DEFAULT_CORE_1 is not set
1025 | CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1
1026 | CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread"
1027 | # end of PThreads
1028 |
1029 | #
1030 | # SPI Flash driver
1031 | #
1032 | # CONFIG_SPI_FLASH_VERIFY_WRITE is not set
1033 | # CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set
1034 | CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y
1035 | CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y
1036 | # CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set
1037 | # CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set
1038 | # CONFIG_SPI_FLASH_USE_LEGACY_IMPL is not set
1039 | # CONFIG_SPI_FLASH_SHARE_SPI1_BUS is not set
1040 | # CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set
1041 | CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y
1042 | CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20
1043 | CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1
1044 |
1045 | #
1046 | # Auto-detect flash chips
1047 | #
1048 | CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y
1049 | CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y
1050 | CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y
1051 | # end of Auto-detect flash chips
1052 | # end of SPI Flash driver
1053 |
1054 | #
1055 | # SPIFFS Configuration
1056 | #
1057 | CONFIG_SPIFFS_MAX_PARTITIONS=3
1058 |
1059 | #
1060 | # SPIFFS Cache Configuration
1061 | #
1062 | CONFIG_SPIFFS_CACHE=y
1063 | CONFIG_SPIFFS_CACHE_WR=y
1064 | # CONFIG_SPIFFS_CACHE_STATS is not set
1065 | # end of SPIFFS Cache Configuration
1066 |
1067 | CONFIG_SPIFFS_PAGE_CHECK=y
1068 | CONFIG_SPIFFS_GC_MAX_RUNS=10
1069 | # CONFIG_SPIFFS_GC_STATS is not set
1070 | CONFIG_SPIFFS_PAGE_SIZE=256
1071 | CONFIG_SPIFFS_OBJ_NAME_LEN=32
1072 | # CONFIG_SPIFFS_FOLLOW_SYMLINKS is not set
1073 | CONFIG_SPIFFS_USE_MAGIC=y
1074 | CONFIG_SPIFFS_USE_MAGIC_LENGTH=y
1075 | CONFIG_SPIFFS_META_LENGTH=4
1076 | CONFIG_SPIFFS_USE_MTIME=y
1077 |
1078 | #
1079 | # Debug Configuration
1080 | #
1081 | # CONFIG_SPIFFS_DBG is not set
1082 | # CONFIG_SPIFFS_API_DBG is not set
1083 | # CONFIG_SPIFFS_GC_DBG is not set
1084 | # CONFIG_SPIFFS_CACHE_DBG is not set
1085 | # CONFIG_SPIFFS_CHECK_DBG is not set
1086 | # CONFIG_SPIFFS_TEST_VISUALISATION is not set
1087 | # end of Debug Configuration
1088 | # end of SPIFFS Configuration
1089 |
1090 | #
1091 | # TinyUSB
1092 | #
1093 |
1094 | #
1095 | # Descriptor configuration
1096 | #
1097 | CONFIG_USB_DESC_CUSTOM_VID=0x1234
1098 | CONFIG_USB_DESC_CUSTOM_PID=0x5678
1099 | # end of Descriptor configuration
1100 | # end of TinyUSB
1101 |
1102 | #
1103 | # Unity unit testing library
1104 | #
1105 | CONFIG_UNITY_ENABLE_FLOAT=y
1106 | CONFIG_UNITY_ENABLE_DOUBLE=y
1107 | # CONFIG_UNITY_ENABLE_COLOR is not set
1108 | CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y
1109 | # CONFIG_UNITY_ENABLE_FIXTURE is not set
1110 | # CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL is not set
1111 | # end of Unity unit testing library
1112 |
1113 | #
1114 | # Virtual file system
1115 | #
1116 | CONFIG_VFS_SUPPORT_IO=y
1117 | CONFIG_VFS_SUPPORT_DIR=y
1118 | CONFIG_VFS_SUPPORT_SELECT=y
1119 | CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y
1120 | CONFIG_VFS_SUPPORT_TERMIOS=y
1121 |
1122 | #
1123 | # Host File System I/O (Semihosting)
1124 | #
1125 | CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1
1126 | CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN=128
1127 | # end of Host File System I/O (Semihosting)
1128 | # end of Virtual file system
1129 |
1130 | #
1131 | # Wear Levelling
1132 | #
1133 | # CONFIG_WL_SECTOR_SIZE_512 is not set
1134 | CONFIG_WL_SECTOR_SIZE_4096=y
1135 | CONFIG_WL_SECTOR_SIZE=4096
1136 | # end of Wear Levelling
1137 |
1138 | #
1139 | # Wi-Fi Provisioning Manager
1140 | #
1141 | CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16
1142 | CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30
1143 | # end of Wi-Fi Provisioning Manager
1144 |
1145 | #
1146 | # Supplicant
1147 | #
1148 | CONFIG_WPA_MBEDTLS_CRYPTO=y
1149 | # CONFIG_WPA_DEBUG_PRINT is not set
1150 | # CONFIG_WPA_TESTING_OPTIONS is not set
1151 | # CONFIG_WPA_WPS_WARS is not set
1152 | # end of Supplicant
1153 | # end of Component config
1154 |
1155 | #
1156 | # Compatibility options
1157 | #
1158 | # CONFIG_LEGACY_INCLUDE_COMMON_HEADERS is not set
1159 | # end of Compatibility options
1160 |
1161 | # Deprecated options for backward compatibility
1162 | CONFIG_TOOLPREFIX="xtensa-esp32-elf-"
1163 | # CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set
1164 | # CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set
1165 | # CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set
1166 | CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y
1167 | # CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set
1168 | # CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set
1169 | CONFIG_LOG_BOOTLOADER_LEVEL=3
1170 | # CONFIG_APP_ROLLBACK_ENABLE is not set
1171 | # CONFIG_FLASH_ENCRYPTION_ENABLED is not set
1172 | # CONFIG_FLASHMODE_QIO is not set
1173 | # CONFIG_FLASHMODE_QOUT is not set
1174 | CONFIG_FLASHMODE_DIO=y
1175 | # CONFIG_FLASHMODE_DOUT is not set
1176 | # CONFIG_MONITOR_BAUD_9600B is not set
1177 | # CONFIG_MONITOR_BAUD_57600B is not set
1178 | CONFIG_MONITOR_BAUD_115200B=y
1179 | # CONFIG_MONITOR_BAUD_230400B is not set
1180 | # CONFIG_MONITOR_BAUD_921600B is not set
1181 | # CONFIG_MONITOR_BAUD_2MB is not set
1182 | # CONFIG_MONITOR_BAUD_OTHER is not set
1183 | CONFIG_MONITOR_BAUD_OTHER_VAL=115200
1184 | CONFIG_MONITOR_BAUD=115200
1185 | # CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG is not set
1186 | CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE=y
1187 | # CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED is not set
1188 | # CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set
1189 | CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED=y
1190 | # CONFIG_CXX_EXCEPTIONS is not set
1191 | # CONFIG_STACK_CHECK_NONE is not set
1192 | CONFIG_STACK_CHECK_NORM=y
1193 | # CONFIG_STACK_CHECK_STRONG is not set
1194 | # CONFIG_STACK_CHECK_ALL is not set
1195 | CONFIG_STACK_CHECK=y
1196 | # CONFIG_WARN_WRITE_STRINGS is not set
1197 | # CONFIG_DISABLE_GCC8_WARNINGS is not set
1198 | CONFIG_ESP32_APPTRACE_DEST_TRAX=y
1199 | # CONFIG_ESP32_APPTRACE_DEST_NONE is not set
1200 | CONFIG_ESP32_APPTRACE_ENABLE=y
1201 | CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y
1202 | CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO=-1
1203 | CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH=0
1204 | CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX=0
1205 | # CONFIG_ESP32_GCOV_ENABLE is not set
1206 | # CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY is not set
1207 | # CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY is not set
1208 | CONFIG_BTDM_CONTROLLER_MODE_BTDM=y
1209 | CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN=2
1210 | CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN=2
1211 | CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN=1
1212 | CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF=2
1213 | CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF=2
1214 | CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF=1
1215 | CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0
1216 | CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI=y
1217 | # CONFIG_BTDM_CONTROLLER_HCI_MODE_UART_H4 is not set
1218 | CONFIG_BTDM_CONTROLLER_MODEM_SLEEP=y
1219 | # CONFIG_BLE_SCAN_DUPLICATE is not set
1220 | CONFIG_BTDM_CONTROLLER_FULL_SCAN_SUPPORTED=y
1221 | CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_SUPPORTED=y
1222 | CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_NUM=100
1223 | CONFIG_BLE_ADV_REPORT_DISCARD_THRSHOLD=20
1224 | CONFIG_BLUEDROID_ENABLED=y
1225 | # CONFIG_NIMBLE_ENABLED is not set
1226 | CONFIG_BTC_TASK_STACK_SIZE=2048
1227 | CONFIG_BLUEDROID_PINNED_TO_CORE_0=y
1228 | # CONFIG_BLUEDROID_PINNED_TO_CORE_1 is not set
1229 | CONFIG_BLUEDROID_PINNED_TO_CORE=0
1230 | CONFIG_BTU_TASK_STACK_SIZE=2048
1231 | # CONFIG_BLUEDROID_MEM_DEBUG is not set
1232 | CONFIG_CLASSIC_BT_ENABLED=y
1233 | # CONFIG_A2DP_ENABLE is not set
1234 | # CONFIG_HFP_ENABLE is not set
1235 | CONFIG_GATTS_ENABLE=y
1236 | # CONFIG_GATTS_SEND_SERVICE_CHANGE_MANUAL is not set
1237 | CONFIG_GATTS_SEND_SERVICE_CHANGE_AUTO=y
1238 | CONFIG_GATTS_SEND_SERVICE_CHANGE_MODE=0
1239 | CONFIG_GATTC_ENABLE=y
1240 | CONFIG_GATTC_CACHE_NVS_FLASH=y
1241 | CONFIG_BLE_SMP_ENABLE=y
1242 | # CONFIG_SMP_SLAVE_CON_PARAMS_UPD_ENABLE is not set
1243 | # CONFIG_BLE_HOST_QUEUE_CONGESTION_CHECK is not set
1244 | CONFIG_SMP_ENABLE=y
1245 | # CONFIG_BLE_ACTIVE_SCAN_REPORT_ADV_SCAN_RSP_INDIVIDUALLY is not set
1246 | CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT=30
1247 | CONFIG_ADC2_DISABLE_DAC=y
1248 | # CONFIG_SPIRAM_SUPPORT is not set
1249 | CONFIG_MEMMAP_TRACEMEM=y
1250 | CONFIG_MEMMAP_TRACEMEM_TWOBANKS=y
1251 | CONFIG_TRACEMEM_RESERVE_DRAM=0x8000
1252 | # CONFIG_TWO_UNIVERSAL_MAC_ADDRESS is not set
1253 | CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y
1254 | CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4
1255 | # CONFIG_ULP_COPROC_ENABLED is not set
1256 | CONFIG_ULP_COPROC_RESERVE_MEM=0
1257 | CONFIG_BROWNOUT_DET=y
1258 | CONFIG_BROWNOUT_DET_LVL_SEL_0=y
1259 | # CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set
1260 | # CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set
1261 | # CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set
1262 | # CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set
1263 | # CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set
1264 | # CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set
1265 | # CONFIG_BROWNOUT_DET_LVL_SEL_7 is not set
1266 | CONFIG_BROWNOUT_DET_LVL=0
1267 | CONFIG_REDUCE_PHY_TX_POWER=y
1268 | CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y
1269 | # CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL is not set
1270 | # CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC is not set
1271 | # CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256 is not set
1272 | # CONFIG_DISABLE_BASIC_ROM_CONSOLE is not set
1273 | # CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set
1274 | CONFIG_SYSTEM_EVENT_QUEUE_SIZE=24
1275 | CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=1792
1276 | CONFIG_MAIN_TASK_STACK_SIZE=2048
1277 | CONFIG_IPC_TASK_STACK_SIZE=2048
1278 | CONFIG_CONSOLE_UART_DEFAULT=y
1279 | # CONFIG_CONSOLE_UART_CUSTOM is not set
1280 | # CONFIG_CONSOLE_UART_NONE is not set
1281 | CONFIG_CONSOLE_UART_NUM=0
1282 | CONFIG_CONSOLE_UART_TX_GPIO=1
1283 | CONFIG_CONSOLE_UART_RX_GPIO=3
1284 | CONFIG_CONSOLE_UART_BAUDRATE=115200
1285 | CONFIG_INT_WDT=y
1286 | CONFIG_INT_WDT_TIMEOUT_MS=500
1287 | CONFIG_INT_WDT_CHECK_CPU1=y
1288 | CONFIG_TASK_WDT=y
1289 | # CONFIG_TASK_WDT_PANIC is not set
1290 | CONFIG_TASK_WDT_TIMEOUT_S=8
1291 | CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y
1292 | CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y
1293 | # CONFIG_EVENT_LOOP_PROFILING is not set
1294 | CONFIG_POST_EVENTS_FROM_ISR=y
1295 | CONFIG_POST_EVENTS_FROM_IRAM_ISR=y
1296 | # CONFIG_ESP32S2_PANIC_PRINT_HALT is not set
1297 | CONFIG_ESP32S2_PANIC_PRINT_REBOOT=y
1298 | # CONFIG_ESP32S2_PANIC_SILENT_REBOOT is not set
1299 | # CONFIG_ESP32S2_PANIC_GDBSTUB is not set
1300 | CONFIG_TIMER_TASK_STACK_SIZE=2048
1301 | CONFIG_SW_COEXIST_ENABLE=y
1302 | CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND=150
1303 | CONFIG_MB_MASTER_DELAY_MS_CONVERT=200
1304 | CONFIG_MB_QUEUE_LENGTH=20
1305 | CONFIG_MB_SERIAL_TASK_STACK_SIZE=2048
1306 | CONFIG_MB_SERIAL_BUF_SIZE=256
1307 | CONFIG_MB_SERIAL_TASK_PRIO=10
1308 | # CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT is not set
1309 | CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20
1310 | CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20
1311 | CONFIG_MB_CONTROLLER_STACK_SIZE=4096
1312 | CONFIG_MB_EVENT_QUEUE_TIMEOUT=20
1313 | CONFIG_MB_TIMER_PORT_ENABLED=y
1314 | CONFIG_MB_TIMER_GROUP=0
1315 | CONFIG_MB_TIMER_INDEX=0
1316 | # CONFIG_SUPPORT_STATIC_ALLOCATION is not set
1317 | CONFIG_TIMER_TASK_PRIORITY=1
1318 | CONFIG_TIMER_TASK_STACK_DEPTH=1536
1319 | CONFIG_TIMER_QUEUE_LENGTH=10
1320 | # CONFIG_L2_TO_L3_COPY is not set
1321 | # CONFIG_USE_ONLY_LWIP_SELECT is not set
1322 | CONFIG_ESP_GRATUITOUS_ARP=y
1323 | CONFIG_GARP_TMR_INTERVAL=60
1324 | CONFIG_TCPIP_RECVMBOX_SIZE=24
1325 | CONFIG_TCP_MAXRTX=12
1326 | CONFIG_TCP_SYNMAXRTX=6
1327 | CONFIG_TCP_MSS=1440
1328 | CONFIG_TCP_MSL=60000
1329 | CONFIG_TCP_SND_BUF_DEFAULT=5744
1330 | CONFIG_TCP_WND_DEFAULT=5744
1331 | CONFIG_TCP_RECVMBOX_SIZE=6
1332 | CONFIG_TCP_QUEUE_OOSEQ=y
1333 | # CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set
1334 | # CONFIG_TCP_OVERSIZE_MSS is not set
1335 | CONFIG_TCP_OVERSIZE_QUARTER_MSS=y
1336 | # CONFIG_TCP_OVERSIZE_DISABLE is not set
1337 | CONFIG_UDP_RECVMBOX_SIZE=6
1338 | CONFIG_TCPIP_TASK_STACK_SIZE=2048
1339 | # CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY is not set
1340 | CONFIG_TCPIP_TASK_AFFINITY_CPU0=y
1341 | # CONFIG_TCPIP_TASK_AFFINITY_CPU1 is not set
1342 | CONFIG_TCPIP_TASK_AFFINITY=0x0
1343 | # CONFIG_PPP_SUPPORT is not set
1344 | CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5
1345 | CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=2048
1346 | CONFIG_ESP32_PTHREAD_STACK_MIN=768
1347 | CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y
1348 | # CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set
1349 | # CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set
1350 | CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1
1351 | CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread"
1352 | CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y
1353 | # CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set
1354 | # CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set
1355 | CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y
1356 | CONFIG_SUPPORT_TERMIOS=y
1357 | CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1
1358 | CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN=128
1359 | # End of deprecated options
1360 |
--------------------------------------------------------------------------------
/src/BluetoothScanner.cpp:
--------------------------------------------------------------------------------
1 | // Basic headers
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | // IDF headers
11 | #include
12 | #include
13 | #include
14 | #include "nvs.h"
15 | #include "nvs_flash.h"
16 | #include "esp_system.h"
17 | #include "esp_log.h"
18 | #include "esp32-hal-bt.h"
19 | #include "esp_bt.h"
20 | #include "esp_bt_main.h"
21 | #include "esp_bt_device.h"
22 | #include "esp_gap_bt_api.h"
23 |
24 | #include
25 | #include
26 |
27 | // Tweaked SDK configuration
28 | #include "sdkconfig.h"
29 |
30 | #include "BluetoothScanner.h"
31 | #include "parameter.h"
32 | #include "mqtt.h"
33 | #include "led.h"
34 |
35 | #include "stackDbgHelper.h"
36 | #include "CallbackHelper.h"
37 |
38 |
39 | #define GAP_TAG "GAP"
40 | #define SPP_TAG "SPP"
41 | #define GATTC_TAG "GATTC"
42 |
43 | #define BLE_SCAN_AFTER_READ_REMOTE_NAMES (0)
44 |
45 |
46 | #define BLE_SCAN_COMPLETE_CALLBACK_SIGNATURE void(BLEScanResults)
47 | #define GAP_CALLBACK_SIGNATURE void(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param)
48 |
49 | typedef void (*scanComplete_cb_t)(BLEScanResults);
50 |
51 |
52 | extern Timezone mTime;
53 |
54 | #define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00) >> 8) + (((x)&0xFF) << 8))
55 |
56 | // =================================================================================
57 | // =================================================================================
58 | // Free Functions:
59 | // =================================================================================
60 |
61 | // -----------------------------------------------
62 | #define BLUETOOTH_MON_VERSION "0.1.001"
63 | String createConfidenceMessage(const char* MAC, uint8_t confidence, const char* name, const char* timestamp, bool retain = false, const char* iBeaconStr = nullptr, const char* type = "KNOWN_MAC", const char* manufacturer = "Unknown") {
64 | char buf[420];
65 | // Wed Jun 09 2021 20:03:45 GMT+0200 (CEST)
66 | snprintf(buf, 420, "{\"id\":\"%s\",%s%s\"confidence\":\"%d\",\"name\":\"%s\",\"manufacturer\":\"%s\",\"type\":\"%s\",\"retained\":\"%s\",\"timestamp\":\"%s\",\"version\":\"%s\"}",
67 | MAC, (iBeaconStr ? iBeaconStr : " "), (iBeaconStr ? "," : " "), confidence, name, manufacturer, type, (retain ? "true" : "false"), timestamp, BLUETOOTH_MON_VERSION);
68 | return buf;
69 | }
70 |
71 | // -----------------------------------------------
72 | char *bda2str(const esp_bd_addr_t bda, char *str, size_t size)
73 | {
74 | if (bda == NULL || str == NULL || size < 18) {
75 | return NULL;
76 | }
77 |
78 | const uint8_t *p = bda;
79 | sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
80 | p[0], p[1], p[2], p[3], p[4], p[5]);
81 | return str;
82 | }
83 |
84 | // -----------------------------------------------
85 | bool str2bda(const char* str, esp_bd_addr_t& mac) {
86 | if(strlen(str) < 12 || strlen(str) > 18) {
87 | return false;
88 | }
89 |
90 | uint8_t *p = mac;
91 | // Scan for MAC with semicolon separators
92 | int args_found = sscanf(str, "%" SCNx8 ":%" SCNx8 ":%" SCNx8 ":%" SCNx8 ":%" SCNx8 ":%" SCNx8,
93 | &p[0], &p[1], &p[2], &p[3], &p[4], &p[5]);
94 | if( args_found == 6 ) {
95 | return true;
96 | }
97 |
98 | // Scan for mac without semicolons
99 | args_found = sscanf(str, "%" SCNx8 "%" SCNx8 "%" SCNx8 "%" SCNx8 "%" SCNx8 "%" SCNx8,
100 | &p[0], &p[1], &p[2], &p[3], &p[4], &p[5]);
101 |
102 | if( args_found == 6 ) {
103 | return true;
104 | }
105 |
106 | // Invalid MAC
107 | return false;
108 | }
109 |
110 | // -----------------------------------------------
111 | static char *uuid2str(esp_bt_uuid_t *uuid, char *str, size_t size)
112 | {
113 | if (uuid == NULL || str == NULL) {
114 | return NULL;
115 | }
116 |
117 | if (uuid->len == 2 && size >= 5) {
118 | sprintf(str, "%04x", uuid->uuid.uuid16);
119 | } else if (uuid->len == 4 && size >= 9) {
120 | sprintf(str, "%08x", uuid->uuid.uuid32);
121 | } else if (uuid->len == 16 && size >= 37) {
122 | uint8_t *p = uuid->uuid.uuid128;
123 | sprintf(str, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
124 | p[15], p[14], p[13], p[12], p[11], p[10], p[9], p[8],
125 | p[7], p[6], p[5], p[4], p[3], p[2], p[1], p[0]);
126 | } else {
127 | return NULL;
128 | }
129 |
130 | return str;
131 | }
132 |
133 | // -----------------------------------------------
134 | static bool get_name_from_eir(uint8_t *eir, uint8_t *bdname, uint8_t *bdname_len)
135 | {
136 | uint8_t *rmt_bdname = NULL;
137 | uint8_t rmt_bdname_len = 0;
138 |
139 | if (!eir) {
140 | return false;
141 | }
142 |
143 | rmt_bdname = esp_bt_gap_resolve_eir_data(eir, ESP_BT_EIR_TYPE_CMPL_LOCAL_NAME, &rmt_bdname_len);
144 | if (!rmt_bdname) {
145 | rmt_bdname = esp_bt_gap_resolve_eir_data(eir, ESP_BT_EIR_TYPE_SHORT_LOCAL_NAME, &rmt_bdname_len);
146 | }
147 |
148 | if (rmt_bdname) {
149 | if (rmt_bdname_len > ESP_BT_GAP_MAX_BDNAME_LEN) {
150 | rmt_bdname_len = ESP_BT_GAP_MAX_BDNAME_LEN;
151 | }
152 |
153 | if (bdname) {
154 | memcpy(bdname, rmt_bdname, rmt_bdname_len);
155 | bdname[rmt_bdname_len] = '\0';
156 | }
157 | if (bdname_len) {
158 | *bdname_len = rmt_bdname_len;
159 | }
160 | return true;
161 | }
162 |
163 | return false;
164 | }
165 |
166 | // -----------------------------------------------
167 |
168 | void BluetoothScanner::onResult(BLEAdvertisedDevice advertisedDevice) {
169 | bleAdvertisedDeviceResultQueue.push(advertisedDevice);
170 | }
171 |
172 | // -----------------------------------------------
173 | void BluetoothScanner::HandleBleAdvertisementResult(BLEAdvertisedDevice& bleAdvertisedDeviceResult) {
174 | SCOPED_STACK_ENTRY;
175 | if (bleAdvertisedDeviceResult.haveName())
176 | {
177 | mSerial.print("Device name: ");
178 | mSerial.println(bleAdvertisedDeviceResult.getName().c_str());
179 | mSerial.println("");
180 | }
181 |
182 | if (bleAdvertisedDeviceResult.haveServiceUUID())
183 | {
184 | // BLEUUID devUUID = bleAdvertisedDeviceResult.getServiceUUID();
185 | // mSerial.print("Found ServiceUUID: ");
186 | // mSerial.println(devUUID.toString().c_str());
187 | // mSerial.println("");
188 | }
189 | else
190 | {
191 | if (bleAdvertisedDeviceResult.haveManufacturerData() == true)
192 | {
193 | std::string strManufacturerData = bleAdvertisedDeviceResult.getManufacturerData();
194 |
195 | uint8_t cManufacturerData[100];
196 | strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0);
197 |
198 | if (strManufacturerData.length() == 25 && cManufacturerData[0] == 0x4C && cManufacturerData[1] == 0x00)
199 | {
200 | mSerial.println("Found an iBeacon!");
201 | String rssi_s = "??";
202 | if(bleAdvertisedDeviceResult.haveRSSI()) {
203 | rssi_s = bleAdvertisedDeviceResult.getRSSI();
204 | }
205 | BLEBeacon oBeacon = BLEBeacon();
206 | oBeacon.setData(strManufacturerData);
207 | mSerial.printf("iBeacon Frame\n");
208 |
209 | BLEUUID uuid_swapped(oBeacon.getProximityUUID().getNative()->uuid.uuid128, 16, true);
210 | mSerial.printf("ID: %04X Major: %d Minor: %d UUID: %s Power: %d, RSSI: %s\n", oBeacon.getManufacturerId(), ENDIAN_CHANGE_U16(oBeacon.getMajor()), ENDIAN_CHANGE_U16(oBeacon.getMinor()), uuid_swapped.toString().c_str(), oBeacon.getSignalPower(), rssi_s.c_str());
211 |
212 | std::lock_guard lock(iBeaconDevicesMutex);
213 | for (auto &iBeacon : iBeaconDevices){
214 | if(iBeacon.uuid.equals(uuid_swapped)) {
215 | if(bleAdvertisedDeviceResult.haveRSSI()) {
216 | iBeacon.addRSSI(bleAdvertisedDeviceResult.getRSSI());
217 | }
218 | iBeacon.power = oBeacon.getSignalPower();
219 | iBeacon.confidence = 100;
220 | iBeacon.last_update_millis = millis();
221 |
222 | int filteredRssi = iBeacon.getFilteredRSSI();
223 | if(abs(filteredRssi - iBeacon.lastSentRssi) > 3) {
224 | char rssi_str[25];
225 | snprintf(rssi_str, 24, "\"rssi\":\"%d\"", filteredRssi);
226 | iBeacon.lastSentRssi = filteredRssi;
227 | std::string topic = m_mqtt_topic + "/" + m_scanner_identity + "/" + iBeacon.name.c_str();
228 | mqtt.send_message(topic.c_str(),
229 | createConfidenceMessage(iBeacon.uuid.toString().c_str(), iBeacon.confidence, iBeacon.name.c_str(), mTime.dateTime("D M d Y H:i:s ~G~M~TO (T)").c_str(), m_retain, rssi_str, "KNOWN_BEACON" ).c_str(), m_retain
230 | );
231 | }
232 | else {
233 | mSerial.printf("%s rssi: %d, last sent rssi: %d\n", iBeacon.name.c_str(), filteredRssi, iBeacon.lastSentRssi);
234 | }
235 | }
236 | }
237 | }
238 | else
239 | { /*
240 | mSerial.println("Found another manufacturers beacon!");
241 | mSerial.printf("strManufacturerData: %d ", strManufacturerData.length());
242 | for (int i = 0; i < strManufacturerData.length(); i++)
243 | {
244 | mSerial.printf("[%X]", cManufacturerData[i]);
245 | }
246 | mSerial.printf("\n");
247 | */
248 | }
249 | }
250 | return;
251 | }
252 |
253 | uint8_t *payLoad = bleAdvertisedDeviceResult.getPayload();
254 |
255 | BLEUUID checkUrlUUID = (uint16_t)0xfeaa;
256 |
257 | if (bleAdvertisedDeviceResult.getServiceUUID().equals(checkUrlUUID))
258 | {
259 | if (payLoad[11] == 0x10)
260 | {
261 | mSerial.println("Found an EddystoneURL beacon!");
262 | BLEEddystoneURL foundEddyURL = BLEEddystoneURL();
263 | std::string eddyContent((char *)&payLoad[11]); // incomplete EddystoneURL struct!
264 |
265 | foundEddyURL.setData(eddyContent);
266 | std::string bareURL = foundEddyURL.getURL();
267 | if (bareURL[0] == 0x00)
268 | {
269 | size_t payLoadLen = bleAdvertisedDeviceResult.getPayloadLength();
270 | mSerial.println("DATA-->");
271 | for (int idx = 0; idx < payLoadLen; idx++)
272 | {
273 | mSerial.printf("0x%08X ", payLoad[idx]);
274 | }
275 | mSerial.println("\nInvalid Data");
276 | return;
277 | }
278 |
279 | mSerial.printf("Found URL: %s\n", foundEddyURL.getURL().c_str());
280 | mSerial.printf("Decoded URL: %s\n", foundEddyURL.getDecodedURL().c_str());
281 | mSerial.printf("TX power %d\n", foundEddyURL.getPower());
282 | mSerial.println("\n");
283 | }
284 | else if (payLoad[11] == 0x20)
285 | {
286 | mSerial.println("Found an EddystoneTLM beacon!");
287 | BLEEddystoneTLM foundEddyURL = BLEEddystoneTLM();
288 | std::string eddyContent((char *)&payLoad[11]); // incomplete EddystoneURL struct!
289 |
290 | eddyContent = "01234567890123";
291 |
292 | for (int idx = 0; idx < 14; idx++)
293 | {
294 | eddyContent[idx] = payLoad[idx + 11];
295 | }
296 |
297 | foundEddyURL.setData(eddyContent);
298 | mSerial.printf("Reported battery voltage: %dmV\n", foundEddyURL.getVolt());
299 | mSerial.printf("Reported temperature from TLM class: %.2fC\n", (double)foundEddyURL.getTemp());
300 | int temp = (int)payLoad[16] + (int)(payLoad[15] << 8);
301 | float calcTemp = temp / 256.0f;
302 | mSerial.printf("Reported temperature from data: %.2fC\n", calcTemp);
303 | mSerial.printf("Reported advertise count: %d\n", foundEddyURL.getCount());
304 | mSerial.printf("Reported time since last reboot: %ds\n", foundEddyURL.getTime());
305 | mSerial.println("\n");
306 | mSerial.print(foundEddyURL.toString().c_str());
307 | mSerial.println("\n");
308 | }
309 | }
310 | }
311 |
312 |
313 | // =================================================================================
314 | // =================================================================================
315 | // Class Functions:
316 | // =================================================================================
317 |
318 | // -----------------------------------------------
319 | void BluetoothScanner::update_device_info(esp_bt_gap_cb_param_t *param)
320 | {
321 | char bda_str[18];
322 | uint32_t cod = 0;
323 | int32_t rssi = -129; /* invalid value */
324 | esp_bt_gap_dev_prop_t *p;
325 |
326 | ESP_LOGI(GAP_TAG, "Device found: %s", bda2str(param->disc_res.bda, bda_str, 18));
327 | for (int i = 0; i < param->disc_res.num_prop; i++) {
328 | p = param->disc_res.prop + i;
329 | switch (p->type) {
330 | case ESP_BT_GAP_DEV_PROP_COD:
331 | cod = *(uint32_t *)(p->val);
332 | ESP_LOGI(GAP_TAG, "--Class of Device: 0x%x", cod);
333 | break;
334 | case ESP_BT_GAP_DEV_PROP_RSSI:
335 | rssi = *(int8_t *)(p->val);
336 | ESP_LOGI(GAP_TAG, "--RSSI: %d", rssi);
337 | break;
338 | case ESP_BT_GAP_DEV_PROP_BDNAME:
339 | default:
340 | break;
341 | }
342 | }
343 |
344 | /* search for device with MAJOR service class as "rendering" in COD */
345 | app_gap_cb_t *p_dev = &m_dev_info;
346 | if (p_dev->dev_found && 0 != memcmp(param->disc_res.bda, p_dev->bda, ESP_BD_ADDR_LEN)) {
347 | return;
348 | }
349 |
350 | if (!esp_bt_gap_is_valid_cod(cod) ||
351 | !(esp_bt_gap_get_cod_major_dev(cod) == ESP_BT_COD_MAJOR_DEV_PHONE)) {
352 | return;
353 | }
354 |
355 | memcpy(p_dev->bda, param->disc_res.bda, ESP_BD_ADDR_LEN);
356 | p_dev->dev_found = true;
357 | for (int i = 0; i < param->disc_res.num_prop; i++) {
358 | p = param->disc_res.prop + i;
359 | switch (p->type) {
360 | case ESP_BT_GAP_DEV_PROP_COD:
361 | p_dev->cod = *(uint32_t *)(p->val);
362 | break;
363 | case ESP_BT_GAP_DEV_PROP_RSSI:
364 | p_dev->rssi = *(int8_t *)(p->val);
365 | break;
366 | case ESP_BT_GAP_DEV_PROP_BDNAME: {
367 | uint8_t len = (p->len > ESP_BT_GAP_MAX_BDNAME_LEN) ? ESP_BT_GAP_MAX_BDNAME_LEN :
368 | (uint8_t)p->len;
369 | memcpy(p_dev->bdname, (uint8_t *)(p->val), len);
370 | p_dev->bdname[len] = '\0';
371 | p_dev->bdname_len = len;
372 | break;
373 | }
374 | case ESP_BT_GAP_DEV_PROP_EIR: {
375 | memcpy(p_dev->eir, (uint8_t *)(p->val), p->len);
376 | p_dev->eir_len = p->len;
377 | break;
378 | }
379 | default:
380 | break;
381 | }
382 | }
383 |
384 | if (p_dev->eir && p_dev->bdname_len == 0) {
385 | get_name_from_eir(p_dev->eir, p_dev->bdname, &p_dev->bdname_len);
386 | ESP_LOGI(GAP_TAG, "Found a target device, address %s, name %s", bda_str, p_dev->bdname);
387 | p_dev->state = APP_GAP_STATE_DEVICE_DISCOVER_COMPLETE;
388 | ESP_LOGI(GAP_TAG, "Cancel device discovery ...");
389 | esp_bt_gap_cancel_discovery();
390 | }
391 | }
392 |
393 | // -----------------------------------------------
394 | void BluetoothScanner::gap_callback(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param)
395 | {
396 | app_gap_cb_t *p_dev = &m_dev_info;
397 | char bda_str[18];
398 | char uuid_str[37];
399 |
400 | switch (event) {
401 | case ESP_BT_GAP_DISC_RES_EVT: {
402 | update_device_info(param);
403 | break;
404 | }
405 | case ESP_BT_GAP_DISC_STATE_CHANGED_EVT: {
406 | if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STOPPED) {
407 | ESP_LOGI(GAP_TAG, "Device discovery stopped.");
408 | if ( (p_dev->state == APP_GAP_STATE_DEVICE_DISCOVER_COMPLETE ||
409 | p_dev->state == APP_GAP_STATE_DEVICE_DISCOVERING)
410 | && p_dev->dev_found) {
411 | p_dev->state = APP_GAP_STATE_SERVICE_DISCOVERING;
412 | ESP_LOGI(GAP_TAG, "Discover services ...");
413 | esp_bt_gap_get_remote_services(p_dev->bda);
414 | }
415 | } else if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STARTED) {
416 | ESP_LOGI(GAP_TAG, "Discovery started.");
417 | }
418 | break;
419 | }
420 | case ESP_BT_GAP_RMT_SRVCS_EVT: {
421 | if (memcmp(param->rmt_srvcs.bda, p_dev->bda, ESP_BD_ADDR_LEN) == 0 &&
422 | p_dev->state == APP_GAP_STATE_SERVICE_DISCOVERING) {
423 | p_dev->state = APP_GAP_STATE_SERVICE_DISCOVER_COMPLETE;
424 | if (param->rmt_srvcs.stat == ESP_BT_STATUS_SUCCESS) {
425 | ESP_LOGI(GAP_TAG, "Services for device %s found", bda2str(p_dev->bda, bda_str, 18));
426 | for (int i = 0; i < param->rmt_srvcs.num_uuids; i++) {
427 | esp_bt_uuid_t *u = param->rmt_srvcs.uuid_list + i;
428 | ESP_LOGI(GAP_TAG, "--%s", uuid2str(u, uuid_str, 37));
429 | // ESP_LOGI(GAP_TAG, "--%d", u->len);
430 | }
431 | } else {
432 | ESP_LOGI(GAP_TAG, "Services for device %s not found", bda2str(p_dev->bda, bda_str, 18));
433 | }
434 | }
435 | break;
436 | }
437 | case ESP_BT_GAP_READ_RSSI_DELTA_EVT:
438 | ESP_LOGI(GAP_TAG, "Remote device status: %d, addr: %s, rssi: %d", param->read_rssi_delta.stat, bda2str(param->read_rssi_delta.bda, bda_str, 18), param->read_rssi_delta.rssi_delta);
439 | break;
440 | case ESP_BT_GAP_READ_REMOTE_NAME_EVT:
441 | SetReadRemoteNameResult(param->read_rmt_name);
442 | break;
443 | case ESP_BT_GAP_RMT_SRVC_REC_EVT:
444 | default: {
445 | ESP_LOGI(GAP_TAG, "event: %d", event);
446 | break;
447 | }
448 | }
449 | return;
450 | }
451 |
452 | // -----------------------------------------------
453 | void BluetoothScanner::init()
454 | {
455 | esp_err_t ret;
456 |
457 | // No mem release allows BT and BLE to work side-by-side, but is there enough mem left for the rest...?
458 | //esp_bt_mem_release(ESP_BT_MODE_BTDM);
459 | // esp_bt_controller_mem_release(ESP_BT_MODE_BLE); // --> This fixes MEM Alloc failures in esp_bluedroid_enable!!!
460 | #if 1
461 | // Call bluetooth start from esp32 arduino framework
462 | if(!btStarted() && !btStart()){
463 | log_e("btStart failed");
464 | return;
465 | }
466 |
467 | esp_bluedroid_status_t bt_state = esp_bluedroid_get_status();
468 | if(bt_state == ESP_BLUEDROID_STATUS_UNINITIALIZED){
469 | if ((ret = esp_bluedroid_init()) != ESP_OK) {
470 | ESP_LOGE(GAP_TAG, "%s initialize bluedroid failed: %s\n", __func__, esp_err_to_name(ret));
471 | return;
472 | }
473 | }
474 |
475 | if (bt_state != ESP_BLUEDROID_STATUS_ENABLED) {
476 | if ((ret = esp_bluedroid_enable()) != ESP_OK) {
477 | ESP_LOGE(GAP_TAG, "%s enable bluedroid failed: %s\n", __func__, esp_err_to_name(ret));
478 | return;
479 | }
480 | }
481 |
482 | gap_init();
483 | startupGap();
484 |
485 | #endif
486 |
487 | // Setup static callback wrapper helper function for ble Scan Completed callback function:
488 | Callback::func = std::bind(&BluetoothScanner::bleScanCompleted, this, std::placeholders::_1);
489 |
490 | BLEDevice::init("");
491 | pBLEScan = BLEDevice::getScan(); //create new scan
492 | pBLEScan->setAdvertisedDeviceCallbacks(this);
493 | pBLEScan->setActiveScan(false); //active scan uses more power, but get results faster
494 | pBLEScan->setInterval(200);
495 | pBLEScan->setWindow(160); // less or equal setInterval value
496 | // Scan for 100ms, then not for 25ms
497 |
498 | bleScan_shouldStart = true;
499 | }
500 |
501 | // -----------------------------------------------
502 | void BluetoothScanner::setup()
503 | {
504 | // BT init malloc failure:
505 |
506 | // config.c L537
507 | // static void config_parse(nvs_handle_t fp, config_t *config)
508 | // ...
509 | // int buf_size = get_config_size_from_flash(fp);
510 | // char *buf = NULL;
511 | // if(buf_size == 0) { //First use nvs
512 | // goto error;
513 | // }
514 | // buf = osi_calloc(buf_size);
515 |
516 | }
517 |
518 | // -----------------------------------------------
519 | void BluetoothScanner::bleScanCompleted(BLEScanResults)
520 | {
521 | mSerial.println(">> bleScanCompleted()");
522 |
523 | bleScan_shouldStart = true;
524 | }
525 |
526 | // -----------------------------------------------
527 | void BluetoothScanner::loop()
528 | {
529 | SCOPED_STACK_ENTRY;
530 | // Handle read remote name result outside of callback if made available:
531 | if(!readRemoteNameResultQueue.empty()) {
532 | HandleReadRemoteNameResult(readRemoteNameResultQueue.front());
533 | readRemoteNameResultQueue.pop();
534 | }
535 |
536 | if(!bleAdvertisedDeviceResultQueue.empty()) {
537 | // mSerial.printf("Found %d ble devices\n", bleAdvertisedDeviceResultQueue.size());
538 | for(uint8_t i = 0; i < min(maxBleProcessPerIteration, bleAdvertisedDeviceResultQueue.size()); i++){
539 | HandleBleAdvertisementResult(bleAdvertisedDeviceResultQueue.front());
540 | bleAdvertisedDeviceResultQueue.pop();
541 | vTaskDelay(1);
542 | }
543 | }
544 |
545 | unsigned long current_millis = millis();
546 |
547 | // If scan is still active but timed out...
548 | if(scanMode != ScanType::None) {
549 | if(current_millis - getLastScanTime(scanMode) > scan_duration_timeout) {
550 | led.set(OFF);
551 | mSerial.println("Scan timed out. Reseting scanning state!\n");
552 | scanIndex = -1;
553 | scanMode = ScanType::None;
554 | }
555 | }
556 |
557 | if(scanMode != ScanType::None && !scanInProgress && btDevices.size() != 0) {
558 | if(current_millis > last_scan_iter_millis + scan_iter_interval || scanIndex != 0) { // only block first device of the list!
559 | last_scan_iter_millis = current_millis;
560 |
561 | // ToDo: walk scanning state machine if scan active...
562 |
563 | // Loop over devices to be scanned:
564 | uint8_t devices_checked;
565 | for (devices_checked = 0; devices_checked <= btDevices.size(); devices_checked++) {
566 | scanIndex = (scanIndex+1)%btDevices.size();
567 | if(scanIndex == 0) {
568 | // If we loop over the devices to scan, we start a new iteration!
569 | iterationScansLeft--;
570 | }
571 |
572 | if(scanForNextDevice()) {
573 | break;
574 | }
575 | }
576 | if (devices_checked >= btDevices.size()) { // All devices scanned. No more scanning
577 | mSerial.println("Stopping All searches...\n\n");
578 | scanIndex = -1;
579 | scanMode = ScanType::None;
580 |
581 | bleScan_shouldStart = true;
582 | }
583 | }
584 | }
585 |
586 | // Check for periodic scan:
587 | if(periodic_scan_interval > 0) {
588 | if(current_millis > getLastScanTime(ScanType::Either) + periodic_scan_interval*1000) {
589 | startBluetoothScan(ScanType::Either);
590 | }
591 | }
592 |
593 | // Start new ble scan only if not performing regular scan
594 | if(bleScan_shouldStart && scanMode == ScanType::None){
595 | pBLEScan->stop();
596 | //pBLEScan->clearResults(); Taken care of when starting with continue!
597 |
598 | scanContinueCount = (scanContinueCount+1)%scanContinueWraparound;
599 | if(scanContinueCount == 0) {
600 | mSerial.println("Starting clean BLE scan");
601 | }
602 | if(!pBLEScan->start(scanTime, static_cast(Callback::callback), scanContinueCount)) {
603 | mSerial.println("Problem starting BLE scan!!");
604 | }
605 | else{
606 | bleScan_shouldStart = false;
607 | }
608 | }
609 |
610 | // Check for outdated ble RSSI measurements and send update if needed:
611 | const auto _millis = millis();
612 | const unsigned long iBeaconTimeout = 30000; // 30s
613 | for (auto &iBeacon : iBeaconDevices){
614 | if(iBeacon.last_update_millis + iBeaconTimeout < _millis && !iBeacon.isVirgin()) {
615 | iBeacon.reset();
616 | mSerial.printf("Lost beacon '%s'. Resetting.\n", iBeacon.name.c_str());
617 |
618 | int filteredRssi = iBeacon.getFilteredRSSI();
619 | if(abs(filteredRssi - iBeacon.lastSentRssi) > 3) {
620 | char rssi_str[25] = "\"rssi\":\"\"";
621 | // snprintf(rssi_str, 24, "\"rssi\":\"\"", filteredRssi);
622 | iBeacon.lastSentRssi = filteredRssi;
623 | std::string topic = m_mqtt_topic + "/" + m_scanner_identity + "/" + iBeacon.name.c_str();
624 | mqtt.send_message(topic.c_str(),
625 | createConfidenceMessage(iBeacon.uuid.toString().c_str(), iBeacon.confidence, iBeacon.name.c_str(), mTime.dateTime("D M d Y H:i:s ~G~M~TO (T)").c_str(), m_retain, rssi_str, "KNOWN_BEACON").c_str(), m_retain
626 | );
627 | }
628 | }
629 | }
630 | }
631 |
632 | // -----------------------------------------------
633 | void BluetoothScanner::stop() {
634 | btStop();
635 | }
636 |
637 | // -----------------------------------------------
638 | uint8_t BluetoothScanner::getNumScans(ScanType scanType) {
639 | uint8_t numScans = 0;
640 | switch(scanType) {
641 | case ScanType::Either:
642 | numScans = max(num_arrival_scans, num_departure_scans);
643 | break;
644 |
645 | case ScanType::Arrival:
646 | numScans = num_arrival_scans;
647 | break;
648 |
649 | case ScanType::Departure:
650 | numScans = num_departure_scans;
651 | break;
652 |
653 | case ScanType::None:
654 | default:
655 | numScans = 0;
656 | }
657 | return numScans;
658 | }
659 |
660 | // -----------------------------------------------
661 | unsigned long BluetoothScanner::getLastScanTime(ScanType scanType) {
662 | switch(scanType) {
663 | case ScanType::Arrival:
664 | return last_arrival_scan_time;
665 | break;
666 | case ScanType::Departure:
667 | return last_departure_scan_time;
668 | break;
669 | case ScanType::Either:
670 | return min(last_departure_scan_time, last_arrival_scan_time);
671 | break;
672 | default:
673 | return 0;
674 | break;
675 | }
676 | return 0;
677 | }
678 |
679 | // -----------------------------------------------
680 | void BluetoothScanner::setLastScanTime(ScanType scanType, unsigned long time) {
681 | switch(scanType) {
682 | case ScanType::Arrival:
683 | last_arrival_scan_time = time;
684 | break;
685 | case ScanType::Departure:
686 | last_departure_scan_time = time;
687 | break;
688 | case ScanType::Either:
689 | last_departure_scan_time = time;
690 | last_arrival_scan_time = time;
691 | break;
692 | default:
693 | break;
694 | }
695 | }
696 |
697 | // -----------------------------------------------
698 | void BluetoothScanner::setNumArrivalScans(uint8_t val) {
699 | num_arrival_scans = val;
700 | }
701 |
702 | // -----------------------------------------------
703 | void BluetoothScanner::setNumDepartureScans(uint8_t val) {
704 | num_departure_scans = val;
705 | }
706 |
707 | // -----------------------------------------------
708 | void BluetoothScanner::setSecondsBetweenScanIters(unsigned long val) {
709 | scan_iter_interval = val;
710 | }
711 |
712 | // -----------------------------------------------
713 | void BluetoothScanner::setBeaconExpiration(uint32_t val) {
714 | beacon_expiration_seconds = val;
715 |
716 | }
717 |
718 | // -----------------------------------------------
719 | void BluetoothScanner::setMinTimeBetweenScans(uint32_t val) {
720 | min_seconds_between_scans = val;
721 | }
722 |
723 | // -----------------------------------------------
724 | void BluetoothScanner::setPeriodicScanInterval(uint32_t val) {
725 | periodic_scan_interval = val;
726 | }
727 |
728 | // -----------------------------------------------
729 | void BluetoothScanner::setScanDurationTimeout(uint32_t val) {
730 | scan_duration_timeout = val*1000;
731 | }
732 |
733 | // -----------------------------------------------
734 | void BluetoothScanner::setMqttTopic(const std::string& topic){
735 | m_mqtt_topic = topic;
736 | }
737 |
738 | // -----------------------------------------------
739 | void BluetoothScanner::setScannerIdentity(const char* identity){
740 | m_scanner_identity = identity;
741 | }
742 |
743 | // -----------------------------------------------
744 | void BluetoothScanner::setRetainFlag(bool flag) {
745 | m_retain = flag;
746 | }
747 |
748 | // -----------------------------------------------
749 | void BluetoothScanner::startBluetoothScan(ScanType scanType)
750 | {
751 | SCOPED_STACK_ENTRY;
752 | uint8_t numScans = getNumScans(scanType);
753 | unsigned long reference_scan_time = getLastScanTime(scanType);
754 | unsigned long _millis = millis();
755 |
756 | // Only scan if the last scan was long ago enough...
757 | if( _millis > reference_scan_time + min_seconds_between_scans*1000 && scanMode == ScanType::None) {
758 | mSerial.printf("Starting search for devices with scantype %d\n Set numScans to %d\n", (int)(scanType), numScans);
759 |
760 | scanMode = scanType;
761 |
762 | // Stop ble scan when starting regular scan:
763 | // pBLEScan->stop();
764 |
765 | std::lock_guard lock(btDevicesMutex);
766 | // Set counter for all devices:
767 | iterationScansLeft = numScans;
768 | for( auto& dev : btDevices ) {
769 | if(scanMode == ScanType::Arrival && dev.state == 1) { // Device already present so only scan for departure
770 | dev.scansLeft = 0;
771 | }
772 | else if (scanMode == ScanType::Departure && dev.state == 0) { // Device not present, only scan for arrival
773 | dev.scansLeft = 0;
774 | }
775 | else {
776 | // ScanMode Either will always scan regardless of state.
777 | dev.scansLeft = numScans;
778 | }
779 | }
780 |
781 | // Start scanning at the beginning:
782 | scanIndex = 0;
783 | scanForNextDevice();
784 |
785 | setLastScanTime(scanMode, _millis);
786 | last_scan_iter_millis = _millis;
787 | }
788 | else {
789 | mSerial.println("Skipping BT scan. Too soon dude...");
790 | mSerial.printf("milllis %lu < %lu, scanIdx: %d\n", _millis, reference_scan_time + min_seconds_between_scans*1000, scanIndex);
791 | }
792 | }
793 |
794 | // -----------------------------------------------
795 | bool BluetoothScanner::scanForNextDevice() {
796 | if(btDevices.size()) {
797 | auto& dev = btDevices.at(scanIndex);
798 | if(dev.scansLeft > 0) {
799 | led.set(128);
800 | scanInProgress = 1;
801 | esp_bt_gap_read_remote_name(dev.mac);
802 | mSerial.printf("Searching device: %s\n", dev.name.c_str());
803 | return true;
804 | }
805 | }
806 | return false;
807 | }
808 |
809 | // -----------------------------------------------
810 | void BluetoothScanner::addKnownDevice(const std::string& input) {
811 | std::string _in = input;
812 | _in.erase(_in.find_last_not_of(" \t\n\v") + 1);
813 | std::string identifier = _in.substr(0, _in.find(" "));
814 | std::string alias = _in.substr(_in.find(" "));
815 |
816 | size_t first = alias.find_first_not_of(" \t\n\v");
817 | size_t last = alias.find_last_not_of(" \t\n\v");
818 | if(first != std::string::npos) {
819 | alias = alias.substr(first, (last-first+1));
820 | }
821 |
822 | BLEUUID ble_uuid = BLEUUID::fromString(identifier);
823 |
824 | esp_bd_addr_t addr;
825 | if(str2bda(identifier.c_str(), addr)) {
826 | addKnownDevice(addr, alias.c_str());
827 | }
828 | else if (!ble_uuid.equals(BLEUUID())) {
829 | addKnownIBeacon(ble_uuid, alias.c_str());
830 | }
831 | }
832 |
833 | // -----------------------------------------------
834 | void BluetoothScanner::addKnownIBeacon(const BLEUUID uuid, const char* alias) {
835 | // Remove entry if it already existed in order to overwrite with updated one:
836 | deleteKnownIBeacon(uuid);
837 |
838 | {
839 | // Add to the set of currently known iBeacons:
840 | std::lock_guard lock(iBeaconDevicesMutex);
841 |
842 | iBeaconDevices.emplace_back(uuid, String(alias));
843 | mSerial.printf("Added iBeacon '%s'\n", alias);
844 | }
845 | }
846 |
847 | // -----------------------------------------------
848 | void BluetoothScanner::deleteKnownIBeacon(const BLEUUID uuid) {
849 | std::lock_guard lock(iBeaconDevicesMutex);
850 | for (auto it = iBeaconDevices.begin(); it != iBeaconDevices.end(); /* NOTHING */) {
851 | if ((*it).uuid.equals(uuid)) {
852 | it = iBeaconDevices.erase(it);
853 | }
854 | else{
855 | ++it;
856 | }
857 | }
858 | }
859 |
860 | // -----------------------------------------------
861 | void BluetoothScanner::addKnownDevice(const esp_bd_addr_t mac, const char* alias) {
862 | char bda_str[18];
863 | if (bda2str(mac, bda_str, 18)) {
864 | // Add to the set of currently known devices:
865 | std::lock_guard lock(btDevicesMutex);
866 | // Remove entry if it already existed in order to overwrite with updated one:
867 | removeFromBtDevices(mac);
868 | btDevices.emplace_back(mac, String(alias));
869 | }
870 | }
871 |
872 | // -----------------------------------------------
873 | void BluetoothScanner::deleteKnownDevice(const std::string& mac) {
874 | esp_bd_addr_t addr;
875 | if(str2bda(mac.c_str(), addr)) {
876 | deleteKnownDevice(addr);
877 | }
878 | }
879 |
880 | // -----------------------------------------------
881 | void BluetoothScanner::removeFromBtDevices(const esp_bd_addr_t mac) {
882 | for (auto it = btDevices.begin(); it != btDevices.end(); /* NOTHING */) {
883 | if (memcmp((*it).mac, mac, sizeof(esp_bd_addr_t)) == 0) {
884 | it = btDevices.erase(it);
885 | }
886 | else{
887 | ++it;
888 | }
889 | }
890 | }
891 |
892 | // -----------------------------------------------
893 | void BluetoothScanner::deleteKnownDevice(const esp_bd_addr_t mac) {
894 | std::lock_guard lock(btDevicesMutex);
895 | removeFromBtDevices(mac);
896 | }
897 |
898 |
899 | // -----------------------------------------------
900 | void BluetoothScanner::clearKnownDevices() {
901 | std::lock_guard lock(btDevicesMutex);
902 | btDevices.clear();
903 | }
904 |
905 |
906 | // -----------------------------------------------
907 | const std::vector& BluetoothScanner::getBtDeviceStates() {
908 | std::lock_guard lock(btDevicesMutex);
909 | return btDevices;
910 | }
911 |
912 | // -----------------------------------------------
913 | void BluetoothScanner::SetReadRemoteNameResult(const esp_bt_gap_cb_param_t::read_rmt_name_param& remoteNameParam) {
914 | readRemoteNameResultQueue.push(remoteNameParam);
915 | }
916 |
917 | // -----------------------------------------------
918 | void BluetoothScanner::HandleReadRemoteNameResult(esp_bt_gap_cb_param_t::read_rmt_name_param& remoteNameParam) {
919 | SCOPED_STACK_ENTRY;
920 | char macbuf[19];
921 | led.set(OFF);
922 | // If more scans are to be done, this causes the main loop to pick it up again!
923 | scanInProgress = 0;
924 |
925 | std::lock_guard lock(btDevicesMutex);
926 | btDeviceId_t& dev = btDevices.at(scanIndex);
927 |
928 | mSerial.printf("ScanResult Callback for dev(%d): %s, scansLeft %d \n", scanIndex, dev.name.c_str(), dev.scansLeft);
929 |
930 | // Decrement scansLeft for each finished scan:
931 | if (dev.scansLeft > 0) {
932 | dev.scansLeft--;
933 | mSerial.printf("Decrement scansleft for dev(%d): %s to %d \n", scanIndex, dev.name.c_str(), dev.scansLeft);
934 | }
935 |
936 | // Device found:
937 | if (ESP_BT_STATUS_SUCCESS == remoteNameParam.stat) {
938 | dev.confidence = 100;
939 | dev.state = 1;
940 |
941 | if(scanMode == ScanType::Arrival) {
942 | mSerial.printf("Found device, stopping Arrival Scan for %s\n", dev.name.c_str());
943 | dev.scansLeft = 0; // Stop scanning, We've found him!
944 | }
945 |
946 | ESP_LOGI(GAP_TAG, "Remote device name: %s", remoteNameParam.rmt_name);
947 | std::string topic = m_mqtt_topic + "/" + m_scanner_identity + "/" + dev.name.c_str();
948 | mqtt.send_message(topic.c_str(),
949 | createConfidenceMessage(bda2str(dev.mac, macbuf, 18), dev.confidence, dev.name.c_str(), mTime.dateTime("D M d Y H:i:s ~G~M~TO (T)").c_str(), m_retain).c_str(), m_retain
950 | );
951 | }
952 | else {
953 | // Odd formula, but based on original in BluetoothPresence scripts...
954 | if(scanMode != ScanType::Arrival) {
955 | uint8_t confidence = min(100.0f, (90.0f * dev.scansLeft) / float(num_departure_scans));
956 | dev.confidence = min(dev.confidence, confidence); // Dont increase confidence on departure scan.
957 | }
958 | else {
959 | dev.confidence = 0;
960 | }
961 |
962 | if(dev.scansLeft == 0) {
963 | dev.state = 0;
964 | dev.confidence = 0;
965 | }
966 | ESP_LOGI(GAP_TAG, "Remote device name read failed. Status: %d", remoteNameParam.stat);
967 | std::string topic = m_mqtt_topic + "/" + m_scanner_identity + "/" + dev.name.c_str();
968 | mqtt.send_message(topic.c_str(),
969 | createConfidenceMessage(bda2str(dev.mac, macbuf, 18), dev.confidence, dev.name.c_str(), mTime.dateTime("D M d Y H:i:s ~G~M~TO (T)").c_str(), m_retain).c_str(), m_retain
970 | );
971 | }
972 | // Next scan is triggered from main loop...
973 | }
974 |
975 | // -----------------------------------------------
976 | void BluetoothScanner::gap_init()
977 | {
978 | app_gap_cb_t *p_dev = &m_dev_info;
979 | memset(p_dev, 0, sizeof(app_gap_cb_t));
980 | }
981 |
982 | // -----------------------------------------------
983 | void BluetoothScanner::startupGap(void)
984 | {
985 | const char *dev_name = "ESP32_scanner";
986 | esp_bt_dev_set_device_name(dev_name);
987 |
988 | // set discoverable and connectable mode, wait to be connected
989 | // esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
990 | esp_bt_gap_set_scan_mode(ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE);
991 |
992 | // register GAP callback function
993 | Callback::func = std::bind(&BluetoothScanner::gap_callback, this, std::placeholders::_1, std::placeholders::_2);
994 | esp_bt_gap_cb_t callback_func = static_cast(Callback::callback);
995 | esp_bt_gap_register_callback(callback_func);
996 |
997 | // inititialize device information and status
998 | app_gap_cb_t *p_dev = &m_dev_info;
999 | memset(p_dev, 0, sizeof(app_gap_cb_t));
1000 |
1001 | // start to discover nearby Bluetooth devices
1002 | // p_dev->state = APP_GAP_STATE_DEVICE_DISCOVERING;
1003 | // esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, 20, 0);
1004 | }
1005 |
--------------------------------------------------------------------------------
/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 |
2 | FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/src/*.*)
3 |
4 | idf_component_register(SRCS ${app_sources}
5 | REQUIRES bt
6 | PRIV_REQUIRES bt)
--------------------------------------------------------------------------------
/src/TelnetSerial.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | TelnetSerial.cpp - Arduino like serial library for printing over Telnet for ESP8266 & ESP32
3 | */
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include "Arduino.h"
10 | #include "TelnetSerial.h"
11 | #include "Esp.h"
12 |
13 | Telnet::Telnet(uint16_t port) : server(port)
14 | {
15 |
16 | }
17 |
18 | void Telnet::begin()
19 | {
20 | end();
21 |
22 | // Start Ser2Net server
23 | server.setTimeout(15); // 15 seconds...
24 | server.begin();
25 | // Keep delay enabled to combine smaller packages and thus reduce WiFi traffic!
26 | // server.setNoDelay(true);
27 | }
28 |
29 | void Telnet::end()
30 | {
31 | for(uint8_t i = 0; i < MAX_TELNET_CLIENTS; i++) {
32 | if(serverClients[i]) {
33 | serverClients[i].stop();
34 | }
35 | }
36 | server.stop();
37 | }
38 |
39 | void Telnet::handleConnections()
40 | {
41 | // Check if there are any new clients ---------
42 | if (server.hasClient()){
43 | for(uint8_t i = 0; i < MAX_TELNET_CLIENTS; i++){
44 | //find free/disconnected spot
45 | if (!serverClients[i] || !serverClients[i].connected()){
46 | if(serverClients[i]){
47 | serverClients[i].stop();
48 | }
49 | serverClients[i] = server.available();
50 | continue;
51 | }
52 | }
53 | // No free/disconnected spot so reject
54 | server.available().stop();
55 | }
56 | }
57 |
58 | int Telnet::getConnectionCount()
59 | {
60 | int cnt = 0;
61 | for(uint8_t i = 0; i < MAX_TELNET_CLIENTS; i++){
62 | if (serverClients[i] && serverClients[i].connected()){
63 | cnt++;
64 | }
65 | }
66 | return cnt;
67 | }
68 |
69 | int Telnet::available(void)
70 | {
71 | int return_value = 0;
72 | for(uint8_t i = 0; i < MAX_TELNET_CLIENTS; i++){
73 | if (serverClients[i] && serverClients[i].connected()){
74 | return_value = serverClients[i].available();
75 | if (return_value > 0) {
76 | break;
77 | }
78 | }
79 | }
80 | return return_value;
81 | }
82 |
83 | void Telnet::flush(void)
84 | {
85 | for(uint8_t i = 0; i < MAX_TELNET_CLIENTS; i++){
86 | if (serverClients[i] && serverClients[i].connected()){
87 | serverClients[i].flush();
88 | }
89 | }
90 | }
--------------------------------------------------------------------------------
/src/WiFiComponent.cpp:
--------------------------------------------------------------------------------
1 |
2 | // Basic headers
3 | #include
4 | #include
5 | #include
6 |
7 | // Tweaked SDK configuration
8 | #include "sdkconfig.h"
9 |
10 | // Arduino includes
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include // https://github.com/tzapu/WiFiManager
16 | #include
17 | #include "esp_sntp.h"
18 |
19 | #include "parameter.h"
20 |
21 | #include "stackDbgHelper.h"
22 | #include "WiFiComponent.h"
23 | #include "led.h"
24 |
25 | // Required available global entities:
26 | extern WiFiManager wm;
27 |
28 | const char* worldNtpServer = "pool.ntp.org";
29 | const char* eurNtpServer = "europe.pool.ntp.org";
30 | const char* nlNtpServer = "nl.pool.ntp.org";
31 | const long gmtOffset_sec = 3600;
32 | const int daylightOffset_sec = 3600;
33 |
34 | // -----------------------------------------------
35 | void WiFiComponent::wifiInfo(){
36 | WiFi.printDiag(mSerial);
37 | mSerial.println("SAVED: " + (String)wm.getWiFiIsSaved() ? "YES" : "NO");
38 | mSerial.println("SSID: " + (String)wm.getWiFiSSID());
39 | mSerial.println("PASS: " + (String)wm.getWiFiPass());
40 | }
41 |
42 | // -----------------------------------------------
43 | void WiFiComponent::setup() {
44 | // Enable AP mode as well as STA, such that WM can create an access point if needed
45 | WiFi.mode(WIFI_MODE_APSTA);
46 |
47 | _hostname = String("ESP32_bt") + String(WIFI_getChipId(),HEX);
48 |
49 | // Load registered parameters from NVS
50 | loadParams();
51 |
52 | // Blocking if not connected WiFi AP
53 | setupConfigPortal();
54 |
55 | setupArduinoOTA();
56 | }
57 |
58 | // -----------------------------------------------
59 | void WiFiComponent::loop() {
60 | SCOPED_STACK_ENTRY;
61 | do {
62 | ArduinoOTA.handle();
63 | feedLoopWDT();
64 | delay(10);
65 | } while(otaBusy);
66 | wm.process();
67 | }
68 |
69 | // -----------------------------------------------
70 | void WiFiComponent::registerOtaStartCallback(std::function callback) {
71 | ota_callback_functions.push_back(callback);
72 | }
73 |
74 | // -----------------------------------------------
75 | void WiFiComponent::registerParamSaveCallback(std::function callback) {
76 | paramSaved_callback_functions.push_back(callback);
77 | }
78 |
79 | // -----------------------------------------------
80 | void WiFiComponent::setupConfigPortal() {
81 |
82 | wm.debugPlatformInfo();
83 |
84 | //reset settings - for testing
85 | // wm.resetSettings();
86 | // wm.erase();
87 |
88 | // callbacks
89 | wm.setAPCallback(std::bind(&WiFiComponent::configModeCallback,this, std::placeholders::_1));
90 | wm.setWebServerCallback(std::bind(&WiFiComponent::bindServerCallback,this));
91 | wm.setSaveConfigCallback(std::bind(&WiFiComponent::saveWifiCallback,this));
92 | wm.setSaveParamsCallback(std::bind(&WiFiComponent::saveParamCallback,this));
93 |
94 | wm.setTitle("ESP32_bt");
95 | wm.setHostname(_hostname.c_str());
96 |
97 | // invert theme, dark
98 | wm.setDarkMode(true);
99 |
100 | // Show update button on info page
101 | wm.setShowInfoUpdate(true);
102 |
103 | // Separate ParamsPage from WiFi page
104 | wm.setParamsPage(true);
105 |
106 | // Clear the original menu list
107 | wm.setMenu(nullptr, 0);
108 | // Use custom menu list only:
109 | wm.setCustomMenuItems({{"/wifi" , "Configure WiFi", false},
110 | {"/param" , "Settings" , false},
111 | {"/info" , "Info" , false},
112 | {"/bt" , "BT Monitor" , false},
113 | {"--" , "" , false}, // Separator
114 | {"/erase" , "Erase" , true },
115 | {"/update" , "Update" , false},
116 | {"/restart", "Restart" , false},
117 | {"--" , "" , false}}); // Ending Separator
118 |
119 |
120 | //sets timeout until configuration portal gets turned off
121 | //useful to make it all retry or go to sleep in seconds
122 | wm.setConfigPortalTimeout(600); // 10 minutes
123 |
124 | // set connection timeout
125 | wm.setConnectTimeout(3);
126 |
127 | // set wifi connect retries
128 | wm.setConnectRetries(3);
129 |
130 | // connect after portal save toggle
131 | wm.setSaveConnect(true); // do not connect, only save
132 |
133 | wm.setWiFiAutoReconnect(true);
134 |
135 | String apName = String(WIFI_getChipId(),HEX);
136 | apName.toUpperCase();
137 | apName = "ESP32_bt_" + apName;
138 |
139 | // Setup httpd authentication for config portal once it's connected to users home WiFi network:
140 | wm.setHttpdAuthCredentials(HTTPD_USER, HTTPD_PASSWD);
141 |
142 | //fetches ssid and pass and tries to connect
143 | //if it does not connect it starts an access point with the specified name
144 | //and goes into a blocking loop awaiting configuration
145 | // --> last parameter ensures a retry to the blocking loop to connect to known WiFi AP
146 | if(!wm.autoConnect(apName.c_str(), AP_PASSWD, true)) {
147 | mSerial.println("failed to connect and hit timeout");
148 | }
149 | else {
150 | wm.setHttpdAuthEnable(true);
151 |
152 | // Disable AP
153 | WiFi.softAPdisconnect(true);
154 | WiFi.mode(WIFI_STA);
155 |
156 | //if you get here you have connected to the WiFi
157 | mSerial.println("connected...yeey :)");
158 | wm.startWebPortal();
159 | }
160 |
161 | wifiInfo();
162 | }
163 |
164 | // -----------------------------------------------
165 | void WiFiComponent::setupArduinoOTA() {
166 |
167 | ArduinoOTA.setPort(3232);
168 |
169 | ArduinoOTA.setHostname("ESP32_BT");
170 |
171 | ArduinoOTA.setPassword("admin");
172 |
173 | ArduinoOTA
174 | .onStart([this]() {
175 | String type;
176 | if (ArduinoOTA.getCommand() == U_FLASH)
177 | type = "sketch";
178 | else // U_SPIFFS
179 | type = "filesystem";
180 |
181 | // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
182 | mSerial.println("Start updating " + type);
183 |
184 | for (auto& cb : ota_callback_functions) {
185 | cb();
186 | }
187 |
188 | // Start with 'blocking' ota loop:
189 | otaBusy = 1;
190 | led.set(OFF);
191 | })
192 | .onEnd([this]() {
193 | Serial.println("\nEnd");
194 | otaBusy = 0;
195 | led.set(ON);
196 | // Succesful end will reset ESP itself
197 | })
198 | .onProgress([this](unsigned int progress, unsigned int total) {
199 | Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
200 | // Have the led fade on 10 times
201 | led.set((progress / (total / 25))%255);
202 |
203 | feedLoopWDT();
204 | })
205 | .onError([this](ota_error_t error) {
206 | mSerial.printf("Error[%u]: ", error);
207 | if (error == OTA_AUTH_ERROR) mSerial.println("Auth Failed");
208 | else if (error == OTA_BEGIN_ERROR) mSerial.println("Begin Failed");
209 | else if (error == OTA_CONNECT_ERROR) mSerial.println("Connect Failed");
210 | else if (error == OTA_RECEIVE_ERROR) mSerial.println("Receive Failed");
211 | else if (error == OTA_END_ERROR) mSerial.println("End Failed");
212 | otaBusy = 0;
213 | led.set(16);
214 |
215 | // Reset in order to have a fresh start on required functionality...
216 | delay(100);
217 | ESP.restart();
218 | });
219 |
220 | ArduinoOTA.begin();
221 | }
222 |
223 | // -----------------------------------------------
224 | void WiFiComponent::stopArduinoOTA() {
225 | ArduinoOTA.end();
226 | }
227 |
228 | // -----------------------------------------------
229 | void WiFiComponent::loadParams() {
230 | WiFiManagerParameter** params = wm.getParameters();
231 | uint16_t paramCount = wm.getParametersCount();
232 | for(uint16_t i = 0; i < paramCount; i++) {
233 | if(params[i]->getID()) {
234 | Parameter* p = static_cast(params[i]);
235 | if(p) {
236 | p->initialize();
237 | }
238 | }
239 | }
240 | }
241 |
242 | // -----------------------------------------------
243 | void WiFiComponent::storeParams() {
244 | WiFiManagerParameter** params = wm.getParameters();
245 | uint16_t paramCount = wm.getParametersCount();
246 | for(uint16_t i = 0; i < paramCount; i++) {
247 | if(params[i]->getID()) {
248 | Parameter* p = static_cast(params[i]);
249 | if(p) {
250 | p->storeValue();
251 | }
252 | }
253 | }
254 | }
255 |
256 | // -----------------------------------------------
257 | void WiFiComponent::addCustomHtmlPage(const char* path, customHtmlHandler_t handler) {
258 | custom_html_page_handlers.emplace_back(path, handler);
259 | }
260 |
261 | // -----------------------------------------------
262 | void WiFiComponent::saveWifiCallback(){
263 |
264 | }
265 |
266 | // -----------------------------------------------
267 | //gets called when WiFiManager enters configuration mode
268 | void WiFiComponent::configModeCallback (WiFiManager *myWiFiManager) {
269 | // ToDo: stop Bluetooth processing!?
270 | }
271 |
272 | // -----------------------------------------------
273 | void WiFiComponent::saveParamCallback(){
274 | storeParams();
275 |
276 | // Call registered callbacks to have them update the parameters
277 | for(auto& cb : paramSaved_callback_functions) {
278 | cb();
279 | }
280 | // wm.stopConfigPortal();
281 | }
282 |
283 | // -----------------------------------------------
284 | void WiFiComponent::handleRoute(){
285 | wm.server->send(200, "text/plain", "hello from user code");
286 | }
287 |
288 | // -----------------------------------------------
289 | void WiFiComponent::bindServerCallback(){
290 | wm.server->on("/custom",std::bind(&WiFiComponent::handleRoute,*this));
291 | // wm.server->on("/info",handleRoute); // you can override wm!
292 |
293 | for(auto& page : custom_html_page_handlers) {
294 | wm.server->on(page.path, page.handler);
295 | }
296 | }
297 |
298 |
--------------------------------------------------------------------------------
/src/main.cpp:
--------------------------------------------------------------------------------
1 | // Basic headers
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | // IDF headers
8 | #include
9 | #include
10 | #include
11 | #include "nvs.h"
12 | #include "nvs_flash.h"
13 | #include "esp_system.h"
14 | #include "esp_log.h"
15 | #include "esp_bt.h"
16 | #include "esp_bt_main.h"
17 | #include "esp_bt_device.h"
18 | #include "esp_gap_bt_api.h"
19 |
20 | // Tweaked SDK configuration
21 | #include "sdkconfig.h"
22 |
23 | // Arduino includes
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include "time.h"
32 |
33 | #include
34 |
35 | #include "esp_task_wdt.h"
36 |
37 | // Custom components:
38 | #include "NestedStruct.h"
39 | #include "TelnetSerial.h"
40 | #include "WiFiComponent.h"
41 | #include "BluetoothScanner.h"
42 | #include "parameter.h"
43 | #include "BluetoothParameter.h"
44 | #include "led.h"
45 | #include "mqtt.h"
46 |
47 | #include "stackDbgHelper.h"
48 |
49 | #ifndef DDUMPTIMEMEMINTERVAL
50 | #define DDUMPTIMEMEMINTERVAL 10
51 | #endif
52 |
53 | #ifndef MAX_NUM_STORED_BLUETOOTH_DEVICES
54 | #define MAX_NUM_STORED_BLUETOOTH_DEVICES (8)
55 | #endif
56 | // Upper limit for max number of stored bluetooth devices.
57 | // Is rediculously large, but more would not fit in NVS!!
58 | static_assert(MAX_NUM_STORED_BLUETOOTH_DEVICES <= 40, "Cannot fit more than 40 bluetooth device identifiers in ESP32 storage!!");
59 |
60 | #define WDT_TIMEOUT 8
61 |
62 | // ================================================
63 | // >>>>>>>>>> Global objects >>>>>>>>>>>>>>>>>>>>
64 |
65 | #ifndef NO_USE_TELNET_SERIAL
66 | TelnetSerial telnetSerial;
67 | Stream& mSerial = telnetSerial;
68 | #else
69 | Stream& mSerial = Serial;
70 | #endif
71 | Preferences preferences;
72 | WiFiManager wm(mSerial);
73 | LED led;
74 |
75 | // >>> All parameters in order shown in WiFiManager:
76 | Parameter time_header ("Timezone
Use e.g. Europe/Amsterdam. List of timezones
(empty for auto-geolocation)
");
77 | Parameter time_zone ("time_zone", "", "", 40);
78 | // MQTT
79 | Parameter mqtt_header ("MQTT parameters
");
80 | Parameter mqtt_server ("mqtt_server", "mqtt server", "", 40);
81 | Parameter mqtt_port ("mqtt_port", "mqtt port", "1883", 6);
82 | Parameter mqtt_username ("mqtt_username", "username", "", 32);
83 | Parameter mqtt_password ("mqtt_password", "password", "", 32);
84 | Parameter mqtt_client_id("mqtt_clid", "Client ID", "", 32);
85 |
86 | Parameter mqtt_topic ("mqtt_topic", "topic root", "monitor", 32);
87 | Parameter mqtt_identity("mqtt_identity", "identity", "", 32);
88 |
89 | // Bluetooth Monitor settings
90 | Parameter bluetooth_monitor_header (PSTR("Bluetooth Monitor settings
"));
91 | U16Parameter bluetooth_monitor_arrival_scans (PSTR("bm_arrival"), PSTR("# Arrival scans"), 1 );
92 | U16Parameter bluetooth_monitor_departure_scans (PSTR("bm_depart"), PSTR("# Departure scans"), 3 );
93 | U16Parameter bluetooth_monitor_seconds_between_scan_iters (PSTR("bm_iter_time"), PSTR("Seconds between scan tries"), 3 );
94 | U16Parameter bluetooth_monitor_scan_timeout_seconds (PSTR("bm_timeout"), PSTR("Scan duration timeout (s)"), 60 );
95 | U16Parameter bluetooth_monitor_beacon_expiration (PSTR("bm_beacon_exp"), PSTR("Beacon expiration time (s)"), 240);
96 | U16Parameter bluetooth_monitor_min_time_between_scans (PSTR("bm_min_time"), PSTR("Min. time between scans (s)"), 10 );
97 | U16Parameter bluetooth_monitor_periodic_scan_interval (PSTR("bm_period"), PSTR("Periodic scan interval (s)
(Leave empty or '0' to disable periodic scanning)"), 0);
98 | BoolParameter bluetooth_monitor_retain_flag (PSTR("bm_retain"), PSTR("MQTT retain flag (true/false)"), false);
99 |
100 | // Known Static Bluetooth MAC
101 | // Nested struct helper to generate objects and reduce boilerplate...
102 | Parameter bluetooth_monitor_devices_header (PSTR("Bluetooth Monitor Devices
"));
103 | NestWrapper bluetooth_monitor_parameter_sets;
104 |
105 | // <<<
106 | WiFiComponent wifi(mSerial);
107 | BluetoothScanner btScanner(mSerial);
108 | MQTT mqtt(mSerial);
109 |
110 | Timezone mTime;
111 | // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
112 |
113 |
114 | std::stack _stack;
115 |
116 | uint32_t startFreeHeap = 0;
117 |
118 | #define USE_SEPARATE_STATS_TASK 0
119 |
120 | #include "freertos/FreeRTOS.h"
121 | #include "freertos/task.h"
122 | #include "esp_heap_task_info.h"
123 |
124 | #define MAX_TASK_NUM 20 // Max number of per tasks info that it can store
125 | #define MAX_BLOCK_NUM 20 // Max number of per block info that it can store
126 |
127 | static size_t s_prepopulated_num = 0;
128 | static heap_task_totals_t s_totals_arr[MAX_TASK_NUM];
129 | static heap_task_block_t s_block_arr[MAX_BLOCK_NUM];
130 |
131 | // -----------------------------------------------
132 | extern "C" void esp_task_wdt_isr_user_handler(void)
133 | {
134 | printf("\nSTACK:\n");
135 | while(!_stack.empty()) {
136 | auto& e = _stack.top();
137 | printf("PC: %d, Func: %s, Line: %d \n", e.pc, e.func, e.line);
138 | _stack.pop();
139 | }
140 | }
141 |
142 | // -----------------------------------------------
143 | static void esp_dump_per_task_heap_info(void)
144 | {
145 | SCOPED_STACK_ENTRY;
146 | heap_task_info_params_t heap_info = {0};
147 | heap_info.caps[0] = MALLOC_CAP_8BIT; // Gets heap with CAP_8BIT capabilities
148 | heap_info.mask[0] = MALLOC_CAP_8BIT;
149 | heap_info.caps[1] = MALLOC_CAP_32BIT; // Gets heap info with CAP_32BIT capabilities
150 | heap_info.mask[1] = MALLOC_CAP_32BIT;
151 | heap_info.tasks = NULL; // Passing NULL captures heap info for all tasks
152 | heap_info.num_tasks = 0;
153 | heap_info.totals = s_totals_arr; // Gets task wise allocation details
154 | heap_info.num_totals = &s_prepopulated_num;
155 | heap_info.max_totals = MAX_TASK_NUM; // Maximum length of "s_totals_arr"
156 | heap_info.blocks = s_block_arr; // Gets block wise allocation details. For each block, gets owner task, address and size
157 | heap_info.max_blocks = MAX_BLOCK_NUM; // Maximum length of "s_block_arr"
158 |
159 | heap_caps_get_per_task_info(&heap_info);
160 |
161 | for (int i = 0 ; i < *heap_info.num_totals; i++) {
162 | const char* taskName = heap_info.totals[i].task ? pcTaskGetTaskName(heap_info.totals[i].task) : nullptr;
163 | bool tryHeap = true;
164 | if(taskName == nullptr) {
165 | tryHeap = false;
166 | }
167 | else {
168 | for (int i = 0; i < strlen(taskName); i++) {
169 | if(!isascii(taskName[i])) {
170 | tryHeap = false;
171 | break;
172 | }
173 | }
174 | }
175 |
176 | mSerial.printf("Task: %22s -> CAP_8BIT: %6d CAP_32BIT: %3d -> HighWaterMark: %5d\n",
177 | heap_info.totals[i].task ? pcTaskGetTaskName(heap_info.totals[i].task) : "Pre-Scheduler allocs" ,
178 | heap_info.totals[i].size[0], // Heap size with CAP_8BIT capabilities
179 | heap_info.totals[i].size[1], // Heap size with CAP32_BIT capabilities
180 | tryHeap ? uxTaskGetStackHighWaterMark(heap_info.totals[i].task) : -1);
181 |
182 | feedLoopWDT(); // Must be done <= 360 mS
183 | }
184 |
185 | mSerial.printf("Free heap at start: %d, min free heap ever: %d\n", startFreeHeap, xPortGetMinimumEverFreeHeapSize());
186 | mSerial.printf("Free heap size: %d, largest fee block: %d\n", heap_caps_get_free_size(MALLOC_CAP_8BIT), heap_caps_get_largest_free_block(MALLOC_CAP_8BIT));
187 |
188 | mSerial.print("HeapCapsFreeSize - Internal: ");
189 | mSerial.print(heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
190 | mSerial.print(" SPIRAM: ");
191 | mSerial.print(heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
192 | mSerial.print(" IRAM8: ");
193 | mSerial.print(heap_caps_get_free_size(MALLOC_CAP_IRAM_8BIT));
194 | mSerial.print(" Default: ");
195 | mSerial.println(heap_caps_get_free_size(MALLOC_CAP_DEFAULT));
196 |
197 | mSerial.printf("\n\n");
198 | }
199 |
200 | // -----------------------------------------------
201 | void heap_caps_alloc_failed_hook(size_t requested_size, uint32_t caps, const char *function_name)
202 | {
203 | // No Printf to avoid MALLOCS!!!
204 | Serial.print(function_name);
205 | Serial.print(" in task ");
206 | Serial.print(pcTaskGetTaskName(NULL));
207 | Serial.print(" was called but failed to allocate ");
208 | Serial.print(requested_size);
209 | Serial.print(" bytes, with capabilities: ");
210 | Serial.println(caps);
211 | Serial.print(" .High water mark: ");
212 | Serial.println(uxTaskGetStackHighWaterMark(NULL));
213 | Serial.print("HeapCapsFreeSize - Internal: ");
214 | Serial.print(heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
215 | Serial.print(" SPIRAM: ");
216 | Serial.print(heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
217 | Serial.print(" IRAM8: ");
218 | Serial.print(heap_caps_get_free_size(MALLOC_CAP_IRAM_8BIT));
219 | Serial.print(" Default: ");
220 | Serial.println(heap_caps_get_free_size(MALLOC_CAP_DEFAULT));
221 |
222 |
223 | Serial.print("Free heap at start: ");
224 | Serial.print(startFreeHeap);
225 | Serial.print(", min free heap ever: ");
226 | Serial.println(xPortGetMinimumEverFreeHeapSize());
227 | Serial.print("Free heap size: ");
228 | Serial.print(heap_caps_get_free_size(MALLOC_CAP_8BIT));
229 | Serial.print(", largest fee block: ");
230 | Serial.println(heap_caps_get_largest_free_block(MALLOC_CAP_8BIT));
231 | //Serial.printf("%s in task '%s' was called but failed to allocate %d bytes with 0x%X capabilities. HighWaterMark: %lu \n",function_name, pcTaskGetTaskName(NULL), requested_size, caps, (unsigned long)uxTaskGetStackHighWaterMark(NULL));
232 | }
233 |
234 | // -----------------------------------------------
235 | bool ensureAllCaps(std::string& str) {
236 | bool strUpdated = false;
237 | for (auto & c: str) {
238 | auto cu = toupper(c);
239 | if(c != cu) {
240 | strUpdated = true;
241 | }
242 | c = cu;
243 | }
244 | return strUpdated;
245 | }
246 |
247 | // -----------------------------------------------
248 | #define PREFERENCES_TAG_VALUE (54)
249 | void setupPreferences() {
250 | preferences.begin("E32BT", false);
251 |
252 | // Perform a factory reset if we have not ran before...
253 | if(preferences.getUInt("ESP32_BT_TAG", 0) != PREFERENCES_TAG_VALUE) {
254 | Serial.print("Could not find Magic value in preferences. Clearing NVS for factory reset!");
255 |
256 | preferences.end();
257 |
258 | nvs_flash_erase(); // erase the NVS partition and...
259 | nvs_flash_init(); // initialize the NVS partition.
260 | Serial.print(" ... ");
261 |
262 | preferences.begin("E32BT", false);
263 | preferences.putUInt("ESP32_BT_TAG", PREFERENCES_TAG_VALUE);
264 | Serial.println("Done!!");
265 | }
266 |
267 | // Set default MQTT Client ID if not set:
268 | if(strlen(mqtt_client_id.getValue()) < 1) {
269 | String client_id = String("ESP32_bt") + String(WIFI_getChipId(),HEX);
270 | mqtt_client_id.setValue(client_id.c_str());
271 | }
272 |
273 | // Remove all preferences under the opened namespace
274 | //preferences.clear();
275 |
276 | // Or remove the counter key only
277 | //preferences.remove("counter");
278 | }
279 |
280 | // -----------------------------------------------
281 | void setupMQTT() {
282 | mqtt.setup( mqtt_server.getValue(),
283 | mqtt_port.getValue(),
284 | mqtt_username.getValue(),
285 | mqtt_password.getValue(),
286 | mqtt_client_id.getValue() );
287 | }
288 |
289 | // -----------------------------------------------
290 | void setupMqttCallbacks() {
291 | // Clear existing topics and callbacks based on old parameters:
292 | mqtt.clear_subscription_topics();
293 | mqtt.clear_callbacks();
294 |
295 | std::string baseTopic = mqtt.trimWildcards(mqtt_topic.getValue());
296 | mqtt.setStateTopic(baseTopic + "/" + mqtt_identity.getValue() + "/status");
297 | mqtt.setIpTopic(baseTopic + "/" + mqtt_identity.getValue() + "/IP");
298 |
299 | // ToDo: this becomes a problem when reloading parameters at runtime!!
300 | // FIX THIS!
301 | //mqtt.add_subscription_topic(mqtt_topic.getValue()); //TEST
302 | mqtt.add_subscription_topic((baseTopic + "/scan/#").c_str());
303 | mqtt.add_subscription_topic((baseTopic + "/setup/#").c_str());
304 | mqtt.add_subscription_topic((baseTopic + "/" + mqtt_identity.getValue() + "/restart").c_str());
305 | mqtt.add_callback((baseTopic + "/" + mqtt_identity.getValue() + "/restart").c_str(), [](const byte* payload, unsigned int length) {
306 | mSerial.println("Restarting!!");
307 | delay(1000);
308 | ESP.restart();
309 | });
310 | mqtt.add_callback((baseTopic + "/scan/ARRIVE").c_str(), [](const byte* payload, unsigned int length) {
311 | btScanner.startBluetoothScan(ScanType::Arrival);
312 | });
313 | mqtt.add_callback((baseTopic + "/scan/DEPART").c_str(), [](const byte* payload, unsigned int length) {
314 | btScanner.startBluetoothScan(ScanType::Departure);
315 | });
316 | mqtt.add_callback((baseTopic + "/scan/ANY").c_str(), [](const byte* payload, unsigned int length) {
317 | btScanner.startBluetoothScan(ScanType::Either);
318 | });
319 | // MQTT setup interfaces:
320 | mqtt.add_callback((baseTopic + "/setup/ADD STATIC DEVICE").c_str(), [](const byte* payload, unsigned int length) {
321 | // Splitting the MAC from the alias:
322 | std::string _in = std::string((const char*)payload, length);
323 | _in.erase(_in.find_last_not_of(" \t\n\v") + 1);
324 | std::string mac = _in.substr(0, _in.find(" "));
325 | std::string alias = _in.substr(_in.find(" "));
326 |
327 | size_t first = alias.find_first_not_of(" \t\n\v");
328 | size_t last = alias.find_last_not_of(" \t\n\v");
329 | if(first != std::string::npos) {
330 | alias = alias.substr(first, (last-first+1));
331 | }
332 |
333 | BLEUUID ble_uuid = BLEUUID::fromString(mac);
334 |
335 | // Add to storage and BluetoothScanner
336 | esp_bd_addr_t addr;
337 | if(str2bda(mac.c_str(), addr)) {
338 | char bda_str[18];
339 | if (bda2str(addr, bda_str, 18)) {
340 | bool device_saved = false;
341 | for(int i = 0; i < bluetooth_monitor_parameter_sets.size; i++) {
342 | if(strlen(bluetooth_monitor_parameter_sets.data[i].getMacAddress()) == 0 || strcmp(bluetooth_monitor_parameter_sets.data[i].getMacAddress(), bda_str) == 0) {
343 | bluetooth_monitor_parameter_sets.data[i].setMacAddress(bda_str);
344 | bluetooth_monitor_parameter_sets.data[i].setAlias(alias.c_str());
345 | device_saved = true;
346 | break;
347 | }
348 | }
349 | if (device_saved){
350 | btScanner.addKnownDevice(addr, alias.c_str());
351 | }
352 | }
353 | }
354 | else if (!ble_uuid.equals(BLEUUID())) {
355 | bool device_saved = false;
356 | for(int i = 0; i < bluetooth_monitor_parameter_sets.size; i++) {
357 | if(strlen(bluetooth_monitor_parameter_sets.data[i].getMacAddress()) == 0 || strcmp(bluetooth_monitor_parameter_sets.data[i].getMacAddress(), ble_uuid.toString().c_str()) == 0) {
358 | bluetooth_monitor_parameter_sets.data[i].setMacAddress(ble_uuid.toString().c_str());
359 | bluetooth_monitor_parameter_sets.data[i].setAlias(alias.c_str());
360 | device_saved = true;
361 | break;
362 | }
363 | }
364 | if (device_saved){
365 | btScanner.addKnownIBeacon(ble_uuid, alias.c_str());
366 | }
367 | }
368 |
369 | });
370 | mqtt.add_callback((baseTopic + "/setup/DELETE STATIC DEVICE").c_str(), [](const byte* payload, unsigned int length) {
371 | esp_bd_addr_t addr;
372 | if(str2bda(std::string((const char*)payload, length).c_str(), addr)) {
373 | char bda_str[18];
374 | if (bda2str(addr, bda_str, 18)) {
375 | btScanner.deleteKnownDevice(addr);
376 | for(int i = 0; i < bluetooth_monitor_parameter_sets.size; i++) {
377 | if(strcmp(bluetooth_monitor_parameter_sets.data[i].getMacAddress(), bda_str) == 0) {
378 | bluetooth_monitor_parameter_sets.data[i].setMacAddress("");
379 | bluetooth_monitor_parameter_sets.data[i].setAlias("");
380 | }
381 | }
382 | }
383 | }
384 | });
385 | }
386 |
387 | // -----------------------------------------------
388 | void setupBtScanner() {
389 | btScanner.setMqttTopic(mqtt.trimWildcards(mqtt_topic.getValue()));
390 | btScanner.setScannerIdentity(mqtt_identity.getValue());
391 | btScanner.setRetainFlag(param2bool(bluetooth_monitor_retain_flag));
392 |
393 | btScanner.setNumArrivalScans (bluetooth_monitor_arrival_scans.getValue());
394 | btScanner.setNumDepartureScans (bluetooth_monitor_departure_scans.getValue());
395 | btScanner.setSecondsBetweenScanIters(bluetooth_monitor_seconds_between_scan_iters.getValue());
396 | btScanner.setBeaconExpiration (bluetooth_monitor_beacon_expiration.getValue());
397 | btScanner.setMinTimeBetweenScans (bluetooth_monitor_min_time_between_scans.getValue());
398 | btScanner.setPeriodicScanInterval (bluetooth_monitor_periodic_scan_interval.getValue());
399 | btScanner.setScanDurationTimeout (bluetooth_monitor_scan_timeout_seconds.getValue());
400 | // ToDo: Reload the rest of Bluetooth parameters
401 |
402 | // (Re)Load known BT devices:
403 | btScanner.clearKnownDevices();
404 | for(int i = 0; i < bluetooth_monitor_parameter_sets.size; i++) {
405 | esp_bd_addr_t mac;
406 | std::string mac_str = bluetooth_monitor_parameter_sets.data[i].getMacAddress();
407 |
408 | // Ensure Mac addresses are all CAPS:
409 | bool updateMac = ensureAllCaps(mac_str);
410 | if(updateMac) {
411 | bluetooth_monitor_parameter_sets.data[i].setMacAddress(mac_str.c_str());
412 | }
413 |
414 | if(mac_str.find_first_not_of(" \t\n\v\f\r") != std::string::npos) {
415 | mSerial.printf("Validating MAC: '%s' \n", mac_str.c_str());
416 |
417 | BLEUUID ble_uuid = BLEUUID::fromString(mac_str);
418 |
419 | // If valid mac address, add it!
420 | if(str2bda(mac_str.c_str(), mac)) {
421 | const char* alias = bluetooth_monitor_parameter_sets.data[i].getAlias();
422 | mSerial.printf(" Adding device: %s, with MAC: %s \n", alias, mac_str.c_str());
423 | btScanner.addKnownDevice(mac, alias);
424 | }
425 | else if (!ble_uuid.equals(BLEUUID())) {
426 | const char* alias = bluetooth_monitor_parameter_sets.data[i].getAlias();
427 | mSerial.printf(" Adding device: %s, with UUID: '%s' \n", alias, mac_str.c_str());
428 | btScanner.addKnownIBeacon(ble_uuid, alias);
429 | }
430 | }
431 | }
432 |
433 | }
434 |
435 | // -----------------------------------------------
436 | void setupTimeZone() {
437 | // Or country codes for countries that do not span multiple timezones
438 | //mTime.setLocation(F("nl"));
439 | const char* timezone = time_zone.getValue();
440 | mTime.setLocation(strlen(timezone) ? timezone : "GeoIP");
441 | Serial.print(F("Local time: "));
442 | Serial.println(mTime.dateTime());
443 | }
444 |
445 |
446 | #if CONFIG_AUTOSTART_ARDUINO
447 | // -----------------------------------------------
448 | void setup() {
449 | startFreeHeap = xPortGetFreeHeapSize();
450 | esp_err_t error = heap_caps_register_failed_alloc_callback(heap_caps_alloc_failed_hook);
451 |
452 | // Turn on LED at start of setup
453 | led.setup();
454 | led.set(ON);
455 |
456 | WiFi.setAutoConnect(true);
457 |
458 | // Begin Serial separate!
459 | Serial.begin(115200, SERIAL_8N1);
460 |
461 | setupPreferences();
462 |
463 | mSerial.println("Booting");
464 | ezt::setDebug(INFO, mSerial);
465 |
466 | if(error != ESP_OK) {
467 | Serial.printf("failed alloc callback error: %d\n", error);
468 | }
469 |
470 | // Note that this will not show up in the MENU!!!
471 | wifi.addCustomHtmlPage("/bt", [](){
472 | String page = FPSTR(HTTP_HEAD_START);
473 | page.replace(FPSTR(T_v), "Bluetooth Status");
474 | page += FPSTR(HTTP_SCRIPT);
475 | page += FPSTR(HTTP_STYLE);
476 | // Selection for DarkMode: _bodyClass = enable ? "invert" : "";
477 | String p = FPSTR(HTTP_HEAD_END);
478 | p.replace(FPSTR(T_c), "invert"); // add class str
479 | page += p;
480 |
481 | auto& devList = btScanner.getBtDeviceStates();
482 | char bda_str[18];
483 | for (auto& dev : devList) {
484 | String str = FPSTR("{n} is {s}
{m}
");
485 | str.replace("{C}", (dev.state == 1 ? "S" : "D"));
486 | str.replace("{n}", dev.name);
487 | str.replace("{s}", (dev.state == 1 ? "Present" : "Away"));
488 | bda2str(dev.mac, bda_str, 18);
489 | str.replace("{m}", bda_str);
490 | page += str;
491 | }
492 |
493 | page += FPSTR("
" // MENU_SEP
494 | "
"
495 | "
"
496 | "
"
497 | "
");
498 |
499 | if(wm.server->hasArg(F("arrive"))) {
500 | btScanner.startBluetoothScan(ScanType::Arrival);
501 | }
502 | if(wm.server->hasArg(F("depart"))) {
503 | btScanner.startBluetoothScan(ScanType::Departure);
504 | }
505 | if(wm.server->hasArg(F("scan"))) {
506 | btScanner.startBluetoothScan(ScanType::Either);
507 | }
508 |
509 | page += FPSTR(HTTP_END);
510 |
511 | wm.server->send(200, FPSTR(HTTP_HEAD_CT), page);
512 | });
513 |
514 | // Blocking if not connected WiFi AP
515 | wifi.setup();
516 | // Stop bluetooth on OTA to reduce chance of failures..
517 | wifi.registerOtaStartCallback([](){
518 | mSerial.println("Stopping BtScanner for OTA...");
519 | btScanner.stop();
520 | });
521 |
522 | #ifndef NO_USE_TELNET_SERIAL
523 | telnetSerial.begin(); // Start the telnet bit...
524 | #endif
525 | setupMQTT();
526 | setupMqttCallbacks();
527 |
528 | // Setup bluetooth AFTER WiFi such that the persistent parameters are loaded!
529 | btScanner.init(); // ESP Bluetooth component, HAL, etc.
530 | setupBtScanner(); // Scanner configuration / settings
531 |
532 | // EZTime: sync time
533 | ezt::waitForSync();
534 | setupTimeZone();
535 |
536 | // Stop bluetooth on OTA to reduce chance of failures..
537 | wifi.registerOtaStartCallback([](){
538 | mSerial.println("Stopping BtScanner for OTA...");
539 | btScanner.stop();
540 | });
541 | // Run MQTT setup again when new parameters are made available
542 | wifi.registerParamSaveCallback(setupMQTT); // This causes pubSub to destruct and panic!!
543 | wifi.registerParamSaveCallback(setupMqttCallbacks);
544 | wifi.registerParamSaveCallback(setupTimeZone);
545 | wifi.registerParamSaveCallback(setupBtScanner);
546 |
547 | // Turn off led at the end of setup
548 | led.set(OFF);
549 |
550 | btScanner.startBluetoothScan(ScanType::Either);
551 |
552 | esp_task_wdt_init(WDT_TIMEOUT, true); //enable panic so ESP32 restarts
553 |
554 | enableLoopWDT();
555 | }
556 |
557 | uint16_t count = 0;
558 |
559 | unsigned long last_millis = 0;
560 | // unsigned long interval=10000; // 10sec
561 | unsigned long interval=DUMPTIMEMEMINTERVAL*1000; // 10sec
562 |
563 | void loop() {
564 | SCOPED_STACK_ENTRY;
565 |
566 | wifi.loop();
567 | #ifndef NO_USE_TELNET_SERIAL
568 | telnetSerial.loop();
569 | #endif
570 |
571 | mqtt.loop();
572 | delay(10);
573 | btScanner.loop();
574 |
575 | unsigned long current_millis = millis();
576 | if(interval > 0 && current_millis > last_millis + interval) {
577 | last_millis = current_millis;
578 | mSerial.println(current_millis);
579 |
580 | mSerial.println(mTime.dateTime());
581 | esp_dump_per_task_heap_info();
582 |
583 | count++;
584 | }
585 |
586 | // WDT Feeding is done in Arduino scope outside of the loop...
587 | // Delay needed to give idle task some room!!
588 | delay(10);
589 | }
590 | #else
591 | #ERROR wrong SDK configuration!
592 | #endif
--------------------------------------------------------------------------------
/src/mqtt.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include
3 |
4 | #include
5 | #include "parameter.h"
6 | #include "mqtt.h"
7 | #include "stackDbgHelper.h"
8 |
9 | #ifndef MQTT_CLEAN_SESSION
10 | #define MQTT_CLEAN_SESSION 1 // 0 = No clean session, 1 = Clean session
11 | #endif
12 |
13 | // Monitor arguments to be used:
14 | // r: repeatedly scan for arrival / departure of known devices
15 | // x: retain mqtt status messages
16 | // b: report bluetooth beacon advertisements
17 | // Can only effectively run in '-tad' mode!!
18 |
19 | // Monitor MQTT preferences
20 | // mqtt address
21 | // mqtt broker username
22 | // mqtt broker password
23 | // mqtt publish topic root
24 | // mqtt publisher identity
25 | // mqtt port
26 |
27 | // Behavioral preferences
28 | // Arrival scan attempts #
29 | // Departure scan attempts #
30 | // Beacon expiration seconds
31 | // min time between scans seconds
32 | // .. others are irrelevant for now as we cannot passively scan...
33 |
34 | // A list of max 16 known mac addresses + aliasses
35 |
36 | // ------------------------------------------------
37 | // Local functions:
38 |
39 | // -----------------------------------------------
40 | void MQTT::setup(
41 | const char* mqtt_server,
42 | const char* mqtt_port,
43 | const char* mqtt_username,
44 | const char* mqtt_password,
45 | const char* mqtt_client_id)
46 | {
47 | // Store MQTT server parameters
48 | _mqtt_server = mqtt_server;
49 | _mqtt_port = mqtt_port;
50 | _mqtt_username = mqtt_username;
51 | _mqtt_password = mqtt_password;
52 | _mqtt_clientId = mqtt_client_id;
53 |
54 | // In case of a re-initialization with new parameters
55 | if(mqtt_client.connected()) {
56 | mqtt_client.disconnect();
57 | }
58 |
59 | // Setup MQTT
60 | if(strlen(_mqtt_server) > 1) {
61 | mSerial.printf("MQTT connecting to: %s:%s\n", _mqtt_server, _mqtt_port);
62 | mqtt_client.setServer(_mqtt_server, atoi(_mqtt_port));
63 | mqtt_client.setCallback(std::bind(&MQTT::mqtt_callback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
64 | }
65 | else {
66 | mSerial.println("MQTT parameters incomplete. Not setting up MQTT.");
67 | }
68 | }
69 |
70 | // -----------------------------------------------
71 | void MQTT::loop() {
72 | SCOPED_STACK_ENTRY;
73 | // Only loop if configured correctly
74 | if(!strlen(_mqtt_server)) {
75 | return;
76 | }
77 |
78 | if (!mqtt_client.connected()) {
79 | unsigned long now = millis();
80 |
81 | if (now - last_reconnect_attempt > 5000) {
82 | last_reconnect_attempt = now;
83 |
84 | if (reconnect()) {
85 | last_reconnect_attempt = 0;
86 | }
87 | else {
88 | mSerial.println("Retrying MQTT connect in 5 seconds");
89 | }
90 | }
91 | }
92 | else {
93 | mqtt_client.loop();
94 | }
95 | }
96 |
97 | // -----------------------------------------------
98 | // Used for setting service online / offline
99 | void MQTT::setStateTopic(std::string state_topic) {
100 | _mqtt_state_topic_str = state_topic;
101 | }
102 |
103 | // -----------------------------------------------
104 | void MQTT::setIpTopic(std::string ip_topic) {
105 | _mqtt_ip_topic_str = ip_topic;
106 | }
107 |
108 | // -----------------------------------------------
109 | std::string MQTT::trimWildcards(const char* topic) {
110 | const char* trimChars = " \t\n\r\f\v#/";
111 | std::string trimmed_topic = topic;
112 |
113 | trimmed_topic.erase(trimmed_topic.find_last_not_of(trimChars) + 1);
114 |
115 | return trimmed_topic;
116 | }
117 |
118 | // -----------------------------------------------
119 | // Send a message to a broker topic
120 | void MQTT::send_message(const char *topic, const char *payload, bool retain)
121 | {
122 | mSerial.printf("MQTT Outgoing on %s: ", topic);
123 | mSerial.println(payload);
124 |
125 | bool result = mqtt_client.publish(topic, payload, retain);
126 |
127 | if (!result)
128 | {
129 | mSerial.printf("MQTT publish to topic %s failed\n", topic);
130 | }
131 | }
132 |
133 | // -----------------------------------------------
134 | void MQTT::add_callback(const char* topic, CallbackFunction_t callbackFunction) {
135 | callback_functions.push_back({topic, callbackFunction});
136 | }
137 |
138 | // -----------------------------------------------
139 | void MQTT::clear_callbacks() {
140 | callback_functions.clear();
141 | }
142 |
143 | // -----------------------------------------------
144 | void MQTT::add_subscription_topic(String topic) {
145 | subscription_topics.push_back(topic);
146 | if(mqtt_client.connected()) {
147 | mqtt_client.subscribe(topic.c_str());
148 | }
149 | }
150 |
151 |
152 | // -----------------------------------------------
153 | void MQTT::remove_subscription_topic(String topic) {
154 | subscription_topics.erase(std::remove(subscription_topics.begin(), subscription_topics.end(), topic), subscription_topics.end());
155 | if(mqtt_client.connected()) {
156 | mqtt_client.unsubscribe(topic.c_str());
157 | }
158 | }
159 |
160 | // -----------------------------------------------
161 | void MQTT::clear_subscription_topics() {
162 | subscription_topics.clear();
163 | }
164 |
165 | // -----------------------------------------------
166 | void MQTT::mqtt_callback(char* topic, byte* payload, unsigned int length) {
167 | mSerial.print("Message arrived [");
168 | mSerial.print(topic);
169 | mSerial.print("] ");
170 | for (unsigned int i = 0; i < length; i++) {
171 | mSerial.print((char)payload[i]);
172 | }
173 | mSerial.println();
174 |
175 | for (auto& cb : callback_functions) {
176 | if(cb.first.equalsIgnoreCase(topic)) {
177 | mSerial.printf("Calling callback for topic '%s'\n", topic);
178 | cb.second(payload, length);
179 | }
180 | }
181 | }
182 | #if 0
183 | // -----------------------------------------------
184 | // Reconnect to MQTT server and subscribe to in and out topics
185 | bool MQTT::reconnect()
186 | {
187 | // * Loop until we're reconnected
188 | int mqtt_reconnect_retries = 0;
189 |
190 | mSerial.println("reconnect();");
191 | while (!mqtt_client.connected() && mqtt_reconnect_retries < mqtt_max_reconnect_tries)
192 | {
193 | mqtt_reconnect_retries++;
194 | mSerial.printf("MQTT connection attempt %d / %d ...\n", mqtt_reconnect_retries, mqtt_max_reconnect_tries);
195 |
196 | // * Attempt to connect
197 |
198 | // if (mqtt_client.connect(_mqtt_server, _mqtt_username, _mqtt_password))
199 | if (mqtt_client.connect(_mqtt_server, _mqtt_username, _mqtt_password, _mqtt_state_topic_str.c_str(), 1, true, "offline", MQTT_CLEAN_SESSION))
200 | {
201 | delay(100);
202 | mSerial.println(F("MQTT connected!"));
203 | send_message(_mqtt_state_topic_str.c_str(), "online", true);
204 |
205 | delay(25);
206 | /*
207 | // Subscribe to root topic
208 | for (auto topic : subscription_topics) {
209 | bool ret = mqtt_client.subscribe(topic.c_str()); // topic may include wildcards. Needs to be trimmed for publish stuff..
210 | mSerial.printf("MQTT root topic: '%s', subscription: %d\n", topic.c_str(), ret);
211 | // Prevent broker disconnect:
212 | // mqtt_client.loop();
213 | }
214 | */
215 | }
216 | else
217 | {
218 | mSerial.print(F("MQTT Connection failed: rc="));
219 | mSerial.println(mqtt_client.state());
220 | // mSerial.println(F(" Retrying in 5 seconds"));
221 | // mSerial.println("");
222 |
223 | return false;
224 | // * Wait 5 seconds before retrying
225 | feedLoopWDT();
226 | delay(5000);
227 | }
228 | }
229 |
230 | if (mqtt_reconnect_retries >= mqtt_max_reconnect_tries)
231 | {
232 | mSerial.printf("*** MQTT connection failed, giving up after %d tries ...\n", mqtt_reconnect_retries);
233 | return false;
234 | }
235 |
236 | return true;
237 | }
238 | #else
239 | // -----------------------------------------------
240 | // Reconnect to MQTT server and subscribe to in and out topics
241 | bool MQTT::reconnect()
242 | {
243 | SCOPED_STACK_ENTRY;
244 | _mqtt_reconnect_retries++;
245 | mSerial.printf("MQTT connection attempt %d ...\n", _mqtt_reconnect_retries);
246 |
247 | if (mqtt_client.connect(_mqtt_clientId, _mqtt_username, _mqtt_password, _mqtt_state_topic_str.c_str(), 1, true, "offline", MQTT_CLEAN_SESSION))
248 | {
249 | delay(50);
250 | mSerial.println(F("MQTT connected!"));
251 | send_message(_mqtt_state_topic_str.c_str(), "online", true);
252 |
253 | if(!_mqtt_ip_topic_str.empty()) {
254 | delay(10);
255 | send_message(_mqtt_ip_topic_str.c_str(), WiFi.localIP().toString().c_str(), true);
256 | }
257 |
258 | delay(25);
259 |
260 | // Subscribe to root topic
261 | for (auto topic : subscription_topics) {
262 | bool ret = mqtt_client.subscribe(topic.c_str()); // topic may include wildcards. Needs to be trimmed for publish stuff..
263 | mSerial.printf("MQTT root topic: '%s', subscription: %d\n", topic.c_str(), ret);
264 | // Prevent broker disconnect:
265 | mqtt_client.loop();
266 | }
267 |
268 | return true;
269 | }
270 |
271 | mSerial.print(F("MQTT Connection failed: rc="));
272 | mSerial.println(mqtt_client.state());
273 |
274 | return false;
275 | }
276 | #endif
277 |
--------------------------------------------------------------------------------
/src/parameter.cpp:
--------------------------------------------------------------------------------
1 | // Basic headers
2 | #include
3 | #include
4 | #include
5 |
6 | // Tweaked SDK configuration
7 | #include "parameter.h"
8 |
9 | // Arduino includes
10 | #include
11 | #include // https://github.com/tzapu/WiFiManager
12 | #include
13 |
14 | // Required available global entities:
15 | extern WiFiManager wm;
16 | extern Preferences preferences;
17 |
18 | // Free functions:
19 | // -----------------------------------------------
20 | bool param2bool(const Parameter& param) {
21 | String val = param.getValue();
22 | val.toLowerCase();
23 |
24 | if(val == "true" || val == "1") {
25 | return true;
26 | }
27 |
28 | // fallback case: always false
29 | return false;
30 | }
31 |
32 |
33 | // Parameter class functions:
34 |
35 | // -----------------------------------------------
36 | Parameter::Parameter(const char *custom) : WiFiManagerParameter(custom)
37 | {
38 | // Automatically add parameter to WiFiManager upon creation.
39 | wm.addParameter(this);
40 | }
41 |
42 | // -----------------------------------------------
43 | Parameter::Parameter(const char *id, const char *label, const char* defaultValue, int length, const char *custom, int labelPlacement)
44 | : WiFiManagerParameter(id, label, defaultValue, length, custom, labelPlacement)
45 | {
46 | // Automatically add parameter to WiFiManager upon creation.
47 | wm.addParameter(this);
48 | }
49 |
50 | // -----------------------------------------------
51 | void Parameter::initialize() {
52 | // CustomHTLM does not store to NVS. No need to read it...
53 | if(getID() != nullptr) {
54 | preferences.getString(WiFiManagerParameter::getID(), WiFiManagerParameter::_value, WiFiManagerParameter::_length);
55 | }
56 | _initialized = true;
57 | }
58 |
59 | // -----------------------------------------------
60 | void Parameter::storeValue() {
61 | // CustomHTLM does not store to NVS. No need to store it...
62 | if(getID() != nullptr) {
63 | if(preferences.getString(WiFiManagerParameter::getID(),"") != WiFiManagerParameter::_value) {
64 | preferences.putString(WiFiManagerParameter::getID(), getValue());
65 | }
66 | }
67 | }
68 |
69 | // -----------------------------------------------
70 | void Parameter::setValue(const char *value) {
71 | if(_initialized) {
72 | preferences.putString(WiFiManagerParameter::getID(), value);
73 | }
74 | WiFiManagerParameter::setValue(value);
75 | }
76 |
--------------------------------------------------------------------------------