forked from DatanoiseTV/esp-find3-client
-
Notifications
You must be signed in to change notification settings - Fork 0
/
esp-find3-client.ino
310 lines (256 loc) · 9.4 KB
/
esp-find3-client.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
/*
This file is part of esp-find3-client by Sylwester aka DatanoiseTV.
The original source can be found at https://github.com/DatanoiseTV/esp-find3-client.
26/04/2020: Adjustements by Wizardry and Steamworks.
esp-find3-client is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
esp-find3-client is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with esp-find3-client. If not, see <http://www.gnu.org/licenses/>.
*/
///////////////////////////////////////////////////////////////////////////
// CONFIGURATION //
///////////////////////////////////////////////////////////////////////////
// Set to the WiFi AP name.
#define WIFI_SSID ""
// Set to the WiFi AP password.
#define WIFI_PSK ""
// Set to 1 for learning mode.
#define MODE_LEARNING 0
#define LOCATION ""
// Family name.
#define FAMILY_NAME ""
// BLE requires large app partition or the sketch will not fit.
// Please pick either of:
// * Tools -> Partition scheme -> Minimal SPIFFS (1.9MB APP / 190KB SPIFFS)
// * Tools -> Partition scheme -> Huge App (3MB No OTA / 1MB SPIFFS)
// Set to 1 to enable BLE.
#define USE_BLE 0
#define BLE_SCANTIME 5
// Set to 1 for power saving. This will make it run less often.
#define USE_DEEPSLEEP 0
// 20 currently results in an interval of 45s
#define TIME_TO_SLEEP 20 /* Time ESP32 will go to sleep (in seconds) */
// Official server: cloud.internalpositioning.com
#define FIND_HOST "cloud.internalpositioning.com"
// Official port: 443 and SSL set to 1
#define FIND_PORT 443
// Whether to use SSL for the HTTP connection.
// Set to 1 for official cloud server.
#define USE_HTTP_SSL 1
// Timeout connecting to find3 server expressed in milliseconds.
#define HTTP_TIMEOUT 2500
// The NTP server to use for time updates.
#define NTP_HOST "pool.ntp.org"
// The offset in seconds from UTC, ie: 3600 for +1 Hour.
#define UTC_OFFSET 0
// Set to 1 to enable. Used for verbose debugging.
#define DEBUG 0
///////////////////////////////////////////////////////////////////////////
// INTERNALS //
///////////////////////////////////////////////////////////////////////////
#ifdef ARDUINO_ARCH_ESP32
#include <WiFiClientSecure.h>
#include <WiFi.h>
#include <WiFiMulti.h>
WiFiMulti wifiMulti;
#else
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <time.h>
ESP8266WiFiMulti wifiMulti;
#endif
#include <WiFiUdp.h>
#include <NTPClient.h>
#if defined(ARDUINO_ARCH_ESP8266)
#define GET_CHIP_ID() String(ESP.getChipId(), HEX)
#elif defined(ARDUINO_ARCH_ESP32)
#define GET_CHIP_ID() String(((uint16_t)(ESP.getEfuseMac()>>32)), HEX)
#endif
#define uS_TO_S_FACTOR 1000000 /* Conversion factor for micro seconds to seconds */
#define ARDUINOJSON_USE_LONG_LONG 1
#include <ArduinoJson.h>
// Automagically disable BLE on ESP8266
#if defined(ARDUINO_ARCH_ESP8266)
#define USE_BLE 0
#endif
#if (USE_BLE == 1)
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
// Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
}
};
#endif
#ifdef ARDUINO_ARCH_ESP32
RTC_DATA_ATTR int bootCount = 0;
#endif
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, NTP_HOST, UTC_OFFSET, 60000);
/*
Method to print the reason by which ESP32
has been awaken from sleep
*/
void print_wakeup_reason() {
#ifdef ARDUINO_ARCH_ESP32
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
++bootCount;
Serial.println("[ INFO ]\tBoot number: " + String(bootCount));
switch (wakeup_reason)
{
case 1 : Serial.println("[ INFO ]\tWakeup caused by external signal using RTC_IO"); break;
case 2 : Serial.println("[ INFO ]\tWakeup caused by external signal using RTC_CNTL"); break;
case 3 : Serial.println("[ INFO ]\tWakeup caused by timer"); break;
case 4 : Serial.println("[ INFO ]\tWakeup caused by touchpad"); break;
case 5 : Serial.println("[ INFO ]\tWakeup caused by ULP program"); break;
default : Serial.println("[ INFO ]\tWakeup was not caused by deep sleep"); break;
}
#endif
}
void SubmitWiFi(void)
{
String request;
StaticJsonDocument<256> jsonBuffer;
JsonObject root = jsonBuffer.to<JsonObject>();
root["d"] = "esp-" + GET_CHIP_ID();
root["f"] = FAMILY_NAME;
root["t"] = timeClient.getEpochTime();
JsonObject data = root.createNestedObject("s");
Serial.println("[ INFO ]\tWiFi scan starting..");
int n = WiFi.scanNetworks(false, true);
Serial.println("[ INFO ]\tWiFi Scan finished.");
if (n == 0) {
Serial.println("[ ERROR ]\tNo networks found");
} else {
Serial.print("[ INFO ]\t");
Serial.print(n);
Serial.println(" WiFi networks found.");
JsonObject wifi_network = data.createNestedObject("wifi");
for (int i = 0; i < n; ++i) {
wifi_network[WiFi.BSSIDstr(i)] = WiFi.RSSI(i);
}
#if (USE_BLE == 1)
Serial.println("[ INFO ]\tBLE scan starting..");
BLEDevice::init("");
BLEScan* pBLEScan = BLEDevice::getScan(); // create new scan
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true); // active scan uses more power, but get results faster
BLEScanResults foundDevices = pBLEScan->start(BLE_SCANTIME);
Serial.print("[ INFO ]\t");
Serial.print(foundDevices.getCount());
Serial.println(" BLE devices found.");
JsonObject bt_network = data.createNestedObject("bluetooth");
for (int i = 0; i < foundDevices.getCount(); i++)
{
std::string mac = foundDevices.getDevice(i).getAddress().toString();
bt_network[(String)mac.c_str()] = (int)foundDevices.getDevice(i).getRSSI();
}
#else
Serial.println("[ INFO ]\tBLE scan skipped (BLE disabled)..");
#endif // USE_BLE
#if (MODE_LEARNING == 1)
root["l"] = LOCATION;
#endif
serializeJson(root, request);
#if (DEBUG == 1)
Serial.println("[ DEBUG ]\t" + request);
#endif
#if (USE_HTTP_SSL == 1)
WiFiClientSecure client;
#else
WiFiClient client;
#endif
if (!client.connect(FIND_HOST, FIND_PORT)) {
Serial.println("[ WARN ]\tConnection to server failed...");
return;
}
// We now create a URI for the request
String url = "/data";
Serial.print("[ INFO ]\tRequesting URL: ");
Serial.println(url);
// This will send the request to the server
client.print(String("POST ") + url + " HTTP/1.1\r\n" +
"Host: " + FIND_HOST + "\r\n" +
"Content-Type: application/json\r\n" +
"Content-Length: " + request.length() + "\r\n\r\n" +
request +
"\r\n\r\n"
);
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > HTTP_TIMEOUT) {
Serial.println("[ ERROR ]\tHTTP Client Timeout !");
client.stop();
return;
}
}
// Check HTTP status
char status[60] = {0};
client.readBytesUntil('\r', status, sizeof(status));
if (strcmp(status, "HTTP/1.1 200 OK") != 0) {
Serial.print(F("[ ERROR ]\tUnexpected Response: "));
Serial.println(status);
return;
}
else
{
Serial.println(F("[ INFO ]\tGot a 200 OK."));
}
char endOfHeaders[] = "\r\n\r\n";
if (!client.find(endOfHeaders)) {
Serial.println(F("[ ERROR ]\t Invalid Response"));
return;
}
else
{
Serial.println("[ INFO ]\tLooks like a valid response.");
}
Serial.println("[ INFO ]\tClosing connection.");
Serial.println("=============================================================");
#if (USE_DEEPSLEEP == 1)
#if defined(ARDUINO_ARCH_ESP8266)
ESP.deepSleep(TIME_TO_SLEEP * uS_TO_S_FACTOR);
#elif defined(ARDUINO_ARCH_ESP32)
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
esp_deep_sleep_start();
#endif
#endif
}
}
void setup() {
Serial.begin(115200);
delay(1000);
#if (USE_BLE == 1)
Serial.println("Find3 ESP client by DatanoiseTV (WiFi + BLE support.)");
#else
Serial.println("Find3 ESP client by DatanoiseTV (WiFi support WITHOUT BLE.)");
#endif
print_wakeup_reason();
Serial.print("[ INFO ]\tChipID is: ");
Serial.println("esp-" + GET_CHIP_ID());
wifiMulti.addAP(WIFI_SSID, WIFI_PSK);
Serial.println("[ INFO ]\tConnecting to WiFi..");
if (wifiMulti.run() == WL_CONNECTED) {
Serial.println("[ INFO ]\tWiFi connection established.");
Serial.print("[ INFO ]\tIP address: ");
Serial.println(WiFi.localIP());
}
timeClient.begin();
}
void loop() {
if (wifiMulti.run() != WL_CONNECTED) {
Serial.println("[ WARN ]\tWiFi not connected, retrying...");
delay(1000);
return;
}
timeClient.update();
SubmitWiFi();
}