mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
fix standalone (use make run)
This commit is contained in:
@@ -37,6 +37,7 @@ static bool __output_pins[256];
|
|||||||
static int __output_level[256];
|
static int __output_level[256];
|
||||||
|
|
||||||
int main(int argc __attribute__((unused)), char * argv[] __attribute__((unused))) {
|
int main(int argc __attribute__((unused)), char * argv[] __attribute__((unused))) {
|
||||||
|
|
||||||
memset(__output_pins, 0, sizeof(__output_pins));
|
memset(__output_pins, 0, sizeof(__output_pins));
|
||||||
memset(__output_level, 0, sizeof(__output_level));
|
memset(__output_level, 0, sizeof(__output_level));
|
||||||
|
|
||||||
@@ -111,71 +112,3 @@ int digitalRead(uint8_t pin) {
|
|||||||
return LOW;
|
return LOW;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copy string src to buffer dst of size dsize. At most dsize-1
|
|
||||||
* chars will be copied. Always NUL terminates (unless dsize == 0).
|
|
||||||
* Returns strlen(src); if retval >= dsize, truncation occurred.
|
|
||||||
*
|
|
||||||
* https://github.com/freebsd/freebsd/blob/master/sys/libkern/strlcpy.c
|
|
||||||
*/
|
|
||||||
size_t strlcpy(char * __restrict dst, const char * __restrict src, size_t dsize) {
|
|
||||||
const char * osrc = src;
|
|
||||||
size_t nleft = dsize;
|
|
||||||
|
|
||||||
/* Copy as many bytes as will fit. */
|
|
||||||
if (nleft != 0) {
|
|
||||||
while (--nleft != 0) {
|
|
||||||
if ((*dst++ = *src++) == '\0')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Not enough room in dst, add NUL and traverse rest of src. */
|
|
||||||
if (nleft == 0) {
|
|
||||||
if (dsize != 0)
|
|
||||||
*dst = '\0'; /* NUL-terminate dst */
|
|
||||||
while (*src++)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (src - osrc - 1); /* count does not include NUL */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Appends src to string dst of size siz (unlike strncat, siz is the
|
|
||||||
* full size of dst, not space left). At most siz-1 characters
|
|
||||||
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
|
|
||||||
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
|
||||||
* If retval >= siz, truncation occurred.
|
|
||||||
*
|
|
||||||
* https://github.com/freebsd/freebsd/blob/master/sys/libkern/strlcat.c
|
|
||||||
*/
|
|
||||||
size_t strlcat(char * dst, const char * src, size_t siz) {
|
|
||||||
char * d = dst;
|
|
||||||
const char * s = src;
|
|
||||||
size_t n = siz;
|
|
||||||
size_t dlen;
|
|
||||||
|
|
||||||
/* Find the end of dst and adjust bytes left but don't go past end */
|
|
||||||
while (n-- != 0 && *d != '\0')
|
|
||||||
d++;
|
|
||||||
dlen = d - dst;
|
|
||||||
n = siz - dlen;
|
|
||||||
|
|
||||||
if (n == 0)
|
|
||||||
return (dlen + strlen(s));
|
|
||||||
while (*s != '\0') {
|
|
||||||
if (n != 1) {
|
|
||||||
*d++ = *s;
|
|
||||||
n--;
|
|
||||||
}
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
*d = '\0';
|
|
||||||
|
|
||||||
return (dlen + (s - src)); /* count does not include NUL */
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -136,34 +136,6 @@ class Stream : public Print {
|
|||||||
virtual int peek() = 0;
|
virtual int peek() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
class String {
|
|
||||||
public:
|
|
||||||
String(const char * data = "")
|
|
||||||
: data_(data) {
|
|
||||||
}
|
|
||||||
|
|
||||||
long toInt() const {
|
|
||||||
return std::stol(data_);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char * c_str() const {
|
|
||||||
return data_.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool equals(String comp) {
|
|
||||||
return (data_ == comp.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isEmpty() {
|
|
||||||
return data_.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string data_;
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
class NativeConsole : public Stream {
|
class NativeConsole : public Stream {
|
||||||
public:
|
public:
|
||||||
void begin(unsigned long baud __attribute__((unused))) {
|
void begin(unsigned long baud __attribute__((unused))) {
|
||||||
@@ -225,10 +197,6 @@ void yield(void);
|
|||||||
void setup(void);
|
void setup(void);
|
||||||
void loop(void);
|
void loop(void);
|
||||||
|
|
||||||
|
|
||||||
size_t strlcpy(char * __restrict dst, const char * __restrict src, size_t dsize);
|
|
||||||
size_t strlcat(char * dst, const char * src, size_t siz);
|
|
||||||
|
|
||||||
#include "WString.h"
|
#include "WString.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -26,14 +26,14 @@ struct AsyncMqttClientMessageProperties {
|
|||||||
|
|
||||||
|
|
||||||
namespace AsyncMqttClientInternals {
|
namespace AsyncMqttClientInternals {
|
||||||
// user callbacks
|
|
||||||
typedef std::function<void(bool sessionPresent)> OnConnectUserCallback;
|
typedef std::function<void(bool sessionPresent)> OnConnectUserCallback;
|
||||||
typedef std::function<void(AsyncMqttClientDisconnectReason reason)> OnDisconnectUserCallback;
|
typedef std::function<void(AsyncMqttClientDisconnectReason reason)> OnDisconnectUserCallback;
|
||||||
typedef std::function<void(uint16_t packetId, uint8_t qos)> OnSubscribeUserCallback;
|
typedef std::function<void(uint16_t packetId, uint8_t qos)> OnSubscribeUserCallback;
|
||||||
typedef std::function<void(uint16_t packetId)> OnUnsubscribeUserCallback;
|
typedef std::function<void(uint16_t packetId)> OnUnsubscribeUserCallback;
|
||||||
typedef std::function<void(char * topic, char * payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total)> OnMessageUserCallback;
|
typedef std::function<void(char * topic, char * payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total)> OnMessageUserCallback;
|
||||||
typedef std::function<void(uint16_t packetId)> OnPublishUserCallback;
|
typedef std::function<void(uint16_t packetId)> OnPublishUserCallback;
|
||||||
};
|
}; // namespace AsyncMqttClientInternals
|
||||||
|
|
||||||
class AsyncMqttClient {
|
class AsyncMqttClient {
|
||||||
public:
|
public:
|
||||||
@@ -45,29 +45,53 @@ class AsyncMqttClient {
|
|||||||
AsyncMqttClient & setCleanSession(bool cleanSession);
|
AsyncMqttClient & setCleanSession(bool cleanSession);
|
||||||
AsyncMqttClient & setMaxTopicLength(uint16_t maxTopicLength);
|
AsyncMqttClient & setMaxTopicLength(uint16_t maxTopicLength);
|
||||||
AsyncMqttClient & setCredentials(const char * username, const char * password = nullptr);
|
AsyncMqttClient & setCredentials(const char * username, const char * password = nullptr);
|
||||||
AsyncMqttClient& setWill(const char* topic, uint8_t qos, bool retain, const char* payload = nullptr, size_t length = 0) { return *this; }
|
AsyncMqttClient & setWill(const char * topic, uint8_t qos, bool retain, const char * payload = nullptr, size_t length = 0) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
AsyncMqttClient & setServer(IPAddress ip, uint16_t port);
|
AsyncMqttClient & setServer(IPAddress ip, uint16_t port);
|
||||||
AsyncMqttClient & setServer(const char * host, uint16_t port);
|
AsyncMqttClient & setServer(const char * host, uint16_t port);
|
||||||
|
|
||||||
AsyncMqttClient& onConnect(AsyncMqttClientInternals::OnConnectUserCallback callback) { return *this; }
|
AsyncMqttClient & onConnect(AsyncMqttClientInternals::OnConnectUserCallback callback) {
|
||||||
AsyncMqttClient& onDisconnect(AsyncMqttClientInternals::OnDisconnectUserCallback callback) { return *this; }
|
return *this;
|
||||||
AsyncMqttClient& onSubscribe(AsyncMqttClientInternals::OnSubscribeUserCallback callback) { return *this; }
|
}
|
||||||
AsyncMqttClient& onUnsubscribe(AsyncMqttClientInternals::OnUnsubscribeUserCallback callback) { return *this; }
|
AsyncMqttClient & onDisconnect(AsyncMqttClientInternals::OnDisconnectUserCallback callback) {
|
||||||
AsyncMqttClient& onMessage(AsyncMqttClientInternals::OnMessageUserCallback callback) { return *this; }
|
return *this;
|
||||||
AsyncMqttClient& onPublish(AsyncMqttClientInternals::OnPublishUserCallback callback) { return *this; }
|
}
|
||||||
|
AsyncMqttClient & onSubscribe(AsyncMqttClientInternals::OnSubscribeUserCallback callback) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
AsyncMqttClient & onUnsubscribe(AsyncMqttClientInternals::OnUnsubscribeUserCallback callback) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
AsyncMqttClient & onMessage(AsyncMqttClientInternals::OnMessageUserCallback callback) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
AsyncMqttClient & onPublish(AsyncMqttClientInternals::OnPublishUserCallback callback) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
bool connected() const { return false; }
|
bool connected() const {
|
||||||
void connect() {}
|
return false;
|
||||||
void disconnect(bool force = false) {}
|
}
|
||||||
uint16_t subscribe(const char* topic, uint8_t qos) {return 0;}
|
void connect() {
|
||||||
uint16_t unsubscribe(const char* topic) {return 0;}
|
}
|
||||||
uint16_t publish(const char* topic, uint8_t qos, bool retain, const char* payload = nullptr, size_t length = 0, bool dup = false, uint16_t message_id = 0) {return 0;}
|
void disconnect(bool force = false) {
|
||||||
|
}
|
||||||
|
uint16_t subscribe(const char * topic, uint8_t qos) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint16_t unsubscribe(const char * topic) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint16_t publish(const char * topic, uint8_t qos, bool retain, const char * payload = nullptr, size_t length = 0, bool dup = false, uint16_t message_id = 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
const char* getClientId() {return "12";}
|
const char * getClientId() {
|
||||||
|
return "12";
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// AsyncClient _client;
|
|
||||||
|
|
||||||
bool _connected;
|
bool _connected;
|
||||||
bool _connectPacketNotEnoughSpace;
|
bool _connectPacketNotEnoughSpace;
|
||||||
bool _disconnectOnPoll;
|
bool _disconnectOnPoll;
|
||||||
@@ -90,54 +114,6 @@ class AsyncMqttClient {
|
|||||||
uint16_t _willPayloadLength;
|
uint16_t _willPayloadLength;
|
||||||
uint8_t _willQos;
|
uint8_t _willQos;
|
||||||
bool _willRetain;
|
bool _willRetain;
|
||||||
|
|
||||||
// std::vector<AsyncMqttClientInternals::OnConnectUserCallback> _onConnectUserCallbacks;
|
|
||||||
// std::vector<AsyncMqttClientInternals::OnDisconnectUserCallback> _onDisconnectUserCallbacks;
|
|
||||||
// std::vector<AsyncMqttClientInternals::OnSubscribeUserCallback> _onSubscribeUserCallbacks;
|
|
||||||
// std::vector<AsyncMqttClientInternals::OnUnsubscribeUserCallback> _onUnsubscribeUserCallbacks;
|
|
||||||
// std::vector<AsyncMqttClientInternals::OnMessageUserCallback> _onMessageUserCallbacks;
|
|
||||||
// std::vector<AsyncMqttClientInternals::OnPublishUserCallback> _onPublishUserCallbacks;
|
|
||||||
|
|
||||||
// AsyncMqttClientInternals::ParsingInformation _parsingInformation;
|
|
||||||
// AsyncMqttClientInternals::Packet* _currentParsedPacket;
|
|
||||||
// uint8_t _remainingLengthBufferPosition;
|
|
||||||
// char _remainingLengthBuffer[4];
|
|
||||||
|
|
||||||
// uint16_t _nextPacketId;
|
|
||||||
|
|
||||||
// std::vector<AsyncMqttClientInternals::PendingPubRel> _pendingPubRels;
|
|
||||||
|
|
||||||
// std::vector<AsyncMqttClientInternals::PendingAck> _toSendAcks;
|
|
||||||
|
|
||||||
// void _clear();
|
|
||||||
// void _freeCurrentParsedPacket();
|
|
||||||
|
|
||||||
// TCP
|
|
||||||
// void _onConnect(AsyncClient* client);
|
|
||||||
// void _onDisconnect(AsyncClient* client);
|
|
||||||
// static void _onError(AsyncClient* client, int8_t error);
|
|
||||||
// void _onTimeout(AsyncClient* client, uint32_t time);
|
|
||||||
// static void _onAck(AsyncClient* client, size_t len, uint32_t time);
|
|
||||||
// void _onData(AsyncClient* client, char* data, size_t len);
|
|
||||||
// void _onPoll(AsyncClient* client);
|
|
||||||
|
|
||||||
// // MQTT
|
|
||||||
// void _onPingResp();
|
|
||||||
// void _onConnAck(bool sessionPresent, uint8_t connectReturnCode);
|
|
||||||
// void _onSubAck(uint16_t packetId, char status);
|
|
||||||
// void _onUnsubAck(uint16_t packetId);
|
|
||||||
// void _onMessage(char* topic, char* payload, uint8_t qos, bool dup, bool retain, size_t len, size_t index, size_t total, uint16_t packetId);
|
|
||||||
// void _onPublish(uint16_t packetId, uint8_t qos);
|
|
||||||
// void _onPubRel(uint16_t packetId);
|
|
||||||
// void _onPubAck(uint16_t packetId);
|
|
||||||
// void _onPubRec(uint16_t packetId);
|
|
||||||
// void _onPubComp(uint16_t packetId);
|
|
||||||
|
|
||||||
// bool _sendPing();
|
|
||||||
// void _sendAcks();
|
|
||||||
// bool _sendDisconnect();
|
|
||||||
|
|
||||||
// uint16_t _getNextPacketId();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,49 +1,11 @@
|
|||||||
/*
|
|
||||||
Asynchronous TCP library for Espressif MCUs
|
|
||||||
|
|
||||||
Copyright (c) 2016 Hristo Gochkov. All rights reserved.
|
|
||||||
This file is part of the esp8266 core for Arduino environment.
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library 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
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ASYNCTCP_H_
|
#ifndef ASYNCTCP_H_
|
||||||
#define ASYNCTCP_H_
|
#define ASYNCTCP_H_
|
||||||
|
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
//If core is not defined, then we are running in Arduino or PIO
|
|
||||||
#ifndef CONFIG_ASYNC_TCP_RUNNING_CORE
|
|
||||||
#define CONFIG_ASYNC_TCP_RUNNING_CORE -1 //any available core
|
|
||||||
#define CONFIG_ASYNC_TCP_USE_WDT 1 //if enabled, adds between 33us and 200us per event
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class AsyncClient;
|
class AsyncClient;
|
||||||
|
|
||||||
#define ASYNC_MAX_ACK_TIME 5000
|
|
||||||
#define ASYNC_WRITE_FLAG_COPY 0x01 //will allocate new buffer to hold the data while sending (else will hold reference to the data given)
|
|
||||||
#define ASYNC_WRITE_FLAG_MORE 0x02 //will not send PSH flag, meaning that there should be more data to be sent before the application should react.
|
|
||||||
|
|
||||||
typedef std::function<void(void*, AsyncClient*)> AcConnectHandler;
|
|
||||||
typedef std::function<void(void*, AsyncClient*, size_t len, uint32_t time)> AcAckHandler;
|
|
||||||
typedef std::function<void(void*, AsyncClient*, int8_t error)> AcErrorHandler;
|
|
||||||
typedef std::function<void(void*, AsyncClient*, void *data, size_t len)> AcDataHandler;
|
|
||||||
typedef std::function<void(void*, AsyncClient*, struct pbuf *pb)> AcPacketHandler;
|
|
||||||
typedef std::function<void(void*, AsyncClient*, uint32_t time)> AcTimeoutHandler;
|
|
||||||
|
|
||||||
struct tcp_pcb;
|
struct tcp_pcb;
|
||||||
struct ip_addr;
|
struct ip_addr;
|
||||||
|
|
||||||
@@ -51,162 +13,17 @@ class AsyncClient {
|
|||||||
public:
|
public:
|
||||||
AsyncClient(tcp_pcb * pcb = 0);
|
AsyncClient(tcp_pcb * pcb = 0);
|
||||||
~AsyncClient();
|
~AsyncClient();
|
||||||
|
|
||||||
AsyncClient & operator=(const AsyncClient &other);
|
|
||||||
AsyncClient & operator+=(const AsyncClient &other);
|
|
||||||
|
|
||||||
bool operator==(const AsyncClient &other);
|
|
||||||
|
|
||||||
bool operator!=(const AsyncClient &other) {
|
|
||||||
return !(*this == other);
|
|
||||||
}
|
|
||||||
bool connect(IPAddress ip, uint16_t port);
|
|
||||||
bool connect(const char* host, uint16_t port);
|
|
||||||
void close(bool now = false);
|
|
||||||
void stop();
|
|
||||||
int8_t abort();
|
|
||||||
bool free();
|
|
||||||
|
|
||||||
bool canSend();//ack is not pending
|
|
||||||
size_t space();//space available in the TCP window
|
|
||||||
size_t add(const char* data, size_t size, uint8_t apiflags=ASYNC_WRITE_FLAG_COPY);//add for sending
|
|
||||||
bool send();//send all data added with the method above
|
|
||||||
|
|
||||||
//write equals add()+send()
|
|
||||||
size_t write(const char* data);
|
|
||||||
size_t write(const char* data, size_t size, uint8_t apiflags=ASYNC_WRITE_FLAG_COPY); //only when canSend() == true
|
|
||||||
|
|
||||||
uint8_t state();
|
|
||||||
bool connecting();
|
|
||||||
bool connected();
|
|
||||||
bool disconnecting();
|
|
||||||
bool disconnected();
|
|
||||||
bool freeable();//disconnected or disconnecting
|
|
||||||
|
|
||||||
uint16_t getMss();
|
|
||||||
|
|
||||||
uint32_t getRxTimeout();
|
|
||||||
void setRxTimeout(uint32_t timeout);//no RX data timeout for the connection in seconds
|
|
||||||
|
|
||||||
uint32_t getAckTimeout();
|
|
||||||
void setAckTimeout(uint32_t timeout);//no ACK timeout for the last sent packet in milliseconds
|
|
||||||
|
|
||||||
void setNoDelay(bool nodelay);
|
|
||||||
bool getNoDelay();
|
|
||||||
|
|
||||||
uint32_t getRemoteAddress();
|
|
||||||
uint16_t getRemotePort();
|
|
||||||
uint32_t getLocalAddress();
|
|
||||||
uint16_t getLocalPort();
|
|
||||||
|
|
||||||
//compatibility
|
|
||||||
IPAddress remoteIP();
|
|
||||||
uint16_t remotePort();
|
|
||||||
IPAddress localIP();
|
|
||||||
uint16_t localPort();
|
|
||||||
|
|
||||||
void onConnect(AcConnectHandler cb, void* arg = 0); //on successful connect
|
|
||||||
void onDisconnect(AcConnectHandler cb, void* arg = 0); //disconnected
|
|
||||||
void onAck(AcAckHandler cb, void* arg = 0); //ack received
|
|
||||||
void onError(AcErrorHandler cb, void* arg = 0); //unsuccessful connect or error
|
|
||||||
void onData(AcDataHandler cb, void* arg = 0); //data received (called if onPacket is not used)
|
|
||||||
void onPacket(AcPacketHandler cb, void* arg = 0); //data received
|
|
||||||
void onTimeout(AcTimeoutHandler cb, void* arg = 0); //ack timeout
|
|
||||||
void onPoll(AcConnectHandler cb, void* arg = 0); //every 125ms when connected
|
|
||||||
|
|
||||||
void ackPacket(struct pbuf * pb);//ack pbuf from onPacket
|
|
||||||
size_t ack(size_t len); //ack data that you have not acked using the method below
|
|
||||||
void ackLater(){ _ack_pcb = false; } //will not ack the current packet. Call from onData
|
|
||||||
|
|
||||||
const char * errorToString(int8_t error);
|
|
||||||
const char * stateToString();
|
|
||||||
|
|
||||||
//Do not use any of the functions below!
|
|
||||||
static int8_t _s_poll(void *arg, struct tcp_pcb *tpcb);
|
|
||||||
static int8_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, int8_t err);
|
|
||||||
static int8_t _s_fin(void *arg, struct tcp_pcb *tpcb, int8_t err);
|
|
||||||
static int8_t _s_lwip_fin(void *arg, struct tcp_pcb *tpcb, int8_t err);
|
|
||||||
static void _s_error(void *arg, int8_t err);
|
|
||||||
static int8_t _s_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len);
|
|
||||||
static int8_t _s_connected(void* arg, void* tpcb, int8_t err);
|
|
||||||
static void _s_dns_found(const char *name, struct ip_addr *ipaddr, void *arg);
|
|
||||||
|
|
||||||
int8_t _recv(tcp_pcb* pcb, pbuf* pb, int8_t err);
|
|
||||||
tcp_pcb * pcb(){ return _pcb; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
tcp_pcb* _pcb;
|
|
||||||
int8_t _closed_slot;
|
|
||||||
|
|
||||||
AcConnectHandler _connect_cb;
|
|
||||||
void* _connect_cb_arg;
|
|
||||||
AcConnectHandler _discard_cb;
|
|
||||||
void* _discard_cb_arg;
|
|
||||||
AcAckHandler _sent_cb;
|
|
||||||
void* _sent_cb_arg;
|
|
||||||
AcErrorHandler _error_cb;
|
|
||||||
void* _error_cb_arg;
|
|
||||||
AcDataHandler _recv_cb;
|
|
||||||
void* _recv_cb_arg;
|
|
||||||
AcPacketHandler _pb_cb;
|
|
||||||
void* _pb_cb_arg;
|
|
||||||
AcTimeoutHandler _timeout_cb;
|
|
||||||
void* _timeout_cb_arg;
|
|
||||||
AcConnectHandler _poll_cb;
|
|
||||||
void* _poll_cb_arg;
|
|
||||||
|
|
||||||
bool _pcb_busy;
|
|
||||||
uint32_t _pcb_sent_at;
|
|
||||||
bool _ack_pcb;
|
|
||||||
uint32_t _rx_ack_len;
|
|
||||||
uint32_t _rx_last_packet;
|
|
||||||
uint32_t _rx_since_timeout;
|
|
||||||
uint32_t _ack_timeout;
|
|
||||||
uint16_t _connect_port;
|
|
||||||
|
|
||||||
int8_t _close();
|
|
||||||
int8_t _connected(void* pcb, int8_t err);
|
|
||||||
void _error(int8_t err);
|
|
||||||
int8_t _poll(tcp_pcb* pcb);
|
|
||||||
int8_t _sent(tcp_pcb* pcb, uint16_t len);
|
|
||||||
int8_t _fin(tcp_pcb* pcb, int8_t err);
|
|
||||||
int8_t _lwip_fin(tcp_pcb* pcb, int8_t err);
|
|
||||||
void _dns_found(struct ip_addr *ipaddr);
|
|
||||||
|
|
||||||
public:
|
|
||||||
AsyncClient* prev;
|
|
||||||
AsyncClient* next;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class AsyncServer {
|
class AsyncServer {
|
||||||
public:
|
public:
|
||||||
AsyncServer(IPAddress addr, uint16_t port) : _port(port), _addr("poep") {};
|
AsyncServer(uint16_t port)
|
||||||
|
: _port(port){};
|
||||||
AsyncServer(uint16_t port) : _port(port) {};
|
|
||||||
|
|
||||||
~AsyncServer(){};
|
~AsyncServer(){};
|
||||||
void onClient(AcConnectHandler cb, void* arg);
|
|
||||||
void begin();
|
|
||||||
void end();
|
|
||||||
void setNoDelay(bool nodelay);
|
|
||||||
bool getNoDelay();
|
|
||||||
uint8_t status();
|
|
||||||
|
|
||||||
//Do not use any of the functions below!
|
|
||||||
static int8_t _s_accept(void *arg, tcp_pcb* newpcb, int8_t err);
|
|
||||||
static int8_t _s_accepted(void *arg, AsyncClient* client);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint16_t _port;
|
uint16_t _port;
|
||||||
IPAddress _addr;
|
|
||||||
bool _noDelay;
|
|
||||||
tcp_pcb* _pcb;
|
|
||||||
AcConnectHandler _connect_cb;
|
|
||||||
void* _connect_cb_arg;
|
|
||||||
|
|
||||||
int8_t _accept(tcp_pcb* newpcb, int8_t err);
|
|
||||||
int8_t _accepted(AsyncClient* client);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* ASYNCTCP_H_ */
|
#endif
|
||||||
|
|||||||
@@ -4,32 +4,31 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <AsyncJson.h>
|
#include <AsyncJson.h>
|
||||||
#include <SecurityManager.h>
|
#include <AsyncMqttClient.h>
|
||||||
#include <ESPAsyncWebServer.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
#include <FS.h>
|
#include <FS.h>
|
||||||
#include <AsyncMqttClient.h>
|
#include <SecurityManager.h>
|
||||||
|
#include <SecuritySettingsService.h>
|
||||||
#include <StatefulService.h>
|
#include <StatefulService.h>
|
||||||
|
|
||||||
class DummySettings {
|
class DummySettings {
|
||||||
public:
|
public:
|
||||||
uint8_t tx_mode;
|
uint8_t tx_mode = 1;
|
||||||
uint8_t ems_bus_id;
|
uint8_t ems_bus_id = 0x0B;
|
||||||
bool system_heartbeat;
|
bool system_heartbeat = false;
|
||||||
int8_t syslog_level; // uuid::log::Level
|
int8_t syslog_level = 1; // uuid::log::Level
|
||||||
uint32_t syslog_mark_interval;
|
uint32_t syslog_mark_interval = 0;
|
||||||
String syslog_host;
|
String syslog_host = "192.168.1.4";
|
||||||
uint8_t master_thermostat;
|
uint8_t master_thermostat = 0;
|
||||||
bool shower_timer;
|
bool shower_timer = false;
|
||||||
bool shower_alert;
|
bool shower_alert = false;
|
||||||
|
uint16_t publish_time = 10; // seconds
|
||||||
uint16_t publish_time; // seconds
|
uint8_t mqtt_format = 1; // 1=single, 2=nested, 3=ha, 4=custom
|
||||||
uint8_t mqtt_format; // 1=single, 2=nested, 3=ha, 4=custom
|
uint8_t mqtt_qos = 0;
|
||||||
uint8_t mqtt_qos;
|
String hostname = "ems-esp";
|
||||||
|
String jwtSecret = "ems-esp";
|
||||||
String hostname;
|
String ssid = "ems-esp";
|
||||||
String jwtSecret;
|
String password = "ems-esp";
|
||||||
String ssid;
|
|
||||||
String password;
|
|
||||||
|
|
||||||
static void read(DummySettings & settings, JsonObject & root){};
|
static void read(DummySettings & settings, JsonObject & root){};
|
||||||
static void read(DummySettings & settings){};
|
static void read(DummySettings & settings){};
|
||||||
@@ -56,13 +55,14 @@ class DummySettingsService : public StatefulService<DummySettings> {
|
|||||||
class ESP8266React {
|
class ESP8266React {
|
||||||
public:
|
public:
|
||||||
ESP8266React(AsyncWebServer * server, FS * fs)
|
ESP8266React(AsyncWebServer * server, FS * fs)
|
||||||
: _settings(server, fs, nullptr){};
|
: _settings(server, fs, nullptr)
|
||||||
|
, _securitySettingsService(server, fs){};
|
||||||
|
|
||||||
void begin(){};
|
void begin(){};
|
||||||
void loop(){};
|
void loop(){};
|
||||||
|
|
||||||
SecurityManager * getSecurityManager() {
|
SecurityManager * getSecurityManager() {
|
||||||
return nullptr;
|
return &_securitySettingsService;
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncMqttClient * getMqttClient() {
|
AsyncMqttClient * getMqttClient() {
|
||||||
@@ -83,6 +83,8 @@ class ESP8266React {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
DummySettingsService _settings;
|
DummySettingsService _settings;
|
||||||
|
SecuritySettingsService _securitySettingsService;
|
||||||
|
|
||||||
AsyncMqttClient * _mqttClient;
|
AsyncMqttClient * _mqttClient;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -7,22 +7,11 @@
|
|||||||
#include <AsyncTCP.h>
|
#include <AsyncTCP.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
#define DEBUGF(...) //Serial.printf(__VA_ARGS__)
|
|
||||||
|
|
||||||
class AsyncWebServer;
|
class AsyncWebServer;
|
||||||
class AsyncWebServerRequest;
|
class AsyncWebServerRequest;
|
||||||
class AsyncWebServerResponse;
|
class AsyncWebServerResponse;
|
||||||
class AsyncWebHeader;
|
|
||||||
class AsyncWebParameter;
|
|
||||||
class AsyncWebRewrite;
|
|
||||||
class AsyncWebHandler;
|
|
||||||
class AsyncStaticWebHandler;
|
|
||||||
class AsyncCallbackWebHandler;
|
|
||||||
class AsyncResponseStream;
|
|
||||||
class AsyncJsonResponse;
|
class AsyncJsonResponse;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
HTTP_GET = 0b00000001,
|
HTTP_GET = 0b00000001,
|
||||||
HTTP_POST = 0b00000010,
|
HTTP_POST = 0b00000010,
|
||||||
@@ -34,89 +23,9 @@ typedef enum {
|
|||||||
HTTP_ANY = 0b01111111,
|
HTTP_ANY = 0b01111111,
|
||||||
} WebRequestMethod;
|
} WebRequestMethod;
|
||||||
|
|
||||||
//if this value is returned when asked for data, packet will not be sent and you will be asked for data again
|
|
||||||
#define RESPONSE_TRY_AGAIN 0xFFFFFFFF
|
|
||||||
|
|
||||||
typedef uint8_t WebRequestMethodComposite;
|
typedef uint8_t WebRequestMethodComposite;
|
||||||
typedef std::function<void(void)> ArDisconnectHandler;
|
typedef std::function<void(void)> ArDisconnectHandler;
|
||||||
|
|
||||||
/*
|
|
||||||
* PARAMETER :: Chainable object to hold GET/POST and FILE parameters
|
|
||||||
* */
|
|
||||||
|
|
||||||
class AsyncWebParameter {
|
|
||||||
private:
|
|
||||||
String _name;
|
|
||||||
String _value;
|
|
||||||
size_t _size;
|
|
||||||
bool _isForm;
|
|
||||||
bool _isFile;
|
|
||||||
|
|
||||||
public:
|
|
||||||
AsyncWebParameter(const String & name, const String & value, bool form = false, bool file = false, size_t size = 0)
|
|
||||||
: _name(name)
|
|
||||||
, _value(value)
|
|
||||||
, _size(size)
|
|
||||||
, _isForm(form)
|
|
||||||
, _isFile(file) {
|
|
||||||
}
|
|
||||||
const String & name() const {
|
|
||||||
return _name;
|
|
||||||
}
|
|
||||||
const String & value() const {
|
|
||||||
return _value;
|
|
||||||
}
|
|
||||||
size_t size() const {
|
|
||||||
return _size;
|
|
||||||
}
|
|
||||||
bool isPost() const {
|
|
||||||
return _isForm;
|
|
||||||
}
|
|
||||||
bool isFile() const {
|
|
||||||
return _isFile;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* HEADER :: Chainable object to hold the headers
|
|
||||||
* */
|
|
||||||
|
|
||||||
class AsyncWebHeader {
|
|
||||||
private:
|
|
||||||
String _name;
|
|
||||||
String _value;
|
|
||||||
|
|
||||||
public:
|
|
||||||
AsyncWebHeader(const String & name, const String & value)
|
|
||||||
: _name(name)
|
|
||||||
, _value(value) {
|
|
||||||
}
|
|
||||||
AsyncWebHeader(const String & data)
|
|
||||||
: _name()
|
|
||||||
, _value() {
|
|
||||||
}
|
|
||||||
~AsyncWebHeader() {
|
|
||||||
}
|
|
||||||
const String & name() const {
|
|
||||||
return _name;
|
|
||||||
}
|
|
||||||
const String & value() const {
|
|
||||||
return _value;
|
|
||||||
}
|
|
||||||
String toString() const {
|
|
||||||
return _value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* REQUEST :: Each incoming Client is wrapped inside a Request and both live together until disconnect
|
|
||||||
* */
|
|
||||||
|
|
||||||
typedef enum { RCT_NOT_USED = -1, RCT_DEFAULT = 0, RCT_HTTP, RCT_WS, RCT_EVENT, RCT_MAX } RequestedConnectionType;
|
|
||||||
|
|
||||||
typedef std::function<size_t(uint8_t *, size_t, size_t)> AwsResponseFiller;
|
|
||||||
typedef std::function<String(const String &)> AwsTemplateProcessor;
|
|
||||||
|
|
||||||
class AsyncWebServerRequest {
|
class AsyncWebServerRequest {
|
||||||
friend class AsyncWebServer;
|
friend class AsyncWebServer;
|
||||||
friend class AsyncCallbackWebHandler;
|
friend class AsyncCallbackWebHandler;
|
||||||
@@ -124,61 +33,7 @@ class AsyncWebServerRequest {
|
|||||||
private:
|
private:
|
||||||
AsyncClient * _client;
|
AsyncClient * _client;
|
||||||
AsyncWebServer * _server;
|
AsyncWebServer * _server;
|
||||||
AsyncWebHandler * _handler;
|
|
||||||
AsyncWebServerResponse * _response;
|
|
||||||
ArDisconnectHandler _onDisconnectfn;
|
|
||||||
|
|
||||||
String _temp;
|
|
||||||
uint8_t _parseState;
|
|
||||||
|
|
||||||
uint8_t _version;
|
|
||||||
WebRequestMethodComposite _method;
|
WebRequestMethodComposite _method;
|
||||||
String _url;
|
|
||||||
String _host;
|
|
||||||
String _contentType;
|
|
||||||
String _boundary;
|
|
||||||
String _authorization;
|
|
||||||
RequestedConnectionType _reqconntype;
|
|
||||||
void _removeNotInterestingHeaders();
|
|
||||||
bool _isDigest;
|
|
||||||
bool _isMultipart;
|
|
||||||
bool _isPlainPost;
|
|
||||||
bool _expectingContinue;
|
|
||||||
size_t _contentLength;
|
|
||||||
size_t _parsedLength;
|
|
||||||
|
|
||||||
uint8_t _multiParseState;
|
|
||||||
uint8_t _boundaryPosition;
|
|
||||||
size_t _itemStartIndex;
|
|
||||||
size_t _itemSize;
|
|
||||||
String _itemName;
|
|
||||||
String _itemFilename;
|
|
||||||
String _itemType;
|
|
||||||
String _itemValue;
|
|
||||||
uint8_t * _itemBuffer;
|
|
||||||
size_t _itemBufferIndex;
|
|
||||||
bool _itemIsFile;
|
|
||||||
|
|
||||||
void _onPoll();
|
|
||||||
void _onAck(size_t len, uint32_t time);
|
|
||||||
void _onError(int8_t error);
|
|
||||||
void _onTimeout(uint32_t time);
|
|
||||||
void _onDisconnect(){};
|
|
||||||
void _onData(void * buf, size_t len);
|
|
||||||
|
|
||||||
void _addParam(AsyncWebParameter *);
|
|
||||||
void _addPathParam(const char * param);
|
|
||||||
|
|
||||||
bool _parseReqHead();
|
|
||||||
bool _parseReqHeader();
|
|
||||||
void _parseLine();
|
|
||||||
void _parsePlainPostChar(uint8_t data);
|
|
||||||
void _parseMultipartPostByte(uint8_t data, bool last);
|
|
||||||
void _addGetParams(const String & params);
|
|
||||||
|
|
||||||
void _handleUploadStart();
|
|
||||||
void _handleUploadByte(uint8_t data, bool last);
|
|
||||||
void _handleUploadEnd();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void * _tempObject;
|
void * _tempObject;
|
||||||
@@ -189,157 +44,30 @@ class AsyncWebServerRequest {
|
|||||||
AsyncClient * client() {
|
AsyncClient * client() {
|
||||||
return _client;
|
return _client;
|
||||||
}
|
}
|
||||||
uint8_t version() const {
|
|
||||||
return _version;
|
|
||||||
}
|
|
||||||
WebRequestMethodComposite method() const {
|
WebRequestMethodComposite method() const {
|
||||||
return _method;
|
return _method;
|
||||||
}
|
}
|
||||||
const String & url() const {
|
|
||||||
return _url;
|
|
||||||
}
|
|
||||||
const String & host() const {
|
|
||||||
return _host;
|
|
||||||
}
|
|
||||||
const String & contentType() const {
|
|
||||||
return _contentType;
|
|
||||||
}
|
|
||||||
size_t contentLength() const {
|
|
||||||
return _contentLength;
|
|
||||||
}
|
|
||||||
bool multipart() const {
|
|
||||||
return _isMultipart;
|
|
||||||
}
|
|
||||||
const char * methodToString() const;
|
|
||||||
const char * requestedConnTypeToString() const;
|
|
||||||
RequestedConnectionType requestedConnType() const {
|
|
||||||
return _reqconntype;
|
|
||||||
}
|
|
||||||
bool isExpectedRequestedConnType(RequestedConnectionType erct1, RequestedConnectionType erct2 = RCT_NOT_USED, RequestedConnectionType erct3 = RCT_NOT_USED);
|
|
||||||
void onDisconnect(ArDisconnectHandler fn){};
|
|
||||||
|
|
||||||
//hash is the string representation of:
|
void addInterestingHeader(const String & name){};
|
||||||
// base64(user:pass) for basic or
|
|
||||||
// user:realm:md5(user:realm:pass) for digest
|
|
||||||
bool authenticate(const char * hash);
|
|
||||||
bool authenticate(const char * username, const char * password, const char * realm = NULL, bool passwordIsHash = false);
|
|
||||||
void requestAuthentication(const char * realm = NULL, bool isDigest = true);
|
|
||||||
|
|
||||||
void setHandler(AsyncWebHandler * handler) {
|
|
||||||
_handler = handler;
|
|
||||||
}
|
|
||||||
void addInterestingHeader(const String & name);
|
|
||||||
|
|
||||||
void redirect(const String & url);
|
|
||||||
|
|
||||||
void send(AsyncWebServerResponse * response){};
|
void send(AsyncWebServerResponse * response){};
|
||||||
void send(AsyncJsonResponse * response){};
|
void send(AsyncJsonResponse * response){};
|
||||||
void send(int code, const String & contentType = String(), const String & content = String()){};
|
void send(int code, const String & contentType = String(), const String & content = String()){};
|
||||||
void send(Stream & stream, const String & contentType, size_t len, AwsTemplateProcessor callback = nullptr);
|
|
||||||
void send(const String & contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr);
|
|
||||||
void sendChunked(const String & contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr);
|
|
||||||
void send_P(int code, const String & contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback = nullptr);
|
|
||||||
void send_P(int code, const String & contentType, PGM_P content, AwsTemplateProcessor callback = nullptr);
|
|
||||||
|
|
||||||
|
AsyncWebServerResponse * beginResponse(int code, const String & contentType = String(), const String & content = String()) {
|
||||||
AsyncWebServerResponse * beginResponse(int code, const String & contentType = String(), const String & content = String());
|
// AsyncWebServerResponse *a = new AsyncWebServerResponse()
|
||||||
AsyncWebServerResponse * beginResponse(Stream & stream, const String & contentType, size_t len, AwsTemplateProcessor callback = nullptr);
|
return nullptr;
|
||||||
AsyncWebServerResponse * beginResponse(const String & contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr);
|
}
|
||||||
AsyncWebServerResponse * beginChunkedResponse(const String & contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr);
|
|
||||||
AsyncResponseStream * beginResponseStream(const String & contentType, size_t bufferSize = 1460);
|
|
||||||
AsyncWebServerResponse * beginResponse_P(int code, const String & contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback = nullptr);
|
|
||||||
AsyncWebServerResponse * beginResponse_P(int code, const String & contentType, PGM_P content, AwsTemplateProcessor callback = nullptr);
|
|
||||||
|
|
||||||
size_t headers() const; // get header count
|
size_t headers() const; // get header count
|
||||||
bool hasHeader(const String & name) const; // check if header exists
|
|
||||||
bool hasHeader(const __FlashStringHelper * data) const; // check if header exists
|
|
||||||
|
|
||||||
AsyncWebHeader * getHeader(const String & name) const;
|
|
||||||
AsyncWebHeader * getHeader(const __FlashStringHelper * data) const;
|
|
||||||
AsyncWebHeader * getHeader(size_t num) const;
|
|
||||||
|
|
||||||
size_t params() const; // get arguments count
|
size_t params() const; // get arguments count
|
||||||
bool hasParam(const String & name, bool post = false, bool file = false) const;
|
|
||||||
bool hasParam(const __FlashStringHelper * data, bool post = false, bool file = false) const;
|
|
||||||
|
|
||||||
AsyncWebParameter * getParam(const String & name, bool post = false, bool file = false) const;
|
|
||||||
AsyncWebParameter * getParam(const __FlashStringHelper * data, bool post, bool file) const;
|
|
||||||
AsyncWebParameter * getParam(size_t num) const;
|
|
||||||
|
|
||||||
size_t args() const {
|
|
||||||
return params();
|
|
||||||
} // get arguments count
|
|
||||||
const String & arg(const String & name) const; // get request argument value by name
|
|
||||||
const String & arg(const __FlashStringHelper * data) const; // get request argument value by F(name)
|
|
||||||
const String & arg(size_t i) const; // get request argument value by number
|
|
||||||
const String & argName(size_t i) const; // get request argument name by number
|
|
||||||
bool hasArg(const char * name) const; // check if argument exists
|
|
||||||
bool hasArg(const __FlashStringHelper * data) const; // check if F(argument) exists
|
|
||||||
|
|
||||||
const String & pathArg(size_t i) const;
|
|
||||||
|
|
||||||
const String & header(const char * name) const; // get request header value by name
|
|
||||||
const String & header(const __FlashStringHelper * data) const; // get request header value by F(name)
|
|
||||||
const String & header(size_t i) const; // get request header value by number
|
|
||||||
const String & headerName(size_t i) const; // get request header name by number
|
|
||||||
String urlDecode(const String & text) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* FILTER :: Callback to filter AsyncWebRewrite and AsyncWebHandler (done by the Server)
|
|
||||||
* */
|
|
||||||
|
|
||||||
typedef std::function<bool(AsyncWebServerRequest * request)> ArRequestFilterFunction;
|
typedef std::function<bool(AsyncWebServerRequest * request)> ArRequestFilterFunction;
|
||||||
|
|
||||||
bool ON_STA_FILTER(AsyncWebServerRequest * request);
|
|
||||||
|
|
||||||
bool ON_AP_FILTER(AsyncWebServerRequest * request);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* REWRITE :: One instance can be handle any Request (done by the Server)
|
|
||||||
* */
|
|
||||||
|
|
||||||
class AsyncWebRewrite {
|
|
||||||
protected:
|
|
||||||
String _from;
|
|
||||||
String _toUrl;
|
|
||||||
String _params;
|
|
||||||
ArRequestFilterFunction _filter;
|
|
||||||
|
|
||||||
public:
|
|
||||||
AsyncWebRewrite(const char * from, const char * to)
|
|
||||||
: _from(from)
|
|
||||||
, _toUrl(to)
|
|
||||||
, _params(String())
|
|
||||||
, _filter(NULL) {
|
|
||||||
}
|
|
||||||
virtual ~AsyncWebRewrite() {
|
|
||||||
}
|
|
||||||
AsyncWebRewrite & setFilter(ArRequestFilterFunction fn) {
|
|
||||||
_filter = fn;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
bool filter(AsyncWebServerRequest * request) const {
|
|
||||||
return _filter == NULL || _filter(request);
|
|
||||||
}
|
|
||||||
const String & from(void) const {
|
|
||||||
return _from;
|
|
||||||
}
|
|
||||||
const String & toUrl(void) const {
|
|
||||||
return _toUrl;
|
|
||||||
}
|
|
||||||
const String & params(void) const {
|
|
||||||
return _params;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* HANDLER :: One instance can be attached to any Request (done by the Server)
|
|
||||||
* */
|
|
||||||
|
|
||||||
class AsyncWebHandler {
|
class AsyncWebHandler {
|
||||||
protected:
|
protected:
|
||||||
ArRequestFilterFunction _filter;
|
|
||||||
String _username;
|
String _username;
|
||||||
String _password;
|
String _password;
|
||||||
|
|
||||||
@@ -348,18 +76,7 @@ class AsyncWebHandler {
|
|||||||
: _username("")
|
: _username("")
|
||||||
, _password("") {
|
, _password("") {
|
||||||
}
|
}
|
||||||
AsyncWebHandler & setFilter(ArRequestFilterFunction fn) {
|
|
||||||
_filter = fn;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
AsyncWebHandler & setAuthentication(const char * username, const char * password) {
|
|
||||||
_username = String(username);
|
|
||||||
_password = String(password);
|
|
||||||
return *this;
|
|
||||||
};
|
|
||||||
bool filter(AsyncWebServerRequest * request) {
|
|
||||||
return _filter == NULL || _filter(request);
|
|
||||||
}
|
|
||||||
virtual ~AsyncWebHandler() {
|
virtual ~AsyncWebHandler() {
|
||||||
}
|
}
|
||||||
virtual bool canHandle(AsyncWebServerRequest * request __attribute__((unused))) {
|
virtual bool canHandle(AsyncWebServerRequest * request __attribute__((unused))) {
|
||||||
@@ -380,51 +97,18 @@ class AsyncWebHandler {
|
|||||||
size_t index __attribute__((unused)),
|
size_t index __attribute__((unused)),
|
||||||
size_t total __attribute__((unused))) {
|
size_t total __attribute__((unused))) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool isRequestHandlerTrivial() {
|
virtual bool isRequestHandlerTrivial() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* RESPONSE :: One instance is created for each Request (attached by the Handler)
|
|
||||||
* */
|
|
||||||
|
|
||||||
typedef enum { RESPONSE_SETUP, RESPONSE_HEADERS, RESPONSE_CONTENT, RESPONSE_WAIT_ACK, RESPONSE_END, RESPONSE_FAILED } WebResponseState;
|
|
||||||
|
|
||||||
class AsyncWebServerResponse {
|
class AsyncWebServerResponse {
|
||||||
protected:
|
|
||||||
int _code;
|
|
||||||
String _contentType;
|
|
||||||
size_t _contentLength;
|
|
||||||
bool _sendContentLength;
|
|
||||||
bool _chunked;
|
|
||||||
size_t _headLength;
|
|
||||||
size_t _sentLength;
|
|
||||||
size_t _ackedLength;
|
|
||||||
size_t _writtenLength;
|
|
||||||
WebResponseState _state;
|
|
||||||
const char * _responseCodeToString(int code);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AsyncWebServerResponse();
|
AsyncWebServerResponse();
|
||||||
virtual ~AsyncWebServerResponse();
|
virtual ~AsyncWebServerResponse();
|
||||||
virtual void setCode(int code);
|
|
||||||
virtual void setContentLength(size_t len);
|
|
||||||
virtual void setContentType(const String & type);
|
|
||||||
virtual void addHeader(const String & name, const String & value);
|
|
||||||
virtual String _assembleHead(uint8_t version);
|
|
||||||
virtual bool _started() const;
|
|
||||||
virtual bool _finished() const;
|
|
||||||
virtual bool _failed() const;
|
|
||||||
virtual bool _sourceValid() const;
|
|
||||||
virtual void _respond(AsyncWebServerRequest * request);
|
|
||||||
virtual size_t _ack(AsyncWebServerRequest * request, size_t len, uint32_t time);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* SERVER :: One instance
|
|
||||||
* */
|
|
||||||
|
|
||||||
typedef std::function<void(AsyncWebServerRequest * request)> ArRequestHandlerFunction;
|
typedef std::function<void(AsyncWebServerRequest * request)> ArRequestHandlerFunction;
|
||||||
typedef std::function<void(AsyncWebServerRequest * request, const String & filename, size_t index, uint8_t * data, size_t len, bool final)> ArUploadHandlerFunction;
|
typedef std::function<void(AsyncWebServerRequest * request, const String & filename, size_t index, uint8_t * data, size_t len, bool final)> ArUploadHandlerFunction;
|
||||||
typedef std::function<void(AsyncWebServerRequest * request, uint8_t * data, size_t len, size_t index, size_t total)> ArBodyHandlerFunction;
|
typedef std::function<void(AsyncWebServerRequest * request, uint8_t * data, size_t len, size_t index, size_t total)> ArBodyHandlerFunction;
|
||||||
@@ -432,90 +116,23 @@ typedef std::function<void(AsyncWebServerRequest * request, uint8_t * data, size
|
|||||||
class AsyncWebServer {
|
class AsyncWebServer {
|
||||||
protected:
|
protected:
|
||||||
AsyncServer _server;
|
AsyncServer _server;
|
||||||
AsyncCallbackWebHandler * _catchAllHandler;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// proddy
|
|
||||||
AsyncWebServer(uint16_t port)
|
AsyncWebServer(uint16_t port)
|
||||||
: _server(port){};
|
: _server(port){};
|
||||||
// , _rewrites(LinkedList<AsyncWebRewrite*>([](AsyncWebRewrite* r){ delete r; }))
|
|
||||||
// , _handlers(LinkedList<AsyncWebHandler*>([](AsyncWebHandler* h){ delete h; }))
|
|
||||||
|
|
||||||
|
|
||||||
~AsyncWebServer(){};
|
~AsyncWebServer(){};
|
||||||
|
|
||||||
void begin(){};
|
void begin(){};
|
||||||
void end();
|
void end();
|
||||||
|
|
||||||
#if ASYNC_TCP_SSL_ENABLED
|
AsyncWebHandler & addHandler(AsyncWebHandler * handler) {
|
||||||
void onSslFileRequest(AcSSlFileHandler cb, void * arg);
|
|
||||||
void beginSecure(const char * cert, const char * private_key_file, const char * password);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
AsyncWebRewrite & addRewrite(AsyncWebRewrite * rewrite);
|
|
||||||
bool removeRewrite(AsyncWebRewrite * rewrite);
|
|
||||||
AsyncWebRewrite & rewrite(const char * from, const char * to);
|
|
||||||
|
|
||||||
AsyncWebHandler & addHandler(AsyncWebHandler * handler);
|
|
||||||
bool removeHandler(AsyncWebHandler * handler);
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
AsyncCallbackWebHandler & on(const char * uri, ArRequestHandlerFunction onRequest) {
|
|
||||||
AsyncCallbackWebHandler * handler = new AsyncCallbackWebHandler();
|
|
||||||
return *handler;
|
return *handler;
|
||||||
};
|
}
|
||||||
AsyncCallbackWebHandler & on(const char * uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest) {
|
|
||||||
AsyncCallbackWebHandler * handler = new AsyncCallbackWebHandler();
|
|
||||||
return handler;
|
|
||||||
};
|
|
||||||
AsyncCallbackWebHandler & on(const char * uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload) {
|
|
||||||
AsyncCallbackWebHandler * handler = new AsyncCallbackWebHandler();
|
|
||||||
return *handler;
|
|
||||||
};
|
|
||||||
AsyncCallbackWebHandler &
|
|
||||||
on(const char * uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload, ArBodyHandlerFunction onBody) {
|
|
||||||
AsyncCallbackWebHandler * handler = new AsyncCallbackWebHandler();
|
|
||||||
return *handler;
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
void on(const char * uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest){};
|
void on(const char * uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest){};
|
||||||
|
|
||||||
void onNotFound(ArRequestHandlerFunction fn); //called when handler is not assigned
|
|
||||||
void onFileUpload(ArUploadHandlerFunction fn); //handle file uploads
|
|
||||||
void onRequestBody(ArBodyHandlerFunction fn); //handle posts with plain body content (JSON often transmitted this way as a request)
|
|
||||||
|
|
||||||
void reset(); //remove all writers and handlers, with onNotFound/onFileUpload/onRequestBody
|
|
||||||
|
|
||||||
void _handleDisconnect(AsyncWebServerRequest * request);
|
|
||||||
void _attachHandler(AsyncWebServerRequest * request);
|
|
||||||
void _rewriteRequest(AsyncWebServerRequest * request);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// class DefaultHeaders {
|
|
||||||
// headers_t _headers;
|
|
||||||
|
|
||||||
// DefaultHeaders()
|
#endif
|
||||||
// public:
|
|
||||||
|
|
||||||
// void addHeader(const String& name, const String& value){
|
|
||||||
// _headers.add(new AsyncWebHeader(name, value));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// DefaultHeaders(DefaultHeaders const &) = delete;
|
|
||||||
// DefaultHeaders &operator=(DefaultHeaders const &) = delete;
|
|
||||||
// static DefaultHeaders &Instance() {
|
|
||||||
// static DefaultHeaders instance;
|
|
||||||
// return instance;
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// #include "WebResponseImpl.h"
|
|
||||||
// #include "WebHandlerImpl.h"
|
|
||||||
// #include "AsyncWebSocket.h"
|
|
||||||
// #include "AsyncEventSource.h"
|
|
||||||
|
|
||||||
typedef std::function<void(AsyncWebServerRequest * request, JsonVariant & json)> ArJsonRequestHandlerFunction;
|
|
||||||
|
|
||||||
#endif /* _AsyncWebServer_H_ */
|
|
||||||
|
|||||||
141
lib_standalone/SecuritySettingsService.cpp
Normal file
141
lib_standalone/SecuritySettingsService.cpp
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
#include <SecuritySettingsService.h>
|
||||||
|
|
||||||
|
#if FT_ENABLED(FT_SECURITY)
|
||||||
|
|
||||||
|
SecuritySettingsService::SecuritySettingsService(AsyncWebServer* server, FS* fs) :
|
||||||
|
_httpEndpoint(SecuritySettings::read, SecuritySettings::update, this, server, SECURITY_SETTINGS_PATH, this),
|
||||||
|
_fsPersistence(SecuritySettings::read, SecuritySettings::update, this, fs, SECURITY_SETTINGS_FILE),
|
||||||
|
_jwtHandler(FACTORY_JWT_SECRET) {
|
||||||
|
addUpdateHandler([&](const String& originId) { configureJWTHandler(); }, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SecuritySettingsService::begin() {
|
||||||
|
_fsPersistence.readFromFS();
|
||||||
|
configureJWTHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
Authentication SecuritySettingsService::authenticateRequest(AsyncWebServerRequest* request) {
|
||||||
|
AsyncWebHeader* authorizationHeader = request->getHeader(AUTHORIZATION_HEADER);
|
||||||
|
if (authorizationHeader) {
|
||||||
|
String value = authorizationHeader->value();
|
||||||
|
if (value.startsWith(AUTHORIZATION_HEADER_PREFIX)) {
|
||||||
|
value = value.substring(AUTHORIZATION_HEADER_PREFIX_LEN);
|
||||||
|
return authenticateJWT(value);
|
||||||
|
}
|
||||||
|
} else if (request->hasParam(ACCESS_TOKEN_PARAMATER)) {
|
||||||
|
AsyncWebParameter* tokenParamater = request->getParam(ACCESS_TOKEN_PARAMATER);
|
||||||
|
String value = tokenParamater->value();
|
||||||
|
return authenticateJWT(value);
|
||||||
|
}
|
||||||
|
return Authentication();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SecuritySettingsService::configureJWTHandler() {
|
||||||
|
_jwtHandler.setSecret(_state.jwtSecret);
|
||||||
|
}
|
||||||
|
|
||||||
|
Authentication SecuritySettingsService::authenticateJWT(String& jwt) {
|
||||||
|
DynamicJsonDocument payloadDocument(MAX_JWT_SIZE);
|
||||||
|
_jwtHandler.parseJWT(jwt, payloadDocument);
|
||||||
|
if (payloadDocument.is<JsonObject>()) {
|
||||||
|
JsonObject parsedPayload = payloadDocument.as<JsonObject>();
|
||||||
|
String username = parsedPayload["username"];
|
||||||
|
for (User _user : _state.users) {
|
||||||
|
if (_user.username == username && validatePayload(parsedPayload, &_user)) {
|
||||||
|
return Authentication(_user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Authentication();
|
||||||
|
}
|
||||||
|
|
||||||
|
Authentication SecuritySettingsService::authenticate(const String& username, const String& password) {
|
||||||
|
for (User _user : _state.users) {
|
||||||
|
if (_user.username == username && _user.password == password) {
|
||||||
|
return Authentication(_user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Authentication();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void populateJWTPayload(JsonObject& payload, User* user) {
|
||||||
|
payload["username"] = user->username;
|
||||||
|
payload["admin"] = user->admin;
|
||||||
|
payload["version"] = EMSESP_APP_VERSION; // proddy added
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean SecuritySettingsService::validatePayload(JsonObject& parsedPayload, User* user) {
|
||||||
|
DynamicJsonDocument jsonDocument(MAX_JWT_SIZE);
|
||||||
|
JsonObject payload = jsonDocument.to<JsonObject>();
|
||||||
|
populateJWTPayload(payload, user);
|
||||||
|
return payload == parsedPayload;
|
||||||
|
}
|
||||||
|
|
||||||
|
String SecuritySettingsService::generateJWT(User* user) {
|
||||||
|
DynamicJsonDocument jsonDocument(MAX_JWT_SIZE);
|
||||||
|
JsonObject payload = jsonDocument.to<JsonObject>();
|
||||||
|
populateJWTPayload(payload, user);
|
||||||
|
return _jwtHandler.buildJWT(payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArRequestFilterFunction SecuritySettingsService::filterRequest(AuthenticationPredicate predicate) {
|
||||||
|
return [this, predicate](AsyncWebServerRequest* request) {
|
||||||
|
Authentication authentication = authenticateRequest(request);
|
||||||
|
return predicate(authentication);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ArRequestHandlerFunction SecuritySettingsService::wrapRequest(ArRequestHandlerFunction onRequest,
|
||||||
|
AuthenticationPredicate predicate) {
|
||||||
|
return [this, onRequest, predicate](AsyncWebServerRequest* request) {
|
||||||
|
Authentication authentication = authenticateRequest(request);
|
||||||
|
if (!predicate(authentication)) {
|
||||||
|
request->send(401);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
onRequest(request);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ArJsonRequestHandlerFunction SecuritySettingsService::wrapCallback(ArJsonRequestHandlerFunction onRequest,
|
||||||
|
AuthenticationPredicate predicate) {
|
||||||
|
return [this, onRequest, predicate](AsyncWebServerRequest* request, JsonVariant& json) {
|
||||||
|
Authentication authentication = authenticateRequest(request);
|
||||||
|
if (!predicate(authentication)) {
|
||||||
|
request->send(401);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
onRequest(request, json);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
User ADMIN_USER = User(FACTORY_ADMIN_USERNAME, FACTORY_ADMIN_PASSWORD, true);
|
||||||
|
|
||||||
|
SecuritySettingsService::SecuritySettingsService(AsyncWebServer* server, FS* fs) : SecurityManager() {
|
||||||
|
}
|
||||||
|
SecuritySettingsService::~SecuritySettingsService() {
|
||||||
|
}
|
||||||
|
|
||||||
|
ArRequestFilterFunction SecuritySettingsService::filterRequest(AuthenticationPredicate predicate) {
|
||||||
|
return [this, predicate](AsyncWebServerRequest* request) { return true; };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the admin user on all request - disabling security features
|
||||||
|
Authentication SecuritySettingsService::authenticateRequest(AsyncWebServerRequest* request) {
|
||||||
|
return Authentication(ADMIN_USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the function unwrapped
|
||||||
|
ArRequestHandlerFunction SecuritySettingsService::wrapRequest(ArRequestHandlerFunction onRequest,
|
||||||
|
AuthenticationPredicate predicate) {
|
||||||
|
return onRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArJsonRequestHandlerFunction SecuritySettingsService::wrapCallback(ArJsonRequestHandlerFunction onRequest,
|
||||||
|
AuthenticationPredicate predicate) {
|
||||||
|
return onRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
116
lib_standalone/SecuritySettingsService.h
Normal file
116
lib_standalone/SecuritySettingsService.h
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
#ifndef SecuritySettingsService_h
|
||||||
|
#define SecuritySettingsService_h
|
||||||
|
|
||||||
|
#include <Features.h>
|
||||||
|
#include <SecurityManager.h>
|
||||||
|
#include <HttpEndpoint.h>
|
||||||
|
#include <FSPersistence.h>
|
||||||
|
|
||||||
|
#include "../../src/version.h" // added by proddy
|
||||||
|
|
||||||
|
#ifndef FACTORY_ADMIN_USERNAME
|
||||||
|
#define FACTORY_ADMIN_USERNAME "admin"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FACTORY_ADMIN_PASSWORD
|
||||||
|
#define FACTORY_ADMIN_PASSWORD "admin"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FACTORY_GUEST_USERNAME
|
||||||
|
#define FACTORY_GUEST_USERNAME "guest"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FACTORY_GUEST_PASSWORD
|
||||||
|
#define FACTORY_GUEST_PASSWORD "guest"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SECURITY_SETTINGS_FILE "/config/securitySettings.json"
|
||||||
|
#define SECURITY_SETTINGS_PATH "/rest/securitySettings"
|
||||||
|
|
||||||
|
#if FT_ENABLED(FT_SECURITY)
|
||||||
|
|
||||||
|
class SecuritySettings {
|
||||||
|
public:
|
||||||
|
String jwtSecret;
|
||||||
|
std::list<User> users;
|
||||||
|
|
||||||
|
static void read(SecuritySettings& settings, JsonObject& root) {
|
||||||
|
// secret
|
||||||
|
root["jwt_secret"] = settings.jwtSecret;
|
||||||
|
|
||||||
|
// users
|
||||||
|
JsonArray users = root.createNestedArray("users");
|
||||||
|
for (User user : settings.users) {
|
||||||
|
JsonObject userRoot = users.createNestedObject();
|
||||||
|
userRoot["username"] = user.username;
|
||||||
|
userRoot["password"] = user.password;
|
||||||
|
userRoot["admin"] = user.admin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static StateUpdateResult update(JsonObject& root, SecuritySettings& settings) {
|
||||||
|
// secret
|
||||||
|
settings.jwtSecret = root["jwt_secret"] | FACTORY_JWT_SECRET;
|
||||||
|
|
||||||
|
// users
|
||||||
|
settings.users.clear();
|
||||||
|
if (root["users"].is<JsonArray>()) {
|
||||||
|
for (JsonVariant user : root["users"].as<JsonArray>()) {
|
||||||
|
settings.users.push_back(User(user["username"], user["password"], user["admin"]));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
settings.users.push_back(User(FACTORY_ADMIN_USERNAME, FACTORY_ADMIN_PASSWORD, true));
|
||||||
|
settings.users.push_back(User(FACTORY_GUEST_USERNAME, FACTORY_GUEST_PASSWORD, false));
|
||||||
|
}
|
||||||
|
return StateUpdateResult::CHANGED;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SecuritySettingsService : public StatefulService<SecuritySettings>, public SecurityManager {
|
||||||
|
public:
|
||||||
|
SecuritySettingsService(AsyncWebServer* server, FS* fs);
|
||||||
|
|
||||||
|
void begin();
|
||||||
|
|
||||||
|
// Functions to implement SecurityManager
|
||||||
|
Authentication authenticate(const String& username, const String& password);
|
||||||
|
Authentication authenticateRequest(AsyncWebServerRequest* request);
|
||||||
|
String generateJWT(User* user);
|
||||||
|
ArRequestFilterFunction filterRequest(AuthenticationPredicate predicate);
|
||||||
|
ArRequestHandlerFunction wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate);
|
||||||
|
ArJsonRequestHandlerFunction wrapCallback(ArJsonRequestHandlerFunction callback, AuthenticationPredicate predicate);
|
||||||
|
|
||||||
|
private:
|
||||||
|
HttpEndpoint<SecuritySettings> _httpEndpoint;
|
||||||
|
FSPersistence<SecuritySettings> _fsPersistence;
|
||||||
|
ArduinoJsonJWT _jwtHandler;
|
||||||
|
|
||||||
|
void configureJWTHandler();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lookup the user by JWT
|
||||||
|
*/
|
||||||
|
Authentication authenticateJWT(String& jwt);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify the payload is correct
|
||||||
|
*/
|
||||||
|
boolean validatePayload(JsonObject& parsedPayload, User* user);
|
||||||
|
};
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
class SecuritySettingsService : public SecurityManager {
|
||||||
|
public:
|
||||||
|
SecuritySettingsService(AsyncWebServer* server, FS* fs);
|
||||||
|
~SecuritySettingsService();
|
||||||
|
|
||||||
|
// minimal set of functions to support framework with security settings disabled
|
||||||
|
Authentication authenticateRequest(AsyncWebServerRequest* request);
|
||||||
|
ArRequestFilterFunction filterRequest(AuthenticationPredicate predicate);
|
||||||
|
ArRequestHandlerFunction wrapRequest(ArRequestHandlerFunction onRequest, AuthenticationPredicate predicate);
|
||||||
|
ArJsonRequestHandlerFunction wrapCallback(ArJsonRequestHandlerFunction onRequest, AuthenticationPredicate predicate);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // end FT_ENABLED(FT_SECURITY)
|
||||||
|
#endif // end SecuritySettingsService_h
|
||||||
@@ -1,863 +1,68 @@
|
|||||||
/*
|
|
||||||
WString.cpp - String library for Wiring & Arduino
|
|
||||||
...mostly rewritten by Paul Stoffregen...
|
|
||||||
Copyright (c) 2009-10 Hernando Barragan. All rights reserved.
|
|
||||||
Copyright 2011, Paul Stoffregen, paul@pjrc.com
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library 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
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
#include "WString.h"
|
#include "WString.h"
|
||||||
|
|
||||||
/*********************************************/
|
/*
|
||||||
/* Constructors */
|
* Copy string src to buffer dst of size dsize. At most dsize-1
|
||||||
/*********************************************/
|
* chars will be copied. Always NUL terminates (unless dsize == 0).
|
||||||
|
* Returns strlen(src); if retval >= dsize, truncation occurred.
|
||||||
|
*
|
||||||
|
* https://github.com/freebsd/freebsd/blob/master/sys/libkern/strlcpy.c
|
||||||
|
*/
|
||||||
|
size_t strlcpy(char * __restrict dst, const char * __restrict src, size_t dsize) {
|
||||||
|
const char * osrc = src;
|
||||||
|
size_t nleft = dsize;
|
||||||
|
|
||||||
char * itoa(signed short value, char * result, const unsigned int base) {
|
/* Copy as many bytes as will fit. */
|
||||||
// check that the base if valid
|
if (nleft != 0) {
|
||||||
if (base < 2 || base > 36) {
|
while (--nleft != 0) {
|
||||||
*result = '\0';
|
if ((*dst++ = *src++) == '\0')
|
||||||
return result;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char * ptr = result, *ptr1 = result, tmp_char;
|
/* Not enough room in dst, add NUL and traverse rest of src. */
|
||||||
signed short tmp_value;
|
if (nleft == 0) {
|
||||||
|
if (dsize != 0)
|
||||||
do {
|
*dst = '\0'; /* NUL-terminate dst */
|
||||||
tmp_value = value;
|
while (*src++)
|
||||||
value /= base;
|
;
|
||||||
*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - value * base)];
|
|
||||||
} while (value);
|
|
||||||
|
|
||||||
// Apply negative sign
|
|
||||||
if (tmp_value < 0) {
|
|
||||||
*ptr++ = '-';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*ptr-- = '\0';
|
return (src - osrc - 1); /* count does not include NUL */
|
||||||
while (ptr1 < ptr) {
|
|
||||||
tmp_char = *ptr;
|
|
||||||
*ptr-- = *ptr1;
|
|
||||||
*ptr1++ = tmp_char;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* ltoa(long value, char* result, int base) {
|
|
||||||
return itoa((int)value, result, base);
|
|
||||||
}
|
|
||||||
|
|
||||||
char* ultoa(unsigned long value, char* result, int base) {
|
|
||||||
return itoa((unsigned int)value, result, base);
|
|
||||||
}
|
|
||||||
|
|
||||||
char * dtostrf(double number, signed char width, unsigned char prec, char *s) {
|
|
||||||
bool negative = false;
|
|
||||||
|
|
||||||
char* out = s;
|
|
||||||
|
|
||||||
int fillme = width; // how many cells to fill for the integer part
|
|
||||||
if (prec > 0) {
|
|
||||||
fillme -= (prec+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle negative numbers
|
|
||||||
if (number < 0.0) {
|
|
||||||
negative = true;
|
|
||||||
fillme--;
|
|
||||||
number = -number;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Round correctly so that print(1.999, 2) prints as "2.00"
|
|
||||||
// I optimized out most of the divisions
|
|
||||||
double rounding = 2.0;
|
|
||||||
for (unsigned int i = 0; i < prec; ++i)
|
|
||||||
rounding *= 10.0;
|
|
||||||
rounding = 1.0 / rounding;
|
|
||||||
|
|
||||||
number += rounding;
|
|
||||||
|
|
||||||
// Figure out how big our number really is
|
|
||||||
double tenpow = 1.0;
|
|
||||||
int digitcount = 1;
|
|
||||||
double nextpow;
|
|
||||||
while (number >= (nextpow = (10.0 * tenpow))) {
|
|
||||||
tenpow = nextpow;
|
|
||||||
digitcount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// minimal compensation for possible lack of precision (#7087 addition)
|
|
||||||
// number *= 1 + std::numeric_limits<decltype(number)>::epsilon();
|
|
||||||
|
|
||||||
number /= tenpow;
|
|
||||||
fillme -= digitcount;
|
|
||||||
|
|
||||||
// Pad unused cells with spaces
|
|
||||||
while (fillme-- > 0) {
|
|
||||||
*out++ = ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle negative sign
|
|
||||||
if (negative) *out++ = '-';
|
|
||||||
|
|
||||||
// Print the digits, and if necessary, the decimal point
|
|
||||||
digitcount += prec;
|
|
||||||
int8_t digit = 0;
|
|
||||||
while (digitcount-- > 0) {
|
|
||||||
digit = (int8_t)number;
|
|
||||||
if (digit > 9) digit = 9; // insurance
|
|
||||||
*out++ = (char)('0' | digit);
|
|
||||||
if ((digitcount == prec) && (prec > 0)) {
|
|
||||||
*out++ = '.';
|
|
||||||
}
|
|
||||||
number -= digit;
|
|
||||||
number *= 10.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure the string is terminated
|
|
||||||
*out = 0;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
String::String(const char *cstr)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
if (cstr) copy(cstr, strlen(cstr));
|
|
||||||
}
|
|
||||||
|
|
||||||
String::String(const String &value)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
*this = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
String::String(const __FlashStringHelper *pstr)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
*this = pstr;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
|
||||||
String::String(String &&rval)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
move(rval);
|
|
||||||
}
|
|
||||||
String::String(StringSumHelper &&rval)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
move(rval);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
String::String(char c)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
char buf[2];
|
|
||||||
buf[0] = c;
|
|
||||||
buf[1] = 0;
|
|
||||||
*this = buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
String::String(unsigned char value, unsigned char base)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
char buf[1 + 8 * sizeof(unsigned char)];
|
|
||||||
itoa(value, buf, base);
|
|
||||||
*this = buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
String::String(int value, unsigned char base)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
char buf[2 + 8 * sizeof(int)];
|
|
||||||
itoa(value, buf, base);
|
|
||||||
*this = buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
String::String(unsigned int value, unsigned char base)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
char buf[1 + 8 * sizeof(unsigned int)];
|
|
||||||
itoa(value, buf, base);
|
|
||||||
*this = buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
String::String(long value, unsigned char base)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
char buf[2 + 8 * sizeof(long)];
|
|
||||||
ltoa(value, buf, base);
|
|
||||||
*this = buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
String::String(unsigned long value, unsigned char base)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
char buf[1 + 8 * sizeof(unsigned long)];
|
|
||||||
ultoa(value, buf, base);
|
|
||||||
*this = buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
String::String(float value, unsigned char decimalPlaces)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
char buf[33];
|
|
||||||
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
String::String(double value, unsigned char decimalPlaces)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
char buf[33];
|
|
||||||
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
String::~String()
|
|
||||||
{
|
|
||||||
free(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************/
|
|
||||||
/* Memory Management */
|
|
||||||
/*********************************************/
|
|
||||||
|
|
||||||
inline void String::init(void)
|
|
||||||
{
|
|
||||||
buffer = NULL;
|
|
||||||
capacity = 0;
|
|
||||||
len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void String::invalidate(void)
|
|
||||||
{
|
|
||||||
if (buffer) free(buffer);
|
|
||||||
buffer = NULL;
|
|
||||||
capacity = len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::reserve(unsigned int size)
|
|
||||||
{
|
|
||||||
if (buffer && capacity >= size) return 1;
|
|
||||||
if (changeBuffer(size)) {
|
|
||||||
if (len == 0) buffer[0] = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::changeBuffer(unsigned int maxStrLen)
|
|
||||||
{
|
|
||||||
char *newbuffer = (char *)realloc(buffer, maxStrLen + 1);
|
|
||||||
if (newbuffer) {
|
|
||||||
buffer = newbuffer;
|
|
||||||
capacity = maxStrLen;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************/
|
|
||||||
/* Copy and Move */
|
|
||||||
/*********************************************/
|
|
||||||
|
|
||||||
String & String::copy(const char *cstr, unsigned int length)
|
|
||||||
{
|
|
||||||
if (!reserve(length)) {
|
|
||||||
invalidate();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
len = length;
|
|
||||||
strcpy(buffer, cstr);
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
String & String::copy(const char *pstr, unsigned int length)
|
* Appends src to string dst of size siz (unlike strncat, siz is the
|
||||||
{
|
* full size of dst, not space left). At most siz-1 characters
|
||||||
if (!reserve(length)) {
|
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
|
||||||
invalidate();
|
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
||||||
return *this;
|
* If retval >= siz, truncation occurred.
|
||||||
}
|
*
|
||||||
len = length;
|
* https://github.com/freebsd/freebsd/blob/master/sys/libkern/strlcat.c
|
||||||
strcpy_P(buffer, pstr);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
*/
|
*/
|
||||||
|
size_t strlcat(char * dst, const char * src, size_t siz) {
|
||||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
char * d = dst;
|
||||||
void String::move(String &rhs)
|
const char * s = src;
|
||||||
{
|
size_t n = siz;
|
||||||
if (buffer) {
|
size_t dlen;
|
||||||
if (rhs && capacity >= rhs.len) {
|
|
||||||
strcpy(buffer, rhs.buffer);
|
/* Find the end of dst and adjust bytes left but don't go past end */
|
||||||
len = rhs.len;
|
while (n-- != 0 && *d != '\0')
|
||||||
rhs.len = 0;
|
d++;
|
||||||
return;
|
dlen = d - dst;
|
||||||
} else {
|
n = siz - dlen;
|
||||||
free(buffer);
|
|
||||||
}
|
if (n == 0)
|
||||||
}
|
return (dlen + strlen(s));
|
||||||
buffer = rhs.buffer;
|
while (*s != '\0') {
|
||||||
capacity = rhs.capacity;
|
if (n != 1) {
|
||||||
len = rhs.len;
|
*d++ = *s;
|
||||||
rhs.buffer = NULL;
|
n--;
|
||||||
rhs.capacity = 0;
|
}
|
||||||
rhs.len = 0;
|
s++;
|
||||||
}
|
}
|
||||||
#endif
|
*d = '\0';
|
||||||
|
|
||||||
String & String::operator = (const String &rhs)
|
return (dlen + (s - src)); /* count does not include NUL */
|
||||||
{
|
|
||||||
if (this == &rhs) return *this;
|
|
||||||
|
|
||||||
if (rhs.buffer) copy(rhs.buffer, rhs.len);
|
|
||||||
else invalidate();
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
|
||||||
String & String::operator = (String &&rval)
|
|
||||||
{
|
|
||||||
if (this != &rval) move(rval);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
String & String::operator = (StringSumHelper &&rval)
|
|
||||||
{
|
|
||||||
if (this != &rval) move(rval);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
String & String::operator = (const char *cstr)
|
|
||||||
{
|
|
||||||
if (cstr) copy(cstr, strlen(cstr));
|
|
||||||
else invalidate();
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
String & String::operator = (const __FlashStringHelper *pstr)
|
|
||||||
{
|
|
||||||
// if (pstr) copy(pstr, strlen_P((PGM_P)pstr));
|
|
||||||
// else invalidate();
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************/
|
|
||||||
/* concat */
|
|
||||||
/*********************************************/
|
|
||||||
|
|
||||||
unsigned char String::concat(const String &s)
|
|
||||||
{
|
|
||||||
return concat(s.buffer, s.len);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::concat(const char *cstr, unsigned int length)
|
|
||||||
{
|
|
||||||
unsigned int newlen = len + length;
|
|
||||||
if (!cstr) return 0;
|
|
||||||
if (length == 0) return 1;
|
|
||||||
if (!reserve(newlen)) return 0;
|
|
||||||
strcpy(buffer + len, cstr);
|
|
||||||
len = newlen;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::concat(const char *cstr)
|
|
||||||
{
|
|
||||||
if (!cstr) return 0;
|
|
||||||
return concat(cstr, strlen(cstr));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::concat(char c)
|
|
||||||
{
|
|
||||||
char buf[2];
|
|
||||||
buf[0] = c;
|
|
||||||
buf[1] = 0;
|
|
||||||
return concat(buf, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::concat(unsigned char num)
|
|
||||||
{
|
|
||||||
char buf[1 + 3 * sizeof(unsigned char)];
|
|
||||||
itoa(num, buf, 10);
|
|
||||||
return concat(buf, strlen(buf));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::concat(int num)
|
|
||||||
{
|
|
||||||
char buf[2 + 3 * sizeof(int)];
|
|
||||||
itoa(num, buf, 10);
|
|
||||||
return concat(buf, strlen(buf));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::concat(unsigned int num)
|
|
||||||
{
|
|
||||||
char buf[1 + 3 * sizeof(unsigned int)];
|
|
||||||
itoa(num, buf, 10);
|
|
||||||
return concat(buf, strlen(buf));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::concat(long num)
|
|
||||||
{
|
|
||||||
char buf[2 + 3 * sizeof(long)];
|
|
||||||
ltoa(num, buf, 10);
|
|
||||||
return concat(buf, strlen(buf));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::concat(unsigned long num)
|
|
||||||
{
|
|
||||||
char buf[1 + 3 * sizeof(unsigned long)];
|
|
||||||
ultoa(num, buf, 10);
|
|
||||||
return concat(buf, strlen(buf));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::concat(float num)
|
|
||||||
{
|
|
||||||
char buf[20];
|
|
||||||
char* string = dtostrf(num, 4, 2, buf);
|
|
||||||
return concat(string, strlen(string));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::concat(double num)
|
|
||||||
{
|
|
||||||
char buf[20];
|
|
||||||
char* string = dtostrf(num, 4, 2, buf);
|
|
||||||
return concat(string, strlen(string));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::concat(const __FlashStringHelper * str)
|
|
||||||
{
|
|
||||||
if (!str) return 0;
|
|
||||||
int length = strlen_P((const char *) str);
|
|
||||||
if (length == 0) return 1;
|
|
||||||
unsigned int newlen = len + length;
|
|
||||||
if (!reserve(newlen)) return 0;
|
|
||||||
strcpy_P(buffer + len, (const char *) str);
|
|
||||||
len = newlen;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************/
|
|
||||||
/* Concatenate */
|
|
||||||
/*********************************************/
|
|
||||||
|
|
||||||
StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs)
|
|
||||||
{
|
|
||||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
|
||||||
if (!a.concat(rhs.buffer, rhs.len)) a.invalidate();
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr)
|
|
||||||
{
|
|
||||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
|
||||||
if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate();
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringSumHelper & operator + (const StringSumHelper &lhs, char c)
|
|
||||||
{
|
|
||||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
|
||||||
if (!a.concat(c)) a.invalidate();
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num)
|
|
||||||
{
|
|
||||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
|
||||||
if (!a.concat(num)) a.invalidate();
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringSumHelper & operator + (const StringSumHelper &lhs, int num)
|
|
||||||
{
|
|
||||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
|
||||||
if (!a.concat(num)) a.invalidate();
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num)
|
|
||||||
{
|
|
||||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
|
||||||
if (!a.concat(num)) a.invalidate();
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringSumHelper & operator + (const StringSumHelper &lhs, long num)
|
|
||||||
{
|
|
||||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
|
||||||
if (!a.concat(num)) a.invalidate();
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num)
|
|
||||||
{
|
|
||||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
|
||||||
if (!a.concat(num)) a.invalidate();
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringSumHelper & operator + (const StringSumHelper &lhs, float num)
|
|
||||||
{
|
|
||||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
|
||||||
if (!a.concat(num)) a.invalidate();
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringSumHelper & operator + (const StringSumHelper &lhs, double num)
|
|
||||||
{
|
|
||||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
|
||||||
if (!a.concat(num)) a.invalidate();
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs)
|
|
||||||
{
|
|
||||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
|
||||||
if (!a.concat(rhs)) a.invalidate();
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************/
|
|
||||||
/* Comparison */
|
|
||||||
/*********************************************/
|
|
||||||
|
|
||||||
int String::compareTo(const String &s) const
|
|
||||||
{
|
|
||||||
if (!buffer || !s.buffer) {
|
|
||||||
if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer;
|
|
||||||
if (buffer && len > 0) return *(unsigned char *)buffer;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return strcmp(buffer, s.buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::isEmpty() const {
|
|
||||||
return (len == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::equals(const String &s2) const
|
|
||||||
{
|
|
||||||
return (len == s2.len && compareTo(s2) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::equals(const char *cstr) const
|
|
||||||
{
|
|
||||||
if (len == 0) return (cstr == NULL || *cstr == 0);
|
|
||||||
if (cstr == NULL) return buffer[0] == 0;
|
|
||||||
return strcmp(buffer, cstr) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::operator<(const String &rhs) const
|
|
||||||
{
|
|
||||||
return compareTo(rhs) < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::operator>(const String &rhs) const
|
|
||||||
{
|
|
||||||
return compareTo(rhs) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::operator<=(const String &rhs) const
|
|
||||||
{
|
|
||||||
return compareTo(rhs) <= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::operator>=(const String &rhs) const
|
|
||||||
{
|
|
||||||
return compareTo(rhs) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::equalsIgnoreCase( const String &s2 ) const
|
|
||||||
{
|
|
||||||
if (this == &s2) return 1;
|
|
||||||
if (len != s2.len) return 0;
|
|
||||||
if (len == 0) return 1;
|
|
||||||
const char *p1 = buffer;
|
|
||||||
const char *p2 = s2.buffer;
|
|
||||||
while (*p1) {
|
|
||||||
if (tolower(*p1++) != tolower(*p2++)) return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::startsWith( const String &s2 ) const
|
|
||||||
{
|
|
||||||
if (len < s2.len) return 0;
|
|
||||||
return startsWith(s2, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::startsWith( const String &s2, unsigned int offset ) const
|
|
||||||
{
|
|
||||||
if (offset > len - s2.len || !buffer || !s2.buffer) return 0;
|
|
||||||
return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char String::endsWith( const String &s2 ) const
|
|
||||||
{
|
|
||||||
if ( len < s2.len || !buffer || !s2.buffer) return 0;
|
|
||||||
return strcmp(&buffer[len - s2.len], s2.buffer) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************/
|
|
||||||
/* Character Access */
|
|
||||||
/*********************************************/
|
|
||||||
|
|
||||||
char String::charAt(unsigned int loc) const
|
|
||||||
{
|
|
||||||
return operator[](loc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void String::setCharAt(unsigned int loc, char c)
|
|
||||||
{
|
|
||||||
if (loc < len) buffer[loc] = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
char & String::operator[](unsigned int index)
|
|
||||||
{
|
|
||||||
static char dummy_writable_char;
|
|
||||||
if (index >= len || !buffer) {
|
|
||||||
dummy_writable_char = 0;
|
|
||||||
return dummy_writable_char;
|
|
||||||
}
|
|
||||||
return buffer[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
char String::operator[]( unsigned int index ) const
|
|
||||||
{
|
|
||||||
if (index >= len || !buffer) return 0;
|
|
||||||
return buffer[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const
|
|
||||||
{
|
|
||||||
if (!bufsize || !buf) return;
|
|
||||||
if (index >= len) {
|
|
||||||
buf[0] = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
unsigned int n = bufsize - 1;
|
|
||||||
if (n > len - index) n = len - index;
|
|
||||||
strncpy((char *)buf, buffer + index, n);
|
|
||||||
buf[n] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************/
|
|
||||||
/* Search */
|
|
||||||
/*********************************************/
|
|
||||||
|
|
||||||
int String::indexOf(char c) const
|
|
||||||
{
|
|
||||||
return indexOf(c, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int String::indexOf( char ch, unsigned int fromIndex ) const
|
|
||||||
{
|
|
||||||
if (fromIndex >= len) return -1;
|
|
||||||
const char* temp = strchr(buffer + fromIndex, ch);
|
|
||||||
if (temp == NULL) return -1;
|
|
||||||
return temp - buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
int String::indexOf(const String &s2) const
|
|
||||||
{
|
|
||||||
return indexOf(s2, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int String::indexOf(const String &s2, unsigned int fromIndex) const
|
|
||||||
{
|
|
||||||
if (fromIndex >= len) return -1;
|
|
||||||
const char *found = strstr(buffer + fromIndex, s2.buffer);
|
|
||||||
if (found == NULL) return -1;
|
|
||||||
return found - buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
int String::lastIndexOf( char theChar ) const
|
|
||||||
{
|
|
||||||
return lastIndexOf(theChar, len - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int String::lastIndexOf(char ch, unsigned int fromIndex) const
|
|
||||||
{
|
|
||||||
if (fromIndex >= len) return -1;
|
|
||||||
char tempchar = buffer[fromIndex + 1];
|
|
||||||
buffer[fromIndex + 1] = '\0';
|
|
||||||
char* temp = strrchr( buffer, ch );
|
|
||||||
buffer[fromIndex + 1] = tempchar;
|
|
||||||
if (temp == NULL) return -1;
|
|
||||||
return temp - buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
int String::lastIndexOf(const String &s2) const
|
|
||||||
{
|
|
||||||
return lastIndexOf(s2, len - s2.len);
|
|
||||||
}
|
|
||||||
|
|
||||||
int String::lastIndexOf(const String &s2, unsigned int fromIndex) const
|
|
||||||
{
|
|
||||||
if (s2.len == 0 || len == 0 || s2.len > len) return -1;
|
|
||||||
if (fromIndex >= len) fromIndex = len - 1;
|
|
||||||
int found = -1;
|
|
||||||
for (char *p = buffer; p <= buffer + fromIndex; p++) {
|
|
||||||
p = strstr(p, s2.buffer);
|
|
||||||
if (!p) break;
|
|
||||||
if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer;
|
|
||||||
}
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
String String::substring(unsigned int left, unsigned int right) const
|
|
||||||
{
|
|
||||||
if (left > right) {
|
|
||||||
unsigned int temp = right;
|
|
||||||
right = left;
|
|
||||||
left = temp;
|
|
||||||
}
|
|
||||||
String out;
|
|
||||||
if (left >= len) return out;
|
|
||||||
if (right > len) right = len;
|
|
||||||
char temp = buffer[right]; // save the replaced character
|
|
||||||
buffer[right] = '\0';
|
|
||||||
out = buffer + left; // pointer arithmetic
|
|
||||||
buffer[right] = temp; //restore character
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************/
|
|
||||||
/* Modification */
|
|
||||||
/*********************************************/
|
|
||||||
|
|
||||||
void String::replace(char find, char replace)
|
|
||||||
{
|
|
||||||
if (!buffer) return;
|
|
||||||
for (char *p = buffer; *p; p++) {
|
|
||||||
if (*p == find) *p = replace;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void String::replace(const String& find, const String& replace)
|
|
||||||
{
|
|
||||||
if (len == 0 || find.len == 0) return;
|
|
||||||
int diff = replace.len - find.len;
|
|
||||||
char *readFrom = buffer;
|
|
||||||
char *foundAt;
|
|
||||||
if (diff == 0) {
|
|
||||||
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
|
|
||||||
memcpy(foundAt, replace.buffer, replace.len);
|
|
||||||
readFrom = foundAt + replace.len;
|
|
||||||
}
|
|
||||||
} else if (diff < 0) {
|
|
||||||
char *writeTo = buffer;
|
|
||||||
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
|
|
||||||
unsigned int n = foundAt - readFrom;
|
|
||||||
memcpy(writeTo, readFrom, n);
|
|
||||||
writeTo += n;
|
|
||||||
memcpy(writeTo, replace.buffer, replace.len);
|
|
||||||
writeTo += replace.len;
|
|
||||||
readFrom = foundAt + find.len;
|
|
||||||
len += diff;
|
|
||||||
}
|
|
||||||
strcpy(writeTo, readFrom);
|
|
||||||
} else {
|
|
||||||
unsigned int size = len; // compute size needed for result
|
|
||||||
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
|
|
||||||
readFrom = foundAt + find.len;
|
|
||||||
size += diff;
|
|
||||||
}
|
|
||||||
if (size == len) return;
|
|
||||||
if (size > capacity && !changeBuffer(size)) return;
|
|
||||||
int index = len - 1;
|
|
||||||
while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
|
|
||||||
readFrom = buffer + index + find.len;
|
|
||||||
memmove(readFrom + diff, readFrom, len - (readFrom - buffer));
|
|
||||||
len += diff;
|
|
||||||
buffer[len] = 0;
|
|
||||||
memcpy(buffer + index, replace.buffer, replace.len);
|
|
||||||
index--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void String::remove(unsigned int index){
|
|
||||||
// Pass the biggest integer as the count. The remove method
|
|
||||||
// below will take care of truncating it at the end of the
|
|
||||||
// string.
|
|
||||||
remove(index, (unsigned int)-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void String::remove(unsigned int index, unsigned int count){
|
|
||||||
if (index >= len) { return; }
|
|
||||||
if (count <= 0) { return; }
|
|
||||||
if (count > len - index) { count = len - index; }
|
|
||||||
char *writeTo = buffer + index;
|
|
||||||
len = len - count;
|
|
||||||
strncpy(writeTo, buffer + index + count,len - index);
|
|
||||||
buffer[len] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void String::toLowerCase(void)
|
|
||||||
{
|
|
||||||
if (!buffer) return;
|
|
||||||
for (char *p = buffer; *p; p++) {
|
|
||||||
*p = tolower(*p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void String::toUpperCase(void)
|
|
||||||
{
|
|
||||||
if (!buffer) return;
|
|
||||||
for (char *p = buffer; *p; p++) {
|
|
||||||
*p = toupper(*p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void String::trim(void)
|
|
||||||
{
|
|
||||||
if (!buffer || len == 0) return;
|
|
||||||
char *begin = buffer;
|
|
||||||
while (isspace(*begin)) begin++;
|
|
||||||
char *end = buffer + len - 1;
|
|
||||||
while (isspace(*end) && end >= begin) end--;
|
|
||||||
len = end + 1 - begin;
|
|
||||||
if (begin > buffer) memcpy(buffer, begin, len);
|
|
||||||
buffer[len] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************/
|
|
||||||
/* Parsing / Conversion */
|
|
||||||
/*********************************************/
|
|
||||||
|
|
||||||
long String::toInt(void) const
|
|
||||||
{
|
|
||||||
if (buffer) return atol(buffer);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float String::toFloat(void) const
|
|
||||||
{
|
|
||||||
return float(toDouble());
|
|
||||||
}
|
|
||||||
|
|
||||||
double String::toDouble(void) const
|
|
||||||
{
|
|
||||||
if (buffer) return atof(buffer);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
@@ -1,236 +1,69 @@
|
|||||||
/*
|
|
||||||
WString.h - String library for Wiring & Arduino
|
|
||||||
...mostly rewritten by Paul Stoffregen...
|
|
||||||
Copyright (c) 2009-10 Hernando Barragan. All right reserved.
|
|
||||||
Copyright 2011, Paul Stoffregen, paul@pjrc.com
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
#ifndef WSTRING_H
|
||||||
modify it under the terms of the GNU Lesser General Public
|
#define WSTRING_H
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
#include <string>
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
// Reproduces Arduino's String class
|
||||||
License along with this library; if not, write to the Free Software
|
class String {
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
public:
|
||||||
*/
|
String & operator+=(const char * rhs) {
|
||||||
|
_str += rhs;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef String_class_h
|
size_t length() const {
|
||||||
#define String_class_h
|
return _str.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
String(const char * str = "")
|
||||||
|
: _str(str) {
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * c_str() const {
|
||||||
|
return _str.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const char * s) const {
|
||||||
|
return _str == s;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend std::ostream & operator<<(std::ostream & lhs, const ::String & rhs) {
|
||||||
|
lhs << rhs._str;
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
bool isEmpty() {
|
||||||
|
return _str.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// long toInt() const {
|
||||||
|
// return std::stol(_str);
|
||||||
|
// }
|
||||||
|
|
||||||
|
bool equals(const char * s) {
|
||||||
|
return _str == s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string _str;
|
||||||
|
};
|
||||||
|
|
||||||
|
class StringSumHelper;
|
||||||
|
|
||||||
|
inline bool operator==(const std::string & lhs, const ::String & rhs) {
|
||||||
|
return lhs == rhs.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t strlcpy(char * __restrict dst, const char * __restrict src, size_t dsize);
|
||||||
|
size_t strlcat(char * dst, const char * src, size_t siz);
|
||||||
|
|
||||||
#define strlen_P strlen
|
#define strlen_P strlen
|
||||||
#define strncpy_P strncpy
|
#define strncpy_P strncpy
|
||||||
#define strcmp_P strcmp
|
#define strcmp_P strcmp
|
||||||
#define strcpy_P strcpy
|
#define strcpy_P strcpy
|
||||||
|
|
||||||
// #include "pgmspace.h"
|
|
||||||
// #include "noniso.h"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
// When compiling programs with this class, the following gcc parameters
|
|
||||||
// dramatically increase performance and memory (RAM) efficiency, typically
|
|
||||||
// with little or no increase in code size.
|
|
||||||
// -felide-constructors
|
|
||||||
// -std=c++0x
|
|
||||||
|
|
||||||
class __FlashStringHelper;
|
|
||||||
// #define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
|
|
||||||
|
|
||||||
// An inherited class for holding the result of a concatenation. These
|
|
||||||
// result objects are assumed to be writable by subsequent concatenations.
|
|
||||||
class StringSumHelper;
|
|
||||||
|
|
||||||
// The string class
|
|
||||||
class String
|
|
||||||
{
|
|
||||||
// use a function pointer to allow for "if (s)" without the
|
|
||||||
// complications of an operator bool(). for more information, see:
|
|
||||||
// http://www.artima.com/cppsource/safebool.html
|
|
||||||
typedef void (String::*StringIfHelperType)() const;
|
|
||||||
void StringIfHelper() const {}
|
|
||||||
|
|
||||||
public:
|
|
||||||
// constructors
|
|
||||||
// creates a copy of the initial value.
|
|
||||||
// if the initial value is null or invalid, or if memory allocation
|
|
||||||
// fails, the string will be marked as invalid (i.e. "if (s)" will
|
|
||||||
// be false).
|
|
||||||
String(const char *cstr = "");
|
|
||||||
String(const String &str);
|
|
||||||
String(const __FlashStringHelper *str);
|
|
||||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
|
||||||
String(String &&rval);
|
|
||||||
String(StringSumHelper &&rval);
|
|
||||||
#endif
|
#endif
|
||||||
explicit String(char c);
|
|
||||||
explicit String(unsigned char, unsigned char base=10);
|
|
||||||
explicit String(int, unsigned char base=10);
|
|
||||||
explicit String(unsigned int, unsigned char base=10);
|
|
||||||
explicit String(long, unsigned char base=10);
|
|
||||||
explicit String(unsigned long, unsigned char base=10);
|
|
||||||
explicit String(float, unsigned char decimalPlaces=2);
|
|
||||||
explicit String(double, unsigned char decimalPlaces=2);
|
|
||||||
~String(void);
|
|
||||||
|
|
||||||
// memory management
|
|
||||||
// return true on success, false on failure (in which case, the string
|
|
||||||
// is left unchanged). reserve(0), if successful, will validate an
|
|
||||||
// invalid string (i.e., "if (s)" will be true afterwards)
|
|
||||||
unsigned char reserve(unsigned int size);
|
|
||||||
inline unsigned int length(void) const {return len;}
|
|
||||||
|
|
||||||
// creates a copy of the assigned value. if the value is null or
|
|
||||||
// invalid, or if the memory allocation fails, the string will be
|
|
||||||
// marked as invalid ("if (s)" will be false).
|
|
||||||
String & operator = (const String &rhs);
|
|
||||||
String & operator = (const char *cstr);
|
|
||||||
String & operator = (const __FlashStringHelper *str);
|
|
||||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
|
||||||
String & operator = (String &&rval);
|
|
||||||
String & operator = (StringSumHelper &&rval);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// concatenate (works w/ built-in types)
|
|
||||||
|
|
||||||
// returns true on success, false on failure (in which case, the string
|
|
||||||
// is left unchanged). if the argument is null or invalid, the
|
|
||||||
// concatenation is considered unsucessful.
|
|
||||||
unsigned char concat(const String &str);
|
|
||||||
unsigned char concat(const char *cstr);
|
|
||||||
unsigned char concat(char c);
|
|
||||||
unsigned char concat(unsigned char c);
|
|
||||||
unsigned char concat(int num);
|
|
||||||
unsigned char concat(unsigned int num);
|
|
||||||
unsigned char concat(long num);
|
|
||||||
unsigned char concat(unsigned long num);
|
|
||||||
unsigned char concat(float num);
|
|
||||||
unsigned char concat(double num);
|
|
||||||
unsigned char concat(const __FlashStringHelper * str);
|
|
||||||
|
|
||||||
// if there's not enough memory for the concatenated value, the string
|
|
||||||
// will be left unchanged (but this isn't signalled in any way)
|
|
||||||
String & operator += (const String &rhs) {concat(rhs); return (*this);}
|
|
||||||
String & operator += (const char *cstr) {concat(cstr); return (*this);}
|
|
||||||
String & operator += (char c) {concat(c); return (*this);}
|
|
||||||
String & operator += (unsigned char num) {concat(num); return (*this);}
|
|
||||||
String & operator += (int num) {concat(num); return (*this);}
|
|
||||||
String & operator += (unsigned int num) {concat(num); return (*this);}
|
|
||||||
String & operator += (long num) {concat(num); return (*this);}
|
|
||||||
String & operator += (unsigned long num) {concat(num); return (*this);}
|
|
||||||
String & operator += (float num) {concat(num); return (*this);}
|
|
||||||
String & operator += (double num) {concat(num); return (*this);}
|
|
||||||
String & operator += (const __FlashStringHelper *str){concat(str); return (*this);}
|
|
||||||
|
|
||||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs);
|
|
||||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr);
|
|
||||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, char c);
|
|
||||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num);
|
|
||||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, int num);
|
|
||||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num);
|
|
||||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, long num);
|
|
||||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num);
|
|
||||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, float num);
|
|
||||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, double num);
|
|
||||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs);
|
|
||||||
|
|
||||||
// comparison (only works w/ Strings and "strings")
|
|
||||||
operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; }
|
|
||||||
int compareTo(const String &s) const;
|
|
||||||
unsigned char equals(const String &s) const;
|
|
||||||
unsigned char equals(const char *cstr) const;
|
|
||||||
unsigned char operator == (const String &rhs) const {return equals(rhs);}
|
|
||||||
unsigned char operator == (const char *cstr) const {return equals(cstr);}
|
|
||||||
unsigned char operator != (const String &rhs) const {return !equals(rhs);}
|
|
||||||
unsigned char operator != (const char *cstr) const {return !equals(cstr);}
|
|
||||||
unsigned char operator < (const String &rhs) const;
|
|
||||||
unsigned char operator > (const String &rhs) const;
|
|
||||||
unsigned char operator <= (const String &rhs) const;
|
|
||||||
unsigned char operator >= (const String &rhs) const;
|
|
||||||
unsigned char equalsIgnoreCase(const String &s) const;
|
|
||||||
unsigned char startsWith( const String &prefix) const;
|
|
||||||
unsigned char startsWith(const String &prefix, unsigned int offset) const;
|
|
||||||
unsigned char endsWith(const String &suffix) const;
|
|
||||||
|
|
||||||
// character acccess
|
|
||||||
char charAt(unsigned int index) const;
|
|
||||||
void setCharAt(unsigned int index, char c);
|
|
||||||
char operator [] (unsigned int index) const;
|
|
||||||
char& operator [] (unsigned int index);
|
|
||||||
void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const;
|
|
||||||
void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const
|
|
||||||
{ getBytes((unsigned char *)buf, bufsize, index); }
|
|
||||||
const char* c_str() const { return buffer; }
|
|
||||||
char* begin() { return buffer; }
|
|
||||||
char* end() { return buffer + length(); }
|
|
||||||
const char* begin() const { return c_str(); }
|
|
||||||
const char* end() const { return c_str() + length(); }
|
|
||||||
|
|
||||||
// search
|
|
||||||
int indexOf( char ch ) const;
|
|
||||||
int indexOf( char ch, unsigned int fromIndex ) const;
|
|
||||||
int indexOf( const String &str ) const;
|
|
||||||
int indexOf( const String &str, unsigned int fromIndex ) const;
|
|
||||||
int lastIndexOf( char ch ) const;
|
|
||||||
int lastIndexOf( char ch, unsigned int fromIndex ) const;
|
|
||||||
int lastIndexOf( const String &str ) const;
|
|
||||||
int lastIndexOf( const String &str, unsigned int fromIndex ) const;
|
|
||||||
String substring( unsigned int beginIndex ) const { return substring(beginIndex, len); };
|
|
||||||
String substring( unsigned int beginIndex, unsigned int endIndex ) const;
|
|
||||||
|
|
||||||
// modification
|
|
||||||
void replace(char find, char replace);
|
|
||||||
void replace(const String& find, const String& replace);
|
|
||||||
void remove(unsigned int index);
|
|
||||||
void remove(unsigned int index, unsigned int count);
|
|
||||||
void toLowerCase(void);
|
|
||||||
void toUpperCase(void);
|
|
||||||
void trim(void);
|
|
||||||
|
|
||||||
// parsing/conversion
|
|
||||||
long toInt(void) const;
|
|
||||||
float toFloat(void) const;
|
|
||||||
double toDouble(void) const;
|
|
||||||
|
|
||||||
unsigned char isEmpty() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
char *buffer; // the actual char array
|
|
||||||
unsigned int capacity; // the array length minus one (for the '\0')
|
|
||||||
unsigned int len; // the String length (not counting the '\0')
|
|
||||||
protected:
|
|
||||||
void init(void);
|
|
||||||
void invalidate(void);
|
|
||||||
unsigned char changeBuffer(unsigned int maxStrLen);
|
|
||||||
unsigned char concat(const char *cstr, unsigned int length);
|
|
||||||
|
|
||||||
// copy and move
|
|
||||||
String & copy(const char *cstr, unsigned int length);
|
|
||||||
String & copy(const __FlashStringHelper *pstr, unsigned int length);
|
|
||||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
|
||||||
void move(String &rhs);
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
class StringSumHelper : public String
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
StringSumHelper(const String &s) : String(s) {}
|
|
||||||
StringSumHelper(const char *p) : String(p) {}
|
|
||||||
StringSumHelper(char c) : String(c) {}
|
|
||||||
StringSumHelper(unsigned char num) : String(num) {}
|
|
||||||
StringSumHelper(int num) : String(num) {}
|
|
||||||
StringSumHelper(unsigned int num) : String(num) {}
|
|
||||||
StringSumHelper(long num) : String(num) {}
|
|
||||||
StringSumHelper(unsigned long num) : String(num) {}
|
|
||||||
StringSumHelper(float num) : String(num) {}
|
|
||||||
StringSumHelper(double num) : String(num) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // String_class_h
|
|
||||||
@@ -70,7 +70,9 @@ void EMSESPDevicesService::device_data(AsyncWebServerRequest * request, JsonVari
|
|||||||
uint8_t id = json["id"]; // get id from selected table row
|
uint8_t id = json["id"]; // get id from selected table row
|
||||||
|
|
||||||
AsyncJsonResponse * response = new AsyncJsonResponse(false, 1024);
|
AsyncJsonResponse * response = new AsyncJsonResponse(false, 1024);
|
||||||
|
#ifndef EMSESP_STANDALONE
|
||||||
EMSESP::device_info(id, (JsonObject &)response->getRoot());
|
EMSESP::device_info(id, (JsonObject &)response->getRoot());
|
||||||
|
#endif
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -197,7 +197,6 @@ void System::syslog_init() {
|
|||||||
syslog_mark_interval_ = settings.syslog_mark_interval;
|
syslog_mark_interval_ = settings.syslog_mark_interval;
|
||||||
syslog_host_ = settings.syslog_host;
|
syslog_host_ = settings.syslog_host;
|
||||||
});
|
});
|
||||||
EMSESP::esp8266React.getWiFiSettingsService()->read([&](WiFiSettings & wifiSettings) { syslog_.hostname(wifiSettings.hostname.c_str()); });
|
|
||||||
|
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
syslog_.start(); // syslog service re-start
|
syslog_.start(); // syslog service re-start
|
||||||
@@ -210,6 +209,7 @@ void System::syslog_init() {
|
|||||||
syslog_.log_level((uuid::log::Level)syslog_level_);
|
syslog_.log_level((uuid::log::Level)syslog_level_);
|
||||||
syslog_.mark_interval(syslog_mark_interval_);
|
syslog_.mark_interval(syslog_mark_interval_);
|
||||||
syslog_.destination(addr);
|
syslog_.destination(addr);
|
||||||
|
EMSESP::esp8266React.getWiFiSettingsService()->read([&](WiFiSettings & wifiSettings) { syslog_.hostname(wifiSettings.hostname.c_str()); });
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,7 +249,11 @@ void System::start() {
|
|||||||
|
|
||||||
// returns true if OTA is uploading
|
// returns true if OTA is uploading
|
||||||
bool System::upload_status() {
|
bool System::upload_status() {
|
||||||
|
#if defined(EMSESP_STANDALONE)
|
||||||
|
return false;
|
||||||
|
#elif
|
||||||
return upload_status_ || Update.isRunning();
|
return upload_status_ || Update.isRunning();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::upload_status(bool in_progress) {
|
void System::upload_status(bool in_progress) {
|
||||||
@@ -380,11 +384,13 @@ int8_t System::wifi_quality() {
|
|||||||
void System::show_users(uuid::console::Shell & shell) {
|
void System::show_users(uuid::console::Shell & shell) {
|
||||||
shell.printfln(F("Users:"));
|
shell.printfln(F("Users:"));
|
||||||
|
|
||||||
|
#ifndef EMSESP_STANDALONE
|
||||||
EMSESP::esp8266React.getSecuritySettingsService()->read([&](SecuritySettings & securitySettings) {
|
EMSESP::esp8266React.getSecuritySettingsService()->read([&](SecuritySettings & securitySettings) {
|
||||||
for (User user : securitySettings.users) {
|
for (User user : securitySettings.users) {
|
||||||
shell.printfln(F(" username: %s, password: %s, is_admin: %s"), user.username.c_str(), user.password.c_str(), user.admin ? F("yes") : F("no"));
|
shell.printfln(F(" username: %s, password: %s, is_admin: %s"), user.username.c_str(), user.password.c_str(), user.admin ? F("yes") : F("no"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
#endif
|
||||||
|
|
||||||
shell.println();
|
shell.println();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(EMSESP_STANADLONE)
|
#if defined(EMSESP_STANDALONE)
|
||||||
|
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user