- make a template class for API Server

- Skip a lot of duplicate code
- add a hexDump output - might come in handy
- refactor directory names
- remove unused debugOut that was generating template errors
This commit is contained in:
Thomas Göttgens
2023-01-09 17:03:52 +01:00
parent 49172e416e
commit 5fd00b2538
20 changed files with 230 additions and 251 deletions

View File

@@ -0,0 +1,67 @@
#include "ServerAPI.h"
#include "configuration.h"
#include <Arduino.h>
template<typename T>
ServerAPI<T>::ServerAPI(T &_client) : StreamAPI(&client), concurrency::OSThread("ServerAPI"), client(_client)
{
LOG_INFO("Incoming wifi connection\n");
}
template<typename T>
ServerAPI<T>::~ServerAPI()
{
client.stop();
}
template<typename T>
void ServerAPI<T>::close()
{
client.stop(); // drop tcp connection
StreamAPI::close();
}
/// Check the current underlying physical link to see if the client is currently connected
template<typename T>
bool ServerAPI<T>::checkIsConnected()
{
return client.connected();
}
template<class T>
int32_t ServerAPI<T>::runOnce()
{
if (client.connected()) {
return StreamAPI::runOncePart();
} else {
LOG_INFO("Client dropped connection, suspending API service\n");
enabled = false; // we no longer need to run
return 0;
}
}
template<class T, class U>
APIServerPort<T, U>::APIServerPort(int port) : U(port), concurrency::OSThread("ApiServer") {}
template<class T, class U>
void APIServerPort<T, U>::init()
{
U::begin();
}
template<class T, class U>
int32_t APIServerPort<T, U>::runOnce()
{
auto client = U::available();
if (client) {
// Close any previous connection (see FIXME in header file)
if (openAPI) {
LOG_INFO("Force closing previous TCP connection\n");
delete openAPI;
}
openAPI = new T(client);
}
return 100; // only check occasionally for incoming connections
}

54
src/mesh/api/ServerAPI.h Normal file
View File

@@ -0,0 +1,54 @@
#pragma once
#include "StreamAPI.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).
*/
template<class T>
class ServerAPI : public StreamAPI, private concurrency::OSThread
{
private:
T client;
public:
explicit ServerAPI(T &_client);
virtual ~ServerAPI();
/// 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
*/
template<class T, class U>
class APIServerPort : public U, 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.
*/
T *openAPI = NULL;
public:
explicit APIServerPort(int port);
void init();
protected:
int32_t runOnce() override;
};

View File

@@ -0,0 +1,25 @@
#include "configuration.h"
#include <Arduino.h>
#if HAS_WIFI
#include "WiFiServerAPI.h"
static WiFiServerPort *apiPort;
void initApiServer(int port)
{
// Start API server on port 4403
if (!apiPort) {
apiPort = new WiFiServerPort(port);
LOG_INFO("API server listening on TCP port %d\n", port);
apiPort->init();
}
}
WiFiServerAPI::WiFiServerAPI(WiFiClient &_client) : ServerAPI(_client)
{
LOG_INFO("Incoming wifi connection\n");
}
WiFiServerPort::WiFiServerPort(int port) : APIServerPort(port) {}
#endif

View File

@@ -0,0 +1,25 @@
#pragma once
#include "ServerAPI.h"
#include <WiFi.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 WiFiServerAPI : public ServerAPI<WiFiClient>
{
public:
explicit WiFiServerAPI(WiFiClient &_client);
};
/**
* Listens for incoming connections and does accepts and creates instances of WiFiServerAPI as needed
*/
class WiFiServerPort : public APIServerPort<WiFiServerAPI, WiFiServer>
{
public:
explicit WiFiServerPort(int port);
};
void initApiServer(int port=4403);

View File

@@ -0,0 +1,27 @@
#include "configuration.h"
#include <Arduino.h>
#if HAS_ETHERNET
#include "ethServerAPI.h"
static ethServerPort *apiPort;
void initApiServer(int port)
{
// Start API server on port 4403
if (!apiPort) {
apiPort = new ethServerPort(port);
LOG_INFO("API server listening on TCP port %d\n", port);
apiPort->init();
}
}
ethServerAPI::ethServerAPI(EthernetClient &_client) : ServerAPI(_client)
{
LOG_INFO("Incoming ethernet connection\n");
}
ethServerPort::ethServerPort(int port) : APIServerPort(port) {}
#endif

View File

@@ -0,0 +1,25 @@
#pragma once
#include "ServerAPI.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 ServerAPI<EthernetClient>
{
public:
explicit ethServerAPI(EthernetClient &_client);
};
/**
* Listens for incoming connections and does accepts and creates instances of WiFiServerAPI as needed
*/
class ethServerPort : public APIServerPort<ethServerAPI, EthernetServer>
{
public:
explicit ethServerPort(int port);
};
void initApiServer(int port=4403);