mirror of
https://github.com/meshtastic/firmware.git
synced 2025-04-26 09:59:01 +00:00
API Server and DHCP Lease Management
This commit is contained in:
parent
6e1b1e3ed7
commit
b7ebe03ca8
@ -33,8 +33,7 @@ lib_deps =
|
|||||||
${environmental_base.lib_deps}
|
${environmental_base.lib_deps}
|
||||||
https://github.com/meshtastic/esp32_https_server.git#657509856ce97e9dddeffb89a559f544faefd5cd
|
https://github.com/meshtastic/esp32_https_server.git#657509856ce97e9dddeffb89a559f544faefd5cd
|
||||||
h2zero/NimBLE-Arduino@^1.4.0
|
h2zero/NimBLE-Arduino@^1.4.0
|
||||||
arduino-libraries/NTPClient@^3.1.0
|
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
|
||||||
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
|
|
||||||
|
|
||||||
lib_ignore =
|
lib_ignore =
|
||||||
segger_rtt
|
segger_rtt
|
||||||
|
@ -33,7 +33,6 @@ lib_deps =
|
|||||||
${environmental_base.lib_deps}
|
${environmental_base.lib_deps}
|
||||||
https://github.com/meshtastic/esp32_https_server.git#657509856ce97e9dddeffb89a559f544faefd5cd
|
https://github.com/meshtastic/esp32_https_server.git#657509856ce97e9dddeffb89a559f544faefd5cd
|
||||||
h2zero/NimBLE-Arduino@^1.4.0
|
h2zero/NimBLE-Arduino@^1.4.0
|
||||||
arduino-libraries/NTPClient@^3.1.0
|
|
||||||
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
|
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
|
||||||
|
|
||||||
lib_ignore =
|
lib_ignore =
|
||||||
|
@ -79,6 +79,7 @@ build_src_filter = ${env.build_src_filter} -<platform/portduino/>
|
|||||||
[networking_base]
|
[networking_base]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
knolleary/PubSubClient@^2.8
|
knolleary/PubSubClient@^2.8
|
||||||
|
arduino-libraries/NTPClient@^3.1.0
|
||||||
meshtastic/json11@^1.0.2
|
meshtastic/json11@^1.0.2
|
||||||
|
|
||||||
; Common libs for environmental measurements in telemetry module
|
; Common libs for environmental measurements in telemetry module
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAS_ETHERNET
|
#if HAS_ETHERNET
|
||||||
|
#include "mesh/eth/ethServerAPI.h"
|
||||||
#include "mqtt/MQTT.h"
|
#include "mqtt/MQTT.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1,15 +1,98 @@
|
|||||||
#include "mesh/eth/ethClient.h"
|
#include "mesh/eth/ethClient.h"
|
||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
|
#include "RTC.h"
|
||||||
|
#include "concurrency/Periodic.h"
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include <RAK13800_W5100S.h>
|
#include <RAK13800_W5100S.h>
|
||||||
#include "target_specific.h"
|
#include "target_specific.h"
|
||||||
|
#include "mesh/eth/ethServerAPI.h"
|
||||||
|
#include "mqtt/MQTT.h"
|
||||||
|
|
||||||
|
#ifndef DISABLE_NTP
|
||||||
|
#include <NTPClient.h>
|
||||||
|
|
||||||
|
// NTP
|
||||||
|
EthernetUDP ntpUDP;
|
||||||
|
|
||||||
|
NTPClient timeClient(ntpUDP, config.network.ntp_server);
|
||||||
|
|
||||||
|
uint32_t ntp_renew = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Stores our hostname
|
||||||
|
char ourHost[16];
|
||||||
|
|
||||||
|
bool ethStartupComplete = 0;
|
||||||
|
|
||||||
|
using namespace concurrency;
|
||||||
|
|
||||||
|
static Periodic *ethEvent;
|
||||||
|
|
||||||
|
static int32_t reconnectETH()
|
||||||
|
{
|
||||||
|
if (config.network.eth_enabled) {
|
||||||
|
Ethernet.maintain();
|
||||||
|
if (!ethStartupComplete) {
|
||||||
|
// Start web server
|
||||||
|
DEBUG_MSG("... Starting network services\n");
|
||||||
|
|
||||||
|
// // start mdns
|
||||||
|
// if (!MDNS.begin("Meshtastic")) {
|
||||||
|
// DEBUG_MSG("Error setting up MDNS responder!\n");
|
||||||
|
// } else {
|
||||||
|
// DEBUG_MSG("mDNS responder started\n");
|
||||||
|
// DEBUG_MSG("mDNS Host: Meshtastic.local\n");
|
||||||
|
// MDNS.addService("http", "tcp", 80);
|
||||||
|
// MDNS.addService("https", "tcp", 443);
|
||||||
|
// }
|
||||||
|
|
||||||
|
#ifndef DISABLE_NTP
|
||||||
|
DEBUG_MSG("Starting NTP time client\n");
|
||||||
|
timeClient.begin();
|
||||||
|
timeClient.setUpdateInterval(60 * 60); // Update once an hour
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// initWebServer();
|
||||||
|
initApiServer();
|
||||||
|
|
||||||
|
ethStartupComplete = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME this is kinda yucky, instead we should just have an observable for 'wifireconnected'
|
||||||
|
if (mqtt && !mqtt->connected()) {
|
||||||
|
mqtt->reconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef DISABLE_NTP
|
||||||
|
if (isEthernetAvailable() && (ntp_renew < millis())) {
|
||||||
|
DEBUG_MSG("Updating NTP time\n");
|
||||||
|
if (timeClient.update()) {
|
||||||
|
DEBUG_MSG("NTP Request Success - Setting RTCQualityNTP if needed\n");
|
||||||
|
|
||||||
|
struct timeval tv;
|
||||||
|
tv.tv_sec = timeClient.getEpochTime();
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
|
perhapsSetRTC(RTCQualityNTP, &tv);
|
||||||
|
|
||||||
|
ntp_renew = millis() + 43200 * 1000; // every 12 hours
|
||||||
|
|
||||||
|
} else {
|
||||||
|
DEBUG_MSG("NTP Update failed\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 5000; // every 5 seconds
|
||||||
|
}
|
||||||
|
|
||||||
// Startup Ethernet
|
// Startup Ethernet
|
||||||
bool initEthernet()
|
bool initEthernet()
|
||||||
{
|
{
|
||||||
|
|
||||||
config.network.eth_enabled = true;
|
// config.network.eth_enabled = true;
|
||||||
config.network.eth_mode = Config_NetworkConfig_EthMode_DHCP;
|
// config.network.eth_mode = Config_NetworkConfig_EthMode_DHCP;
|
||||||
|
|
||||||
if (config.network.eth_enabled) {
|
if (config.network.eth_enabled) {
|
||||||
|
|
||||||
@ -26,6 +109,8 @@ bool initEthernet()
|
|||||||
|
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
|
// createSSLCert();
|
||||||
|
|
||||||
getMacAddr(mac); // FIXME use the BLE MAC for now...
|
getMacAddr(mac); // FIXME use the BLE MAC for now...
|
||||||
|
|
||||||
if (config.network.eth_mode == Config_NetworkConfig_EthMode_DHCP) {
|
if (config.network.eth_mode == Config_NetworkConfig_EthMode_DHCP) {
|
||||||
@ -56,6 +141,9 @@ bool initEthernet()
|
|||||||
DEBUG_MSG("Gateway IP %u.%u.%u.%u\n",Ethernet.gatewayIP()[0], Ethernet.gatewayIP()[1], Ethernet.gatewayIP()[2], Ethernet.gatewayIP()[3]);
|
DEBUG_MSG("Gateway IP %u.%u.%u.%u\n",Ethernet.gatewayIP()[0], Ethernet.gatewayIP()[1], Ethernet.gatewayIP()[2], Ethernet.gatewayIP()[3]);
|
||||||
DEBUG_MSG("DNS Server IP %u.%u.%u.%u\n",Ethernet.dnsServerIP()[0], Ethernet.dnsServerIP()[1], Ethernet.dnsServerIP()[2], Ethernet.dnsServerIP()[3]);
|
DEBUG_MSG("DNS Server IP %u.%u.%u.%u\n",Ethernet.dnsServerIP()[0], Ethernet.dnsServerIP()[1], Ethernet.dnsServerIP()[2], Ethernet.dnsServerIP()[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ethEvent = new Periodic("ethConnect", reconnectETH);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
82
src/mesh/eth/ethServerAPI.cpp
Normal file
82
src/mesh/eth/ethServerAPI.cpp
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#include "ethServerAPI.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
static ethServerPort *apiPort;
|
||||||
|
|
||||||
|
void initApiServer(int port)
|
||||||
|
{
|
||||||
|
// Start API server on port 4403
|
||||||
|
if (!apiPort) {
|
||||||
|
apiPort = new ethServerPort(port);
|
||||||
|
DEBUG_MSG("API server listening on TCP port %d\n", port);
|
||||||
|
apiPort->init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ethServerAPI::ethServerAPI(EthernetClient &_client) : StreamAPI(&client), client(_client)
|
||||||
|
{
|
||||||
|
DEBUG_MSG("Incoming ethernet connection\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
ethServerAPI::~ethServerAPI()
|
||||||
|
{
|
||||||
|
client.stop();
|
||||||
|
|
||||||
|
// FIXME - delete this if the client dropps the connection!
|
||||||
|
}
|
||||||
|
|
||||||
|
/// override close to also shutdown the TCP link
|
||||||
|
void ethServerAPI::close()
|
||||||
|
{
|
||||||
|
client.stop(); // drop tcp connection
|
||||||
|
StreamAPI::close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check the current underlying physical link to see if the client is currently connected
|
||||||
|
bool ethServerAPI::checkIsConnected()
|
||||||
|
{
|
||||||
|
return client.connected();
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ethServerAPI::runOnce()
|
||||||
|
{
|
||||||
|
if (client.connected()) {
|
||||||
|
return StreamAPI::runOnce();
|
||||||
|
} else {
|
||||||
|
DEBUG_MSG("Client dropped connection, suspending API service\n");
|
||||||
|
enabled = false; // we no longer need to run
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If an api server is running, we try to spit out debug 'serial' characters there
|
||||||
|
void ethServerPort::debugOut(char c)
|
||||||
|
{
|
||||||
|
if (apiPort && apiPort->openAPI)
|
||||||
|
apiPort->openAPI->debugOut(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ethServerPort::ethServerPort(int port) : EthernetServer(port), concurrency::OSThread("ApiServer") {}
|
||||||
|
|
||||||
|
void ethServerPort::init()
|
||||||
|
{
|
||||||
|
begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ethServerPort::runOnce()
|
||||||
|
{
|
||||||
|
auto client = available();
|
||||||
|
if (client) {
|
||||||
|
// Close any previous connection (see FIXME in header file)
|
||||||
|
if (openAPI) {
|
||||||
|
DEBUG_MSG("Force closing previous TCP connection\n");
|
||||||
|
delete openAPI;
|
||||||
|
}
|
||||||
|
|
||||||
|
openAPI = new ethServerAPI(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 100; // only check occasionally for incoming connections
|
||||||
|
}
|
58
src/mesh/eth/ethServerAPI.h
Normal file
58
src/mesh/eth/ethServerAPI.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "StreamAPI.h"
|
||||||
|
#include <RAK13800_W5100S.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs
|
||||||
|
* (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs).
|
||||||
|
*/
|
||||||
|
class ethServerAPI : public StreamAPI
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
EthernetClient client;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ethServerAPI(EthernetClient &_client);
|
||||||
|
|
||||||
|
virtual ~ethServerAPI();
|
||||||
|
|
||||||
|
/// override close to also shutdown the TCP link
|
||||||
|
virtual void close();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// We override this method to prevent publishing EVENT_SERIAL_CONNECTED/DISCONNECTED for wifi links (we want the board to
|
||||||
|
/// stay in the POWERED state to prevent disabling wifi)
|
||||||
|
virtual void onConnectionChanged(bool connected) override {}
|
||||||
|
|
||||||
|
virtual int32_t runOnce() override; // Check for dropped client connections
|
||||||
|
|
||||||
|
/// Check the current underlying physical link to see if the client is currently connected
|
||||||
|
virtual bool checkIsConnected() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listens for incoming connections and does accepts and creates instances of WiFiServerAPI as needed
|
||||||
|
*/
|
||||||
|
class ethServerPort : public EthernetServer, private concurrency::OSThread
|
||||||
|
{
|
||||||
|
/** The currently open port
|
||||||
|
*
|
||||||
|
* FIXME: We currently only allow one open TCP connection at a time, because we depend on the loop() call in this class to
|
||||||
|
* delegate to the worker. Once coroutines are implemented we can relax this restriction.
|
||||||
|
*/
|
||||||
|
ethServerAPI *openAPI = NULL;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ethServerPort(int port);
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
|
/// If an api server is running, we try to spit out debug 'serial' characters there
|
||||||
|
static void debugOut(char c);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int32_t runOnce() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
void initApiServer(int port=4403);
|
@ -107,6 +107,11 @@ MQTT::MQTT() : concurrency::OSThread("mqtt"), pubSub(mqttClient)
|
|||||||
// preflightSleepObserver.observe(&preflightSleep);
|
// preflightSleepObserver.observe(&preflightSleep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MQTT::connected()
|
||||||
|
{
|
||||||
|
return pubSub.connected();
|
||||||
|
}
|
||||||
|
|
||||||
void MQTT::reconnect()
|
void MQTT::reconnect()
|
||||||
{
|
{
|
||||||
if (wantsLink()) {
|
if (wantsLink()) {
|
||||||
@ -197,6 +202,7 @@ bool MQTT::wantsLink() const
|
|||||||
#if HAS_ETHERNET
|
#if HAS_ETHERNET
|
||||||
return hasChannel && (Ethernet.linkStatus() == LinkON);
|
return hasChannel && (Ethernet.linkStatus() == LinkON);
|
||||||
#endif
|
#endif
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t MQTT::runOnce()
|
int32_t MQTT::runOnce()
|
||||||
|
@ -49,6 +49,8 @@ class MQTT : private concurrency::OSThread
|
|||||||
*/
|
*/
|
||||||
void reconnect();
|
void reconnect();
|
||||||
|
|
||||||
|
bool connected();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual int32_t runOnce() override;
|
virtual int32_t runOnce() override;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user