Using HTTPS protocol for ESP32 web server, and implemented POST /api/info handler
This commit is contained in:
parent
ee531c7ffe
commit
6c40ba4e1f
@ -15,7 +15,7 @@
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration artifactName="ESP32" buildProperties="" description="" id="0.910961921" name="Default" parent="org.eclipse.cdt.build.core.prefbase.cfg">
|
||||
<configuration artifactName="ESP32" buildProperties="" description="" id="0.910961921" name="Default" optionalBuildProperties="" parent="org.eclipse.cdt.build.core.prefbase.cfg">
|
||||
<folderInfo id="0.910961921." name="/" resourcePath="">
|
||||
<toolChain id="org.eclipse.cdt.build.core.prefbase.toolchain.952979152" name="No ToolChain" resourceTypeBasedDiscovery="false" superClass="org.eclipse.cdt.build.core.prefbase.toolchain">
|
||||
<targetPlatform binaryParser="org.eclipse.cdt.core.ELF" id="org.eclipse.cdt.build.core.prefbase.toolchain.952979152.52310970" name=""/>
|
||||
@ -232,6 +232,9 @@
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/ESP32/src}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/ESP32/lib/AsyncTCP/src}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/ESP32/lib/DigitalPressureSensor/src}""/>
|
||||
<listOptionValue builtIn="false" value=""${HOME}/.platformio/packages/toolchain-xtensa-esp32/xtensa-esp32-elf/include/c++/8.4.0""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/ESP32/.pio/libdeps/nodemcu-32s/esp32_https_server/src}""/>
|
||||
<listOptionValue builtIn="false" value=""${HOME}/.platformio/packages/toolchain-xtensa-esp32/xtensa-esp32-elf/include""/>
|
||||
</option>
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="org.eclipse.cdt.build.core.settings.holder.symbols.1198905600" name="Symbols" superClass="org.eclipse.cdt.build.core.settings.holder.symbols" valueType="definedSymbols">
|
||||
<listOptionValue builtIn="false" value="PLATFORMIO=50205"/>
|
||||
|
9
ESP32/src/Info.h
Normal file
9
ESP32/src/Info.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
struct Info
|
||||
{
|
||||
char realtime[32] = {0}; // UTC date and time, in format YYYY-MM-DDTHH:mm:ss.sssZ
|
||||
float latitude = -1000.0f; // in decimal degrees
|
||||
float longitude = -1000.0f; // in decimal degrees
|
||||
float gpsAltitude = -1000.0f; // in meters, above sea level
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <stdint.h>
|
||||
|
||||
struct Status
|
||||
{
|
||||
|
@ -2,16 +2,23 @@
|
||||
|
||||
#include "DebugLog.h"
|
||||
#include "DataLogger.h"
|
||||
#include "Info.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <SPIFFS.h>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
||||
#include "HTTPServer.hpp"
|
||||
#include "HTTPSServer.hpp"
|
||||
#include "SSLCert.hpp"
|
||||
#include "HTTPRequest.hpp"
|
||||
#include "HTTPResponse.hpp"
|
||||
|
||||
// generated certificate data
|
||||
#include "cert.h"
|
||||
#include "private_key.h"
|
||||
|
||||
/** Check if we have multiple cores */
|
||||
#if CONFIG_FREERTOS_UNICORE
|
||||
#define WEBSERVER_RUNNING_CORE 0
|
||||
@ -25,7 +32,13 @@ detail::WebServer WebServer;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
HTTPServer httpServer;
|
||||
// Create an SSL certificate object from the files included above
|
||||
SSLCert cert = SSLCert(
|
||||
crt_DER, crt_DER_len,
|
||||
private_key_DER, private_key_DER_len
|
||||
);
|
||||
|
||||
HTTPSServer httpServer = HTTPSServer(&cert);
|
||||
|
||||
WebServer::WebServer()
|
||||
{
|
||||
@ -121,7 +134,76 @@ namespace detail
|
||||
|
||||
void WebServer::HandlePostInfo_(httpsserver::HTTPRequest * request, httpsserver::HTTPResponse * response)
|
||||
{
|
||||
char body[128]; // in current implementation, we expect the whole body to fit here
|
||||
size_t bodySize = request->readChars(body, sizeof(body) - 1);
|
||||
body[bodySize] = 0;
|
||||
|
||||
request->discardRequestBody();
|
||||
|
||||
//::DebugLog.println(body.c_str());
|
||||
|
||||
Info receivedInfo;
|
||||
|
||||
char* nextParam = body;
|
||||
while (true)
|
||||
{
|
||||
char* sepPos = strstr(nextParam, "&");
|
||||
if(sepPos == nullptr) sepPos = &body[bodySize];
|
||||
if(nextParam == sepPos)
|
||||
break; // should happen only if body is an empty string or ends with an "&" character
|
||||
|
||||
*sepPos = 0; // split the string in-place, this overrides the separating character which is fine
|
||||
//::DebugLog.println(nextParam);
|
||||
|
||||
char* eqPos = strstr(nextParam, "=");
|
||||
if(eqPos != nullptr && eqPos != nextParam && *(eqPos+1) != 0)
|
||||
{
|
||||
*eqPos = 0; // split the string in-place, overriding the equal sign
|
||||
|
||||
char* paramName = nextParam;
|
||||
char* paramValue = eqPos + 1;
|
||||
utils::replaceString(paramValue, "%3A", ":");
|
||||
//::DebugLog.print(paramName); ::DebugLog.print(" = "); ::DebugLog.println(paramValue);
|
||||
|
||||
if(strcmp(paramName, "lat") == 0)
|
||||
{
|
||||
char *ending = nullptr;
|
||||
receivedInfo.latitude = strtof(paramValue, &ending);
|
||||
if (*ending != 0)
|
||||
receivedInfo.latitude = -1000.0f;
|
||||
|
||||
}
|
||||
else if(strcmp(paramName, "lng") == 0)
|
||||
{
|
||||
char *ending = nullptr;
|
||||
receivedInfo.longitude = strtof(paramValue, &ending);
|
||||
if (*ending != 0)
|
||||
receivedInfo.longitude = -1000.0f;
|
||||
|
||||
}
|
||||
else if(strcmp(paramName, "alt") == 0)
|
||||
{
|
||||
char *ending = nullptr;
|
||||
receivedInfo.gpsAltitude = strtof(paramValue, &ending);
|
||||
if (*ending != 0)
|
||||
receivedInfo.gpsAltitude = -1000.0f;
|
||||
|
||||
}
|
||||
else if(strcmp(paramName, "time") == 0)
|
||||
{
|
||||
strncpy(receivedInfo.realtime, paramValue, sizeof(receivedInfo.realtime));
|
||||
}
|
||||
}
|
||||
|
||||
if(sepPos == &body[bodySize])
|
||||
break;
|
||||
nextParam = sepPos + 1;
|
||||
}
|
||||
|
||||
if(::WebServer.infoReceived_ != nullptr)
|
||||
{
|
||||
::WebServer.infoReceived_(receivedInfo);
|
||||
}
|
||||
}
|
||||
|
||||
void WebServer::HandleDefault_(HTTPRequest * request, HTTPResponse * response)
|
||||
@ -165,7 +247,7 @@ namespace detail
|
||||
|
||||
void WebServer::SendContent_(Stream& stream, httpsserver::HTTPResponse * response)
|
||||
{
|
||||
uint8_t buffer[512];
|
||||
uint8_t buffer[128];
|
||||
while(stream.available())
|
||||
{
|
||||
size_t numBytes = stream.readBytes(buffer, sizeof(buffer));
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "Status.h"
|
||||
|
||||
class Stream;
|
||||
struct Info;
|
||||
|
||||
namespace httpsserver
|
||||
{
|
||||
@ -14,6 +15,9 @@ namespace detail
|
||||
{
|
||||
class WebServer
|
||||
{
|
||||
public:
|
||||
typedef void (*InfoReceived)(const Info& info);
|
||||
|
||||
public:
|
||||
WebServer();
|
||||
~WebServer();
|
||||
@ -22,6 +26,8 @@ namespace detail
|
||||
|
||||
void setStatus(const Status& status);
|
||||
|
||||
void setInfoReceivedCallback(InfoReceived infoReceived) { infoReceived_ = infoReceived; }
|
||||
|
||||
private:
|
||||
static void ServerTask_(void* params);
|
||||
static void HandleIndex_(httpsserver::HTTPRequest * request, httpsserver::HTTPResponse * response);
|
||||
@ -33,6 +39,7 @@ namespace detail
|
||||
|
||||
private:
|
||||
Status status_;
|
||||
InfoReceived infoReceived_ = nullptr;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -33,4 +33,33 @@ namespace utils
|
||||
return (biggestValue - from) + to + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void replaceString(char* str, char* searchStr, char* replacementStr)
|
||||
{
|
||||
size_t searchStrLen = strlen(searchStr);
|
||||
size_t replacementStrLen = strlen(replacementStr);
|
||||
|
||||
char* newPos = str;
|
||||
char* nextSearchPos = str;
|
||||
while(true)
|
||||
{
|
||||
char* p = strstr(nextSearchPos, searchStr);
|
||||
if(p == nullptr) p = nextSearchPos + strlen(nextSearchPos);
|
||||
|
||||
size_t l = p - nextSearchPos;
|
||||
if(newPos != nextSearchPos)
|
||||
{
|
||||
memcpy(newPos, nextSearchPos, l);
|
||||
}
|
||||
newPos += l;
|
||||
|
||||
if(*p == 0)
|
||||
break;
|
||||
|
||||
memcpy(newPos, replacementStr, replacementStrLen);
|
||||
newPos += replacementStrLen;
|
||||
|
||||
nextSearchPos = p + searchStrLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,7 @@
|
||||
namespace utils
|
||||
{
|
||||
unsigned long elapsed(unsigned long from, unsigned long to);
|
||||
|
||||
//! Replace all occurences of searchStr by remplacementStr, in-place within input str. This function can only be used if replacementStr is shorter or the same size as searchStr.
|
||||
void replaceString(char* str, char* searchStr, char* replacementStr);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "DataLogger.h"
|
||||
#include "WebServer.h"
|
||||
#include "Status.h"
|
||||
#include "Info.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <WiFi.h>
|
||||
@ -151,6 +152,14 @@ void connectWifi()
|
||||
}
|
||||
}
|
||||
|
||||
void onInfoReceived(const Info& info)
|
||||
{
|
||||
if(info.latitude > -900.0f) status.latitude = info.latitude;
|
||||
if(info.longitude > -900.0f) status.longitude = info.longitude;
|
||||
if(info.gpsAltitude > -900.0f) status.gpsAltitude = info.gpsAltitude;
|
||||
if(info.realtime[0] != 0) strncpy(status.realtime, info.realtime, sizeof(status.realtime));
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
pinMode(debugLedPin, OUTPUT);
|
||||
@ -198,6 +207,7 @@ void setup()
|
||||
|
||||
//currentSensor2.begin(0x48, &Wire);
|
||||
|
||||
WebServer.setInfoReceivedCallback(onInfoReceived);
|
||||
WebServer.begin();
|
||||
|
||||
/*server.on("/api/debug/log", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
|
@ -50,6 +50,7 @@ export class MonitorApi {
|
||||
private mockServer: boolean;
|
||||
private lastStatus: Status = null;
|
||||
private lastKnownPosition: GeolocationPosition = null;
|
||||
private watchingPosition: boolean = false;
|
||||
private static api: MonitorApi = null;
|
||||
|
||||
private lastFetchTime = 0;
|
||||
@ -74,18 +75,19 @@ export class MonitorApi {
|
||||
getStatus() { return this.lastStatus; }
|
||||
|
||||
async autoUpdateInfo(): Promise<void> {
|
||||
if (navigator.geolocation) {
|
||||
if (!this.watchingPosition && navigator.geolocation) {
|
||||
let updatePosition = (position: GeolocationPosition) => {
|
||||
this.lastKnownPosition = position;
|
||||
};
|
||||
|
||||
const options = {
|
||||
enableHighAccuracy: true,
|
||||
timeout: 6000,
|
||||
maximumAge: 3000,
|
||||
timeout: 10000,
|
||||
maximumAge: 5000,
|
||||
};
|
||||
|
||||
navigator.geolocation.getCurrentPosition(updatePosition, () => updatePosition(null), options);
|
||||
navigator.geolocation.watchPosition(updatePosition, () => updatePosition(null), options);
|
||||
this.watchingPosition = true;
|
||||
}
|
||||
|
||||
const defaultPosition : GeolocationPosition = {
|
||||
|
Loading…
Reference in New Issue
Block a user