Merge branch 'main' into feature/event-CAN-timing

This commit is contained in:
Daniel 2024-03-30 10:43:58 +02:00
commit d17e677a90
18 changed files with 171 additions and 66 deletions

View file

@ -374,11 +374,19 @@ void update_values_battery() { //This function maps all the values fetched via
system_remaining_capacity_Wh = (battery_energy_content_maximum_kWh * 1000); // Convert kWh to Wh
system_max_charge_power_W = (battery_max_charge_amperage * system_battery_voltage_dV);
if ((battery_max_charge_amperage * system_battery_voltage_dV) > 65000) {
system_max_charge_power_W = 65000;
} else {
system_max_charge_power_W = (battery_max_charge_amperage * system_battery_voltage_dV);
}
system_max_discharge_power_W = (battery_max_discharge_amperage * system_battery_voltage_dV);
if ((battery_max_discharge_amperage * system_battery_voltage_dV) > 65000) {
system_max_discharge_power_W = 65000;
} else {
system_max_discharge_power_W = (battery_max_discharge_amperage * system_battery_voltage_dV);
}
battery_power = (system_battery_current_dA * (system_battery_voltage_dV / 10));
battery_power = (system_battery_current_dA * (system_battery_voltage_dV / 100));
system_active_power_W = battery_power;
@ -429,8 +437,8 @@ void receive_can_battery(CAN_frame_t rx_frame) {
case 0x112: //BMS [10ms] Status Of High-Voltage Battery - 2
battery_awake = true;
CANstillAlive = 12; //This message is only sent if 30C (Wakeup pin on battery) is energized with 12V
battery_current = ((rx_frame.data.u8[1] << 8 | rx_frame.data.u8[0]) / 10) - 819; //Amps
battery_volts = (rx_frame.data.u8[3] << 8 | rx_frame.data.u8[2]); //500.0 V
battery_current = (rx_frame.data.u8[1] << 8 | rx_frame.data.u8[0]) - 8192; //deciAmps (-819.2 to 819.0A)
battery_volts = (rx_frame.data.u8[3] << 8 | rx_frame.data.u8[2]); //500.0 V
battery_HVBatt_SOC = ((rx_frame.data.u8[5] & 0x0F) << 8 | rx_frame.data.u8[4]);
battery_request_open_contactors = (rx_frame.data.u8[5] & 0xC0) >> 6;
battery_request_open_contactors_instantly = (rx_frame.data.u8[6] & 0x03);
@ -463,7 +471,7 @@ void receive_can_battery(CAN_frame_t rx_frame) {
break;
case 0x2BD: //BMS [100ms] Status diagnosis high voltage - 1
battery_awake = true;
if (calculateCRC(rx_frame, 3, 0x15) != rx_frame.data.u8[0]) {
if (calculateCRC(rx_frame, rx_frame.FIR.B.DLC, 0x15) != rx_frame.data.u8[0]) {
//If calculated CRC does not match transmitted CRC, increase CANerror counter
CANerror++;
break;

View file

@ -1,5 +1,3 @@
This is commit 9ab44bd from https://github.com/ayushsharma82/ElegantOTA
<p><br/></p>
<p align="center"><img src="/docs/feature.png?sanitize=true&raw=true" width="700"></p>

View file

@ -15,7 +15,7 @@
"maintainer": true
}
],
"version": "3.1.0",
"version": "3.1.1",
"frameworks": "arduino",
"platforms": ["espressif8266", "espressif32", "raspberrypi"]
}

View file

@ -1,5 +1,5 @@
name=ElegantOTA
version=3.1.0
version=3.1.1
author=Ayush Sharma
category=Communication
maintainer=Ayush Sharma <asrocks5@gmail.com>

View file

@ -16,6 +16,7 @@ import requests
import hashlib
from urllib.parse import urlparse
import time
from requests.auth import HTTPDigestAuth
Import("env")
try:
@ -29,7 +30,9 @@ except ImportError:
def on_upload(source, target, env):
firmware_path = str(source[0])
upload_url_compatibility = env.GetProjectOption('upload_url')
auth = None
upload_url_compatibility = env.GetProjectOption('custom_upload_url')
upload_url = upload_url_compatibility.replace("/update", "")
with open(firmware_path, 'rb') as firmware:
@ -50,12 +53,37 @@ def on_upload(source, target, env):
'Referer': f'{upload_url}/update',
'Connection': 'keep-alive'
}
start_response = requests.get(start_url, headers=start_headers)
if start_response.status_code != 200:
print("start-request faild " + str(start_response.status_code))
return
checkAuthResponse = requests.get(f"{upload_url_compatibility}/update")
if checkAuthResponse.status_code == 401:
try:
username = env.GetProjectOption('custom_username')
password = env.GetProjectOption('custom_password')
except:
username = None
password = None
print("No authentication values specified.")
print('Please, add some Options in your .ini file like: \n\ncustom_username=username\ncustom_password=password\n')
if username is None or password is None:
print("Authentication required, but no credentials provided.")
return
print("Serverconfiguration: authentication needed.")
auth = HTTPDigestAuth(username, password)
doUpdateAuth = requests.get(start_url, headers=start_headers, auth=auth)
if doUpdateAuth.status_code != 200:
print("authentication faild " + str(doUpdateAuth.status_code))
return
print("Authentication successfull")
else:
auth = None
print("Serverconfiguration: autentication not needed.")
doUpdate = requests.get(start_url, headers=start_headers)
if doUpdate.status_code != 200:
print("start-request faild " + str(doUpdate.status_code))
return
firmware.seek(0)
encoder = MultipartEncoder(fields={
@ -87,7 +115,7 @@ def on_upload(source, target, env):
}
response = requests.post(f"{upload_url}/ota/upload", data=monitor, headers=post_headers)
response = requests.post(f"{upload_url}/ota/upload", data=monitor, headers=post_headers, auth=auth)
bar.close()
time.sleep(0.1)
@ -100,4 +128,4 @@ def on_upload(source, target, env):
tqdm.write(message)
env.Replace(UPLOADCMD=on_upload)
env.Replace(UPLOADCMD=on_upload)

View file

@ -226,11 +226,11 @@
#define ARDUINOJSON_BIN2ALPHA_1111() P
#define ARDUINOJSON_BIN2ALPHA_(A, B, C, D) ARDUINOJSON_BIN2ALPHA_##A##B##C##D()
#define ARDUINOJSON_BIN2ALPHA(A, B, C, D) ARDUINOJSON_BIN2ALPHA_(A, B, C, D)
#define ARDUINOJSON_VERSION "7.0.3"
#define ARDUINOJSON_VERSION "7.0.4"
#define ARDUINOJSON_VERSION_MAJOR 7
#define ARDUINOJSON_VERSION_MINOR 0
#define ARDUINOJSON_VERSION_REVISION 3
#define ARDUINOJSON_VERSION_MACRO V703
#define ARDUINOJSON_VERSION_REVISION 4
#define ARDUINOJSON_VERSION_MACRO V704
#ifndef ARDUINOJSON_VERSION_NAMESPACE
# define ARDUINOJSON_VERSION_NAMESPACE \
ARDUINOJSON_CONCAT4(ARDUINOJSON_VERSION_MACRO, \
@ -7498,11 +7498,11 @@ ARDUINOJSON_END_PUBLIC_NAMESPACE
#define ARDUINOJSON_NAMESPACE _Pragma ("GCC warning \"ARDUINOJSON_NAMESPACE is deprecated, use ArduinoJson instead\"") ArduinoJson
#define JSON_ARRAY_SIZE(N) _Pragma ("GCC warning \"JSON_ARRAY_SIZE is deprecated, you don't need to compute the size anymore\"") (ArduinoJson::detail::sizeofArray(N))
#define JSON_OBJECT_SIZE(N) _Pragma ("GCC warning \"JSON_OBJECT_SIZE is deprecated, you don't need to compute the size anymore\"") (ArduinoJson::detail::sizeofObject(N))
#define JSON_STRING_SIZE(N) _Pragma ("GCC warning \"JSON_STRING_SIZE is deprecated, you don't need to compute the size anymore\"") (ArduinoJson::detail::sizeofString(N))
#define JSON_STRING_SIZE(N) _Pragma ("GCC warning \"JSON_STRING_SIZE is deprecated, you don't need to compute the size anymore\"") (N+1)
#else
#define JSON_ARRAY_SIZE(N) (ArduinoJson::detail::sizeofArray(N))
#define JSON_OBJECT_SIZE(N) (ArduinoJson::detail::sizeofObject(N))
#define JSON_STRING_SIZE(N) (ArduinoJson::detail::sizeofString(N))
#define JSON_STRING_SIZE(N) (N+1)
#endif
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
template <size_t N>

View file

@ -98,7 +98,7 @@ public:
// Return number of coils set to 0 (or OFF)
uint16_t coilsSetOFF() const;
#if !ISLINUX
#if !LINUX
// Helper function to dump out coils in logical order
void print(const char *label, Print& s);
#endif

View file

@ -29,8 +29,8 @@ public:
ModbusBridge();
// Constructors for the RTU variant. Parameters as are for ModbusServerRTU
ModbusBridge(HardwareSerial& serial, uint32_t timeout, int rtsPin = -1);
ModbusBridge(HardwareSerial& serial, uint32_t timeout, RTScallback rts);
ModbusBridge(uint32_t timeout, int rtsPin = -1);
ModbusBridge(uint32_t timeout, RTScallback rts);
// Destructor
~ModbusBridge();
@ -85,13 +85,13 @@ ModbusBridge<SERVERCLASS>::ModbusBridge() :
// Constructors for RTU variant
template<typename SERVERCLASS>
ModbusBridge<SERVERCLASS>::ModbusBridge(HardwareSerial& serial, uint32_t timeout, int rtsPin) :
SERVERCLASS(serial, timeout, rtsPin) { }
ModbusBridge<SERVERCLASS>::ModbusBridge(uint32_t timeout, int rtsPin) :
SERVERCLASS(timeout, rtsPin) { }
// Alternate constructors for RTU variant
template<typename SERVERCLASS>
ModbusBridge<SERVERCLASS>::ModbusBridge(HardwareSerial& serial, uint32_t timeout, RTScallback rts) :
SERVERCLASS(serial, timeout, rts) { }
ModbusBridge<SERVERCLASS>::ModbusBridge(uint32_t timeout, RTScallback rts) :
SERVERCLASS(timeout, rts) { }
// Destructor
template<typename SERVERCLASS>

View file

@ -10,7 +10,7 @@
// #define LOCAL_LOG_LEVEL LOG_LEVEL_VERBOSE
#include "Logging.h"
// Constructor takes Serial reference and optional DE/RE pin
// Constructor takes an optional DE/RE pin and queue size
ModbusClientRTU::ModbusClientRTU(int8_t rtsPin, uint16_t queueLimit) :
ModbusClient(),
MR_serial(nullptr),
@ -32,7 +32,7 @@ ModbusClientRTU::ModbusClientRTU(int8_t rtsPin, uint16_t queueLimit) :
}
}
// Alternative constructor takes Serial reference and RTS callback function
// Alternative constructor takes an RTS callback function
ModbusClientRTU::ModbusClientRTU(RTScallback rts, uint16_t queueLimit) :
ModbusClient(),
MR_serial(nullptr),
@ -54,20 +54,20 @@ ModbusClientRTU::~ModbusClientRTU() {
}
// begin: start worker task - general version
void ModbusClientRTU::begin(Stream& serial, uint32_t baudRate, int coreID) {
void ModbusClientRTU::begin(Stream& serial, uint32_t baudRate, int coreID, uint32_t userInterval) {
MR_serial = &serial;
doBegin(baudRate, coreID);
doBegin(baudRate, coreID, userInterval);
}
// begin: start worker task - HardwareSerial version
void ModbusClientRTU::begin(HardwareSerial& serial, int coreID) {
void ModbusClientRTU::begin(HardwareSerial& serial, int coreID, uint32_t userInterval) {
MR_serial = &serial;
uint32_t baudRate = serial.baudRate();
serial.setRxFIFOFull(1);
doBegin(baudRate, coreID);
doBegin(baudRate, coreID, userInterval);
}
void ModbusClientRTU::doBegin(uint32_t baudRate, int coreID) {
void ModbusClientRTU::doBegin(uint32_t baudRate, int coreID, uint32_t userInterval) {
// Task already running? End it in case
end();
@ -77,11 +77,16 @@ void ModbusClientRTU::doBegin(uint32_t baudRate, int coreID) {
// Set minimum interval time
MR_interval = RTUutils::calculateInterval(baudRate);
// If user defined interval is longer, use that
if (MR_interval < userInterval) {
MR_interval = userInterval;
}
// Create unique task name
char taskName[18];
snprintf(taskName, 18, "Modbus%02XRTU", instanceCounter);
// Start task to handle the queue
xTaskCreatePinnedToCore((TaskFunction_t)&handleConnection, taskName, 4096, this, 6, &worker, coreID >= 0 ? coreID : NULL);
xTaskCreatePinnedToCore((TaskFunction_t)&handleConnection, taskName, CLIENT_TASK_STACK, this, 6, &worker, coreID >= 0 ? coreID : NULL);
LOG_D("Client task %d started. Interval=%d\n", (uint32_t)worker, MR_interval);
}
@ -102,6 +107,7 @@ void ModbusClientRTU::end() {
// Kill task
vTaskDelete(worker);
LOG_D("Client task %d killed.\n", (uint32_t)worker);
worker = nullptr;
}
}
@ -140,6 +146,14 @@ uint32_t ModbusClientRTU::pendingRequests() {
return requests.size();
}
// Remove all pending request from queue
void ModbusClientRTU::clearQueue()
{
std::queue<RequestEntry> empty;
LOCK_GUARD(lockGuard, qLock);
std::swap(requests, empty);
}
// Base addRequest taking a preformatted data buffer and length as parameters
Error ModbusClientRTU::addRequestM(ModbusMessage msg, uint32_t token) {
Error rc = SUCCESS; // Return value

View file

@ -21,19 +21,19 @@ using std::queue;
class ModbusClientRTU : public ModbusClient {
public:
// Constructor takes Serial reference and optional DE/RE pin and queue limit
// Constructor takes an optional DE/RE pin and queue limit
explicit ModbusClientRTU(int8_t rtsPin = -1, uint16_t queueLimit = 100);
// Alternative Constructor takes Serial reference and RTS line toggle callback
// Alternative Constructor takes an RTS line toggle callback
explicit ModbusClientRTU(RTScallback rts, uint16_t queueLimit = 100);
// Destructor: clean up queue, task etc.
~ModbusClientRTU();
// begin: start worker task
void begin(Stream& serial, uint32_t baudrate, int coreID = -1);
void begin(Stream& serial, uint32_t baudrate, int coreID = -1, uint32_t userInterval = 0);
// Special variant for HardwareSerial
void begin(HardwareSerial& serial, int coreID = -1);
void begin(HardwareSerial& serial, int coreID = -1, uint32_t userInterval = 0);
// end: stop the worker
void end();
@ -56,6 +56,9 @@ public:
// Return number of unprocessed requests in queue
uint32_t pendingRequests();
// Remove all pending request from queue
void clearQueue();
// addBroadcastMessage: create a fire-and-forget message to all servers on the RTU bus
Error addBroadcastMessage(const uint8_t *data, uint8_t len);
@ -84,7 +87,7 @@ protected:
ModbusMessage receive(const ModbusMessage request);
// start background task
void doBegin(uint32_t baudRate, int coreID);
void doBegin(uint32_t baudRate, int coreID, uint32_t userInterval);
void isInstance() { return; } // make class instantiable
queue<RequestEntry> requests; // Queue to hold requests to be processed

View file

@ -18,30 +18,48 @@ void ModbusServer::registerWorker(uint8_t serverID, uint8_t functionCode, MBSwor
// getWorker: if a worker function is registered, return its address, nullptr otherwise
MBSworker ModbusServer::getWorker(uint8_t serverID, uint8_t functionCode) {
bool serverFound = false;
LOG_D("Need worker for %02X-%02X : ", serverID, functionCode);
// Search the FC map associated with the serverID
auto svmap = workerMap.find(serverID);
// Is there one?
if (svmap != workerMap.end()) {
serverFound = true;
// No explicit serverID entry found, but we may have one for ANY_SERVER
} else {
svmap = workerMap.find(ANY_SERVER);
if (svmap != workerMap.end()) {
serverFound = true;
serverID = ANY_SERVER;
}
}
// Did we find a serverID?
if (serverFound) {
// Yes. Now look for the function code in the inner map
bool functionCodeFound = false;
auto fcmap = svmap->second.find(functionCode);;
// Found it?
if (fcmap != svmap->second.end()) {
// Yes. Return the function pointer for it.
LOG_D("Worker found for %02X/%02X\n", serverID, functionCode);
return fcmap->second;
functionCodeFound = true;
// No, no explicit worker found, but may be there is one for ANY_FUNCTION_CODE?
} else {
fcmap = svmap->second.find(ANY_FUNCTION_CODE);;
// Found it?
if (fcmap != svmap->second.end()) {
// Yes. Return the function pointer for it.
LOG_D("Worker found for %02X/ANY\n", serverID);
return fcmap->second;
functionCodeFound = true;
functionCode = ANY_FUNCTION_CODE;
}
}
if (functionCodeFound) {
// Yes. Return the function pointer for it.
LOGRAW_D("Worker found for %02X/%02X\n", serverID, functionCode);
return fcmap->second;
}
}
// No matching function pointer found
LOG_D("No matching worker found\n");
LOGRAW_D("No matching worker found\n");
return nullptr;
}
@ -68,16 +86,29 @@ bool ModbusServer::unregisterWorker(uint8_t serverID, uint8_t functionCode) {
return (numEntries ? true : false);
}
// isServerFor: if any worker function is registered for the given serverID, return true
bool ModbusServer::isServerFor(uint8_t serverID) {
// Search the FC map for the serverID
auto svmap = workerMap.find(serverID);
// Is it there? Then return true
if (svmap != workerMap.end()) return true;
// No, serverID was not found. Return false
// isServerFor: if a worker function is registered for the given serverID, return true
// functionCode defaults to ANY_FUNCTION_CODE and will yield true for any function code,
// including ANY_FUNCTION_CODE :D
bool ModbusServer::isServerFor(uint8_t serverID, uint8_t functionCode) {
// Check if there is a non-nullptr function for the given combination
if (getWorker(serverID, functionCode)) {
return true;
}
return false;
}
// isServerFor: short version to look up if the server is known at all
bool ModbusServer::isServerFor(uint8_t serverID) {
// Check if there is a non-nullptr function for the given combination
auto svmap = workerMap.find(serverID);
// Is there one?
if (svmap != workerMap.end()) {
return true;
}
return false;
}
// getMessageCount: read number of messages processed
uint32_t ModbusServer::getMessageCount() {
return messageCount;
@ -104,6 +135,7 @@ ModbusMessage ModbusServer::localRequest(ModbusMessage msg) {
uint8_t functionCode = msg.getFunctionCode();
LOG_D("Local request for %02X/%02X\n", serverID, functionCode);
HEXDUMP_V("Request", msg.data(), msg.size());
messageCount++;
// Try to get a worker for the request
MBSworker worker = getWorker(serverID, functionCode);
// Did we get one?
@ -129,6 +161,9 @@ ModbusMessage ModbusServer::localRequest(ModbusMessage msg) {
}
}
HEXDUMP_V("Response", m.data(), m.size());
if (m.getError() != SUCCESS) {
errorCount++;
}
return m;
} else {
LOG_D("No worker found. Error response.\n");
@ -140,11 +175,13 @@ ModbusMessage ModbusServer::localRequest(ModbusMessage msg) {
// No. Respond with "Invalid server ID"
m.setError(serverID, functionCode, INVALID_SERVER);
}
errorCount++;
return m;
}
// We should never get here...
LOG_C("Internal problem: should not get here!\n");
m.setError(serverID, functionCode, UNDEFINED_ERROR);
errorCount++;
return m;
}

View file

@ -42,7 +42,10 @@ public:
// Returns true if the worker was found and removed
bool unregisterWorker(uint8_t serverID, uint8_t functionCode = 0);
// isServerFor: if any worker function is registered for the given serverID, return true
// isServerFor: if a worker function is registered for the given serverID, return true
bool isServerFor(uint8_t serverID, uint8_t functionCode);
// isServerFor: short version to look up if the server is known at all
bool isServerFor(uint8_t serverID);
// getMessageCount: read number of messages processed

View file

@ -64,32 +64,37 @@ ModbusServerRTU::~ModbusServerRTU() {
}
// start: create task with RTU server - general version
void ModbusServerRTU::begin(Stream& serial, uint32_t baudRate, int coreID) {
void ModbusServerRTU::begin(Stream& serial, uint32_t baudRate, int coreID, uint32_t userInterval) {
MSRserial = &serial;
doBegin(baudRate, coreID);
doBegin(baudRate, coreID, userInterval);
}
// start: create task with RTU server - HardwareSerial versions
void ModbusServerRTU::begin(HardwareSerial& serial, int coreID) {
void ModbusServerRTU::begin(HardwareSerial& serial, int coreID, uint32_t userInterval) {
MSRserial = &serial;
uint32_t baudRate = serial.baudRate();
serial.setRxFIFOFull(1);
doBegin(baudRate, coreID);
doBegin(baudRate, coreID, userInterval);
}
void ModbusServerRTU::doBegin(uint32_t baudRate, int coreID) {
void ModbusServerRTU::doBegin(uint32_t baudRate, int coreID, uint32_t userInterval) {
// Task already running? Stop it in case.
end();
// Set minimum interval time
MSRinterval = RTUutils::calculateInterval(baudRate);
// If user defined interval is longer, use that
if (MSRinterval < userInterval) {
MSRinterval = userInterval;
}
// Create unique task name
char taskName[18];
snprintf(taskName, 18, "MBsrv%02XRTU", instanceCounter);
// Start task to handle the client
xTaskCreatePinnedToCore((TaskFunction_t)&serve, taskName, 4096, this, 8, &serverTask, coreID >= 0 ? coreID : NULL);
xTaskCreatePinnedToCore((TaskFunction_t)&serve, taskName, SERVER_TASK_STACK, this, 8, &serverTask, coreID >= 0 ? coreID : NULL);
LOG_D("Server task %d started. Interval=%d\n", (uint32_t)serverTask, MSRinterval);
}
@ -180,10 +185,12 @@ void ModbusServerRTU::serve(ModbusServerRTU *myServer) {
}
// Is it a broadcast?
if (request[0] == 0) {
LOG_D("Broadcast!\n");
// Yes. Do we have a listener?
if (myServer->listener) {
// Yes. call it
myServer->listener(request);
LOG_D("Broadcast served.\n");
}
// else we simply ignore it
} else {

View file

@ -32,8 +32,8 @@ public:
~ModbusServerRTU();
// begin: create task with RTU server to accept requests
void begin(Stream& serial, uint32_t baudRate, int coreID = -1);
void begin(HardwareSerial& serial, int coreID = -1);
void begin(Stream& serial, uint32_t baudRate, int coreID = -1, uint32_t userInterval = 0);
void begin(HardwareSerial& serial, int coreID = -1, uint32_t userInterval = 0);
// end: kill server task
void end();
@ -64,7 +64,7 @@ protected:
inline void isInstance() { } // Make class instantiable
// internal common begin function
void doBegin(uint32_t baudRate, int coreID);
void doBegin(uint32_t baudRate, int coreID, uint32_t userInterval);
static uint8_t instanceCounter; // Number of RTU servers created (for task names)
TaskHandle_t serverTask; // task of the started server

View file

@ -50,7 +50,7 @@ FCType FCT::getType(uint8_t functionCode) {
return table[functionCode & 0x7F];
}
// setType: change the type of a function code.
// redefineType: change the type of a function code.
// This is possible only for the codes undefined yet and will return
// the effective type
FCType FCT::redefineType(uint8_t functionCode, const FCType type) {

View file

@ -84,6 +84,9 @@ enum Error : uint8_t {
UNDEFINED_ERROR = 0xFF // otherwise uncovered communication error
};
// Readable expression for the "illegal" server ID of 0
#define ANY_SERVER 0x00
#ifndef MINIMAL
// Constants for float and double re-ordering

View file

@ -9,6 +9,7 @@
// #define LOCAL_LOG_LEVEL LOG_LEVEL_VERBOSE
#include "Logging.h"
#if HAS_FREERTOS
// calcCRC: calculate Modbus CRC16 on a given array of bytes
uint16_t RTUutils::calcCRC(const uint8_t *data, uint16_t len) {
// CRC16 pre-calculated tables
@ -463,3 +464,4 @@ const char RTUutils::ASCIIread[] = {
const char RTUutils::ASCIIwrite[] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46
};
#endif

View file

@ -13,6 +13,8 @@
#define HAS_ETHERNET 1
#define IS_LINUX 0
#define NEED_UART_PATCH 1
const unsigned int SERVER_TASK_STACK = 4096;
const unsigned int CLIENT_TASK_STACK = 4096;
/* === ESP8266 DEFINITIONS AND MACROS === */
#elif defined(ESP8266)