mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-09-12 01:24:04 +00:00
[Cleanup] Move structs to separate .h/.cpp files
This commit is contained in:
@@ -14,4 +14,5 @@ struct CRCStruct{
|
||||
uint32_t numberOfCRCBytes=0;
|
||||
};
|
||||
|
||||
|
||||
#endif // DATASTRUCTS_CRCSTRUCT_H
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "DataStructs/ControllerSettingsStruct.h"
|
||||
|
||||
#include "ESPEasy_common.h"
|
||||
#include "ESPEasy_fdwdecl.h"
|
||||
#include "DataStructs/ControllerSettingsStruct.h"
|
||||
#include "DataStructs/ESPEasyLimits.h"
|
||||
#include "DataStructs/ESPEasyDefaults.h"
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
* ControllerSettingsStruct definition
|
||||
\*********************************************************************************************/
|
||||
#include <Arduino.h>
|
||||
#include <memory> // For std::shared_ptr
|
||||
|
||||
class IPAddress;
|
||||
class WiFiClient;
|
||||
class WiFiUDP;
|
||||
@@ -24,6 +26,31 @@ class WiFiUDP;
|
||||
#define CONTROLLER_CLIENTTIMEOUT_DFLT 100
|
||||
|
||||
|
||||
|
||||
// ********************************************************************************
|
||||
// IDs of controller settings, used to generate web forms
|
||||
// ********************************************************************************
|
||||
|
||||
#define CONTROLLER_USE_DNS 1
|
||||
#define CONTROLLER_HOSTNAME 2
|
||||
#define CONTROLLER_IP 3
|
||||
#define CONTROLLER_PORT 4
|
||||
#define CONTROLLER_USER 5
|
||||
#define CONTROLLER_PASS 6
|
||||
#define CONTROLLER_MIN_SEND_INTERVAL 7
|
||||
#define CONTROLLER_MAX_QUEUE_DEPTH 8
|
||||
#define CONTROLLER_MAX_RETRIES 9
|
||||
#define CONTROLLER_FULL_QUEUE_ACTION 10
|
||||
#define CONTROLLER_CHECK_REPLY 12
|
||||
#define CONTROLLER_SUBSCRIBE 13
|
||||
#define CONTROLLER_PUBLISH 14
|
||||
#define CONTROLLER_LWT_TOPIC 15
|
||||
#define CONTROLLER_LWT_CONNECT_MESSAGE 16
|
||||
#define CONTROLLER_LWT_DISCONNECT_MESSAGE 17
|
||||
#define CONTROLLER_TIMEOUT 18
|
||||
#define CONTROLLER_SAMPLE_SET_INITIATOR 19
|
||||
#define CONTROLLER_ENABLED 20 // Keep this as last, is used to loop over all parameters
|
||||
|
||||
struct ControllerSettingsStruct
|
||||
{
|
||||
ControllerSettingsStruct();
|
||||
@@ -74,5 +101,5 @@ private:
|
||||
typedef std::shared_ptr<ControllerSettingsStruct> ControllerSettingsStruct_ptr_type;
|
||||
#define MakeControllerSettings(T) ControllerSettingsStruct_ptr_type ControllerSettingsStruct_ptr(new ControllerSettingsStruct());\
|
||||
ControllerSettingsStruct& T = *ControllerSettingsStruct_ptr;
|
||||
|
||||
|
||||
#endif // DATASTRUCTS_CONTROLLERSETTINGSSTRUCT_H
|
||||
@@ -0,0 +1,66 @@
|
||||
#ifndef DATASTRUCTS_DEVICESTRUCTS_H
|
||||
#define DATASTRUCTS_DEVICESTRUCTS_H
|
||||
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <vector>
|
||||
|
||||
#define DEVICE_TYPE_SINGLE 1 // connected through 1 datapin
|
||||
#define DEVICE_TYPE_DUAL 2 // connected through 2 datapins
|
||||
#define DEVICE_TYPE_TRIPLE 3 // connected through 3 datapins
|
||||
#define DEVICE_TYPE_ANALOG 10 // AIN/tout pin
|
||||
#define DEVICE_TYPE_I2C 20 // connected through I2C
|
||||
#define DEVICE_TYPE_DUMMY 99 // Dummy device, has no physical connection
|
||||
|
||||
// Used for VType
|
||||
#define SENSOR_TYPE_NONE 0
|
||||
#define SENSOR_TYPE_SINGLE 1
|
||||
#define SENSOR_TYPE_TEMP_HUM 2
|
||||
#define SENSOR_TYPE_TEMP_BARO 3
|
||||
#define SENSOR_TYPE_TEMP_HUM_BARO 4
|
||||
#define SENSOR_TYPE_DUAL 5
|
||||
#define SENSOR_TYPE_TRIPLE 6
|
||||
#define SENSOR_TYPE_QUAD 7
|
||||
#define SENSOR_TYPE_TEMP_EMPTY_BARO 8
|
||||
#define SENSOR_TYPE_SWITCH 10
|
||||
#define SENSOR_TYPE_DIMMER 11
|
||||
#define SENSOR_TYPE_LONG 20
|
||||
#define SENSOR_TYPE_WIND 21
|
||||
#define SENSOR_TYPE_STRING 22
|
||||
|
||||
/*********************************************************************************************\
|
||||
* DeviceStruct
|
||||
\*********************************************************************************************/
|
||||
struct DeviceStruct
|
||||
{
|
||||
DeviceStruct() :
|
||||
Number(0), Type(0), VType(SENSOR_TYPE_NONE), Ports(0), ValueCount(0),
|
||||
PullUpOption(false), InverseLogicOption(false), FormulaOption(false),
|
||||
Custom(false), SendDataOption(false), GlobalSyncOption(false),
|
||||
TimerOption(false), TimerOptional(false), DecimalsOnly(false) {}
|
||||
|
||||
bool connectedToGPIOpins() {
|
||||
return (Type >= DEVICE_TYPE_SINGLE && Type <= DEVICE_TYPE_TRIPLE);
|
||||
}
|
||||
|
||||
|
||||
byte Number; // Plugin ID number. (PLUGIN_ID_xxx)
|
||||
byte Type; // How the device is connected. e.g. DEVICE_TYPE_SINGLE => connected through 1 datapin
|
||||
byte VType; // Type of value the plugin will return, used only for Domoticz
|
||||
byte Ports; // Port to use when device has multiple I/O pins (N.B. not used much)
|
||||
byte ValueCount; // The number of output values of a plugin. The value should match the number of keys PLUGIN_VALUENAME1_xxx
|
||||
bool PullUpOption : 1; // Allow to set internal pull-up resistors.
|
||||
bool InverseLogicOption : 1; // Allow to invert the boolean state (e.g. a switch)
|
||||
bool FormulaOption : 1; // Allow to enter a formula to convert values during read. (not possible with Custom enabled)
|
||||
bool Custom : 1;
|
||||
bool SendDataOption : 1; // Allow to send data to a controller.
|
||||
bool GlobalSyncOption : 1; // No longer used. Was used for ESPeasy values sync between nodes
|
||||
bool TimerOption : 1; // Allow to set the "Interval" timer for the plugin.
|
||||
bool TimerOptional : 1; // When taskdevice timer is not set and not optional, use default "Interval" delay (Settings.Delay)
|
||||
bool DecimalsOnly : 1; // Allow to set the number of decimals (otherwise treated a 0 decimals)
|
||||
};
|
||||
typedef std::vector<DeviceStruct> DeviceVector;
|
||||
DeviceVector Device;
|
||||
|
||||
|
||||
#endif // DATASTRUCTS_DEVICESTRUCTS_H
|
||||
@@ -183,11 +183,6 @@
|
||||
#define DEFAULT_USE_DST false // (true|false) Use Daily Time Saving
|
||||
#endif
|
||||
|
||||
#define LOG_TO_SERIAL 1
|
||||
#define LOG_TO_SYSLOG 2
|
||||
#define LOG_TO_WEBLOG 3
|
||||
#define LOG_TO_SDCARD 4
|
||||
|
||||
#ifndef DEFAULT_SYSLOG_IP
|
||||
#define DEFAULT_SYSLOG_IP "" // Syslog IP Address
|
||||
#endif
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
#ifndef DATASTRUCTS_ESPEASY_LIMITS_H
|
||||
#define DATASTRUCTS_ESPEASY_LIMITS_H
|
||||
|
||||
#if defined(PLUGIN_BUILD_TESTING) || defined(PLUGIN_BUILD_DEV)
|
||||
#define DEVICES_MAX 95
|
||||
#else
|
||||
#ifdef ESP32
|
||||
#define DEVICES_MAX 85
|
||||
#else
|
||||
#define DEVICES_MAX 60
|
||||
#endif
|
||||
#endif
|
||||
// ***********************************************************************
|
||||
// * These limits have direct impact on the settings files
|
||||
// * Do not change them!
|
||||
// * Else settings files will no longer be compatible with official builds
|
||||
// ***********************************************************************
|
||||
|
||||
#if defined(ESP8266)
|
||||
#define TASKS_MAX 12 // max 12!
|
||||
@@ -23,25 +19,68 @@
|
||||
#define CONTROLLER_MAX 3 // max 4!
|
||||
#define NOTIFICATION_MAX 3 // max 4!
|
||||
#define VARS_PER_TASK 4
|
||||
#define PLUGIN_MAX DEVICES_MAX
|
||||
#define PLUGIN_CONFIGVAR_MAX 8
|
||||
#define PLUGIN_CONFIGFLOATVAR_MAX 4
|
||||
#define PLUGIN_CONFIGLONGVAR_MAX 4
|
||||
#define PLUGIN_EXTRACONFIGVAR_MAX 16
|
||||
#define NAME_FORMULA_LENGTH_MAX 40
|
||||
|
||||
|
||||
|
||||
// ***********************************************************************
|
||||
// * The next limits affect memory usage
|
||||
// ***********************************************************************
|
||||
|
||||
#if defined(PLUGIN_BUILD_TESTING) || defined(PLUGIN_BUILD_DEV)
|
||||
#define DEVICES_MAX 95
|
||||
#else
|
||||
#ifdef ESP32
|
||||
#define DEVICES_MAX 85
|
||||
#else
|
||||
#define DEVICES_MAX 60
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define PLUGIN_MAX DEVICES_MAX
|
||||
#define CPLUGIN_MAX 20
|
||||
#define NPLUGIN_MAX 4
|
||||
|
||||
#define UNIT_MAX 254 // unit 255 = broadcast
|
||||
#define CUSTOM_VARS_MAX 16
|
||||
|
||||
|
||||
|
||||
// ***********************************************************************
|
||||
// * Limits regarding Rules
|
||||
// ***********************************************************************
|
||||
|
||||
#define RULES_TIMER_MAX 8
|
||||
//#define PINSTATE_TABLE_MAX 32
|
||||
#define RULES_MAX_SIZE 2048
|
||||
#define RULES_MAX_NESTING_LEVEL 3
|
||||
#define RULESETS_MAX 4
|
||||
#define RULES_BUFFER_SIZE 64
|
||||
#define NAME_FORMULA_LENGTH_MAX 40
|
||||
#define RULES_IF_MAX_NESTING_LEVEL 4
|
||||
#define CUSTOM_VARS_MAX 16
|
||||
|
||||
#define RULES_IF_MAX_NESTING_LEVEL 4
|
||||
|
||||
|
||||
#define INPUT_COMMAND_SIZE 240 // Affects maximum command length in rules and other commands
|
||||
// FIXME TD-er: INPUT_COMMAND_SIZE is also used in commands where simply a check for valid parameter is needed
|
||||
// and some may need less memory. (which is stack allocated)
|
||||
|
||||
|
||||
// ***********************************************************************
|
||||
// * Other operational limits
|
||||
// ***********************************************************************
|
||||
|
||||
#define MAX_FLASHWRITES_PER_DAY 100 // per 24 hour window
|
||||
#define UDP_PACKETSIZE_MAX 2048
|
||||
#define TIMER_GRATUITOUS_ARP_MAX 5000
|
||||
|
||||
#define UNIT_NUMBER_MAX 9999 // Stored in Settings.Unit
|
||||
#define DOMOTICZ_MAX_IDX 999999999 // Looks like it is an unsigned int, so could be up to 4 bln.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
#include "DataStructs/ExtraTaskSettingsStruct.h"
|
||||
|
||||
#include "ESPEasy_common.h"
|
||||
|
||||
ExtraTaskSettingsStruct::ExtraTaskSettingsStruct() : TaskIndex(TASKS_MAX) {
|
||||
clear();
|
||||
}
|
||||
|
||||
void ExtraTaskSettingsStruct::clear() {
|
||||
TaskIndex = TASKS_MAX;
|
||||
ZERO_FILL(TaskDeviceName);
|
||||
for (byte i = 0; i < VARS_PER_TASK; ++i) {
|
||||
TaskDeviceValueDecimals[i] = 2;
|
||||
ZERO_FILL(TaskDeviceFormula[i]);
|
||||
ZERO_FILL(TaskDeviceValueNames[i]);
|
||||
}
|
||||
for (byte i = 0; i < PLUGIN_EXTRACONFIGVAR_MAX; ++i) {
|
||||
TaskDevicePluginConfigLong[i] = 0;
|
||||
TaskDevicePluginConfig[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ExtraTaskSettingsStruct::validate() {
|
||||
ZERO_TERMINATE(TaskDeviceName);
|
||||
for (byte i = 0; i < VARS_PER_TASK; ++i) {
|
||||
ZERO_TERMINATE(TaskDeviceFormula[i]);
|
||||
ZERO_TERMINATE(TaskDeviceValueNames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool ExtraTaskSettingsStruct::checkUniqueValueNames() const {
|
||||
for (int i = 0; i < (VARS_PER_TASK - 1); ++i) {
|
||||
for (int j = i; j < VARS_PER_TASK; ++j) {
|
||||
if (i != j && TaskDeviceValueNames[i][0] != 0) {
|
||||
if (strcasecmp(TaskDeviceValueNames[i], TaskDeviceValueNames[j]) == 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ExtraTaskSettingsStruct::clearUnusedValueNames(byte usedVars) {
|
||||
for (byte i = usedVars; i < VARS_PER_TASK; ++i) {
|
||||
TaskDeviceValueDecimals[i] = 2;
|
||||
ZERO_FILL(TaskDeviceFormula[i]);
|
||||
ZERO_FILL(TaskDeviceValueNames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool ExtraTaskSettingsStruct::checkInvalidCharInNames(const char* name) const {
|
||||
int pos = 0;
|
||||
while (*(name+pos) != 0) {
|
||||
switch (*(name+pos)) {
|
||||
case ',':
|
||||
case ' ':
|
||||
case '#':
|
||||
case '[':
|
||||
case ']':
|
||||
return false;
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExtraTaskSettingsStruct::checkInvalidCharInNames() const {
|
||||
if (!checkInvalidCharInNames(&TaskDeviceName[0])) return false;
|
||||
for (int i = 0; i < (VARS_PER_TASK - 1); ++i) {
|
||||
if (!checkInvalidCharInNames(&TaskDeviceValueNames[i][0])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#ifndef DATASTRUCTS_EXTRATASKSETTINGSSTRUCT_H
|
||||
#define DATASTRUCTS_EXTRATASKSETTINGSSTRUCT_H
|
||||
|
||||
/*********************************************************************************************\
|
||||
* ExtraTaskSettingsStruct
|
||||
\*********************************************************************************************/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "DataStructs/ESPEasyLimits.h"
|
||||
|
||||
// This is only used by some plugins to store extra settings like formula descriptions.
|
||||
// These settings can only be active for one plugin, meaning they have to be loaded
|
||||
// over and over again from flash when another active plugin uses these values.
|
||||
//FIXME @TD-er: Should think of another mechanism to make this more efficient.
|
||||
struct ExtraTaskSettingsStruct
|
||||
{
|
||||
ExtraTaskSettingsStruct();
|
||||
|
||||
void clear();
|
||||
|
||||
void validate();
|
||||
|
||||
bool checkUniqueValueNames() const;
|
||||
|
||||
void clearUnusedValueNames(byte usedVars);
|
||||
|
||||
bool checkInvalidCharInNames(const char* name) const;
|
||||
|
||||
bool checkInvalidCharInNames() const;
|
||||
|
||||
byte TaskIndex; // Always < TASKS_MAX
|
||||
char TaskDeviceName[NAME_FORMULA_LENGTH_MAX + 1];
|
||||
char TaskDeviceFormula[VARS_PER_TASK][NAME_FORMULA_LENGTH_MAX + 1];
|
||||
char TaskDeviceValueNames[VARS_PER_TASK][NAME_FORMULA_LENGTH_MAX + 1];
|
||||
long TaskDevicePluginConfigLong[PLUGIN_EXTRACONFIGVAR_MAX];
|
||||
byte TaskDeviceValueDecimals[VARS_PER_TASK];
|
||||
int16_t TaskDevicePluginConfig[PLUGIN_EXTRACONFIGVAR_MAX];
|
||||
};
|
||||
|
||||
|
||||
#endif // DATASTRUCTS_EXTRATASKSETTINGSSTRUCT_H
|
||||
@@ -0,0 +1,102 @@
|
||||
#include "DataStructs/LogStruct.h"
|
||||
#include "ESPEasy_fdwdecl.h"
|
||||
|
||||
|
||||
LogStruct::LogStruct() : write_idx(0), read_idx(0), lastReadTimeStamp(0) {
|
||||
for (int i = 0; i < LOG_STRUCT_MESSAGE_LINES; ++i) {
|
||||
timeStamp[i] = 0;
|
||||
log_level[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void LogStruct::add(const byte loglevel, const char *line) {
|
||||
write_idx = (write_idx + 1) % LOG_STRUCT_MESSAGE_LINES;
|
||||
if (write_idx == read_idx) {
|
||||
// Buffer full, move read_idx to overwrite oldest entry.
|
||||
read_idx = (read_idx + 1) % LOG_STRUCT_MESSAGE_LINES;
|
||||
}
|
||||
timeStamp[write_idx] = millis();
|
||||
log_level[write_idx] = loglevel;
|
||||
unsigned linelength = strlen(line);
|
||||
if (linelength > LOG_STRUCT_MESSAGE_SIZE-1)
|
||||
linelength = LOG_STRUCT_MESSAGE_SIZE-1;
|
||||
Message[write_idx] = "";
|
||||
Message[write_idx].reserve(linelength);
|
||||
for (unsigned i = 0; i < linelength; ++i) {
|
||||
Message[write_idx] += *(line + i);
|
||||
}
|
||||
}
|
||||
|
||||
// Read the next item and append it to the given string.
|
||||
// Returns whether new lines are available.
|
||||
bool LogStruct::get(String& output, const String& lineEnd) {
|
||||
lastReadTimeStamp = millis();
|
||||
if (!isEmpty()) {
|
||||
read_idx = (read_idx + 1) % LOG_STRUCT_MESSAGE_LINES;
|
||||
output += formatLine(read_idx, lineEnd);
|
||||
}
|
||||
return !isEmpty();
|
||||
}
|
||||
|
||||
String LogStruct::get_logjson_formatted(bool& logLinesAvailable, unsigned long& timestamp) {
|
||||
lastReadTimeStamp = millis();
|
||||
logLinesAvailable = false;
|
||||
if (isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
read_idx = (read_idx + 1) % LOG_STRUCT_MESSAGE_LINES;
|
||||
timestamp = timeStamp[read_idx];
|
||||
String output = logjson_formatLine(read_idx);
|
||||
if (isEmpty()) return output;
|
||||
output += ",\n";
|
||||
logLinesAvailable = true;
|
||||
return output;
|
||||
}
|
||||
|
||||
bool LogStruct::isEmpty() {
|
||||
return (write_idx == read_idx);
|
||||
}
|
||||
|
||||
bool LogStruct::logActiveRead() {
|
||||
clearExpiredEntries();
|
||||
return timePassedSince(lastReadTimeStamp) < LOG_BUFFER_EXPIRE;
|
||||
}
|
||||
|
||||
String LogStruct::formatLine(int index, const String& lineEnd) {
|
||||
String output;
|
||||
output += timeStamp[index];
|
||||
output += " : ";
|
||||
output += Message[index];
|
||||
output += lineEnd;
|
||||
return output;
|
||||
}
|
||||
|
||||
String LogStruct::logjson_formatLine(int index) {
|
||||
String output;
|
||||
output.reserve(LOG_STRUCT_MESSAGE_SIZE + 64);
|
||||
output = "{";
|
||||
output += to_json_object_value("timestamp", String(timeStamp[index]));
|
||||
output += ",\n";
|
||||
output += to_json_object_value("text", Message[index]);
|
||||
output += ",\n";
|
||||
output += to_json_object_value("level", String(log_level[index]));
|
||||
output += "}";
|
||||
return output;
|
||||
}
|
||||
|
||||
void LogStruct::clearExpiredEntries() {
|
||||
if (isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (timePassedSince(lastReadTimeStamp) > LOG_BUFFER_EXPIRE) {
|
||||
// Clear the entire log.
|
||||
// If web log is the only log active, it will not be checked again until it is read.
|
||||
for (read_idx = 0; read_idx < LOG_STRUCT_MESSAGE_LINES; ++read_idx) {
|
||||
Message[read_idx] = String(); // Free also the reserved memory.
|
||||
timeStamp[read_idx] = 0;
|
||||
log_level[read_idx] = 0;
|
||||
}
|
||||
read_idx = 0;
|
||||
write_idx = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#ifndef DATASTRUCTS_LOGSTRUCT_H
|
||||
#define DATASTRUCTS_LOGSTRUCT_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
/*********************************************************************************************\
|
||||
* LogStruct
|
||||
\*********************************************************************************************/
|
||||
#define LOG_STRUCT_MESSAGE_SIZE 128
|
||||
#ifdef ESP32
|
||||
#define LOG_STRUCT_MESSAGE_LINES 30
|
||||
#define LOG_BUFFER_EXPIRE 30000 // Time after which a buffered log item is considered expired.
|
||||
#else
|
||||
#if defined(PLUGIN_BUILD_TESTING) || defined(PLUGIN_BUILD_DEV)
|
||||
#define LOG_STRUCT_MESSAGE_LINES 10
|
||||
#else
|
||||
#define LOG_STRUCT_MESSAGE_LINES 15
|
||||
#endif
|
||||
#define LOG_BUFFER_EXPIRE 5000 // Time after which a buffered log item is considered expired.
|
||||
#endif
|
||||
|
||||
struct LogStruct {
|
||||
LogStruct();
|
||||
|
||||
void add(const byte loglevel, const char *line);
|
||||
|
||||
// Read the next item and append it to the given string.
|
||||
// Returns whether new lines are available.
|
||||
bool get(String& output, const String& lineEnd);
|
||||
|
||||
String get_logjson_formatted(bool& logLinesAvailable, unsigned long& timestamp);
|
||||
|
||||
bool isEmpty();
|
||||
|
||||
bool logActiveRead();
|
||||
|
||||
private:
|
||||
String formatLine(int index, const String& lineEnd);
|
||||
|
||||
String logjson_formatLine(int index);
|
||||
|
||||
void clearExpiredEntries();
|
||||
|
||||
String Message[LOG_STRUCT_MESSAGE_LINES];
|
||||
unsigned long timeStamp[LOG_STRUCT_MESSAGE_LINES];
|
||||
int write_idx;
|
||||
int read_idx;
|
||||
unsigned long lastReadTimeStamp;
|
||||
byte log_level[LOG_STRUCT_MESSAGE_LINES];
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // DATASTRUCTS_LOGSTRUCT_H
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef DATASTRUCTS_NODESTRUCT_H
|
||||
#define DATASTRUCTS_NODESTRUCT_H
|
||||
|
||||
#include "ESPEasy_common.h"
|
||||
#include <map>
|
||||
#include <IPAddress.h>
|
||||
|
||||
/*********************************************************************************************\
|
||||
* NodeStruct
|
||||
\*********************************************************************************************/
|
||||
struct NodeStruct
|
||||
{
|
||||
NodeStruct() :
|
||||
build(0), age(0), nodeType(0)
|
||||
{
|
||||
for (byte i = 0; i < 4; ++i) { ip[i] = 0; }
|
||||
}
|
||||
|
||||
String nodeName;
|
||||
IPAddress ip;
|
||||
uint16_t build;
|
||||
byte age;
|
||||
byte nodeType;
|
||||
};
|
||||
typedef std::map<byte, NodeStruct> NodesMap;
|
||||
NodesMap Nodes;
|
||||
|
||||
|
||||
#endif // DATASTRUCTS_NODESTRUCT_H
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "DataStructs/NotificationSettingsStruct.h"
|
||||
|
||||
#include "ESPEasy_common.h"
|
||||
|
||||
|
||||
NotificationSettingsStruct::NotificationSettingsStruct() : Port(0), Pin1(0), Pin2(0) {
|
||||
ZERO_FILL(Server);
|
||||
ZERO_FILL(Domain);
|
||||
ZERO_FILL(Sender);
|
||||
ZERO_FILL(Receiver);
|
||||
ZERO_FILL(Subject);
|
||||
ZERO_FILL(Body);
|
||||
ZERO_FILL(User);
|
||||
ZERO_FILL(Pass);
|
||||
}
|
||||
|
||||
void NotificationSettingsStruct::validate() {
|
||||
ZERO_TERMINATE(Server);
|
||||
ZERO_TERMINATE(Domain);
|
||||
ZERO_TERMINATE(Sender);
|
||||
ZERO_TERMINATE(Receiver);
|
||||
ZERO_TERMINATE(Subject);
|
||||
ZERO_TERMINATE(Body);
|
||||
ZERO_TERMINATE(User);
|
||||
ZERO_TERMINATE(Pass);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef DATASTRUCTS_NOTIFICATIONSETTINGSSTRUCT_H
|
||||
#define DATASTRUCTS_NOTIFICATIONSETTINGSSTRUCT_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <memory> // For std::shared_ptr
|
||||
|
||||
/*********************************************************************************************\
|
||||
* NotificationSettingsStruct
|
||||
\*********************************************************************************************/
|
||||
struct NotificationSettingsStruct
|
||||
{
|
||||
NotificationSettingsStruct();
|
||||
|
||||
void validate();
|
||||
|
||||
char Server[65];
|
||||
unsigned int Port;
|
||||
char Domain[65];
|
||||
char Sender[65];
|
||||
char Receiver[65];
|
||||
char Subject[129];
|
||||
char Body[513];
|
||||
byte Pin1;
|
||||
byte Pin2;
|
||||
char User[49];
|
||||
char Pass[33];
|
||||
//its safe to extend this struct, up to 4096 bytes, default values in config are 0
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<NotificationSettingsStruct> NotificationSettingsStruct_ptr_type;
|
||||
#define MakeNotificationSettings(T) NotificationSettingsStruct_ptr_type NotificationSettingsStruct_ptr(new NotificationSettingsStruct());\
|
||||
NotificationSettingsStruct& T = *NotificationSettingsStruct_ptr;
|
||||
|
||||
#endif // DATASTRUCTS_NOTIFICATIONSETTINGSSTRUCT_H
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef DATASTRUCTS_NOTIFICATIONSTRUCT_H
|
||||
#define DATASTRUCTS_NOTIFICATIONSTRUCT_H
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
* NotificationStruct
|
||||
\*********************************************************************************************/
|
||||
struct NotificationStruct
|
||||
{
|
||||
NotificationStruct() :
|
||||
Number(0), usesMessaging(false), usesGPIO(0) {}
|
||||
|
||||
byte Number;
|
||||
boolean usesMessaging;
|
||||
byte usesGPIO;
|
||||
};
|
||||
|
||||
|
||||
#endif // DATASTRUCTS_NOTIFICATIONSTRUCT_H
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef DATASTRUCTS_PORTSTATUSSTRUCT_H
|
||||
#define DATASTRUCTS_PORTSTATUSSTRUCT_H
|
||||
|
||||
#include "ESPEasy_common.h"
|
||||
#include <map>
|
||||
|
||||
struct portStatusStruct {
|
||||
portStatusStruct() : state(-1), output(-1), command(0), init(0), mode(0), task(0), monitor(0), forceMonitor(0), forceEvent(0), previousTask(
|
||||
-1), x(-1) {}
|
||||
|
||||
int8_t state : 2; // -1,0,1
|
||||
int8_t output : 2; // -1,0,1
|
||||
int8_t command : 2; // 0,1
|
||||
int8_t init : 2; // 0,1
|
||||
|
||||
uint8_t mode : 3; // 6 current values (max. 8)
|
||||
uint8_t task : 2; // 0-3 (max. 4)
|
||||
uint8_t monitor : 1; // 0,1
|
||||
uint8_t forceMonitor : 1; // 0,1
|
||||
uint8_t forceEvent : 1; // 0,1
|
||||
|
||||
int8_t previousTask : 8;
|
||||
|
||||
int8_t x; // used to synchronize the Plugin_prt vector index (x) with the PLUGIN_ID
|
||||
};
|
||||
|
||||
std::map<uint32_t, portStatusStruct> globalMapPortStatus;
|
||||
|
||||
|
||||
#endif // DATASTRUCTS_PORTSTATUSSTRUCT_H
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef DATASTRUCTS_PROTOCOLSTRUCT_H
|
||||
#define DATASTRUCTS_PROTOCOLSTRUCT_H
|
||||
|
||||
#include "ESPEasy_common.h"
|
||||
#include <vector>
|
||||
|
||||
/*********************************************************************************************\
|
||||
* ProtocolStruct
|
||||
\*********************************************************************************************/
|
||||
struct ProtocolStruct
|
||||
{
|
||||
ProtocolStruct() :
|
||||
defaultPort(0), Number(0), usesMQTT(false), usesAccount(false), usesPassword(false),
|
||||
usesTemplate(false), usesID(false), Custom(false), usesHost(true), usesPort(true),
|
||||
usesQueue(true), usesSampleSets(false) {}
|
||||
|
||||
uint16_t defaultPort;
|
||||
byte Number;
|
||||
bool usesMQTT : 1;
|
||||
bool usesAccount : 1;
|
||||
bool usesPassword : 1;
|
||||
bool usesTemplate : 1; // When set, the protocol will pre-load some templates like default MQTT topics
|
||||
bool usesID : 1; // Whether a controller supports sending an IDX value sent along with plugin data
|
||||
bool Custom : 1; // When set, the controller has to define all parameters on the controller setup page
|
||||
bool usesHost : 1;
|
||||
bool usesPort : 1;
|
||||
bool usesQueue : 1;
|
||||
bool usesSampleSets : 1;
|
||||
};
|
||||
|
||||
typedef std::vector<ProtocolStruct> ProtocolVector;
|
||||
ProtocolVector Protocol;
|
||||
|
||||
|
||||
#endif // DATASTRUCTS_PROTOCOLSTRUCT_H
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef DATASTRUCTS_RTC_STRUCTS_H
|
||||
#define DATASTRUCTS_RTC_STRUCTS_H
|
||||
|
||||
#include "ESPEasy_common.h"
|
||||
|
||||
// this offsets are in blocks, bytes = blocks * 4
|
||||
#define RTC_BASE_STRUCT 64
|
||||
#define RTC_BASE_USERVAR 74
|
||||
#define RTC_BASE_CACHE 124
|
||||
|
||||
#define RTC_CACHE_DATA_SIZE 240
|
||||
#define CACHE_FILE_MAX_SIZE 24000
|
||||
|
||||
/*********************************************************************************************\
|
||||
* RTCStruct
|
||||
\*********************************************************************************************/
|
||||
//max 40 bytes: ( 74 - 64 ) * 4
|
||||
struct RTCStruct
|
||||
{
|
||||
RTCStruct() : ID1(0), ID2(0), unused1(false), factoryResetCounter(0),
|
||||
deepSleepState(0), bootFailedCount(0), flashDayCounter(0),
|
||||
flashCounter(0), bootCounter(0), lastMixedSchedulerId(0) {}
|
||||
byte ID1;
|
||||
byte ID2;
|
||||
boolean unused1;
|
||||
byte factoryResetCounter;
|
||||
byte deepSleepState;
|
||||
byte bootFailedCount;
|
||||
byte flashDayCounter;
|
||||
unsigned long flashCounter;
|
||||
unsigned long bootCounter;
|
||||
unsigned long lastMixedSchedulerId;
|
||||
};
|
||||
|
||||
|
||||
#endif // DATASTRUCTS_RTC_STRUCTS_H
|
||||
@@ -0,0 +1,32 @@
|
||||
#include "DataStructs/SecurityStruct.h"
|
||||
|
||||
#include "ESPEasy_common.h"
|
||||
#include "DataStructs/ESPEasyLimits.h"
|
||||
|
||||
SecurityStruct::SecurityStruct() {
|
||||
ZERO_FILL(WifiSSID);
|
||||
ZERO_FILL(WifiKey);
|
||||
ZERO_FILL(WifiSSID2);
|
||||
ZERO_FILL(WifiKey2);
|
||||
ZERO_FILL(WifiAPKey);
|
||||
|
||||
for (byte i = 0; i < CONTROLLER_MAX; ++i) {
|
||||
ZERO_FILL(ControllerUser[i]);
|
||||
ZERO_FILL(ControllerPassword[i]);
|
||||
}
|
||||
ZERO_FILL(Password);
|
||||
}
|
||||
|
||||
void SecurityStruct::validate() {
|
||||
ZERO_TERMINATE(WifiSSID);
|
||||
ZERO_TERMINATE(WifiKey);
|
||||
ZERO_TERMINATE(WifiSSID2);
|
||||
ZERO_TERMINATE(WifiKey2);
|
||||
ZERO_TERMINATE(WifiAPKey);
|
||||
|
||||
for (byte i = 0; i < CONTROLLER_MAX; ++i) {
|
||||
ZERO_TERMINATE(ControllerUser[i]);
|
||||
ZERO_TERMINATE(ControllerPassword[i]);
|
||||
}
|
||||
ZERO_TERMINATE(Password);
|
||||
}
|
||||
@@ -1,37 +1,17 @@
|
||||
#ifndef DATASTRUCTS_SECURITYSTRUCT_H
|
||||
#define DATASTRUCTS_SECURITYSTRUCT_H
|
||||
|
||||
#include "ESPEasy_common.h"
|
||||
#include "DataStructs/ESPEasyLimits.h"
|
||||
|
||||
/*********************************************************************************************\
|
||||
* SecurityStruct
|
||||
\*********************************************************************************************/
|
||||
struct SecurityStruct
|
||||
{
|
||||
SecurityStruct() {
|
||||
ZERO_FILL(WifiSSID);
|
||||
ZERO_FILL(WifiKey);
|
||||
ZERO_FILL(WifiSSID2);
|
||||
ZERO_FILL(WifiKey2);
|
||||
ZERO_FILL(WifiAPKey);
|
||||
for (byte i = 0; i < CONTROLLER_MAX; ++i) {
|
||||
ZERO_FILL(ControllerUser[i]);
|
||||
ZERO_FILL(ControllerPassword[i]);
|
||||
}
|
||||
ZERO_FILL(Password);
|
||||
}
|
||||
SecurityStruct();
|
||||
|
||||
void validate() {
|
||||
ZERO_TERMINATE(WifiSSID);
|
||||
ZERO_TERMINATE(WifiKey);
|
||||
ZERO_TERMINATE(WifiSSID2);
|
||||
ZERO_TERMINATE(WifiKey2);
|
||||
ZERO_TERMINATE(WifiAPKey);
|
||||
for (byte i = 0; i < CONTROLLER_MAX; ++i) {
|
||||
ZERO_TERMINATE(ControllerUser[i]);
|
||||
ZERO_TERMINATE(ControllerPassword[i]);
|
||||
}
|
||||
ZERO_TERMINATE(Password);
|
||||
}
|
||||
void validate();
|
||||
|
||||
char WifiSSID[32];
|
||||
char WifiKey[64];
|
||||
@@ -50,4 +30,5 @@ struct SecurityStruct
|
||||
uint8_t md5[16] = {0};
|
||||
};
|
||||
|
||||
|
||||
#endif // DATASTRUCTS_SECURITYSTRUCT_H
|
||||
@@ -160,4 +160,6 @@ SettingsStruct* SettingsStruct_ptr = new SettingsStruct;
|
||||
SettingsStruct& Settings = *SettingsStruct_ptr;
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#endif // DATASTRUCTS_SETTINGSSTRUCT_H
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef DATASTRUCTS_SYSTEMTIMERSTRUCT_H
|
||||
#define DATASTRUCTS_SYSTEMTIMERSTRUCT_H
|
||||
|
||||
#include "ESPEasy_common.h"
|
||||
#include <map>
|
||||
|
||||
/*********************************************************************************************\
|
||||
* systemTimerStruct
|
||||
\*********************************************************************************************/
|
||||
struct systemTimerStruct
|
||||
{
|
||||
systemTimerStruct() :
|
||||
timer(0), Par1(0), Par2(0), Par3(0), Par4(0), Par5(0), TaskIndex(-1), plugin(0) {}
|
||||
|
||||
unsigned long timer;
|
||||
int Par1;
|
||||
int Par2;
|
||||
int Par3;
|
||||
int Par4;
|
||||
int Par5;
|
||||
int16_t TaskIndex;
|
||||
byte plugin;
|
||||
};
|
||||
std::map<unsigned long, systemTimerStruct> systemTimers;
|
||||
|
||||
|
||||
|
||||
#endif // DATASTRUCTS_SYSTEMTIMERSTRUCT_H
|
||||
@@ -0,0 +1,213 @@
|
||||
#include "DataStructs/TimingStats.h"
|
||||
#include "ESPEasy_common.h"
|
||||
#include "ESPEasy_plugindefs.h"
|
||||
#include "_CPlugin_Helper.h"
|
||||
|
||||
TimingStats::TimingStats() : _timeTotal(0.0), _count(0), _maxVal(0), _minVal(4294967295) {}
|
||||
|
||||
void TimingStats::add(unsigned long time) {
|
||||
_timeTotal += time;
|
||||
++_count;
|
||||
|
||||
if (time > _maxVal) { _maxVal = time; }
|
||||
|
||||
if (time < _minVal) { _minVal = time; }
|
||||
}
|
||||
|
||||
void TimingStats::reset() {
|
||||
_timeTotal = 0.0;
|
||||
_count = 0;
|
||||
_maxVal = 0;
|
||||
_minVal = 4294967295;
|
||||
}
|
||||
|
||||
bool TimingStats::isEmpty() const {
|
||||
return _count == 0;
|
||||
}
|
||||
|
||||
float TimingStats::getAvg() const {
|
||||
if (_count == 0) { return 0.0; }
|
||||
return _timeTotal / _count;
|
||||
}
|
||||
|
||||
unsigned int TimingStats::getMinMax(unsigned long& minVal, unsigned long& maxVal) const {
|
||||
if (_count == 0) {
|
||||
minVal = 0;
|
||||
maxVal = 0;
|
||||
return 0;
|
||||
}
|
||||
minVal = _minVal;
|
||||
maxVal = _maxVal;
|
||||
return _count;
|
||||
}
|
||||
|
||||
bool TimingStats::thresholdExceeded(unsigned long threshold) const {
|
||||
if (_count == 0) {
|
||||
return false;
|
||||
}
|
||||
return _maxVal > threshold;
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Functions used for displaying timing stats
|
||||
\*********************************************************************************************/
|
||||
String getPluginFunctionName(int function) {
|
||||
switch (function) {
|
||||
case PLUGIN_INIT_ALL: return F("INIT_ALL");
|
||||
case PLUGIN_INIT: return F("INIT");
|
||||
case PLUGIN_READ: return F("READ");
|
||||
case PLUGIN_ONCE_A_SECOND: return F("ONCE_A_SECOND");
|
||||
case PLUGIN_TEN_PER_SECOND: return F("TEN_PER_SECOND");
|
||||
case PLUGIN_DEVICE_ADD: return F("DEVICE_ADD");
|
||||
case PLUGIN_EVENTLIST_ADD: return F("EVENTLIST_ADD");
|
||||
case PLUGIN_WEBFORM_SAVE: return F("WEBFORM_SAVE");
|
||||
case PLUGIN_WEBFORM_LOAD: return F("WEBFORM_LOAD");
|
||||
case PLUGIN_WEBFORM_SHOW_VALUES: return F("WEBFORM_SHOW_VALUES");
|
||||
case PLUGIN_GET_DEVICENAME: return F("GET_DEVICENAME");
|
||||
case PLUGIN_GET_DEVICEVALUENAMES: return F("GET_DEVICEVALUENAMES");
|
||||
case PLUGIN_WRITE: return F("WRITE");
|
||||
case PLUGIN_EVENT_OUT: return F("EVENT_OUT");
|
||||
case PLUGIN_WEBFORM_SHOW_CONFIG: return F("WEBFORM_SHOW_CONFIG");
|
||||
case PLUGIN_SERIAL_IN: return F("SERIAL_IN");
|
||||
case PLUGIN_UDP_IN: return F("UDP_IN");
|
||||
case PLUGIN_CLOCK_IN: return F("CLOCK_IN");
|
||||
case PLUGIN_TIMER_IN: return F("TIMER_IN");
|
||||
case PLUGIN_FIFTY_PER_SECOND: return F("FIFTY_PER_SECOND");
|
||||
case PLUGIN_SET_CONFIG: return F("SET_CONFIG");
|
||||
case PLUGIN_GET_DEVICEGPIONAMES: return F("GET_DEVICEGPIONAMES");
|
||||
case PLUGIN_EXIT: return F("EXIT");
|
||||
case PLUGIN_GET_CONFIG: return F("GET_CONFIG");
|
||||
case PLUGIN_UNCONDITIONAL_POLL: return F("UNCONDITIONAL_POLL");
|
||||
case PLUGIN_REQUEST: return F("REQUEST");
|
||||
}
|
||||
return getUnknownString();
|
||||
}
|
||||
|
||||
bool mustLogFunction(int function) {
|
||||
switch (function) {
|
||||
case PLUGIN_INIT_ALL: return false;
|
||||
case PLUGIN_INIT: return false;
|
||||
case PLUGIN_READ: return true;
|
||||
case PLUGIN_ONCE_A_SECOND: return true;
|
||||
case PLUGIN_TEN_PER_SECOND: return true;
|
||||
case PLUGIN_DEVICE_ADD: return false;
|
||||
case PLUGIN_EVENTLIST_ADD: return false;
|
||||
case PLUGIN_WEBFORM_SAVE: return false;
|
||||
case PLUGIN_WEBFORM_LOAD: return false;
|
||||
case PLUGIN_WEBFORM_SHOW_VALUES: return false;
|
||||
case PLUGIN_GET_DEVICENAME: return false;
|
||||
case PLUGIN_GET_DEVICEVALUENAMES: return false;
|
||||
case PLUGIN_WRITE: return true;
|
||||
case PLUGIN_EVENT_OUT: return true;
|
||||
case PLUGIN_WEBFORM_SHOW_CONFIG: return false;
|
||||
case PLUGIN_SERIAL_IN: return true;
|
||||
case PLUGIN_UDP_IN: return true;
|
||||
case PLUGIN_CLOCK_IN: return false;
|
||||
case PLUGIN_TIMER_IN: return true;
|
||||
case PLUGIN_FIFTY_PER_SECOND: return true;
|
||||
case PLUGIN_SET_CONFIG: return false;
|
||||
case PLUGIN_GET_DEVICEGPIONAMES: return false;
|
||||
case PLUGIN_EXIT: return false;
|
||||
case PLUGIN_GET_CONFIG: return false;
|
||||
case PLUGIN_UNCONDITIONAL_POLL: return false;
|
||||
case PLUGIN_REQUEST: return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
String getCPluginCFunctionName(int function) {
|
||||
switch (function) {
|
||||
case CPLUGIN_PROTOCOL_ADD: return F("CPLUGIN_PROTOCOL_ADD");
|
||||
case CPLUGIN_PROTOCOL_TEMPLATE: return F("CPLUGIN_PROTOCOL_TEMPLATE");
|
||||
case CPLUGIN_PROTOCOL_SEND: return F("CPLUGIN_PROTOCOL_SEND");
|
||||
case CPLUGIN_PROTOCOL_RECV: return F("CPLUGIN_PROTOCOL_RECV");
|
||||
case CPLUGIN_GET_DEVICENAME: return F("CPLUGIN_GET_DEVICENAME");
|
||||
case CPLUGIN_WEBFORM_SAVE: return F("CPLUGIN_WEBFORM_SAVE");
|
||||
case CPLUGIN_WEBFORM_LOAD: return F("CPLUGIN_WEBFORM_LOAD");
|
||||
case CPLUGIN_GET_PROTOCOL_DISPLAY_NAME: return F("CPLUGIN_GET_PROTOCOL_DISPLAY_NAME");
|
||||
case CPLUGIN_TASK_CHANGE_NOTIFICATION: return F("CPLUGIN_TASK_CHANGE_NOTIFICATION");
|
||||
case CPLUGIN_INIT: return F("CPLUGIN_INIT");
|
||||
case CPLUGIN_UDP_IN: return F("CPLUGIN_UDP_IN");
|
||||
}
|
||||
return getUnknownString();
|
||||
}
|
||||
|
||||
bool mustLogCFunction(int function) {
|
||||
switch (function) {
|
||||
case CPLUGIN_PROTOCOL_ADD: return false;
|
||||
case CPLUGIN_PROTOCOL_TEMPLATE: return false;
|
||||
case CPLUGIN_PROTOCOL_SEND: return true;
|
||||
case CPLUGIN_PROTOCOL_RECV: return true;
|
||||
case CPLUGIN_GET_DEVICENAME: return false;
|
||||
case CPLUGIN_WEBFORM_SAVE: return false;
|
||||
case CPLUGIN_WEBFORM_LOAD: return false;
|
||||
case CPLUGIN_GET_PROTOCOL_DISPLAY_NAME: return false;
|
||||
case CPLUGIN_TASK_CHANGE_NOTIFICATION: return false;
|
||||
case CPLUGIN_INIT: return false;
|
||||
case CPLUGIN_UDP_IN: return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
String getMiscStatsName(int stat) {
|
||||
switch (stat) {
|
||||
case LOADFILE_STATS: return F("Load File");
|
||||
case SAVEFILE_STATS: return F("Save File");
|
||||
case LOOP_STATS: return F("Loop");
|
||||
case PLUGIN_CALL_50PS: return F("Plugin call 50 p/s");
|
||||
case PLUGIN_CALL_10PS: return F("Plugin call 10 p/s");
|
||||
case PLUGIN_CALL_10PSU: return F("Plugin call 10 p/s U");
|
||||
case PLUGIN_CALL_1PS: return F("Plugin call 1 p/s");
|
||||
case SENSOR_SEND_TASK: return F("SensorSendTask()");
|
||||
case SEND_DATA_STATS: return F("sendData()");
|
||||
case COMPUTE_FORMULA_STATS: return F("Compute formula");
|
||||
case PROC_SYS_TIMER: return F("proc_system_timer()");
|
||||
case SET_NEW_TIMER: return F("setNewTimerAt()");
|
||||
case TIME_DIFF_COMPUTE: return F("timeDiff()");
|
||||
case MQTT_DELAY_QUEUE: return F("Delay queue MQTT");
|
||||
case TRY_CONNECT_HOST_TCP: return F("try_connect_host() (TCP)");
|
||||
case TRY_CONNECT_HOST_UDP: return F("try_connect_host() (UDP)");
|
||||
case HOST_BY_NAME_STATS: return F("hostByName()");
|
||||
case CONNECT_CLIENT_STATS: return F("connectClient()");
|
||||
case LOAD_CUSTOM_TASK_STATS: return F("LoadCustomTaskSettings()");
|
||||
case WIFI_ISCONNECTED_STATS: return F("WiFi.isConnected()");
|
||||
case WIFI_NOTCONNECTED_STATS: return F("WiFi.isConnected() (fail)");
|
||||
case LOAD_TASK_SETTINGS: return F("LoadTaskSettings()");
|
||||
case TRY_OPEN_FILE: return F("TryOpenFile()");
|
||||
case SPIFFS_GC_SUCCESS: return F("SPIFFS GC success");
|
||||
case SPIFFS_GC_FAIL: return F("SPIFFS GC fail");
|
||||
case RULES_PROCESSING: return F("rulesProcessing()");
|
||||
case GRAT_ARP_STATS: return F("sendGratuitousARP()");
|
||||
case BACKGROUND_TASKS: return F("backgroundtasks()");
|
||||
case HANDLE_SCHEDULER_IDLE: return F("handle_schedule() idle");
|
||||
case HANDLE_SCHEDULER_TASK: return F("handle_schedule() task");
|
||||
case C001_DELAY_QUEUE:
|
||||
case C002_DELAY_QUEUE:
|
||||
case C003_DELAY_QUEUE:
|
||||
case C004_DELAY_QUEUE:
|
||||
case C005_DELAY_QUEUE:
|
||||
case C006_DELAY_QUEUE:
|
||||
case C007_DELAY_QUEUE:
|
||||
case C008_DELAY_QUEUE:
|
||||
case C009_DELAY_QUEUE:
|
||||
case C010_DELAY_QUEUE:
|
||||
case C011_DELAY_QUEUE:
|
||||
case C012_DELAY_QUEUE:
|
||||
case C013_DELAY_QUEUE:
|
||||
case C014_DELAY_QUEUE:
|
||||
case C015_DELAY_QUEUE:
|
||||
case C016_DELAY_QUEUE:
|
||||
case C017_DELAY_QUEUE:
|
||||
case C018_DELAY_QUEUE:
|
||||
case C019_DELAY_QUEUE:
|
||||
case C020_DELAY_QUEUE:
|
||||
{
|
||||
String result;
|
||||
result.reserve(16);
|
||||
result = F("Delay queue ");
|
||||
result += get_formatted_Controller_number(static_cast<int>(stat - C001_DELAY_QUEUE + 1));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return getUnknownString();
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
#ifndef DATASTRUCTS_TIMINGSTATS_H
|
||||
#define DATASTRUCTS_TIMINGSTATS_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <map>
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
* TimingStats
|
||||
\*********************************************************************************************/
|
||||
|
||||
|
||||
#define LOADFILE_STATS 0
|
||||
#define SAVEFILE_STATS 1
|
||||
#define LOOP_STATS 2
|
||||
#define PLUGIN_CALL_50PS 3
|
||||
#define PLUGIN_CALL_10PS 4
|
||||
#define PLUGIN_CALL_10PSU 5
|
||||
#define PLUGIN_CALL_1PS 6
|
||||
#define SENSOR_SEND_TASK 7
|
||||
#define SEND_DATA_STATS 8
|
||||
#define COMPUTE_FORMULA_STATS 9
|
||||
#define PROC_SYS_TIMER 10
|
||||
#define SET_NEW_TIMER 11
|
||||
#define TIME_DIFF_COMPUTE 12
|
||||
#define MQTT_DELAY_QUEUE 13
|
||||
#define C001_DELAY_QUEUE 14
|
||||
#define C002_DELAY_QUEUE 15
|
||||
#define C003_DELAY_QUEUE 16
|
||||
#define C004_DELAY_QUEUE 17
|
||||
#define C005_DELAY_QUEUE 18
|
||||
#define C006_DELAY_QUEUE 19
|
||||
#define C007_DELAY_QUEUE 20
|
||||
#define C008_DELAY_QUEUE 21
|
||||
#define C009_DELAY_QUEUE 22
|
||||
#define C010_DELAY_QUEUE 23
|
||||
#define C011_DELAY_QUEUE 24
|
||||
#define C012_DELAY_QUEUE 25
|
||||
#define C013_DELAY_QUEUE 26
|
||||
#define C014_DELAY_QUEUE 27
|
||||
#define C015_DELAY_QUEUE 28
|
||||
#define C016_DELAY_QUEUE 29
|
||||
#define C017_DELAY_QUEUE 30
|
||||
#define C018_DELAY_QUEUE 31
|
||||
#define C019_DELAY_QUEUE 32
|
||||
#define C020_DELAY_QUEUE 33
|
||||
#define TRY_CONNECT_HOST_TCP 34
|
||||
#define TRY_CONNECT_HOST_UDP 35
|
||||
#define HOST_BY_NAME_STATS 36
|
||||
#define CONNECT_CLIENT_STATS 37
|
||||
#define LOAD_CUSTOM_TASK_STATS 38
|
||||
#define WIFI_ISCONNECTED_STATS 39
|
||||
#define WIFI_NOTCONNECTED_STATS 40
|
||||
#define LOAD_TASK_SETTINGS 41
|
||||
#define TRY_OPEN_FILE 42
|
||||
#define SPIFFS_GC_SUCCESS 43
|
||||
#define SPIFFS_GC_FAIL 44
|
||||
#define RULES_PROCESSING 45
|
||||
#define GRAT_ARP_STATS 46
|
||||
#define BACKGROUND_TASKS 47
|
||||
#define HANDLE_SCHEDULER_IDLE 48
|
||||
#define HANDLE_SCHEDULER_TASK 49
|
||||
|
||||
class TimingStats {
|
||||
public:
|
||||
|
||||
TimingStats();
|
||||
|
||||
void add(unsigned long time);
|
||||
void reset();
|
||||
bool isEmpty() const;
|
||||
float getAvg() const;
|
||||
unsigned int getMinMax(unsigned long& minVal,
|
||||
unsigned long& maxVal) const;
|
||||
bool thresholdExceeded(unsigned long threshold) const;
|
||||
|
||||
private:
|
||||
|
||||
float _timeTotal;
|
||||
unsigned int _count;
|
||||
unsigned long _maxVal;
|
||||
unsigned long _minVal;
|
||||
};
|
||||
|
||||
|
||||
String getPluginFunctionName(int function);
|
||||
bool mustLogFunction(int function);
|
||||
String getCPluginCFunctionName(int function);
|
||||
bool mustLogCFunction(int function);
|
||||
String getMiscStatsName(int stat);
|
||||
|
||||
|
||||
#endif // DATASTRUCTS_TIMINGSTATS_H
|
||||
@@ -0,0 +1,643 @@
|
||||
#ifndef DELAY_QUEUE_ELEMENTS_H
|
||||
#define DELAY_QUEUE_ELEMENTS_H
|
||||
|
||||
#include "DataStructs/ControllerSettingsStruct.h"
|
||||
#include "ESPEasy_fdwdecl.h"
|
||||
|
||||
// These element classes should be defined as class, to be used as template.
|
||||
|
||||
/*********************************************************************************************\
|
||||
* MQTT_queue_element for all MQTT base controllers
|
||||
\*********************************************************************************************/
|
||||
class MQTT_queue_element {
|
||||
public:
|
||||
|
||||
MQTT_queue_element() : controller_idx(0), _retained(false) {}
|
||||
|
||||
MQTT_queue_element(int ctrl_idx,
|
||||
const String& topic, const String& payload, boolean retained) :
|
||||
controller_idx(ctrl_idx), _topic(topic), _payload(payload), _retained(retained)
|
||||
{}
|
||||
|
||||
size_t getSize() const {
|
||||
return sizeof(this) + _topic.length() + _payload.length();
|
||||
}
|
||||
|
||||
int controller_idx;
|
||||
String _topic;
|
||||
String _payload;
|
||||
boolean _retained;
|
||||
};
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Simple queue element, only storing controller index and some String
|
||||
\*********************************************************************************************/
|
||||
class simple_queue_element_string_only {
|
||||
public:
|
||||
|
||||
simple_queue_element_string_only() : controller_idx(0) {}
|
||||
|
||||
simple_queue_element_string_only(int ctrl_idx, const String& req) :
|
||||
controller_idx(ctrl_idx), txt(req) {}
|
||||
|
||||
size_t getSize() const {
|
||||
return sizeof(this) + txt.length();
|
||||
}
|
||||
|
||||
int controller_idx;
|
||||
String txt;
|
||||
};
|
||||
|
||||
|
||||
//#ifdef USES_C001
|
||||
/*********************************************************************************************\
|
||||
* C001_queue_element for queueing requests for C001.
|
||||
\*********************************************************************************************/
|
||||
#define C001_queue_element simple_queue_element_string_only
|
||||
//#endif //USES_C001
|
||||
|
||||
//#ifdef USES_C003
|
||||
/*********************************************************************************************\
|
||||
* C003_queue_element for queueing requests for C003 Nodo Telnet.
|
||||
\*********************************************************************************************/
|
||||
#define C003_queue_element simple_queue_element_string_only
|
||||
//#endif //USES_C003
|
||||
|
||||
//#ifdef USES_C004
|
||||
/*********************************************************************************************\
|
||||
* C004_queue_element for queueing requests for C004 ThingSpeak.
|
||||
* Typical use case for Thingspeak is to only send values every N seconds/minutes.
|
||||
* So we just store everything needed to recreate the event when the time is ready.
|
||||
\*********************************************************************************************/
|
||||
class C004_queue_element {
|
||||
public:
|
||||
|
||||
C004_queue_element() : controller_idx(0), TaskIndex(0), idx(0), sensorType(0) {}
|
||||
|
||||
C004_queue_element(const struct EventStruct *event) :
|
||||
controller_idx(event->ControllerIndex),
|
||||
TaskIndex(event->TaskIndex),
|
||||
idx(event->idx),
|
||||
sensorType(event->sensorType) {
|
||||
if (sensorType == SENSOR_TYPE_STRING) {
|
||||
txt = event->String2;
|
||||
}
|
||||
}
|
||||
|
||||
size_t getSize() const {
|
||||
return sizeof(this) + txt.length();
|
||||
}
|
||||
|
||||
int controller_idx;
|
||||
byte TaskIndex;
|
||||
int idx;
|
||||
byte sensorType;
|
||||
String txt;
|
||||
};
|
||||
//#endif //USES_C004
|
||||
|
||||
//#ifdef USES_C007
|
||||
/*********************************************************************************************\
|
||||
* C007_queue_element for queueing requests for C007 Emoncms
|
||||
\*********************************************************************************************/
|
||||
class C007_queue_element {
|
||||
public:
|
||||
|
||||
C007_queue_element() : controller_idx(0), TaskIndex(0), idx(0), sensorType(0) {}
|
||||
|
||||
C007_queue_element(const struct EventStruct *event) :
|
||||
controller_idx(event->ControllerIndex),
|
||||
TaskIndex(event->TaskIndex),
|
||||
idx(event->idx),
|
||||
sensorType(event->sensorType) {}
|
||||
|
||||
size_t getSize() const {
|
||||
return sizeof(this);
|
||||
}
|
||||
|
||||
int controller_idx;
|
||||
byte TaskIndex;
|
||||
int idx;
|
||||
byte sensorType;
|
||||
};
|
||||
//#endif //USES_C007
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Base class for controllers that only send a single value per request and thus needs to
|
||||
* keep track of the number of values already sent.
|
||||
\*********************************************************************************************/
|
||||
class queue_element_single_value_base {
|
||||
public:
|
||||
|
||||
queue_element_single_value_base() : controller_idx(0), TaskIndex(0), idx(0), valuesSent(0) {}
|
||||
|
||||
queue_element_single_value_base(const struct EventStruct *event, byte value_count) :
|
||||
controller_idx(event->ControllerIndex),
|
||||
TaskIndex(event->TaskIndex),
|
||||
idx(event->idx),
|
||||
valuesSent(0),
|
||||
valueCount(value_count) {}
|
||||
|
||||
bool checkDone(bool succesfull) const {
|
||||
if (succesfull) { ++valuesSent; }
|
||||
return valuesSent >= valueCount || valuesSent >= VARS_PER_TASK;
|
||||
}
|
||||
|
||||
size_t getSize() const {
|
||||
size_t total = sizeof(this);
|
||||
|
||||
for (int i = 0; i < VARS_PER_TASK; ++i) {
|
||||
total += txt[i].length();
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
String txt[VARS_PER_TASK];
|
||||
int controller_idx;
|
||||
byte TaskIndex;
|
||||
int idx;
|
||||
mutable byte valuesSent; // Value must be set by const function checkDone()
|
||||
byte valueCount;
|
||||
};
|
||||
|
||||
|
||||
//#ifdef USES_C008
|
||||
/*********************************************************************************************\
|
||||
* C008_queue_element for queueing requests for 008: Generic HTTP
|
||||
* Using queue_element_single_value_base
|
||||
\*********************************************************************************************/
|
||||
#define C008_queue_element queue_element_single_value_base
|
||||
//#endif //USES_C008
|
||||
|
||||
//#ifdef USES_C009
|
||||
/*********************************************************************************************\
|
||||
* C009_queue_element for queueing requests for C009: FHEM HTTP.
|
||||
\*********************************************************************************************/
|
||||
class C009_queue_element {
|
||||
public:
|
||||
|
||||
C009_queue_element() : controller_idx(0), TaskIndex(0), idx(0), sensorType(0) {}
|
||||
|
||||
C009_queue_element(const struct EventStruct *event) :
|
||||
controller_idx(event->ControllerIndex),
|
||||
TaskIndex(event->TaskIndex),
|
||||
idx(event->idx),
|
||||
sensorType(event->sensorType) {}
|
||||
|
||||
size_t getSize() const {
|
||||
size_t total = sizeof(this);
|
||||
|
||||
for (int i = 0; i < VARS_PER_TASK; ++i) {
|
||||
total += txt[i].length();
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
String txt[VARS_PER_TASK];
|
||||
int controller_idx;
|
||||
byte TaskIndex;
|
||||
int idx;
|
||||
byte sensorType;
|
||||
};
|
||||
//#endif //USES_C009
|
||||
|
||||
|
||||
//#ifdef USES_C010
|
||||
/*********************************************************************************************\
|
||||
* C010_queue_element for queueing requests for 010: Generic UDP
|
||||
* Using queue_element_single_value_base
|
||||
\*********************************************************************************************/
|
||||
#define C010_queue_element queue_element_single_value_base
|
||||
//#endif //USES_C010
|
||||
|
||||
//#ifdef USES_C011
|
||||
/*********************************************************************************************\
|
||||
* C011_queue_element for queueing requests for 011: Generic HTTP Advanced
|
||||
\*********************************************************************************************/
|
||||
#define C011_queue_element simple_queue_element_string_only
|
||||
//#endif //USES_C011
|
||||
|
||||
//#ifdef USES_C012
|
||||
/*********************************************************************************************\
|
||||
* C012_queue_element for queueing requests for 012: Blynk
|
||||
* Using queue_element_single_value_base
|
||||
\*********************************************************************************************/
|
||||
#define C012_queue_element queue_element_single_value_base
|
||||
//#endif //USES_C012
|
||||
|
||||
//#ifdef USES_C015
|
||||
/*********************************************************************************************\
|
||||
* C015_queue_element for queueing requests for 015: Blynk
|
||||
* Using queue_element_single_value_base
|
||||
\*********************************************************************************************/
|
||||
|
||||
// #define C015_queue_element queue_element_single_value_base
|
||||
class C015_queue_element {
|
||||
public:
|
||||
|
||||
C015_queue_element() : controller_idx(0), TaskIndex(0), idx(0), valuesSent(0) {}
|
||||
|
||||
C015_queue_element(const struct EventStruct *event, byte value_count) :
|
||||
controller_idx(event->ControllerIndex),
|
||||
TaskIndex(event->TaskIndex),
|
||||
idx(event->idx),
|
||||
valuesSent(0),
|
||||
valueCount(value_count) {}
|
||||
|
||||
bool checkDone(bool succesfull) const {
|
||||
if (succesfull) { ++valuesSent; }
|
||||
return valuesSent >= valueCount || valuesSent >= VARS_PER_TASK;
|
||||
}
|
||||
|
||||
size_t getSize() const {
|
||||
size_t total = sizeof(this);
|
||||
|
||||
for (int i = 0; i < VARS_PER_TASK; ++i) {
|
||||
total += txt[i].length();
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
String txt[VARS_PER_TASK];
|
||||
int vPin[VARS_PER_TASK] = {0};
|
||||
int controller_idx;
|
||||
byte TaskIndex;
|
||||
int idx;
|
||||
mutable byte valuesSent; // Value must be set by const function checkDone()
|
||||
byte valueCount;
|
||||
};
|
||||
//#endif //USES_C015
|
||||
|
||||
//#ifdef USES_C016
|
||||
/*********************************************************************************************\
|
||||
* C016_queue_element for queueing requests for C016: Cached HTTP.
|
||||
\*********************************************************************************************/
|
||||
class C016_queue_element {
|
||||
public:
|
||||
|
||||
C016_queue_element() : timestamp(0), controller_idx(0), TaskIndex(0), sensorType(0) {}
|
||||
|
||||
C016_queue_element(const struct EventStruct *event, byte value_count, unsigned long unixTime) :
|
||||
timestamp(unixTime),
|
||||
controller_idx(event->ControllerIndex),
|
||||
TaskIndex(event->TaskIndex),
|
||||
sensorType(event->sensorType),
|
||||
valueCount(value_count)
|
||||
{
|
||||
const byte BaseVarIndex = TaskIndex * VARS_PER_TASK;
|
||||
|
||||
for (byte i = 0; i < VARS_PER_TASK; ++i) {
|
||||
if (i < value_count) {
|
||||
values[i] = UserVar[BaseVarIndex + i];
|
||||
} else {
|
||||
values[i] = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t getSize() const {
|
||||
return sizeof(this);
|
||||
}
|
||||
|
||||
float values[VARS_PER_TASK];
|
||||
unsigned long timestamp; // Unix timestamp
|
||||
byte controller_idx;
|
||||
byte TaskIndex;
|
||||
byte sensorType;
|
||||
byte valueCount;
|
||||
};
|
||||
|
||||
//#endif //USES_C016
|
||||
|
||||
//#ifdef USES_C017
|
||||
/*********************************************************************************************\
|
||||
* C017_queue_element for queueing requests for C017: Zabbix Trapper Protocol.
|
||||
\*********************************************************************************************/
|
||||
class C017_queue_element {
|
||||
public:
|
||||
|
||||
C017_queue_element() : controller_idx(0), TaskIndex(0), idx(0), sensorType(0) {}
|
||||
|
||||
C017_queue_element(const struct EventStruct *event) :
|
||||
controller_idx(event->ControllerIndex),
|
||||
TaskIndex(event->TaskIndex),
|
||||
idx(event->idx),
|
||||
sensorType(event->sensorType) {}
|
||||
|
||||
size_t getSize() const {
|
||||
size_t total = sizeof(this);
|
||||
|
||||
for (int i = 0; i < VARS_PER_TASK; ++i) {
|
||||
total += txt[i].length();
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
String txt[VARS_PER_TASK];
|
||||
int controller_idx;
|
||||
byte TaskIndex;
|
||||
int idx;
|
||||
byte sensorType;
|
||||
};
|
||||
//#endif //USES_C017
|
||||
|
||||
//#ifdef USES_C018
|
||||
/*********************************************************************************************\
|
||||
* C018_queue_element for queueing requests for C018: TTN/RN2483
|
||||
\*********************************************************************************************/
|
||||
|
||||
#ifdef USES_PACKED_RAW_DATA
|
||||
String getPackedFromPlugin(struct EventStruct *event, uint8_t sampleSetCount);
|
||||
#endif // USES_PACKED_RAW_DATA
|
||||
|
||||
|
||||
class C018_queue_element {
|
||||
public:
|
||||
|
||||
C018_queue_element() {}
|
||||
|
||||
C018_queue_element(struct EventStruct *event, uint8_t sampleSetCount) :
|
||||
controller_idx(event->ControllerIndex)
|
||||
{
|
||||
#ifdef USES_PACKED_RAW_DATA
|
||||
packed = getPackedFromPlugin(event, sampleSetCount);
|
||||
#endif // USES_PACKED_RAW_DATA
|
||||
}
|
||||
|
||||
size_t getSize() const {
|
||||
return sizeof(this) + packed.length();
|
||||
}
|
||||
|
||||
int controller_idx = 0;
|
||||
String packed;
|
||||
};
|
||||
|
||||
//#endif //USES_C018
|
||||
|
||||
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
* ControllerDelayHandlerStruct
|
||||
\*********************************************************************************************/
|
||||
template<class T>
|
||||
struct ControllerDelayHandlerStruct {
|
||||
ControllerDelayHandlerStruct() :
|
||||
lastSend(0),
|
||||
minTimeBetweenMessages(CONTROLLER_DELAY_QUEUE_DELAY_DFLT),
|
||||
max_queue_depth(CONTROLLER_DELAY_QUEUE_DEPTH_DFLT),
|
||||
attempt(0),
|
||||
max_retries(CONTROLLER_DELAY_QUEUE_RETRY_DFLT),
|
||||
delete_oldest(false),
|
||||
must_check_reply(false) {}
|
||||
|
||||
void configureControllerSettings(const ControllerSettingsStruct& settings) {
|
||||
minTimeBetweenMessages = settings.MinimalTimeBetweenMessages;
|
||||
max_queue_depth = settings.MaxQueueDepth;
|
||||
max_retries = settings.MaxRetry;
|
||||
delete_oldest = settings.DeleteOldest;
|
||||
must_check_reply = settings.MustCheckReply;
|
||||
|
||||
// Set some sound limits when not configured
|
||||
if (max_queue_depth == 0) { max_queue_depth = CONTROLLER_DELAY_QUEUE_DEPTH_DFLT; }
|
||||
|
||||
if (max_retries == 0) { max_retries = CONTROLLER_DELAY_QUEUE_RETRY_DFLT; }
|
||||
|
||||
if (minTimeBetweenMessages == 0) { minTimeBetweenMessages = CONTROLLER_DELAY_QUEUE_DELAY_DFLT; }
|
||||
|
||||
// No less than 10 msec between messages.
|
||||
if (minTimeBetweenMessages < 10) { minTimeBetweenMessages = 10; }
|
||||
}
|
||||
|
||||
bool queueFull(const T& element) const {
|
||||
if (sendQueue.size() >= max_queue_depth) { return true; }
|
||||
|
||||
// Number of elements is not exceeding the limit, check memory
|
||||
int freeHeap = ESP.getFreeHeap();
|
||||
|
||||
if (freeHeap > 5000) { return false; // Memory is not an issue.
|
||||
}
|
||||
#ifndef BUILD_NO_DEBUG
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
|
||||
String log = "Controller-";
|
||||
log += element.controller_idx + 1;
|
||||
log += " : Memory used: ";
|
||||
log += getQueueMemorySize();
|
||||
log += " bytes ";
|
||||
log += sendQueue.size();
|
||||
log += " items ";
|
||||
log += freeHeap;
|
||||
log += " free";
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
}
|
||||
#endif // ifndef BUILD_NO_DEBUG
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to add to the queue, if permitted by "delete_oldest"
|
||||
// Return false when no item was added.
|
||||
bool addToQueue(const T& element) {
|
||||
if (delete_oldest) {
|
||||
// Force add to the queue.
|
||||
// If max buffer is reached, the oldest in the queue (first to be served) will be removed.
|
||||
while (queueFull(element)) {
|
||||
sendQueue.pop_front();
|
||||
}
|
||||
sendQueue.emplace_back(element);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!queueFull(element)) {
|
||||
sendQueue.emplace_back(element);
|
||||
return true;
|
||||
}
|
||||
#ifndef BUILD_NO_DEBUG
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
|
||||
String log = get_formatted_Controller_number(element.controller_idx);
|
||||
log += " : queue full";
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
}
|
||||
#endif // ifndef BUILD_NO_DEBUG
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the next element.
|
||||
// Remove front element when max_retries is reached.
|
||||
T* getNext() {
|
||||
if (sendQueue.empty()) { return NULL; }
|
||||
|
||||
if (attempt > max_retries) {
|
||||
sendQueue.pop_front();
|
||||
attempt = 0;
|
||||
|
||||
if (sendQueue.empty()) { return NULL; }
|
||||
}
|
||||
return &sendQueue.front();
|
||||
}
|
||||
|
||||
// Mark as processed and return time to schedule for next process.
|
||||
// Return 0 when nothing to process.
|
||||
// @param remove_from_queue indicates whether the elements should be removed from the queue.
|
||||
unsigned long markProcessed(bool remove_from_queue) {
|
||||
if (sendQueue.empty()) { return 0; }
|
||||
|
||||
if (remove_from_queue) {
|
||||
sendQueue.pop_front();
|
||||
attempt = 0;
|
||||
} else {
|
||||
++attempt;
|
||||
}
|
||||
lastSend = millis();
|
||||
return getNextScheduleTime();
|
||||
}
|
||||
|
||||
unsigned long getNextScheduleTime() const {
|
||||
if (sendQueue.empty()) { return 0; }
|
||||
unsigned long nextTime = lastSend + minTimeBetweenMessages;
|
||||
|
||||
if (timePassedSince(nextTime) > 0) {
|
||||
nextTime = millis();
|
||||
}
|
||||
|
||||
if (nextTime == 0) { nextTime = 1; // Just to make sure it will be executed
|
||||
}
|
||||
return nextTime;
|
||||
}
|
||||
|
||||
size_t getQueueMemorySize() const {
|
||||
size_t totalSize = 0;
|
||||
|
||||
for (auto it = sendQueue.begin(); it != sendQueue.end(); ++it) {
|
||||
totalSize += it->getSize();
|
||||
}
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
std::list<T> sendQueue;
|
||||
unsigned long lastSend;
|
||||
unsigned int minTimeBetweenMessages;
|
||||
byte max_queue_depth;
|
||||
byte attempt;
|
||||
byte max_retries;
|
||||
bool delete_oldest;
|
||||
bool must_check_reply;
|
||||
};
|
||||
|
||||
ControllerDelayHandlerStruct<MQTT_queue_element> MQTTDelayHandler;
|
||||
|
||||
// Uncrustify must not be used on macros, so turn it off.
|
||||
// *INDENT-OFF*
|
||||
|
||||
|
||||
// This macro defines the code needed to create the 'process_c##NNN####M##_delay_queue()'
|
||||
// function and all needed objects and forward declarations.
|
||||
// It is a macro to prevent common typo errors.
|
||||
// This function will perform the (re)scheduling and mark if it is processed (and can be removed)
|
||||
// The controller itself must implement the 'do_process_c004_delay_queue' function to actually
|
||||
// send the data.
|
||||
// Its return value must state whether it can be marked 'Processed'.
|
||||
// N.B. some controllers only can send one value per iteration, so a returned "false" can mean it
|
||||
// was still successful. The controller should keep track of the last value sent
|
||||
// in the element stored in the queue.
|
||||
#define DEFINE_Cxxx_DELAY_QUEUE_MACRO(NNN, M) \
|
||||
ControllerDelayHandlerStruct<C##NNN####M##_queue_element>C##NNN####M##_DelayHandler; \
|
||||
bool do_process_c##NNN####M##_delay_queue(int controller_number, \
|
||||
const C##NNN####M##_queue_element & element, \
|
||||
ControllerSettingsStruct & ControllerSettings); \
|
||||
void process_c##NNN####M##_delay_queue() { \
|
||||
C##NNN####M##_queue_element *element(C##NNN####M##_DelayHandler.getNext()); \
|
||||
if (element == NULL) return; \
|
||||
MakeControllerSettings (ControllerSettings); \
|
||||
LoadControllerSettings(element->controller_idx, ControllerSettings); \
|
||||
C##NNN####M##_DelayHandler.configureControllerSettings(ControllerSettings); \
|
||||
if (!WiFiConnected(10)) { \
|
||||
scheduleNextDelayQueue(TIMER_C##NNN####M##_DELAY_QUEUE, C##NNN####M##_DelayHandler.getNextScheduleTime()); \
|
||||
return; \
|
||||
} \
|
||||
START_TIMER; \
|
||||
C##NNN####M##_DelayHandler.markProcessed(do_process_c##NNN####M##_delay_queue(M, *element, ControllerSettings)); \
|
||||
STOP_TIMER(C##NNN####M##_DELAY_QUEUE); \
|
||||
scheduleNextDelayQueue(TIMER_C##NNN####M##_DELAY_QUEUE, C##NNN####M##_DelayHandler.getNextScheduleTime()); \
|
||||
}
|
||||
|
||||
// Define the function wrappers to handle the calling to Cxxx_DelayHandler etc.
|
||||
// If someone knows how to add leading zeros in macros, please be my guest :)
|
||||
#ifdef USES_C001
|
||||
DEFINE_Cxxx_DELAY_QUEUE_MACRO(00, 1)
|
||||
#endif // ifdef USES_C001
|
||||
#ifdef USES_C003
|
||||
DEFINE_Cxxx_DELAY_QUEUE_MACRO(00, 3)
|
||||
#endif // ifdef USES_C003
|
||||
#ifdef USES_C004
|
||||
DEFINE_Cxxx_DELAY_QUEUE_MACRO(00, 4)
|
||||
#endif // ifdef USES_C004
|
||||
#ifdef USES_C007
|
||||
DEFINE_Cxxx_DELAY_QUEUE_MACRO(00, 7)
|
||||
#endif // ifdef USES_C007
|
||||
#ifdef USES_C008
|
||||
DEFINE_Cxxx_DELAY_QUEUE_MACRO(00, 8)
|
||||
#endif // ifdef USES_C008
|
||||
#ifdef USES_C009
|
||||
DEFINE_Cxxx_DELAY_QUEUE_MACRO(00, 9)
|
||||
#endif // ifdef USES_C009
|
||||
#ifdef USES_C010
|
||||
DEFINE_Cxxx_DELAY_QUEUE_MACRO(0, 10)
|
||||
#endif // ifdef USES_C010
|
||||
#ifdef USES_C011
|
||||
DEFINE_Cxxx_DELAY_QUEUE_MACRO(0, 11)
|
||||
#endif // ifdef USES_C011
|
||||
#ifdef USES_C012
|
||||
DEFINE_Cxxx_DELAY_QUEUE_MACRO(0, 12)
|
||||
#endif // ifdef USES_C012
|
||||
|
||||
/*
|
||||
#ifdef USES_C013
|
||||
DEFINE_Cxxx_DELAY_QUEUE_MACRO(0, 13)
|
||||
#endif
|
||||
*/
|
||||
|
||||
/*
|
||||
#ifdef USES_C014
|
||||
DEFINE_Cxxx_DELAY_QUEUE_MACRO(0, 14)
|
||||
#endif
|
||||
*/
|
||||
#ifdef USES_C015
|
||||
DEFINE_Cxxx_DELAY_QUEUE_MACRO(0, 15)
|
||||
#endif // ifdef USES_C015
|
||||
|
||||
#ifdef USES_C016
|
||||
DEFINE_Cxxx_DELAY_QUEUE_MACRO(0, 16)
|
||||
#endif // ifdef USES_C016
|
||||
|
||||
|
||||
#ifdef USES_C017
|
||||
DEFINE_Cxxx_DELAY_QUEUE_MACRO(0, 17)
|
||||
#endif // ifdef USES_C017
|
||||
|
||||
#ifdef USES_C018
|
||||
DEFINE_Cxxx_DELAY_QUEUE_MACRO(0, 18)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
#ifdef USES_C019
|
||||
DEFINE_Cxxx_DELAY_QUEUE_MACRO(0, 19)
|
||||
#endif
|
||||
*/
|
||||
|
||||
/*
|
||||
#ifdef USES_C020
|
||||
DEFINE_Cxxx_DELAY_QUEUE_MACRO(0, 20)
|
||||
#endif
|
||||
*/
|
||||
|
||||
|
||||
// When extending this, also extend in Scheduler.ino:
|
||||
// void process_interval_timer(unsigned long id, unsigned long lasttimer)
|
||||
|
||||
// Uncrustify must not be used on macros, but we're now done, so turn Uncrustify on again.
|
||||
// *INDENT-ON*
|
||||
|
||||
#endif // DELAY_QUEUE_ELEMENTS_H
|
||||
+58
-1051
File diff suppressed because it is too large
Load Diff
@@ -82,8 +82,25 @@
|
||||
// SHT1X temperature/humidity sensors
|
||||
// Ser2Net server
|
||||
|
||||
|
||||
// Define globals before plugin sets to allow a personal override of the selected plugins
|
||||
#include "ESPEasy-Globals.h"
|
||||
// Must be included after all the defines, since it is using TASKS_MAX
|
||||
#include "_Plugin_Helper.h"
|
||||
// Plugin helper needs the defined controller sets, thus include after 'define_plugin_sets.h'
|
||||
#include "_CPlugin_Helper.h"
|
||||
#include "DelayQueueElements.h"
|
||||
|
||||
|
||||
// Get functions to give access to global defined variables.
|
||||
// These are needed to get direct access to global defined variables, since they cannot be defined in .h files and included more than once.
|
||||
SettingsStruct& getSettings() { return Settings; }
|
||||
SecurityStruct& getSecuritySettings() { return SecuritySettings; }
|
||||
CRCStruct& getCRCValues() { return CRCValues; }
|
||||
|
||||
unsigned long& getConnectionFailures() { return connectionFailures; }
|
||||
byte& getHighestActiveLogLevel() { return highest_active_log_level; }
|
||||
int getPluginId_from_TaskIndex(byte taskIndex) { return Task_id_to_Plugin_id[taskIndex]; }
|
||||
|
||||
|
||||
#ifdef USES_BLYNK
|
||||
@@ -121,6 +138,9 @@ void sw_watchdog_callback(void *arg)
|
||||
++sw_watchdog_callback_count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
* SETUP
|
||||
\*********************************************************************************************/
|
||||
|
||||
@@ -403,6 +403,31 @@ byte disableNotification(byte bootFailedCount) {
|
||||
return bootFailedCount;
|
||||
}
|
||||
|
||||
|
||||
#define DAT_TASKS_DISTANCE 2048 // DAT_TASKS_SIZE + DAT_TASKS_CUSTOM_SIZE
|
||||
#define DAT_TASKS_SIZE 1024
|
||||
#define DAT_TASKS_CUSTOM_OFFSET 1024 // Equal to DAT_TASKS_SIZE
|
||||
#define DAT_TASKS_CUSTOM_SIZE 1024
|
||||
#define DAT_CUSTOM_CONTROLLER_SIZE 1024
|
||||
#define DAT_CONTROLLER_SIZE 1024
|
||||
#define DAT_NOTIFICATION_SIZE 1024
|
||||
|
||||
#define DAT_BASIC_SETTINGS_SIZE 4096
|
||||
|
||||
#if defined(ESP8266)
|
||||
#define DAT_OFFSET_TASKS 4096 // each task = 2k, (1024 basic + 1024 bytes custom), 12 max
|
||||
#define DAT_OFFSET_CONTROLLER 28672 // each controller = 1k, 4 max
|
||||
#define DAT_OFFSET_CUSTOM_CONTROLLER 32768 // each custom controller config = 1k, 4 max.
|
||||
#define CONFIG_FILE_SIZE 65536
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
#define DAT_OFFSET_CONTROLLER 8192 // each controller = 1k, 4 max
|
||||
#define DAT_OFFSET_CUSTOM_CONTROLLER 12288 // each custom controller config = 1k, 4 max.
|
||||
#define DAT_OFFSET_TASKS 32768 // each task = 2k, (1024 basic + 1024 bytes custom), 32 max
|
||||
#define CONFIG_FILE_SIZE 131072
|
||||
#endif
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Offsets in settings files
|
||||
\*********************************************************************************************/
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
#ifndef ESP_EASY_LOG_H
|
||||
#define ESP_EASY_LOG_H
|
||||
|
||||
|
||||
#include "ESPEasy_common.h"
|
||||
|
||||
#define LOG_LEVEL_NONE 0
|
||||
#define LOG_LEVEL_ERROR 1
|
||||
#define LOG_LEVEL_INFO 2
|
||||
#define LOG_LEVEL_DEBUG 3
|
||||
#define LOG_LEVEL_DEBUG_MORE 4
|
||||
#define LOG_LEVEL_DEBUG_DEV 9 // use for testing/debugging only, not for regular use
|
||||
#define LOG_LEVEL_NRELEMENTS 5 // Update this and getLogLevelDisplayString() when new log levels are added
|
||||
|
||||
#define LOG_TO_SERIAL 1
|
||||
#define LOG_TO_SYSLOG 2
|
||||
#define LOG_TO_WEBLOG 3
|
||||
#define LOG_TO_SDCARD 4
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Logging
|
||||
\*********************************************************************************************/
|
||||
String getLogLevelDisplayString(int logLevel);
|
||||
|
||||
String getLogLevelDisplayStringFromIndex(byte index, int& logLevel);
|
||||
|
||||
void addToLog(byte loglevel, const String& string);
|
||||
void addToLog(byte logLevel, const __FlashStringHelper* flashString);
|
||||
|
||||
void disableSerialLog();
|
||||
|
||||
void setLogLevelFor(byte destination, byte logLevel);
|
||||
|
||||
void updateLogLevelCache();
|
||||
|
||||
bool loglevelActiveFor(byte logLevel);
|
||||
|
||||
byte getSerialLogLevel();
|
||||
|
||||
byte getWebLogLevel();
|
||||
|
||||
bool loglevelActiveFor(byte destination, byte logLevel);
|
||||
|
||||
|
||||
bool loglevelActive(byte logLevel, byte logLevelSettings);
|
||||
|
||||
void addToLog(byte logLevel, const char *line);
|
||||
|
||||
// Do this in a template to prevent casting to String when not needed.
|
||||
#define addLog(L,S) if (loglevelActiveFor(L)) { addToLog(L,S); }
|
||||
|
||||
|
||||
#endif // ESP_EASY_LOG_H
|
||||
@@ -0,0 +1,185 @@
|
||||
#include "ESPEasy_Log.h"
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Init critical variables for logging (important during initial factory reset stuff )
|
||||
\*********************************************************************************************/
|
||||
void initLog()
|
||||
{
|
||||
//make sure addLog doesnt do any stuff before initalisation of Settings is complete.
|
||||
Settings.UseSerial=true;
|
||||
Settings.SyslogFacility=0;
|
||||
setLogLevelFor(LOG_TO_SYSLOG, 0);
|
||||
setLogLevelFor(LOG_TO_SERIAL, 2); //logging during initialisation
|
||||
setLogLevelFor(LOG_TO_WEBLOG, 2);
|
||||
setLogLevelFor(LOG_TO_SDCARD, 0);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Logging
|
||||
\*********************************************************************************************/
|
||||
String getLogLevelDisplayString(int logLevel) {
|
||||
switch (logLevel) {
|
||||
case LOG_LEVEL_NONE: return F("None");
|
||||
case LOG_LEVEL_ERROR: return F("Error");
|
||||
case LOG_LEVEL_INFO: return F("Info");
|
||||
case LOG_LEVEL_DEBUG: return F("Debug");
|
||||
case LOG_LEVEL_DEBUG_MORE: return F("Debug More");
|
||||
case LOG_LEVEL_DEBUG_DEV: return F("Debug dev");
|
||||
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
String getLogLevelDisplayStringFromIndex(byte index, int& logLevel) {
|
||||
switch (index) {
|
||||
case 0: logLevel = LOG_LEVEL_ERROR; break;
|
||||
case 1: logLevel = LOG_LEVEL_INFO; break;
|
||||
case 2: logLevel = LOG_LEVEL_DEBUG; break;
|
||||
case 3: logLevel = LOG_LEVEL_DEBUG_MORE; break;
|
||||
case 4: logLevel = LOG_LEVEL_DEBUG_DEV; break;
|
||||
|
||||
default: logLevel = -1; return "";
|
||||
}
|
||||
return getLogLevelDisplayString(logLevel);
|
||||
}
|
||||
|
||||
void addToLog(byte loglevel, const String& string)
|
||||
{
|
||||
addToLog(loglevel, string.c_str());
|
||||
}
|
||||
|
||||
void addToLog(byte logLevel, const __FlashStringHelper* flashString)
|
||||
{
|
||||
checkRAM(F("addToLog"));
|
||||
String s(flashString);
|
||||
addToLog(logLevel, s.c_str());
|
||||
}
|
||||
|
||||
void disableSerialLog() {
|
||||
log_to_serial_disabled = true;
|
||||
setLogLevelFor(LOG_TO_SERIAL, 0);
|
||||
}
|
||||
|
||||
void setLogLevelFor(byte destination, byte logLevel) {
|
||||
switch (destination) {
|
||||
case LOG_TO_SERIAL:
|
||||
if (!log_to_serial_disabled || logLevel == 0)
|
||||
Settings.SerialLogLevel = logLevel; break;
|
||||
case LOG_TO_SYSLOG: Settings.SyslogLevel = logLevel; break;
|
||||
case LOG_TO_WEBLOG: Settings.WebLogLevel = logLevel; break;
|
||||
case LOG_TO_SDCARD: Settings.SDLogLevel = logLevel; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
updateLogLevelCache();
|
||||
}
|
||||
|
||||
void updateLogLevelCache() {
|
||||
byte max_lvl = 0;
|
||||
if (log_to_serial_disabled) {
|
||||
if (Settings.UseSerial) {
|
||||
Serial.setDebugOutput(false);
|
||||
}
|
||||
} else {
|
||||
max_lvl = _max(max_lvl, Settings.SerialLogLevel);
|
||||
#ifndef BUILD_NO_DEBUG
|
||||
if (Settings.UseSerial && Settings.SerialLogLevel >= LOG_LEVEL_DEBUG_MORE) {
|
||||
Serial.setDebugOutput(true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
max_lvl = _max(max_lvl, Settings.SyslogLevel);
|
||||
if (Logging.logActiveRead()) {
|
||||
max_lvl = _max(max_lvl, Settings.WebLogLevel);
|
||||
}
|
||||
#ifdef FEATURE_SD
|
||||
max_lvl = _max(max_lvl, Settings.SDLogLevel);
|
||||
#endif
|
||||
highest_active_log_level = max_lvl;
|
||||
}
|
||||
|
||||
bool loglevelActiveFor(byte logLevel) {
|
||||
return loglevelActive(logLevel, highest_active_log_level);
|
||||
}
|
||||
|
||||
byte getSerialLogLevel() {
|
||||
if (log_to_serial_disabled || !Settings.UseSerial) return 0;
|
||||
if (wifiStatus != ESPEASY_WIFI_SERVICES_INITIALIZED){
|
||||
if (Settings.SerialLogLevel < LOG_LEVEL_INFO) {
|
||||
return LOG_LEVEL_INFO;
|
||||
}
|
||||
}
|
||||
return Settings.SerialLogLevel;
|
||||
}
|
||||
|
||||
byte getWebLogLevel() {
|
||||
byte logLevelSettings = 0;
|
||||
if (Logging.logActiveRead()) {
|
||||
logLevelSettings = Settings.WebLogLevel;
|
||||
} else {
|
||||
if (Settings.WebLogLevel != 0) {
|
||||
updateLogLevelCache();
|
||||
}
|
||||
}
|
||||
return logLevelSettings;
|
||||
}
|
||||
|
||||
bool loglevelActiveFor(byte destination, byte logLevel) {
|
||||
byte logLevelSettings = 0;
|
||||
switch (destination) {
|
||||
case LOG_TO_SERIAL: {
|
||||
logLevelSettings = getSerialLogLevel();
|
||||
break;
|
||||
}
|
||||
case LOG_TO_SYSLOG: {
|
||||
logLevelSettings = Settings.SyslogLevel;
|
||||
break;
|
||||
}
|
||||
case LOG_TO_WEBLOG: {
|
||||
logLevelSettings = getWebLogLevel();
|
||||
break;
|
||||
}
|
||||
case LOG_TO_SDCARD: {
|
||||
#ifdef FEATURE_SD
|
||||
logLevelSettings = Settings.SDLogLevel;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return loglevelActive(logLevel, logLevelSettings);
|
||||
}
|
||||
|
||||
|
||||
bool loglevelActive(byte logLevel, byte logLevelSettings) {
|
||||
return (logLevel <= logLevelSettings);
|
||||
}
|
||||
|
||||
void addToLog(byte logLevel, const char *line)
|
||||
{
|
||||
if (loglevelActiveFor(LOG_TO_SERIAL, logLevel)) {
|
||||
addToSerialBuffer(String(millis()).c_str());
|
||||
addToSerialBuffer(" : ");
|
||||
addToSerialBuffer(line);
|
||||
addNewlineToSerialBuffer();
|
||||
}
|
||||
if (loglevelActiveFor(LOG_TO_SYSLOG, logLevel)) {
|
||||
syslog(logLevel, line);
|
||||
}
|
||||
if (loglevelActiveFor(LOG_TO_WEBLOG, logLevel)) {
|
||||
Logging.add(logLevel, line);
|
||||
}
|
||||
|
||||
#ifdef FEATURE_SD
|
||||
if (loglevelActiveFor(LOG_TO_SDCARD, logLevel)) {
|
||||
File logFile = SD.open("log.dat", FILE_WRITE);
|
||||
if (logFile)
|
||||
logFile.println(line);
|
||||
logFile.close();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef ESPEASY_BUILD_INFO_H
|
||||
#define ESPEASY_BUILD_INFO_H
|
||||
|
||||
|
||||
// ********************************************************************************
|
||||
// DO NOT CHANGE ANYTHING BELOW THIS LINE
|
||||
// ********************************************************************************
|
||||
#define ESP_PROJECT_PID 2016110801L
|
||||
|
||||
#if defined(ESP8266)
|
||||
# define VERSION 2 // config file version (not ESPEasy version). increase if you make incompatible changes to
|
||||
// config system.
|
||||
#endif // if defined(ESP8266)
|
||||
#if defined(ESP32)
|
||||
# define VERSION 3 // Change in config.dat mapping needs a full reset
|
||||
#endif // if defined(ESP32)
|
||||
|
||||
#define BUILD 20103 // git version 2.1.03
|
||||
#if defined(ESP8266)
|
||||
# define BUILD_NOTES " - Mega"
|
||||
#endif // if defined(ESP8266)
|
||||
#if defined(ESP32)
|
||||
# define BUILD_NOTES " - Mega32"
|
||||
#endif // if defined(ESP32)
|
||||
|
||||
#ifndef BUILD_GIT
|
||||
# define BUILD_GIT "(custom)"
|
||||
#endif // ifndef BUILD_GIT
|
||||
|
||||
|
||||
#endif // ESPEASY_BUILD_INFO_H
|
||||
@@ -1,5 +1,8 @@
|
||||
#include "ESPEasy_common.h"
|
||||
|
||||
|
||||
String getUnknownString() { return F("Unknown"); }
|
||||
|
||||
/*********************************************************************************************\
|
||||
Bitwise operators
|
||||
\*********************************************************************************************/
|
||||
|
||||
@@ -15,6 +15,8 @@ namespace std
|
||||
#define ZERO_TERMINATE(S) S[sizeof(S) - 1] = 0
|
||||
|
||||
|
||||
String getUnknownString();
|
||||
|
||||
/*********************************************************************************************\
|
||||
Bitwise operators
|
||||
\*********************************************************************************************/
|
||||
|
||||
+18
-15
@@ -20,22 +20,35 @@
|
||||
|
||||
#include <FS.h>
|
||||
|
||||
struct SettingsStruct;
|
||||
struct SecurityStruct;
|
||||
struct CRCStruct;
|
||||
|
||||
// Forward declaration to give access to global member variables
|
||||
SettingsStruct& getSettings();
|
||||
SecurityStruct& getSecuritySettings();
|
||||
CRCStruct& getCRCValues();
|
||||
unsigned long& getConnectionFailures();
|
||||
byte& getHighestActiveLogLevel();
|
||||
int getPluginId_from_TaskIndex(byte taskIndex);
|
||||
|
||||
|
||||
// Forward declaration
|
||||
struct ControllerSettingsStruct;
|
||||
String getUnknownString();
|
||||
void scheduleNextDelayQueue(unsigned long id, unsigned long nextTime);
|
||||
String LoadControllerSettings(int ControllerIndex, ControllerSettingsStruct& controller_settings);
|
||||
String get_formatted_Controller_number(int controller_index);
|
||||
bool loglevelActiveFor(byte logLevel);
|
||||
void addToLog(byte loglevel, const String& string);
|
||||
void addToLog(byte logLevel, const __FlashStringHelper* flashString);
|
||||
void statusLED(boolean traffic);
|
||||
void backgroundtasks();
|
||||
uint32_t getCurrentFreeStack();
|
||||
uint32_t getFreeStackWatermark();
|
||||
bool canYield();
|
||||
|
||||
|
||||
boolean timeOutReached(unsigned long timer);
|
||||
long timePassedSince(unsigned long timestamp);
|
||||
long usecPassedSince(unsigned long timestamp);
|
||||
|
||||
void serialHelper_getGpioNames(struct EventStruct *event, bool rxOptional=false, bool txOptional=false);
|
||||
|
||||
fs::File tryOpenFile(const String& fname, const String& mode);
|
||||
@@ -76,17 +89,6 @@ void rulesProcessing(String& event);
|
||||
void setIntervalTimer(unsigned long id);
|
||||
byte getProtocolIndex(byte Number);
|
||||
|
||||
#ifdef USES_PACKED_RAW_DATA
|
||||
// Forward declarations PackedData related functions
|
||||
typedef uint32_t PackedData_enum;
|
||||
uint8_t getPackedDataTypeSize(PackedData_enum dtype, float& factor, float& offset);
|
||||
void LoRa_uintToBytes(uint64_t value, uint8_t byteSize, byte *data, uint8_t& cursor);
|
||||
String LoRa_base16Encode(byte *data, size_t size);
|
||||
String LoRa_addInt(uint64_t value, PackedData_enum datatype);
|
||||
static String LoRa_addFloat(float value, PackedData_enum datatype);
|
||||
//String getPackedFromPlugin(struct EventStruct *event, uint8_t sampleSetCount);
|
||||
#endif // USES_PACKED_RAW_DATA
|
||||
|
||||
#ifdef USES_MQTT
|
||||
//void runPeriodicalMQTT();
|
||||
//void updateMQTTclient_connected();
|
||||
@@ -99,4 +101,5 @@ bool MQTTCheck(int controller_idx);
|
||||
void schedule_all_tasks_using_MQTT_controller();
|
||||
#endif
|
||||
|
||||
|
||||
#endif // ESPEASY_FWD_DECL_H
|
||||
@@ -0,0 +1,91 @@
|
||||
#include "ESPEasy_packed_raw_data.h"
|
||||
|
||||
|
||||
uint8_t getPackedDataTypeSize(PackedData_enum dtype, float& factor, float& offset) {
|
||||
offset = 0;
|
||||
factor = 1;
|
||||
if (dtype > 0x1000 && dtype < 0x12FF) {
|
||||
const uint8_t exponent = dtype & 0xF;
|
||||
switch(exponent) {
|
||||
case 0: factor = 1; break;
|
||||
case 1: factor = 1e1; break;
|
||||
case 2: factor = 1e2; break;
|
||||
case 3: factor = 1e3; break;
|
||||
case 4: factor = 1e4; break;
|
||||
case 5: factor = 1e5; break;
|
||||
case 6: factor = 1e6; break;
|
||||
}
|
||||
const uint8_t size = (dtype >> 8) & 0xF;
|
||||
return size;
|
||||
}
|
||||
switch (dtype) {
|
||||
case PackedData_pluginid: factor = 1; return 1;
|
||||
case PackedData_latLng: factor = 46600; return 3; // 2^23 / 180
|
||||
case PackedData_hdop: factor = 10; return 1;
|
||||
case PackedData_altitude: factor = 4; offset = 1000; return 2; // -1000 .. 15383.75 meter
|
||||
case PackedData_vcc: factor = 41.83; offset = 1; return 1; // -1 .. 5.12V
|
||||
case PackedData_pct_8: factor = 2.56; return 1; // 0 .. 100%
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Unknown type
|
||||
factor = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LoRa_uintToBytes(uint64_t value, uint8_t byteSize, byte *data, uint8_t& cursor) {
|
||||
// Clip values to upper limit
|
||||
const uint64_t upperlimit = (1 << (8*byteSize)) - 1;
|
||||
if (value > upperlimit) { value = upperlimit; }
|
||||
for (uint8_t x = 0; x < byteSize; x++) {
|
||||
byte next = 0;
|
||||
if (sizeof(value) > x) {
|
||||
next = static_cast<byte>((value >> (x * 8)) & 0xFF);
|
||||
}
|
||||
data[cursor] = next;
|
||||
++cursor;
|
||||
}
|
||||
}
|
||||
|
||||
void LoRa_intToBytes(int64_t value, uint8_t byteSize, byte *data, uint8_t& cursor) {
|
||||
// Clip values to lower limit
|
||||
const int64_t lowerlimit = (1 << ((8*byteSize) - 1)) * -1;
|
||||
if (value < lowerlimit) { value = lowerlimit; }
|
||||
if (value < 0) {
|
||||
value += (1 << (8*byteSize));
|
||||
}
|
||||
LoRa_uintToBytes(value, byteSize, data, cursor);
|
||||
}
|
||||
|
||||
String LoRa_base16Encode(byte *data, size_t size) {
|
||||
String output;
|
||||
output.reserve(size * 2);
|
||||
char buffer[3];
|
||||
for (unsigned i=0; i<size; i++)
|
||||
{
|
||||
sprintf(buffer, "%02X", data[i]);
|
||||
output += buffer[0];
|
||||
output += buffer[1];
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
String LoRa_addInt(uint64_t value, PackedData_enum datatype) {
|
||||
float factor, offset;
|
||||
uint8_t byteSize = getPackedDataTypeSize(datatype, factor, offset);
|
||||
byte data[4] = {0};
|
||||
uint8_t cursor = 0;
|
||||
LoRa_uintToBytes((value + offset) * factor, byteSize, &data[0], cursor);
|
||||
return LoRa_base16Encode(data, cursor);
|
||||
}
|
||||
|
||||
|
||||
String LoRa_addFloat(float value, PackedData_enum datatype) {
|
||||
float factor, offset;
|
||||
uint8_t byteSize = getPackedDataTypeSize(datatype, factor, offset);
|
||||
byte data[4] = {0};
|
||||
uint8_t cursor = 0;
|
||||
LoRa_intToBytes((value + offset) * factor, byteSize, &data[0], cursor);
|
||||
return LoRa_base16Encode(data, cursor);
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
#ifndef ESPEASY_PACKED_RAW_DATA_H
|
||||
#define ESPEASY_PACKED_RAW_DATA_H
|
||||
|
||||
#include "ESPEasy_common.h"
|
||||
|
||||
// Data types used in packed encoder.
|
||||
// p_uint16_1e2 means it is a 16 bit unsigned int, but multiplied by 100 first.
|
||||
// This allows to store 2 decimals of a floating point value in 8 bits, ranging from 0.00 ... 2.55
|
||||
// For example p_int24_1e6 is a 24-bit signed value, ideal to store a GPS coordinate
|
||||
// with 6 decimals using only 3 bytes instead of 4 a normal float would use.
|
||||
//
|
||||
// PackedData_uintX_1eY = 0x11XY (X= #bytes, Y=exponent)
|
||||
// PackedData_intX_1eY = 0x12XY (X= #bytes, Y=exponent)
|
||||
typedef uint32_t PackedData_enum;
|
||||
#define PackedData_uint8 0x1110
|
||||
#define PackedData_uint16 0x1120
|
||||
#define PackedData_uint24 0x1130
|
||||
#define PackedData_uint32 0x1140
|
||||
#define PackedData_uint8_1e3 0x1113
|
||||
#define PackedData_uint8_1e2 0x1112
|
||||
#define PackedData_uint8_1e1 0x1111
|
||||
#define PackedData_uint16_1e5 0x1125
|
||||
#define PackedData_uint16_1e4 0x1124
|
||||
#define PackedData_uint16_1e3 0x1123
|
||||
#define PackedData_uint16_1e2 0x1122
|
||||
#define PackedData_uint16_1e1 0x1121
|
||||
#define PackedData_uint24_1e6 0x1136
|
||||
#define PackedData_uint24_1e5 0x1135
|
||||
#define PackedData_uint24_1e4 0x1134
|
||||
#define PackedData_uint24_1e3 0x1133
|
||||
#define PackedData_uint24_1e2 0x1132
|
||||
#define PackedData_uint24_1e1 0x1131
|
||||
#define PackedData_uint32_1e6 0x1146
|
||||
#define PackedData_uint32_1e5 0x1145
|
||||
#define PackedData_uint32_1e4 0x1144
|
||||
#define PackedData_uint32_1e3 0x1143
|
||||
#define PackedData_uint32_1e2 0x1142
|
||||
#define PackedData_uint32_1e1 0x1141
|
||||
#define PackedData_int8 0x1210
|
||||
#define PackedData_int16 0x1220
|
||||
#define PackedData_int24 0x1230
|
||||
#define PackedData_int32 0x1240
|
||||
#define PackedData_int8_1e3 0x1213
|
||||
#define PackedData_int8_1e2 0x1212
|
||||
#define PackedData_int8_1e1 0x1211
|
||||
#define PackedData_int16_1e5 0x1225
|
||||
#define PackedData_int16_1e4 0x1224
|
||||
#define PackedData_int16_1e3 0x1223
|
||||
#define PackedData_int16_1e2 0x1222
|
||||
#define PackedData_int16_1e1 0x1221
|
||||
#define PackedData_int24_1e6 0x1236
|
||||
#define PackedData_int24_1e5 0x1235
|
||||
#define PackedData_int24_1e4 0x1234
|
||||
#define PackedData_int24_1e3 0x1233
|
||||
#define PackedData_int24_1e2 0x1232
|
||||
#define PackedData_int24_1e1 0x1231
|
||||
#define PackedData_int32_1e6 0x1246
|
||||
#define PackedData_int32_1e5 0x1245
|
||||
#define PackedData_int32_1e4 0x1244
|
||||
#define PackedData_int32_1e3 0x1243
|
||||
#define PackedData_int32_1e2 0x1242
|
||||
#define PackedData_int32_1e1 0x1241
|
||||
#define PackedData_pluginid 1
|
||||
#define PackedData_latLng 2
|
||||
#define PackedData_hdop 3
|
||||
#define PackedData_altitude 4
|
||||
#define PackedData_vcc 5
|
||||
#define PackedData_pct_8 6
|
||||
|
||||
uint8_t getPackedDataTypeSize(PackedData_enum dtype, float& factor, float& offset);
|
||||
|
||||
void LoRa_uintToBytes(uint64_t value, uint8_t byteSize, byte *data, uint8_t& cursor);
|
||||
|
||||
void LoRa_intToBytes(int64_t value, uint8_t byteSize, byte *data, uint8_t& cursor);
|
||||
|
||||
String LoRa_base16Encode(byte *data, size_t size);
|
||||
|
||||
String LoRa_addInt(uint64_t value, PackedData_enum datatype);
|
||||
|
||||
String LoRa_addFloat(float value, PackedData_enum datatype);
|
||||
|
||||
|
||||
#endif // ESPEASY_PACKED_RAW_DATA_H
|
||||
@@ -0,0 +1,81 @@
|
||||
#ifndef ESPEASY_PLUGIN_DEFS_H
|
||||
#define ESPEASY_PLUGIN_DEFS_H
|
||||
|
||||
|
||||
// ********************************************************************************
|
||||
// Plugin (Task) function calls
|
||||
// ********************************************************************************
|
||||
#define PLUGIN_INIT_ALL 1
|
||||
#define PLUGIN_INIT 2
|
||||
#define PLUGIN_READ 3 // This call can yield new data (when success = true) and then send to controllers
|
||||
#define PLUGIN_ONCE_A_SECOND 4 // Called once a second
|
||||
#define PLUGIN_TEN_PER_SECOND 5 // Called 10x per second (typical for checking new data instead of waiting)
|
||||
#define PLUGIN_DEVICE_ADD 6 // Called at boot for letting a plugin adding itself to list of available plugins/devices
|
||||
#define PLUGIN_EVENTLIST_ADD 7
|
||||
#define PLUGIN_WEBFORM_SAVE 8 // Call from web interface to save settings
|
||||
#define PLUGIN_WEBFORM_LOAD 9 // Call from web interface for presenting settings and status of plugin
|
||||
#define PLUGIN_WEBFORM_SHOW_VALUES 10 // Call from devices overview page to format values in HTML
|
||||
#define PLUGIN_GET_DEVICENAME 11
|
||||
#define PLUGIN_GET_DEVICEVALUENAMES 12
|
||||
#define PLUGIN_WRITE 13
|
||||
#define PLUGIN_EVENT_OUT 14
|
||||
#define PLUGIN_WEBFORM_SHOW_CONFIG 15
|
||||
#define PLUGIN_SERIAL_IN 16
|
||||
#define PLUGIN_UDP_IN 17
|
||||
#define PLUGIN_CLOCK_IN 18
|
||||
#define PLUGIN_TIMER_IN 19
|
||||
#define PLUGIN_FIFTY_PER_SECOND 20
|
||||
#define PLUGIN_SET_CONFIG 21
|
||||
#define PLUGIN_GET_DEVICEGPIONAMES 22
|
||||
#define PLUGIN_EXIT 23
|
||||
#define PLUGIN_GET_CONFIG 24
|
||||
#define PLUGIN_UNCONDITIONAL_POLL 25
|
||||
#define PLUGIN_REQUEST 26
|
||||
#define PLUGIN_TIME_CHANGE 27
|
||||
#define PLUGIN_MONITOR 28
|
||||
#define PLUGIN_SET_DEFAULTS 29
|
||||
#define PLUGIN_GET_PACKED_RAW_DATA 30 // Return all data in a compact binary format specific for that plugin.
|
||||
// Needs USES_PACKED_RAW_DATA
|
||||
|
||||
// ********************************************************************************
|
||||
// CPlugin (Controller) function calls
|
||||
// ********************************************************************************
|
||||
|
||||
// Make sure the CPLUGIN_* does not overlap PLUGIN_*
|
||||
#define CPLUGIN_PROTOCOL_ADD 41 // Called at boot for letting a controller adding itself to list of available controllers
|
||||
#define CPLUGIN_PROTOCOL_TEMPLATE 42
|
||||
#define CPLUGIN_PROTOCOL_SEND 43
|
||||
#define CPLUGIN_PROTOCOL_RECV 44
|
||||
#define CPLUGIN_GET_DEVICENAME 45
|
||||
#define CPLUGIN_WEBFORM_SAVE 46
|
||||
#define CPLUGIN_WEBFORM_LOAD 47
|
||||
#define CPLUGIN_GET_PROTOCOL_DISPLAY_NAME 48
|
||||
#define CPLUGIN_TASK_CHANGE_NOTIFICATION 49
|
||||
#define CPLUGIN_INIT 50
|
||||
#define CPLUGIN_UDP_IN 51
|
||||
#define CPLUGIN_FLUSH 52 // Force offloading data stored in buffers, called before sleep/reboot
|
||||
|
||||
// new messages for autodiscover controller plugins (experimental) i.e. C014
|
||||
#define CPLUGIN_GOT_CONNECTED 53 // call after connected to mqtt server to publich device autodicover features
|
||||
#define CPLUGIN_GOT_INVALID 54 // should be called before major changes i.e. changing the device name to clean up data on the controller. !ToDo
|
||||
#define CPLUGIN_INTERVAL 55 // call every interval loop
|
||||
#define CPLUGIN_ACKNOWLEDGE 56 // call for sending acknowledges !ToDo done by direct function call in PluginCall() for now.
|
||||
|
||||
#define CPLUGIN_WEBFORM_SHOW_HOST_CONFIG 57 // Used for showing host information for the controller.
|
||||
|
||||
|
||||
|
||||
|
||||
// ********************************************************************************
|
||||
// NPlugin (Notification) function calls
|
||||
// ********************************************************************************
|
||||
#define NPLUGIN_PROTOCOL_ADD 1
|
||||
#define NPLUGIN_GET_DEVICENAME 2
|
||||
#define NPLUGIN_WEBFORM_SAVE 3
|
||||
#define NPLUGIN_WEBFORM_LOAD 4
|
||||
#define NPLUGIN_WRITE 5
|
||||
#define NPLUGIN_NOTIFY 6
|
||||
#define NPLUGIN_NOT_FOUND 255
|
||||
|
||||
|
||||
#endif // ESPEASY_PLUGIN_DEFS_H
|
||||
-182
@@ -2,7 +2,6 @@
|
||||
ESPEasy specific strings
|
||||
\*********************************************************************************************/
|
||||
|
||||
String getUnknownString() { return F("Unknown"); }
|
||||
|
||||
String getNodeTypeDisplayString(byte nodeType) {
|
||||
switch (nodeType)
|
||||
@@ -1400,187 +1399,6 @@ float timeStringToSeconds(String tBuf) {
|
||||
return sec;
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Init critical variables for logging (important during initial factory reset stuff )
|
||||
\*********************************************************************************************/
|
||||
void initLog()
|
||||
{
|
||||
//make sure addLog doesnt do any stuff before initalisation of Settings is complete.
|
||||
Settings.UseSerial=true;
|
||||
Settings.SyslogFacility=0;
|
||||
setLogLevelFor(LOG_TO_SYSLOG, 0);
|
||||
setLogLevelFor(LOG_TO_SERIAL, 2); //logging during initialisation
|
||||
setLogLevelFor(LOG_TO_WEBLOG, 2);
|
||||
setLogLevelFor(LOG_TO_SDCARD, 0);
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Logging
|
||||
\*********************************************************************************************/
|
||||
String getLogLevelDisplayString(int logLevel) {
|
||||
switch (logLevel) {
|
||||
case LOG_LEVEL_NONE: return F("None");
|
||||
case LOG_LEVEL_ERROR: return F("Error");
|
||||
case LOG_LEVEL_INFO: return F("Info");
|
||||
case LOG_LEVEL_DEBUG: return F("Debug");
|
||||
case LOG_LEVEL_DEBUG_MORE: return F("Debug More");
|
||||
case LOG_LEVEL_DEBUG_DEV: return F("Debug dev");
|
||||
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
String getLogLevelDisplayStringFromIndex(byte index, int& logLevel) {
|
||||
switch (index) {
|
||||
case 0: logLevel = LOG_LEVEL_ERROR; break;
|
||||
case 1: logLevel = LOG_LEVEL_INFO; break;
|
||||
case 2: logLevel = LOG_LEVEL_DEBUG; break;
|
||||
case 3: logLevel = LOG_LEVEL_DEBUG_MORE; break;
|
||||
case 4: logLevel = LOG_LEVEL_DEBUG_DEV; break;
|
||||
|
||||
default: logLevel = -1; return "";
|
||||
}
|
||||
return getLogLevelDisplayString(logLevel);
|
||||
}
|
||||
|
||||
void addToLog(byte loglevel, const String& string)
|
||||
{
|
||||
addToLog(loglevel, string.c_str());
|
||||
}
|
||||
|
||||
void addToLog(byte logLevel, const __FlashStringHelper* flashString)
|
||||
{
|
||||
checkRAM(F("addToLog"));
|
||||
String s(flashString);
|
||||
addToLog(logLevel, s.c_str());
|
||||
}
|
||||
|
||||
void disableSerialLog() {
|
||||
log_to_serial_disabled = true;
|
||||
setLogLevelFor(LOG_TO_SERIAL, 0);
|
||||
}
|
||||
|
||||
void setLogLevelFor(byte destination, byte logLevel) {
|
||||
switch (destination) {
|
||||
case LOG_TO_SERIAL:
|
||||
if (!log_to_serial_disabled || logLevel == 0)
|
||||
Settings.SerialLogLevel = logLevel; break;
|
||||
case LOG_TO_SYSLOG: Settings.SyslogLevel = logLevel; break;
|
||||
case LOG_TO_WEBLOG: Settings.WebLogLevel = logLevel; break;
|
||||
case LOG_TO_SDCARD: Settings.SDLogLevel = logLevel; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
updateLogLevelCache();
|
||||
}
|
||||
|
||||
void updateLogLevelCache() {
|
||||
byte max_lvl = 0;
|
||||
if (log_to_serial_disabled) {
|
||||
if (Settings.UseSerial) {
|
||||
Serial.setDebugOutput(false);
|
||||
}
|
||||
} else {
|
||||
max_lvl = _max(max_lvl, Settings.SerialLogLevel);
|
||||
#ifndef BUILD_NO_DEBUG
|
||||
if (Settings.UseSerial && Settings.SerialLogLevel >= LOG_LEVEL_DEBUG_MORE) {
|
||||
Serial.setDebugOutput(true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
max_lvl = _max(max_lvl, Settings.SyslogLevel);
|
||||
if (Logging.logActiveRead()) {
|
||||
max_lvl = _max(max_lvl, Settings.WebLogLevel);
|
||||
}
|
||||
#ifdef FEATURE_SD
|
||||
max_lvl = _max(max_lvl, Settings.SDLogLevel);
|
||||
#endif
|
||||
highest_active_log_level = max_lvl;
|
||||
}
|
||||
|
||||
bool loglevelActiveFor(byte logLevel) {
|
||||
return loglevelActive(logLevel, highest_active_log_level);
|
||||
}
|
||||
|
||||
byte getSerialLogLevel() {
|
||||
if (log_to_serial_disabled || !Settings.UseSerial) return 0;
|
||||
if (wifiStatus != ESPEASY_WIFI_SERVICES_INITIALIZED){
|
||||
if (Settings.SerialLogLevel < LOG_LEVEL_INFO) {
|
||||
return LOG_LEVEL_INFO;
|
||||
}
|
||||
}
|
||||
return Settings.SerialLogLevel;
|
||||
}
|
||||
|
||||
byte getWebLogLevel() {
|
||||
byte logLevelSettings = 0;
|
||||
if (Logging.logActiveRead()) {
|
||||
logLevelSettings = Settings.WebLogLevel;
|
||||
} else {
|
||||
if (Settings.WebLogLevel != 0) {
|
||||
updateLogLevelCache();
|
||||
}
|
||||
}
|
||||
return logLevelSettings;
|
||||
}
|
||||
|
||||
boolean loglevelActiveFor(byte destination, byte logLevel) {
|
||||
byte logLevelSettings = 0;
|
||||
switch (destination) {
|
||||
case LOG_TO_SERIAL: {
|
||||
logLevelSettings = getSerialLogLevel();
|
||||
break;
|
||||
}
|
||||
case LOG_TO_SYSLOG: {
|
||||
logLevelSettings = Settings.SyslogLevel;
|
||||
break;
|
||||
}
|
||||
case LOG_TO_WEBLOG: {
|
||||
logLevelSettings = getWebLogLevel();
|
||||
break;
|
||||
}
|
||||
case LOG_TO_SDCARD: {
|
||||
#ifdef FEATURE_SD
|
||||
logLevelSettings = Settings.SDLogLevel;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return loglevelActive(logLevel, logLevelSettings);
|
||||
}
|
||||
|
||||
|
||||
boolean loglevelActive(byte logLevel, byte logLevelSettings) {
|
||||
return (logLevel <= logLevelSettings);
|
||||
}
|
||||
|
||||
void addToLog(byte logLevel, const char *line)
|
||||
{
|
||||
if (loglevelActiveFor(LOG_TO_SERIAL, logLevel)) {
|
||||
addToSerialBuffer(String(millis()).c_str());
|
||||
addToSerialBuffer(" : ");
|
||||
addToSerialBuffer(line);
|
||||
addNewlineToSerialBuffer();
|
||||
}
|
||||
if (loglevelActiveFor(LOG_TO_SYSLOG, logLevel)) {
|
||||
syslog(logLevel, line);
|
||||
}
|
||||
if (loglevelActiveFor(LOG_TO_WEBLOG, logLevel)) {
|
||||
Logging.add(logLevel, line);
|
||||
}
|
||||
|
||||
#ifdef FEATURE_SD
|
||||
if (loglevelActiveFor(LOG_TO_SDCARD, logLevel)) {
|
||||
File logFile = SD.open("log.dat", FILE_WRITE);
|
||||
if (logFile)
|
||||
logFile.println(line);
|
||||
logFile.close();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
|
||||
+1
-1
@@ -334,7 +334,7 @@ void process_interval_timer(unsigned long id, unsigned long lasttimer) {
|
||||
#endif
|
||||
*/
|
||||
|
||||
// When extending this, also extend in _CPlugin_Helper.h
|
||||
// When extending this, also extend in DelayQueueElements.h
|
||||
// Look for DEFINE_Cxxx_DELAY_QUEUE_MACRO
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,422 @@
|
||||
#include "_CPlugin_Helper.h"
|
||||
|
||||
#include "ESPEasy_fdwdecl.h"
|
||||
#include "ESPEasy_Log.h"
|
||||
#include "ESPEasy_buildinfo.h"
|
||||
|
||||
#include "DataStructs/SecurityStruct.h"
|
||||
#include "DataStructs/CRCStruct.h"
|
||||
#include "DataStructs/SettingsStruct.h"
|
||||
|
||||
#include "DataStructs/ControllerSettingsStruct.h"
|
||||
#include "DataStructs/ESPEasyLimits.h"
|
||||
#include "DataStructs/TimingStats.h"
|
||||
|
||||
#include <WiFiClient.h>
|
||||
#include <WiFiUdp.h>
|
||||
#include <base64.h>
|
||||
|
||||
bool safeReadStringUntil(Stream & input,
|
||||
String & str,
|
||||
char terminator,
|
||||
unsigned int maxSize,
|
||||
unsigned int timeout)
|
||||
{
|
||||
int c;
|
||||
const unsigned long start = millis();
|
||||
const unsigned long timer = start + timeout;
|
||||
unsigned long backgroundtasks_timer = start + 10;
|
||||
|
||||
str = "";
|
||||
|
||||
do {
|
||||
// read character
|
||||
if (input.available()) {
|
||||
c = input.read();
|
||||
|
||||
if (c >= 0) {
|
||||
// found terminator, we're ok
|
||||
if (c == terminator) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// found character, add to string
|
||||
else {
|
||||
str += char(c);
|
||||
|
||||
// string at max size?
|
||||
if (str.length() >= maxSize) {
|
||||
addLog(LOG_LEVEL_ERROR, F("Not enough bufferspace to read all input data!"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We must run the backgroundtasks every now and then.
|
||||
if (timeOutReached(backgroundtasks_timer)) {
|
||||
backgroundtasks_timer += 10;
|
||||
backgroundtasks();
|
||||
} else {
|
||||
delay(0);
|
||||
}
|
||||
} else {
|
||||
delay(0);
|
||||
}
|
||||
} while (!timeOutReached(timer));
|
||||
|
||||
addLog(LOG_LEVEL_ERROR, F("Timeout while reading input data!"));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool valid_controller_number(int controller_number) {
|
||||
if (controller_number < 0) { return false; }
|
||||
return true;
|
||||
|
||||
// return getProtocolIndex(controller_number) <= protocolCount;
|
||||
}
|
||||
|
||||
String get_formatted_Controller_number(int controller_number) {
|
||||
if (!valid_controller_number(controller_number)) {
|
||||
return F("C---");
|
||||
}
|
||||
String result = F("C");
|
||||
|
||||
if (controller_number < 100) { result += '0'; }
|
||||
|
||||
if (controller_number < 10) { result += '0'; }
|
||||
result += controller_number;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
String get_auth_header(const String& user, const String& pass) {
|
||||
String authHeader = "";
|
||||
|
||||
if (user.length() != 0 && pass.length() != 0) {
|
||||
base64 encoder;
|
||||
String auth = user;
|
||||
auth += ":";
|
||||
auth += pass;
|
||||
authHeader = F("Authorization: Basic ");
|
||||
authHeader += encoder.encode(auth);
|
||||
authHeader += F(" \r\n");
|
||||
}
|
||||
return authHeader;
|
||||
}
|
||||
|
||||
String get_auth_header(int controller_index) {
|
||||
String authHeader = "";
|
||||
|
||||
if (controller_index < CONTROLLER_MAX) {
|
||||
if ((getSecuritySettings().ControllerUser[controller_index][0] != 0) &&
|
||||
(getSecuritySettings().ControllerPassword[controller_index][0] != 0))
|
||||
{
|
||||
authHeader = get_auth_header(
|
||||
String(getSecuritySettings().ControllerUser[controller_index]),
|
||||
String(getSecuritySettings().ControllerPassword[controller_index]));
|
||||
}
|
||||
} else {
|
||||
addLog(LOG_LEVEL_ERROR, F("Invalid controller index"));
|
||||
}
|
||||
return authHeader;
|
||||
}
|
||||
|
||||
String get_user_agent_request_header_field() {
|
||||
static unsigned int agent_size = 20;
|
||||
String request;
|
||||
|
||||
request.reserve(agent_size);
|
||||
request = F("User-Agent: ");
|
||||
request += F("ESP Easy/");
|
||||
request += BUILD;
|
||||
request += '/';
|
||||
request += String(getCRCValues().compileDate);
|
||||
request += ' ';
|
||||
request += String(getCRCValues().compileTime);
|
||||
request += "\r\n";
|
||||
agent_size = request.length();
|
||||
return request;
|
||||
}
|
||||
|
||||
String do_create_http_request(
|
||||
const String& hostportString,
|
||||
const String& method, const String& uri,
|
||||
const String& auth_header, const String& additional_options,
|
||||
int content_length) {
|
||||
int estimated_size = hostportString.length() + method.length()
|
||||
+ uri.length() + auth_header.length()
|
||||
+ additional_options.length()
|
||||
+ 42;
|
||||
|
||||
if (content_length >= 0) { estimated_size += 25; }
|
||||
String request;
|
||||
request.reserve(estimated_size);
|
||||
request += method;
|
||||
request += ' ';
|
||||
|
||||
if (!uri.startsWith("/")) { request += '/'; }
|
||||
request += uri;
|
||||
request += F(" HTTP/1.1");
|
||||
request += "\r\n";
|
||||
|
||||
if (content_length >= 0) {
|
||||
request += F("Content-Length: ");
|
||||
request += content_length;
|
||||
request += "\r\n";
|
||||
}
|
||||
request += F("Host: ");
|
||||
request += hostportString;
|
||||
request += "\r\n";
|
||||
request += auth_header;
|
||||
request += additional_options;
|
||||
request += get_user_agent_request_header_field();
|
||||
request += F("Connection: close\r\n");
|
||||
request += "\r\n";
|
||||
#ifndef BUILD_NO_DEBUG
|
||||
addLog(LOG_LEVEL_DEBUG, request);
|
||||
#endif // ifndef BUILD_NO_DEBUG
|
||||
return request;
|
||||
}
|
||||
|
||||
String do_create_http_request(
|
||||
const String& hostportString,
|
||||
const String& method, const String& uri) {
|
||||
return do_create_http_request(hostportString, method, uri,
|
||||
"", // auth_header
|
||||
"", // additional_options
|
||||
-1 // content_length
|
||||
);
|
||||
}
|
||||
|
||||
String do_create_http_request(
|
||||
int controller_number, ControllerSettingsStruct& ControllerSettings,
|
||||
const String& method, const String& uri,
|
||||
int content_length) {
|
||||
const bool defaultport = ControllerSettings.Port == 0 || ControllerSettings.Port == 80;
|
||||
|
||||
return do_create_http_request(
|
||||
defaultport ? ControllerSettings.getHost() : ControllerSettings.getHostPortString(),
|
||||
method,
|
||||
uri,
|
||||
"", // auth_header
|
||||
"", // additional_options
|
||||
content_length);
|
||||
}
|
||||
|
||||
String create_http_request_auth(
|
||||
int controller_number, int controller_index, ControllerSettingsStruct& ControllerSettings,
|
||||
const String& method, const String& uri,
|
||||
int content_length) {
|
||||
const bool defaultport = ControllerSettings.Port == 0 || ControllerSettings.Port == 80;
|
||||
|
||||
return do_create_http_request(
|
||||
defaultport ? ControllerSettings.getHost() : ControllerSettings.getHostPortString(),
|
||||
method,
|
||||
uri,
|
||||
get_auth_header(controller_index),
|
||||
"", // additional_options
|
||||
content_length);
|
||||
}
|
||||
|
||||
String create_http_get_request(int controller_number, ControllerSettingsStruct& ControllerSettings,
|
||||
const String& uri) {
|
||||
return do_create_http_request(controller_number, ControllerSettings, F("GET"), uri, -1);
|
||||
}
|
||||
|
||||
String create_http_request_auth(int controller_number, int controller_index, ControllerSettingsStruct& ControllerSettings,
|
||||
const String& method, const String& uri) {
|
||||
return create_http_request_auth(controller_number, controller_index, ControllerSettings, method, uri, -1);
|
||||
}
|
||||
|
||||
#ifndef BUILD_NO_DEBUG
|
||||
void log_connecting_to(const String& prefix, int controller_number, ControllerSettingsStruct& ControllerSettings) {
|
||||
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
|
||||
String log = prefix;
|
||||
log += get_formatted_Controller_number(controller_number);
|
||||
log += F(" connecting to ");
|
||||
log += ControllerSettings.getHostPortString();
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ifndef BUILD_NO_DEBUG
|
||||
|
||||
void log_connecting_fail(const String& prefix, int controller_number, ControllerSettingsStruct& ControllerSettings) {
|
||||
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
|
||||
String log = prefix;
|
||||
log += get_formatted_Controller_number(controller_number);
|
||||
log += F(" connection failed (");
|
||||
log += getConnectionFailures();
|
||||
log += F("/");
|
||||
log += getSettings().ConnectionFailuresThreshold;
|
||||
log += F(")");
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
}
|
||||
}
|
||||
|
||||
bool count_connection_results(bool success, const String& prefix, int controller_number, ControllerSettingsStruct& ControllerSettings) {
|
||||
if (!success)
|
||||
{
|
||||
getConnectionFailures()++;
|
||||
log_connecting_fail(prefix, controller_number, ControllerSettings);
|
||||
return false;
|
||||
}
|
||||
statusLED(true);
|
||||
|
||||
if (getConnectionFailures()) {
|
||||
getConnectionFailures()--;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool try_connect_host(int controller_number, WiFiUDP& client, ControllerSettingsStruct& ControllerSettings) {
|
||||
//START_TIMER; // FIXME TD-er Timingstats macros currently not callable from .cpp file
|
||||
if (!WiFiConnected()) return false;
|
||||
client.setTimeout(ControllerSettings.ClientTimeout);
|
||||
#ifndef BUILD_NO_DEBUG
|
||||
log_connecting_to(F("UDP : "), controller_number, ControllerSettings);
|
||||
#endif // ifndef BUILD_NO_DEBUG
|
||||
bool success = ControllerSettings.beginPacket(client) != 0;
|
||||
const bool result = count_connection_results(
|
||||
success,
|
||||
F("UDP : "), controller_number, ControllerSettings);
|
||||
//STOP_TIMER(TRY_CONNECT_HOST_UDP);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool try_connect_host(int controller_number, WiFiClient& client, ControllerSettingsStruct& ControllerSettings) {
|
||||
//START_TIMER; // FIXME TD-er Timingstats macros currently not callable from .cpp file
|
||||
if (!WiFiConnected()) return false;
|
||||
|
||||
// Use WiFiClient class to create TCP connections
|
||||
client.setTimeout(ControllerSettings.ClientTimeout);
|
||||
#ifndef BUILD_NO_DEBUG
|
||||
log_connecting_to(F("HTTP : "), controller_number, ControllerSettings);
|
||||
#endif // ifndef BUILD_NO_DEBUG
|
||||
bool success = ControllerSettings.connectToHost(client);
|
||||
const bool result = count_connection_results(
|
||||
success,
|
||||
F("HTTP : "), controller_number, ControllerSettings);
|
||||
//STOP_TIMER(TRY_CONNECT_HOST_TCP);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Use "client.available() || client.connected()" to read all lines from slow servers.
|
||||
// See: https://github.com/esp8266/Arduino/pull/5113
|
||||
// https://github.com/esp8266/Arduino/pull/1829
|
||||
bool client_available(WiFiClient& client) {
|
||||
delay(0);
|
||||
return client.available() || client.connected();
|
||||
}
|
||||
|
||||
bool send_via_http(const String& logIdentifier, WiFiClient& client, const String& postStr, bool must_check_reply) {
|
||||
bool success = !must_check_reply;
|
||||
|
||||
// This will send the request to the server
|
||||
byte written = client.print(postStr);
|
||||
|
||||
// as of 2018/11/01 the print function only returns one byte (upd to 256 chars sent). However if the string sent can be longer than this
|
||||
// therefore we calculate modulo 256.
|
||||
// see discussion here https://github.com/letscontrolit/ESPEasy/pull/1979
|
||||
// and implementation here
|
||||
// https://github.com/esp8266/Arduino/blob/561426c0c77e9d05708f2c4bf2a956d3552a3706/libraries/ESP8266WiFi/src/include/ClientContext.h#L437-L467
|
||||
// this needs to be adjusted if the WiFiClient.print method changes.
|
||||
if (written != (postStr.length() % 256)) {
|
||||
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
|
||||
String log = F("HTTP : ");
|
||||
log += logIdentifier;
|
||||
log += F(" Error: could not write to client (");
|
||||
log += written;
|
||||
log += "/";
|
||||
log += postStr.length();
|
||||
log += ")";
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
}
|
||||
success = false;
|
||||
}
|
||||
#ifndef BUILD_NO_DEBUG
|
||||
else {
|
||||
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
|
||||
String log = F("HTTP : ");
|
||||
log += logIdentifier;
|
||||
log += F(" written to client (");
|
||||
log += written;
|
||||
log += "/";
|
||||
log += postStr.length();
|
||||
log += ")";
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
}
|
||||
}
|
||||
#endif // ifndef BUILD_NO_DEBUG
|
||||
|
||||
if (must_check_reply) {
|
||||
unsigned long timer = millis() + 200;
|
||||
|
||||
while (!client_available(client)) {
|
||||
if (timeOutReached(timer)) { return false; }
|
||||
delay(1);
|
||||
}
|
||||
|
||||
// Read all the lines of the reply from server and print them to Serial
|
||||
while (client_available(client) && !success) {
|
||||
// String line = client.readStringUntil('\n');
|
||||
String line;
|
||||
safeReadStringUntil(client, line, '\n');
|
||||
|
||||
#ifndef BUILD_NO_DEBUG
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_DEBUG_MORE)) {
|
||||
if (line.length() > 80) {
|
||||
addLog(LOG_LEVEL_DEBUG_MORE, line.substring(0, 80));
|
||||
} else {
|
||||
addLog(LOG_LEVEL_DEBUG_MORE, line);
|
||||
}
|
||||
}
|
||||
#endif // ifndef BUILD_NO_DEBUG
|
||||
|
||||
if (line.startsWith(F("HTTP/1.1 2")))
|
||||
{
|
||||
success = true;
|
||||
|
||||
// Leave this debug info in the build, regardless of the
|
||||
// BUILD_NO_DEBUG flags.
|
||||
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
|
||||
String log = F("HTTP : ");
|
||||
log += logIdentifier;
|
||||
log += F(" Success! ");
|
||||
log += line;
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
}
|
||||
} else if (line.startsWith(F("HTTP/1.1 4"))) {
|
||||
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
|
||||
String log = F("HTTP : ");
|
||||
log += logIdentifier;
|
||||
log += F(" Error: ");
|
||||
log += line;
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
}
|
||||
#ifndef BUILD_NO_DEBUG
|
||||
addLog(LOG_LEVEL_DEBUG_MORE, postStr);
|
||||
#endif // ifndef BUILD_NO_DEBUG
|
||||
}
|
||||
delay(0);
|
||||
}
|
||||
}
|
||||
#ifndef BUILD_NO_DEBUG
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
|
||||
String log = F("HTTP : ");
|
||||
log += logIdentifier;
|
||||
log += F(" closing connection");
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
}
|
||||
#endif // ifndef BUILD_NO_DEBUG
|
||||
|
||||
client.flush();
|
||||
client.stop();
|
||||
return success;
|
||||
}
|
||||
|
||||
bool send_via_http(int controller_number, WiFiClient& client, const String& postStr, bool must_check_reply) {
|
||||
return send_via_http(get_formatted_Controller_number(controller_number), client, postStr, must_check_reply);
|
||||
}
|
||||
+24
-996
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,7 @@
|
||||
|
||||
#if defined(USES_PACKED_RAW_DATA)
|
||||
|
||||
#include "ESPEasy_packed_raw_data.h"
|
||||
|
||||
|
||||
String getPackedFromPlugin(struct EventStruct *event, uint8_t sampleSetCount)
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
//#######################################################################################################
|
||||
|
||||
|
||||
#include "ESPEasy_packed_raw_data.h"
|
||||
|
||||
#define PLUGIN_026
|
||||
#define PLUGIN_ID_026 26
|
||||
#define PLUGIN_NAME_026 "Generic - System Info"
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <ESPeasySerial.h>
|
||||
#include <TinyGPS++.h>
|
||||
#include "ESPEasy_packed_raw_data.h"
|
||||
|
||||
#define PLUGIN_082
|
||||
#define PLUGIN_ID_082 82
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
#include "_Plugin_Helper.h"
|
||||
|
||||
#include "ESPEasy_common.h"
|
||||
#include "ESPEasy_fdwdecl.h"
|
||||
|
||||
#include "DataStructs/ESPEasyLimits.h"
|
||||
#include "DataStructs/SettingsStruct.h"
|
||||
|
||||
PluginTaskData_base *Plugin_task_data[TASKS_MAX] = { NULL, };
|
||||
|
||||
String PCONFIG_LABEL(int n) {
|
||||
if (n < PLUGIN_CONFIGVAR_MAX) {
|
||||
String result = F("pconf_");
|
||||
result += n;
|
||||
return result;
|
||||
}
|
||||
return F("error");
|
||||
}
|
||||
|
||||
|
||||
void resetPluginTaskData() {
|
||||
for (byte i = 0; i < TASKS_MAX; ++i) {
|
||||
Plugin_task_data[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void clearPluginTaskData(byte taskIndex) {
|
||||
if (taskIndex < TASKS_MAX) {
|
||||
if (Plugin_task_data[taskIndex] != nullptr) {
|
||||
delete Plugin_task_data[taskIndex];
|
||||
Plugin_task_data[taskIndex] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void initPluginTaskData(byte taskIndex, PluginTaskData_base *data) {
|
||||
clearPluginTaskData(taskIndex);
|
||||
|
||||
if ((taskIndex < TASKS_MAX) && getSettings().TaskDeviceEnabled[taskIndex]) {
|
||||
Plugin_task_data[taskIndex] = data;
|
||||
Plugin_task_data[taskIndex]->_taskdata_plugin_id = getPluginId_from_TaskIndex(taskIndex);
|
||||
}
|
||||
}
|
||||
|
||||
PluginTaskData_base* getPluginTaskData(byte taskIndex) {
|
||||
if (taskIndex >= TASKS_MAX) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ((Plugin_task_data[taskIndex] != nullptr) && (Plugin_task_data[taskIndex]->_taskdata_plugin_id == getPluginId_from_TaskIndex(taskIndex))) {
|
||||
return Plugin_task_data[taskIndex];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool pluginTaskData_initialized(byte taskIndex) {
|
||||
// FIXME TD-er: Must check for type also.
|
||||
if (taskIndex < TASKS_MAX) {
|
||||
return Plugin_task_data[taskIndex] != nullptr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
String getPluginCustomArgName(int varNr) {
|
||||
String argName = F("plugin_custom_arg");
|
||||
argName += varNr + 1;
|
||||
return argName;
|
||||
}
|
||||
|
||||
// Helper function to create formatted custom values for display in the devices overview page.
|
||||
// When called from PLUGIN_WEBFORM_SHOW_VALUES, the last item should add a traling div_br class
|
||||
// if the regular values should also be displayed.
|
||||
// The call to PLUGIN_WEBFORM_SHOW_VALUES should only return success = true when no regular values should be displayed
|
||||
// Note that the varNr of the custom values should not conflict with the existing variable numbers (e.g. start at VARS_PER_TASK)
|
||||
String pluginWebformShowValue(byte taskIndex, byte varNr, const String& label, const String& value, bool addTrailingBreak) {
|
||||
String result;
|
||||
size_t length = 96 + label.length() + value.length();
|
||||
String breakStr = F("<div class='div_br'></div>");
|
||||
if (addTrailingBreak) {
|
||||
length += breakStr.length();
|
||||
}
|
||||
result.reserve(length);
|
||||
if (varNr > 0) {
|
||||
result += breakStr;
|
||||
}
|
||||
result += F("<div class='div_l' id='valuename_");
|
||||
result += String(taskIndex);
|
||||
result += '_';
|
||||
result += String(varNr);
|
||||
result += "'>";
|
||||
result += label;
|
||||
result += F(":</div><div class='div_r' id='value_");
|
||||
result += String(taskIndex);
|
||||
result += '_';
|
||||
result += String(varNr);
|
||||
result += "'>";
|
||||
result += value;
|
||||
result += "</div>";
|
||||
if (addTrailingBreak) {
|
||||
result += breakStr;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
+13
-83
@@ -1,6 +1,9 @@
|
||||
#ifndef PLUGIN_HELPER_H
|
||||
#define PLUGIN_HELPER_H
|
||||
|
||||
#include "ESPEasy_common.h"
|
||||
#include "DataStructs/ESPEasyLimits.h"
|
||||
|
||||
// Defines to make plugins more readable.
|
||||
|
||||
#ifndef PCONFIG
|
||||
@@ -30,14 +33,7 @@
|
||||
# define CONFIG_PORT (Settings.TaskDevicePort[event->TaskIndex])
|
||||
#endif // ifndef CONFIG_PORT
|
||||
|
||||
String PCONFIG_LABEL(int n) {
|
||||
if (n < PLUGIN_CONFIGVAR_MAX) {
|
||||
String result = "pconf_";
|
||||
result += n;
|
||||
return result;
|
||||
}
|
||||
return "error";
|
||||
}
|
||||
String PCONFIG_LABEL(int n);
|
||||
|
||||
// ==============================================
|
||||
// Data used by instances of plugins.
|
||||
@@ -56,94 +52,28 @@ struct PluginTaskData_base {
|
||||
int _taskdata_plugin_id = -1;
|
||||
};
|
||||
|
||||
PluginTaskData_base *Plugin_task_data[TASKS_MAX] = { NULL, };
|
||||
|
||||
void resetPluginTaskData() {
|
||||
for (byte i = 0; i < TASKS_MAX; ++i) {
|
||||
Plugin_task_data[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void clearPluginTaskData(byte taskIndex) {
|
||||
if (taskIndex < TASKS_MAX) {
|
||||
if (Plugin_task_data[taskIndex] != nullptr) {
|
||||
delete Plugin_task_data[taskIndex];
|
||||
Plugin_task_data[taskIndex] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
void resetPluginTaskData();
|
||||
|
||||
void initPluginTaskData(byte taskIndex, PluginTaskData_base *data) {
|
||||
clearPluginTaskData(taskIndex);
|
||||
void clearPluginTaskData(byte taskIndex);
|
||||
|
||||
if ((taskIndex < TASKS_MAX) && Settings.TaskDeviceEnabled[taskIndex]) {
|
||||
Plugin_task_data[taskIndex] = data;
|
||||
Plugin_task_data[taskIndex]->_taskdata_plugin_id = Task_id_to_Plugin_id[taskIndex];
|
||||
}
|
||||
}
|
||||
void initPluginTaskData(byte taskIndex, PluginTaskData_base *data);
|
||||
|
||||
PluginTaskData_base* getPluginTaskData(byte taskIndex) {
|
||||
if (taskIndex >= TASKS_MAX) {
|
||||
return nullptr;
|
||||
}
|
||||
PluginTaskData_base* getPluginTaskData(byte taskIndex);
|
||||
|
||||
if ((Plugin_task_data[taskIndex] != nullptr) && (Plugin_task_data[taskIndex]->_taskdata_plugin_id == Task_id_to_Plugin_id[taskIndex])) {
|
||||
return Plugin_task_data[taskIndex];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
bool pluginTaskData_initialized(byte taskIndex);
|
||||
|
||||
bool pluginTaskData_initialized(byte taskIndex) {
|
||||
// FIXME TD-er: Must check for type also.
|
||||
if (taskIndex < TASKS_MAX) {
|
||||
return Plugin_task_data[taskIndex] != nullptr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
String getPluginCustomArgName(int varNr) {
|
||||
String argName = F("plugin_custom_arg");
|
||||
argName += varNr + 1;
|
||||
return argName;
|
||||
}
|
||||
String getPluginCustomArgName(int varNr);
|
||||
|
||||
// Helper function to create formatted custom values for display in the devices overview page.
|
||||
// When called from PLUGIN_WEBFORM_SHOW_VALUES, the last item should add a traling div_br class
|
||||
// if the regular values should also be displayed.
|
||||
// The call to PLUGIN_WEBFORM_SHOW_VALUES should only return success = true when no regular values should be displayed
|
||||
// Note that the varNr of the custom values should not conflict with the existing variable numbers (e.g. start at VARS_PER_TASK)
|
||||
String pluginWebformShowValue(byte taskIndex, byte varNr, const String& label, const String& value, bool addTrailingBreak) {
|
||||
String result;
|
||||
size_t length = 96 + label.length() + value.length();
|
||||
String breakStr = F("<div class='div_br'></div>");
|
||||
if (addTrailingBreak) {
|
||||
length += breakStr.length();
|
||||
}
|
||||
result.reserve(length);
|
||||
if (varNr > 0) {
|
||||
result += breakStr;
|
||||
}
|
||||
result += F("<div class='div_l' id='valuename_");
|
||||
result += String(taskIndex);
|
||||
result += '_';
|
||||
result += String(varNr);
|
||||
result += "'>";
|
||||
result += label;
|
||||
result += F(":</div><div class='div_r' id='value_");
|
||||
result += String(taskIndex);
|
||||
result += '_';
|
||||
result += String(varNr);
|
||||
result += "'>";
|
||||
result += value;
|
||||
result += "</div>";
|
||||
if (addTrailingBreak) {
|
||||
result += breakStr;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
String pluginWebformShowValue(byte taskIndex, byte varNr, const String& label, const String& value, bool addTrailingBreak = false);
|
||||
|
||||
|
||||
|
||||
String pluginWebformShowValue(byte taskIndex, byte varNr, const String& label, const String& value) {
|
||||
return pluginWebformShowValue(taskIndex, varNr, label, value, false);
|
||||
}
|
||||
|
||||
#endif // PLUGIN_HELPER_H
|
||||
|
||||
Reference in New Issue
Block a user