-
Notifications
You must be signed in to change notification settings - Fork 569
Allow definition of custom network interfaces #921
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
An open questions are:
I would also like to test it with a POC class that toggles between WiFi and TinyGSM, like that published by @Naheel-Azawy : ESP32GSMNetClient before marking this MR as ready. |
using the next free number is fine. not sure if setting some custom defines via compiler option will work, since will be intresting to see how you solve this. |
One option I found that compiles, but isn't pretty is the following. One thing that won't work is using defines to set include paths. Looking into 1-2 other approaches. lib/arduinoWebSockets/src/WebSockets.h
...
#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_CUSTOM)
#include <../../../src/CustomNetworkClient.h>
#else
#error "no network type selected!"
#endif
... src/CustomNetworkClient.h
#pragma once
#include <WiFi.h>
#include "managers/network_client.h"
#define SSL_AXTLS
#define WEBSOCKETS_NETWORK_CLASS inamata::NetworkClient
#define WEBSOCKETS_NETWORK_SSL_CLASS inamata::NetworkClient
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer src/managers/network_client.h
#pragma once
#include <Client.h>
#include <WiFiClient.h>
namespace inamata {
class NetworkClient : public Client {
public:
NetworkClient();
NetworkClient(WiFiClient wifi_client);
virtual ~NetworkClient() = default;
int connect(IPAddress ip, uint16_t port) final;
int connect(const char *host, uint16_t port) final;
int connect(const char *host, uint16_t port, int32_t timeout);
size_t write(uint8_t) final;
size_t write(const uint8_t *buf, size_t size) final;
size_t write(const char *str);
int available() final;
int read() final;
int read(uint8_t *buf, size_t size) final;
int peek() final;
void flush() final;
void stop() final;
uint8_t connected() final;
operator bool() final;
void setCACert(const char *rootCA);
void setCACertBundle(const uint8_t *bundle);
void setInsecure();
bool verify(const char *fingerprint, const char *domain_name);
};
} // namespace inamata |
A better approach is probably to use the PIMPL approach, an interface class that implements all methods that are called on WiFiClient and WiFiClientSecure and then implement those class methods in the application code. This should be more robust than the relative import Adding the following file is the minimum to implement stub interfaces in the app source code including the WebSockets library. To keep the WiFiClientSecure behavior, an instance of it can be saved in the NetworkClient::Impl class and then called via the implemented methods (connect(), write(), ...). To connect it to TinyGSM, create an instance of that class... #include <NetworkClient.h>
struct NetworkClient::Impl {
~Impl() = default;
int a;
bool b;
};
NetworkClient::NetworkClient() : _impl(new NetworkClient::Impl()) {}
NetworkClient::NetworkClient(WiFiClient wifi_client)
: _impl(new NetworkClient::Impl()) {}
NetworkClient::~NetworkClient() {}
int NetworkClient::connect(IPAddress ip, uint16_t port) { return 0; }
int NetworkClient::connect(const char *host, uint16_t port) { return 0; }
int NetworkClient::connect(const char *host, uint16_t port, int32_t timeout) {
return 0;
}
size_t NetworkClient::write(uint8_t) { return 0; }
size_t NetworkClient::write(const uint8_t *buf, size_t size) { return 0; }
size_t NetworkClient::write(const char *str) { return 0; }
int NetworkClient::available() { return 0; }
int NetworkClient::read() { return 0; }
int NetworkClient::read(uint8_t *buf, size_t size) { return 0; }
int NetworkClient::peek() { return 0; }
void NetworkClient::flush() {}
void NetworkClient::stop() {}
uint8_t NetworkClient::connected() { return 0; }
NetworkClient::operator bool() { return 0; }
void NetworkClient::setCACert(const char *rootCA) {}
void NetworkClient::setCACertBundle(const uint8_t *bundle) {}
void NetworkClient::setInsecure() {}
bool NetworkClient::verify(const char *fingerprint, const char *domain_name) {
return false;
} I still have to test it with a complete implementation, but it compiles and should allow enough flexibility to implement IO with both WiFi and a mobile modem (or even also Ethernet). |
Here is a VS Code / PlatformIO example project that uses the PIMPL approach. I tried compiling it with Arduino IDE but it failed as it takes the class method implementations and creates duplicate definitions for the NetworkClient class. Also tried using a separate cpp file to implement the NetworkClient class, but that also failed. I would argue that using a custom network interface is quite advanced anyway, so primarily targeting VS Code / PlatformIO users shouldn't be the biggest deal breaker. |
Why: - Show users how to use multiple network interfaces This change addresses the need by: - Adding an example PIO project to use Wi-Fi and GSM/LTE
@Links2004 I've update the MR to include an example project. The implementation is currently being used in a production unit (ergo tested a bit) and I thought I'd back port the changes for general use. If you find the changes useful, would be glad to work and get this merged, but I also understand that this might be a bit more niche of a use case. |
I just had a look at upgrading to Arduino 3.2.1 and IDF 5.4.2 via pioarduino and found out that they included a library called NetworkClient. As no one is using namespaces, this collided and thus it would be sensible to rename the NetworkClient class to something else like CustomNetworkClient, GenericNetworkClient or AbstractNetworkClient. |
sounds good, I like the Idea of having a way for users to there own network interface / stack. |
Two open questions are, what do we name the class and do you have an idea why the UNO R4 fails to compile? |
since the @kakopappa can you take a look at the arduino:renesas_uno:unor4wifi fails? the log does not make sense to me, I only see warnings no errors. |
` /home/runner/Arduino/libraries/arduinoWebSockets/src/WebSocketsClient.cpp: In member function 'virtual void WebSocketsClient::clientDisconnect(WSclient_t*)': Just saw this in the log, bit hard to see it |
thanks for looking, they must have implemented some lazy loading on the log page. |
Why:
This change addresses the need by:
Related issues: #779 #910