mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-28 04:07:47 +00:00
Merge branch 'mega' of https://github.com/letscontrolit/ESPEasy into feature/P073_improve_7dtext_add_7ddt
This commit is contained in:
@@ -51,3 +51,5 @@ tools/vagrant/pio_envlist.txt
|
||||
build_output/
|
||||
|
||||
**/__tmpfile.cpp
|
||||
|
||||
src/_Custom.h
|
||||
|
||||
@@ -486,7 +486,7 @@ void TinyGPSDate::commit()
|
||||
}
|
||||
{
|
||||
const uint16_t newyear = year();
|
||||
if (newyear < 2020) {
|
||||
if (newyear < 2021) {
|
||||
// Looks like it is an old GPS unit not working well with the 1024 week rollover.
|
||||
struct tm tm;
|
||||
tm.tm_year = newyear - 1900;
|
||||
|
||||
@@ -100,7 +100,7 @@ lib_ignore = ${esp82xx_defaults.lib_ignore}
|
||||
|
||||
[core_2_7_4]
|
||||
extends = esp82xx_2_6_x
|
||||
platform = espressif8266@2.6.2
|
||||
platform = espressif8266@2.6.3
|
||||
platform_packages =
|
||||
framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git#2.7.4
|
||||
build_flags = ${esp82xx_2_6_x.build_flags}
|
||||
@@ -111,7 +111,7 @@ build_flags = ${esp82xx_2_6_x.build_flags}
|
||||
; e.g. Sonoff Basic R2.
|
||||
[core_2_7_4_alt_wifi]
|
||||
extends = esp82xx_2_6_x
|
||||
platform = espressif8266@2.6.2
|
||||
platform = espressif8266@2.6.3
|
||||
platform_packages =
|
||||
framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git#2.7.4
|
||||
build_flags = ${esp82xx_2_6_x.build_flags}
|
||||
@@ -120,7 +120,7 @@ build_flags = ${esp82xx_2_6_x.build_flags}
|
||||
|
||||
[core_2_7_4_sdk3]
|
||||
extends = esp82xx_2_6_x
|
||||
platform = espressif8266@2.6.2
|
||||
platform = espressif8266@2.6.3
|
||||
platform_packages =
|
||||
framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git#2.7.4
|
||||
build_flags = ${esp82xx_2_6_x.build_flags}
|
||||
@@ -131,6 +131,7 @@ extends = esp82xx_2_6_x
|
||||
platform = https://github.com/platformio/platform-espressif8266.git
|
||||
build_flags = ${esp82xx_2_6_x.build_flags}
|
||||
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191122
|
||||
-DPHASE_LOCKED_WAVEFORM
|
||||
-Wno-deprecated-declarations
|
||||
platform_packages =
|
||||
platformio/framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ pathtools==0.1.2
|
||||
platformio>=5.0.1
|
||||
port-for==0.3.1
|
||||
pycparser==2.20
|
||||
pyelftools==0.26
|
||||
pyelftools==0.27
|
||||
pygit2==1.2.1
|
||||
Pygments==2.6.1
|
||||
pyparsing==2.4.7
|
||||
|
||||
@@ -160,6 +160,10 @@
|
||||
|
||||
#include "src/WebServer/WebServer.h"
|
||||
|
||||
#ifdef PHASE_LOCKED_WAVEFORM
|
||||
#include <core_esp8266_waveform.h>
|
||||
#endif
|
||||
|
||||
#if FEATURE_ADC_VCC
|
||||
ADC_MODE(ADC_VCC);
|
||||
#endif
|
||||
@@ -203,6 +207,9 @@ void setup()
|
||||
{
|
||||
#ifdef ESP8266_DISABLE_EXTRA4K
|
||||
disable_extra4k_at_link_time();
|
||||
#endif
|
||||
#ifdef PHASE_LOCKED_WAVEFORM
|
||||
enablePhaseLockedWaveform();
|
||||
#endif
|
||||
initWiFi();
|
||||
|
||||
|
||||
+1
-1
@@ -372,4 +372,4 @@ bool Plugin_003_pulseinit(byte Par1, byte Index, byte Mode)
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // USES_P003
|
||||
#endif // USES_P003
|
||||
+3
-5
@@ -108,8 +108,7 @@ boolean Plugin_008(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
if (Plugin_008_init && PCONFIG(2) == 0) { // PCONFIG(2) check uses inversed logic!
|
||||
// Reset card id on timeout
|
||||
UserVar[event->BaseVarIndex] = PCONFIG_LONG(0) & 0xFFFF;
|
||||
UserVar[event->BaseVarIndex + 1] = (PCONFIG_LONG(0) >> 16) & 0xFFFF;
|
||||
UserVar.setSensorTypeLong(event->TaskIndex, PCONFIG_LONG(0));
|
||||
addLog(LOG_LEVEL_INFO, F("RFID : Removed Tag"));
|
||||
if (PCONFIG(3) == 1) {
|
||||
sendData(event);
|
||||
@@ -156,15 +155,14 @@ boolean Plugin_008(byte function, struct EventStruct *event, String& string)
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned long old_key = ((uint32_t) UserVar[event->BaseVarIndex]) | ((uint32_t) UserVar[event->BaseVarIndex + 1])<<16;
|
||||
unsigned long old_key = UserVar.getSensorTypeLong(event->TaskIndex);
|
||||
bool new_key = false;
|
||||
if (PCONFIG(1) == 1) {
|
||||
Plugin_008_keyBuffer = castHexAsDec(Plugin_008_keyBuffer);
|
||||
}
|
||||
|
||||
if (old_key != Plugin_008_keyBuffer) {
|
||||
UserVar[event->BaseVarIndex] = (Plugin_008_keyBuffer & 0xFFFF);
|
||||
UserVar[event->BaseVarIndex + 1] = ((Plugin_008_keyBuffer >> 16) & 0xFFFF);
|
||||
UserVar.setSensorTypeLong(event->TaskIndex, Plugin_008_keyBuffer);
|
||||
new_key = true;
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -520,8 +520,7 @@ boolean Plugin_016(byte function, struct EventStruct *event, String &string)
|
||||
if (P016_SEND_IR_TO_CONTROLLER) sendData(event);
|
||||
else {
|
||||
unsigned long IRcode = results.value;
|
||||
UserVar[event->BaseVarIndex] = (IRcode & 0xFFFF);
|
||||
UserVar[event->BaseVarIndex + 1] = ((IRcode >> 16) & 0xFFFF);
|
||||
UserVar.setSensorTypeLong(event->TaskIndex, IRcode);
|
||||
sendData(event);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-5
@@ -121,8 +121,7 @@ boolean Plugin_017(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
// Reset card id on timeout
|
||||
if (PCONFIG(0) == 0) {
|
||||
UserVar[event->BaseVarIndex + 0] = PCONFIG_LONG(0) && 0xFFFF;
|
||||
UserVar[event->BaseVarIndex + 1] = (PCONFIG_LONG(0) >> 16) & 0xFFFF;
|
||||
UserVar.setSensorTypeLong(event->TaskIndex, PCONFIG_LONG(0));
|
||||
addLog(LOG_LEVEL_INFO, F("RFID : Removed Tag"));
|
||||
if (PCONFIG(1) == 1) {
|
||||
sendData(event);
|
||||
@@ -180,12 +179,11 @@ boolean Plugin_017(byte function, struct EventStruct *event, String& string)
|
||||
key <<= 8;
|
||||
key += uid[i];
|
||||
}
|
||||
unsigned long old_key = ((uint32_t)UserVar[event->BaseVarIndex]) | ((uint32_t)UserVar[event->BaseVarIndex + 1]) << 16;
|
||||
unsigned long old_key = UserVar.getSensorTypeLong(event->TaskIndex);
|
||||
bool new_key = false;
|
||||
|
||||
if (old_key != key) {
|
||||
UserVar[event->BaseVarIndex] = (key & 0xFFFF);
|
||||
UserVar[event->BaseVarIndex + 1] = ((key >> 16) & 0xFFFF);
|
||||
UserVar.setSensorTypeLong(event->TaskIndex, key);
|
||||
new_key = true;
|
||||
}
|
||||
|
||||
|
||||
+3
-5
@@ -59,8 +59,7 @@ boolean Plugin_040(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
if (Plugin_040_init) {
|
||||
// Reset card id on timeout
|
||||
UserVar[event->BaseVarIndex] = 0;
|
||||
UserVar[event->BaseVarIndex + 1] = 0;
|
||||
UserVar.setSensorTypeLong(event->TaskIndex, 0);
|
||||
addLog(LOG_LEVEL_INFO, F("RFID : Removed Tag"));
|
||||
sendData(event);
|
||||
success = true;
|
||||
@@ -136,12 +135,11 @@ boolean Plugin_040(byte function, struct EventStruct *event, String& string)
|
||||
// endof workaround
|
||||
|
||||
unsigned long key = 0, old_key = 0;
|
||||
old_key = ((uint32_t) UserVar[event->BaseVarIndex]) | ((uint32_t) UserVar[event->BaseVarIndex + 1])<<16;
|
||||
old_key = UserVar.getSensorTypeLong(event->TaskIndex);
|
||||
for (byte i = 1; i < 5; i++) key = key | (((unsigned long) code[i] << ((4 - i) * 8)));
|
||||
bool new_key = false;
|
||||
if (old_key != key) {
|
||||
UserVar[event->BaseVarIndex] = (key & 0xFFFF);
|
||||
UserVar[event->BaseVarIndex + 1] = ((key >> 16) & 0xFFFF);
|
||||
UserVar.setSensorTypeLong(event->TaskIndex, key);
|
||||
new_key = true;
|
||||
}
|
||||
|
||||
|
||||
+24
-31
@@ -26,8 +26,8 @@ extern "C"
|
||||
# define PLUGIN_081_DEBUG false // set to true for extra log info in the debug
|
||||
#endif // ifndef PLUGIN_081_DEBUG
|
||||
#define PLUGIN_081_EXPRESSION_SIZE 41
|
||||
#define LASTEXECUTION UserVar[event->BaseVarIndex]
|
||||
#define NEXTEXECUTION UserVar[event->BaseVarIndex + 1]
|
||||
#define LASTEXECUTION 0
|
||||
#define NEXTEXECUTION 1
|
||||
|
||||
|
||||
struct P081_data_struct : public PluginTaskData_base {
|
||||
@@ -74,12 +74,6 @@ private:
|
||||
bool _initialized = false;
|
||||
};
|
||||
|
||||
union timeToFloat
|
||||
{
|
||||
time_t time;
|
||||
float value;
|
||||
};
|
||||
|
||||
|
||||
String P081_getCronExpr(taskIndex_t taskIndex)
|
||||
{
|
||||
@@ -120,22 +114,14 @@ time_t P081_computeNextCronTime(taskIndex_t taskIndex, time_t last)
|
||||
return CRON_INVALID_INSTANT;
|
||||
}
|
||||
|
||||
time_t P081_getCronExecTime(float execTime)
|
||||
time_t P081_getCronExecTime(taskIndex_t taskIndex, byte varNr)
|
||||
{
|
||||
timeToFloat converter;
|
||||
|
||||
converter.value = execTime;
|
||||
return converter.time;
|
||||
return static_cast<time_t>(UserVar.getUint32(taskIndex, varNr));
|
||||
}
|
||||
|
||||
void P081_setCronExecTimes(struct EventStruct *event, time_t lastExecTime, time_t nextExecTime) {
|
||||
timeToFloat converter;
|
||||
|
||||
converter.time = lastExecTime;
|
||||
LASTEXECUTION = converter.value;
|
||||
|
||||
converter.time = nextExecTime;
|
||||
NEXTEXECUTION = converter.value;
|
||||
UserVar.setUint32(event->TaskIndex, LASTEXECUTION, static_cast<uint32_t>(lastExecTime));
|
||||
UserVar.setUint32(event->TaskIndex, NEXTEXECUTION, static_cast<uint32_t>(nextExecTime));
|
||||
}
|
||||
|
||||
time_t P081_getCurrentTime()
|
||||
@@ -151,8 +137,8 @@ void P081_check_or_init(struct EventStruct *event)
|
||||
{
|
||||
if (node_time.systemTimePresent()) {
|
||||
const time_t current_time = P081_getCurrentTime();
|
||||
time_t last_exec_time = P081_getCronExecTime(LASTEXECUTION);
|
||||
time_t next_exec_time = P081_getCronExecTime(NEXTEXECUTION);
|
||||
time_t last_exec_time = P081_getCronExecTime(event->TaskIndex, LASTEXECUTION);
|
||||
time_t next_exec_time = P081_getCronExecTime(event->TaskIndex, NEXTEXECUTION);
|
||||
|
||||
// Must check if the values of LASTEXECUTION and NEXTEXECUTION make sense.
|
||||
// These can be invalid values from a reboot, or simply contain uninitialized values.
|
||||
@@ -250,11 +236,18 @@ boolean Plugin_081(byte function, struct EventStruct *event, String& string)
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
case PLUGIN_WEBFORM_SHOW_VALUES:
|
||||
|
||||
case PLUGIN_FORMAT_USERVAR:
|
||||
{
|
||||
pluginWebformShowValue(ExtraTaskSettings.TaskDeviceValueNames[0], P081_formatExecTime(LASTEXECUTION));
|
||||
pluginWebformShowValue(ExtraTaskSettings.TaskDeviceValueNames[1], P081_formatExecTime(NEXTEXECUTION), false);
|
||||
success = true;
|
||||
switch (event->idx) {
|
||||
case 0:
|
||||
string = P081_formatExecTime(event->TaskIndex, LASTEXECUTION);
|
||||
break;
|
||||
case 1:
|
||||
string = P081_formatExecTime(event->TaskIndex, NEXTEXECUTION);
|
||||
break;
|
||||
}
|
||||
success = string.length() > 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -291,7 +284,7 @@ boolean Plugin_081(byte function, struct EventStruct *event, String& string)
|
||||
// code to be executed once a second. Tasks which do not require fast response can be added here
|
||||
if (node_time.systemTimePresent()) {
|
||||
P081_check_or_init(event);
|
||||
time_t next_exec_time = P081_getCronExecTime(NEXTEXECUTION);
|
||||
time_t next_exec_time = P081_getCronExecTime(event->TaskIndex, NEXTEXECUTION);
|
||||
|
||||
if (next_exec_time != CRON_INVALID_INSTANT) {
|
||||
const time_t current_time = P081_getCurrentTime();
|
||||
@@ -386,8 +379,8 @@ void PrintCronExp(struct cron_expr_t e) {
|
||||
#endif // if PLUGIN_081_DEBUG
|
||||
|
||||
|
||||
String P081_formatExecTime(float execTime_f) {
|
||||
time_t exec_time = P081_getCronExecTime(execTime_f);
|
||||
String P081_formatExecTime(taskIndex_t taskIndex, byte varNr) {
|
||||
time_t exec_time = P081_getCronExecTime(taskIndex, varNr);
|
||||
|
||||
if (exec_time != CRON_INVALID_INSTANT) {
|
||||
return ESPEasy_time::getDateTimeString(*gmtime(&exec_time));
|
||||
@@ -407,9 +400,9 @@ void P081_html_show_cron_expr(struct EventStruct *event) {
|
||||
addHtml(error);
|
||||
} else {
|
||||
addRowLabel(F("Last Exec Time"));
|
||||
addHtml(P081_formatExecTime(LASTEXECUTION));
|
||||
addHtml(P081_formatExecTime(event->TaskIndex, LASTEXECUTION));
|
||||
addRowLabel(F("Next Exec Time"));
|
||||
addHtml(P081_formatExecTime(NEXTEXECUTION));
|
||||
addHtml(P081_formatExecTime(event->TaskIndex, NEXTEXECUTION));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,8 +71,8 @@ String Command_DateTime(struct EventStruct *event, const char *Line)
|
||||
struct tm tm;
|
||||
int yr, mnth, d;
|
||||
sscanf(TmpStr1.c_str(), "%4d-%2d-%2d", &yr, &mnth, &d);
|
||||
tm.tm_year = yr - 1970;
|
||||
tm.tm_mon = mnth;
|
||||
tm.tm_year = yr - 1900;
|
||||
tm.tm_mon = mnth - 1; // tm_mon starts at 0
|
||||
tm.tm_mday = d;
|
||||
|
||||
if (GetArgv(Line, TmpStr1, 3)) {
|
||||
|
||||
@@ -21,12 +21,14 @@
|
||||
|
||||
|
||||
#define BUILD 20112 // git version e.g. "20103" can be read as "2.1.03" (stored in int16_t)
|
||||
#ifndef BUILD_NOTES
|
||||
#if defined(ESP8266)
|
||||
# define BUILD_NOTES " - Mega"
|
||||
#endif // if defined(ESP8266)
|
||||
#if defined(ESP32)
|
||||
# define BUILD_NOTES " - Mega32"
|
||||
#endif // if defined(ESP32)
|
||||
#endif
|
||||
|
||||
#ifndef BUILD_GIT
|
||||
# define BUILD_GIT "(custom)"
|
||||
|
||||
@@ -78,6 +78,7 @@ String getPluginFunctionName(int function) {
|
||||
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_FORMAT_USERVAR: return F("FORMAT_USERVAR");
|
||||
case PLUGIN_GET_DEVICENAME: return F("GET_DEVICENAME");
|
||||
case PLUGIN_GET_DEVICEVALUENAMES: return F("GET_DEVICEVALUENAMES");
|
||||
case PLUGIN_WRITE: return F("WRITE");
|
||||
@@ -110,6 +111,7 @@ bool mustLogFunction(int function) {
|
||||
case PLUGIN_WEBFORM_SAVE: return false;
|
||||
case PLUGIN_WEBFORM_LOAD: return false;
|
||||
case PLUGIN_WEBFORM_SHOW_VALUES: return false;
|
||||
case PLUGIN_FORMAT_USERVAR: return false;
|
||||
case PLUGIN_GET_DEVICENAME: return false;
|
||||
case PLUGIN_GET_DEVICEVALUENAMES: return false;
|
||||
case PLUGIN_WRITE: return true;
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
#include "../DataStructs/UserVarStruct.h"
|
||||
|
||||
#include "../ESPEasyCore/ESPEasy_Log.h"
|
||||
#include "../Globals/Plugins.h"
|
||||
|
||||
UserVarStruct::UserVarStruct()
|
||||
{
|
||||
_data.resize(VARS_PER_TASK * TASKS_MAX, 0.0f);
|
||||
}
|
||||
|
||||
// Implementation of [] operator. This function must return a
|
||||
// reference as array element can be put on left side
|
||||
float& UserVarStruct::operator[](unsigned int index)
|
||||
{
|
||||
if (index >= _data.size()) {
|
||||
static float errorvalue = NAN;
|
||||
addLog(LOG_LEVEL_ERROR, F("UserVar index out of range"));
|
||||
return errorvalue;
|
||||
}
|
||||
return _data.at(index);
|
||||
}
|
||||
|
||||
const float& UserVarStruct::operator[](unsigned int index) const
|
||||
{
|
||||
if (index >= _data.size()) {
|
||||
static float errorvalue = NAN;
|
||||
addLog(LOG_LEVEL_ERROR, F("UserVar index out of range"));
|
||||
return errorvalue;
|
||||
}
|
||||
return _data.at(index);
|
||||
}
|
||||
|
||||
unsigned long UserVarStruct::getSensorTypeLong(taskIndex_t taskIndex) const
|
||||
{
|
||||
unsigned long value = 0;
|
||||
|
||||
if (validTaskIndex(taskIndex)) {
|
||||
const unsigned int baseVarIndex = taskIndex * VARS_PER_TASK;
|
||||
value = static_cast<unsigned long>(_data[baseVarIndex]) + (static_cast<unsigned long>(_data[baseVarIndex + 1]) << 16);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void UserVarStruct::setSensorTypeLong(taskIndex_t taskIndex, unsigned long value)
|
||||
{
|
||||
if (!validTaskIndex(taskIndex)) {
|
||||
return;
|
||||
}
|
||||
const unsigned int baseVarIndex = taskIndex * VARS_PER_TASK;
|
||||
|
||||
_data[baseVarIndex] = value & 0xFFFF;
|
||||
_data[baseVarIndex + 1] = (value >> 16) & 0xFFFF;
|
||||
}
|
||||
|
||||
uint32_t UserVarStruct::getUint32(taskIndex_t taskIndex, byte varNr) const
|
||||
{
|
||||
if (!validTaskIndex(taskIndex) || (varNr >= VARS_PER_TASK)) {
|
||||
addLog(LOG_LEVEL_ERROR, F("UserVar index out of range"));
|
||||
return 0;
|
||||
}
|
||||
const unsigned int baseVarIndex = taskIndex * VARS_PER_TASK;
|
||||
uint32_t res;
|
||||
memcpy(&res, &_data[baseVarIndex + varNr], sizeof(float));
|
||||
return res;
|
||||
}
|
||||
|
||||
void UserVarStruct::setUint32(taskIndex_t taskIndex, byte varNr, uint32_t value)
|
||||
{
|
||||
if (!validTaskIndex(taskIndex) || (varNr >= VARS_PER_TASK)) {
|
||||
addLog(LOG_LEVEL_ERROR, F("UserVar index out of range"));
|
||||
return;
|
||||
}
|
||||
const unsigned int baseVarIndex = taskIndex * VARS_PER_TASK;
|
||||
|
||||
// Store in a new variable to prevent
|
||||
// warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
|
||||
float tmp;
|
||||
memcpy(&tmp, &value, sizeof(float));
|
||||
_data[baseVarIndex + varNr] = tmp;
|
||||
}
|
||||
|
||||
size_t UserVarStruct::getNrElements() const
|
||||
{
|
||||
return _data.size();
|
||||
}
|
||||
|
||||
byte * UserVarStruct::get()
|
||||
{
|
||||
return (byte *)(&_data[0]);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef DATASTRUCTS_USERVARSTRUCT_H
|
||||
#define DATASTRUCTS_USERVARSTRUCT_H
|
||||
|
||||
#include "../../ESPEasy_common.h"
|
||||
|
||||
#include "../DataTypes/TaskIndex.h"
|
||||
|
||||
struct UserVarStruct {
|
||||
UserVarStruct();
|
||||
|
||||
// Overloading [] operator to access elements in array style
|
||||
float & operator[](unsigned int index);
|
||||
const float & operator[](unsigned int index) const;
|
||||
|
||||
unsigned long getSensorTypeLong(taskIndex_t taskIndex) const;
|
||||
void setSensorTypeLong(taskIndex_t taskIndex,
|
||||
unsigned long value);
|
||||
|
||||
// 32 bit unsigned int stored at the memory location of the float
|
||||
uint32_t getUint32(taskIndex_t taskIndex,
|
||||
byte varNr) const;
|
||||
void setUint32(taskIndex_t taskIndex,
|
||||
byte varNr,
|
||||
uint32_t value);
|
||||
|
||||
|
||||
size_t getNrElements() const;
|
||||
|
||||
byte * get();
|
||||
|
||||
private:
|
||||
|
||||
std::vector<float>_data;
|
||||
};
|
||||
|
||||
#endif // ifndef DATASTRUCTS_USERVARSTRUCT_H
|
||||
@@ -43,6 +43,7 @@
|
||||
#define PLUGIN_WEBFORM_SHOW_SERIAL_PARAMS 35 // When needed, show additional parameters like baudrate or specific serial config
|
||||
#define PLUGIN_MQTT_CONNECTION_STATE 36 // Signal when connection to MQTT broker is re-established
|
||||
#define PLUGIN_MQTT_IMPORT 37 // For P037 MQTT import
|
||||
#define PLUGIN_FORMAT_USERVAR 38 // Allow plugin specific formatting of a task variable (event->idx = variable)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -386,7 +386,7 @@ String getLWT_topic(const ControllerSettingsStruct& ControllerSettings) {
|
||||
LWTTopic = ControllerSettings.Subscribe;
|
||||
LWTTopic += F("/LWT");
|
||||
}
|
||||
LWTTopic.replace(F("/#"), F("/status"));
|
||||
LWTTopic.replace(String(F("/#")), String(F("/status")));
|
||||
parseSystemVariables(LWTTopic, false);
|
||||
}
|
||||
return LWTTopic;
|
||||
|
||||
@@ -94,6 +94,7 @@ void WiFiEvent(system_event_id_t event, system_event_info_t info) {
|
||||
processEthernetConnected();
|
||||
break;
|
||||
case SYSTEM_EVENT_ETH_GOT_IP:
|
||||
eth_connected = true;
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO))
|
||||
{
|
||||
String log = F("ETH MAC: ");
|
||||
@@ -114,7 +115,6 @@ void WiFiEvent(system_event_id_t event, system_event_info_t info) {
|
||||
log += F("Mbps");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
eth_connected = true;
|
||||
break;
|
||||
case SYSTEM_EVENT_ETH_DISCONNECTED:
|
||||
addLog(LOG_LEVEL_ERROR, F("ETH Disconnected"));
|
||||
@@ -130,6 +130,11 @@ void WiFiEvent(system_event_id_t event, system_event_info_t info) {
|
||||
break;
|
||||
#endif //HAS_ETHERNET
|
||||
default:
|
||||
{
|
||||
String log = F("UNKNOWN EVENT: ");
|
||||
log += event;
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ void process_serialWriteBuffer() {
|
||||
|
||||
if (snip < bytes_to_write) { bytes_to_write = snip; }
|
||||
|
||||
while (bytes_to_write > 0) {
|
||||
while (bytes_to_write > 0 && !serialWriteBuffer.empty()) {
|
||||
const char c = serialWriteBuffer.front();
|
||||
Serial.write(c);
|
||||
serialWriteBuffer.pop_front();
|
||||
|
||||
@@ -580,6 +580,7 @@ bool PluginCall(byte Function, struct EventStruct *event, String& str)
|
||||
case PLUGIN_WEBFORM_SHOW_CONFIG:
|
||||
case PLUGIN_WEBFORM_SHOW_I2C_PARAMS:
|
||||
case PLUGIN_WEBFORM_SHOW_SERIAL_PARAMS:
|
||||
case PLUGIN_FORMAT_USERVAR:
|
||||
case PLUGIN_SET_CONFIG:
|
||||
case PLUGIN_SET_DEFAULTS:
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
|
||||
std::map<uint32_t, double> customFloatVar;
|
||||
|
||||
float UserVar[VARS_PER_TASK * TASKS_MAX];
|
||||
//float UserVar[VARS_PER_TASK * TASKS_MAX];
|
||||
|
||||
UserVarStruct UserVar;
|
||||
|
||||
|
||||
double getCustomFloatVar(uint32_t index) {
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include "../CustomBuild/ESPEasyLimits.h"
|
||||
|
||||
#include "../DataStructs/UserVarStruct.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
/*********************************************************************************************\
|
||||
@@ -28,7 +30,9 @@ bool getNextCustomFloatVar(uint32_t& index, double& value);
|
||||
* let,1,10
|
||||
* if %v1%=10 do ...
|
||||
\*********************************************************************************************/
|
||||
extern float UserVar[VARS_PER_TASK * TASKS_MAX];
|
||||
//extern float UserVar[VARS_PER_TASK * TASKS_MAX];
|
||||
|
||||
extern UserVarStruct UserVar;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
// these offsets are in blocks, bytes = blocks * 4
|
||||
// 64 RTCStruct max 40 bytes: ( 74 - 64 ) * 4
|
||||
// 74 UserVar
|
||||
// 122 UserVar checksum: RTC_BASE_USERVAR + (sizeof(UserVar) / 4)
|
||||
// 122 UserVar checksum: RTC_BASE_USERVAR + UserVar.getNrElements()
|
||||
// 128 Cache (C016) metadata 4 blocks
|
||||
// 132 Cache (C016) data 6 blocks per sample => max 10 samples
|
||||
|
||||
@@ -87,7 +87,7 @@ void initRTC()
|
||||
RTC.init();
|
||||
saveToRTC();
|
||||
|
||||
for (size_t i = 0; i < sizeof(UserVar) / sizeof(float); ++i) {
|
||||
for (size_t i = 0; i < UserVar.getNrElements(); ++i) {
|
||||
UserVar[i] = 0.0f;
|
||||
}
|
||||
saveUserVarToRTC();
|
||||
@@ -119,8 +119,8 @@ bool saveUserVarToRTC()
|
||||
#else // if defined(ESP32)
|
||||
|
||||
// addLog(LOG_LEVEL_DEBUG, F("RTCMEM: saveUserVarToRTC"));
|
||||
byte *buffer = (byte *)&UserVar;
|
||||
size_t size = sizeof(UserVar);
|
||||
byte *buffer = UserVar.get();
|
||||
size_t size = UserVar.getNrElements() * sizeof(float);
|
||||
uint32_t sum = calc_CRC32(buffer, size);
|
||||
bool ret = system_rtc_mem_write(RTC_BASE_USERVAR, buffer, size);
|
||||
ret &= system_rtc_mem_write(RTC_BASE_USERVAR + (size >> 2), (byte *)&sum, 4);
|
||||
@@ -138,8 +138,8 @@ bool readUserVarFromRTC()
|
||||
#else // if defined(ESP32)
|
||||
|
||||
// addLog(LOG_LEVEL_DEBUG, F("RTCMEM: readUserVarFromRTC"));
|
||||
byte *buffer = (byte *)&UserVar;
|
||||
size_t size = sizeof(UserVar);
|
||||
byte *buffer = UserVar.get();
|
||||
size_t size = UserVar.getNrElements() * sizeof(float);
|
||||
bool ret = system_rtc_mem_read(RTC_BASE_USERVAR, buffer, size);
|
||||
uint32_t sumRAM = calc_CRC32(buffer, size);
|
||||
uint32_t sumRTC = 0;
|
||||
|
||||
@@ -40,13 +40,7 @@ struct tm ESPEasy_time::addSeconds(const struct tm& ts, int seconds, bool toLoca
|
||||
|
||||
|
||||
void ESPEasy_time::breakTime(unsigned long timeInput, struct tm& tm) {
|
||||
uint8_t year;
|
||||
uint8_t month, monthLength;
|
||||
uint32_t time;
|
||||
unsigned long days;
|
||||
const uint8_t monthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
time = (uint32_t)timeInput;
|
||||
uint32_t time = (uint32_t)timeInput;
|
||||
tm.tm_sec = time % 60;
|
||||
time /= 60; // now it is minutes
|
||||
tm.tm_min = time % 60;
|
||||
@@ -55,40 +49,27 @@ void ESPEasy_time::breakTime(unsigned long timeInput, struct tm& tm) {
|
||||
time /= 24; // now it is days
|
||||
tm.tm_wday = ((time + 4) % 7) + 1; // Sunday is day 1
|
||||
|
||||
year = 0;
|
||||
days = 0;
|
||||
|
||||
int year = 1970;
|
||||
unsigned long days = 0;
|
||||
while ((unsigned)(days += (isLeapYear(year) ? 366 : 365)) <= time) {
|
||||
year++;
|
||||
}
|
||||
tm.tm_year = year; // year is offset from 1970
|
||||
tm.tm_year = year - 1900; // tm_year starts at 1900
|
||||
|
||||
days -= isLeapYear(year) ? 366 : 365;
|
||||
time -= days; // now it is days in this year, starting at 0
|
||||
|
||||
days = 0;
|
||||
month = 0;
|
||||
monthLength = 0;
|
||||
|
||||
uint8_t month = 0;
|
||||
for (month = 0; month < 12; month++) {
|
||||
if (month == 1) { // february
|
||||
if (isLeapYear(year)) {
|
||||
monthLength = 29;
|
||||
} else {
|
||||
monthLength = 28;
|
||||
}
|
||||
} else {
|
||||
monthLength = monthDays[month];
|
||||
}
|
||||
|
||||
const uint8_t monthLength = getMonthDays(year, month);
|
||||
if (time >= monthLength) {
|
||||
time -= monthLength;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
tm.tm_mon = month + 1; // jan is month 1
|
||||
tm.tm_mday = time + 1; // day of month
|
||||
tm.tm_mon = month; // Jan is month 0
|
||||
tm.tm_mday = time + 1; // day of month start at 1
|
||||
}
|
||||
|
||||
|
||||
@@ -415,9 +396,9 @@ String ESPEasy_time::getDateString(char delimiter) const
|
||||
String ESPEasy_time::getDateString(const struct tm& ts, char delimiter) {
|
||||
// time format example with ':' delimiter: 23:59:59 (HH:MM:SS)
|
||||
char DateString[20]; // 19 digits plus the null char
|
||||
const int year = 1970 + ts.tm_year;
|
||||
const int year = 1900 + ts.tm_year;
|
||||
|
||||
sprintf_P(DateString, PSTR("%4d%c%02d%c%02d"), year, delimiter, ts.tm_mon, delimiter, ts.tm_mday);
|
||||
sprintf_P(DateString, PSTR("%4d%c%02d%c%02d"), year, delimiter, ts.tm_mon + 1, delimiter, ts.tm_mday);
|
||||
return DateString;
|
||||
}
|
||||
|
||||
@@ -494,7 +475,7 @@ int ESPEasy_time::year(unsigned long t)
|
||||
struct tm tmp;
|
||||
|
||||
breakTime(t, tmp);
|
||||
return 1970 + tmp.tm_year;
|
||||
return 1900 + tmp.tm_year;
|
||||
}
|
||||
|
||||
int ESPEasy_time::weekday(unsigned long t)
|
||||
@@ -615,7 +596,7 @@ int ESPEasy_time::dayOfYear(int year, int month, int day) {
|
||||
}
|
||||
|
||||
void ESPEasy_time::calcSunRiseAndSet() {
|
||||
int doy = dayOfYear(tm.tm_year, tm.tm_mon, tm.tm_mday);
|
||||
int doy = dayOfYear(tm.tm_year, tm.tm_mon + 1, tm.tm_mday);
|
||||
float eqt = equationOfTime(doy);
|
||||
float dec = sunDeclination(doy);
|
||||
float da = diurnalArc(dec, Settings.Latitude);
|
||||
|
||||
@@ -94,13 +94,13 @@ static String weekday_str(int wday);
|
||||
// Get current year.
|
||||
int year() const
|
||||
{
|
||||
return 1970 + tm.tm_year;
|
||||
return 1900 + tm.tm_year;
|
||||
}
|
||||
|
||||
// Get current month
|
||||
byte month() const
|
||||
{
|
||||
return tm.tm_mon;
|
||||
return tm.tm_mon + 1; // tm_mon starts at 0
|
||||
}
|
||||
|
||||
// Get current day of the month
|
||||
|
||||
@@ -13,7 +13,18 @@
|
||||
|
||||
|
||||
bool isLeapYear(int year) {
|
||||
return (((1970 + year) > 0) && !((1970 + year) % 4) && (((1970 + year) % 100) || !((1970 + year) % 400)));
|
||||
return ((year > 0) && !(year % 4) && ((year % 100) || !(year % 400)));
|
||||
}
|
||||
|
||||
uint8_t getMonthDays(int year, uint8_t month) {
|
||||
const uint8_t monthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
if (month == 1 && isLeapYear(year)) {
|
||||
return 29;
|
||||
}
|
||||
if (month > 11) {
|
||||
return 0;
|
||||
}
|
||||
return monthDays[month];
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
@@ -24,32 +35,34 @@ uint32_t makeTime(const struct tm& tm) {
|
||||
// assemble time elements into uint32_t
|
||||
// note year argument is offset from 1970 (see macros in time.h to convert to other formats)
|
||||
// previous version used full four digit year (or digits since 2000),i.e. 2009 was 2009 or 9
|
||||
const uint8_t monthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
int i;
|
||||
uint32_t seconds;
|
||||
const int tm_year = tm.tm_year + 1900;
|
||||
|
||||
// seconds from 1970 till 1 jan 00:00:00 of the given year
|
||||
seconds = tm.tm_year * (SECS_PER_DAY * 365);
|
||||
// tm_year starts at 1900
|
||||
uint32_t seconds = 1577836800; // 01/01/2020 @ 12:00am (UTC)
|
||||
int year = 2020;
|
||||
if (tm_year < year) {
|
||||
// Just in case this function is called on old dates
|
||||
year = 1970;
|
||||
seconds = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < tm.tm_year; i++) {
|
||||
if (isLeapYear(i)) {
|
||||
seconds += SECS_PER_DAY; // add extra days for leap years
|
||||
for (; year < tm_year; ++year) {
|
||||
seconds += SECS_PER_DAY * 365;
|
||||
if (isLeapYear(year)) {
|
||||
seconds += SECS_PER_DAY; // add extra days for leap years
|
||||
}
|
||||
}
|
||||
|
||||
// add days for this year, months start from 1
|
||||
for (i = 1; i < tm.tm_mon; i++) {
|
||||
if ((i == 2) && isLeapYear(tm.tm_year)) {
|
||||
seconds += SECS_PER_DAY * 29;
|
||||
} else {
|
||||
seconds += SECS_PER_DAY * monthDays[i - 1]; // monthDay array starts from 0
|
||||
}
|
||||
// add days for this year, months start from 0
|
||||
for (int i = 0; i < tm.tm_mon; i++) {
|
||||
seconds += SECS_PER_DAY * getMonthDays(tm_year, i);
|
||||
}
|
||||
seconds += (tm.tm_mday - 1) * SECS_PER_DAY;
|
||||
seconds += tm.tm_hour * SECS_PER_HOUR;
|
||||
seconds += tm.tm_min * SECS_PER_MIN;
|
||||
seconds += tm.tm_sec;
|
||||
return (uint32_t)seconds;
|
||||
return seconds;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -59,6 +59,10 @@ bool usecTimeOutReached(unsigned long timer);
|
||||
\*********************************************************************************************/
|
||||
bool isLeapYear(int year);
|
||||
|
||||
// Get number of days in a month.
|
||||
// Month starts at 0 for January.
|
||||
uint8_t getMonthDays(int year, uint8_t month);
|
||||
|
||||
uint32_t makeTime(const struct tm& tm);
|
||||
|
||||
/********************************************************************************************\
|
||||
|
||||
@@ -90,7 +90,7 @@ void ESPEasy_time_zone::logTimeZoneInfo() {
|
||||
// *----------------------------------------------------------------------*/
|
||||
uint32_t ESPEasy_time_zone::calcTimeChangeForRule(const TimeChangeRule& r, int yr)
|
||||
{
|
||||
uint8_t m = r.month; // temp copies of r.month and r.week
|
||||
uint8_t m = r.month;
|
||||
uint8_t w = r.week;
|
||||
|
||||
if (w == 0) // is this a "Last week" rule?
|
||||
@@ -109,8 +109,8 @@ uint32_t ESPEasy_time_zone::calcTimeChangeForRule(const TimeChangeRule& r, int y
|
||||
tm.tm_min = 0;
|
||||
tm.tm_sec = 0;
|
||||
tm.tm_mday = 1;
|
||||
tm.tm_mon = m;
|
||||
tm.tm_year = yr - 1970;
|
||||
tm.tm_mon = m - 1; // TimeChangeRule month starts at 1
|
||||
tm.tm_year = yr - 1900;
|
||||
uint32_t t = makeTime(tm);
|
||||
|
||||
// add offset from the first of the month to r.dow, and offset for the given week
|
||||
|
||||
@@ -151,14 +151,40 @@ bool mustConsiderAsString(NumericalType detectedType) {
|
||||
case NumericalType::HexadecimalUInt:
|
||||
case NumericalType::BinaryUint:
|
||||
return true; // Has '0x' or '0b' as prefix
|
||||
case NumericalType::Unknown:
|
||||
return true; // Apparently it is not a numerical, when printed consider it a string
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool mustConsiderAsString(const String& value) {
|
||||
const unsigned int length = value.length();
|
||||
if (length == 0) return true;
|
||||
unsigned int i = 0;
|
||||
char c = value[i];
|
||||
if (c == '+' || c == '-') {
|
||||
++i;
|
||||
if (length == i) return true;
|
||||
c = value[i];
|
||||
}
|
||||
|
||||
bool dotFound = false;
|
||||
for (; i < length; ++i) {
|
||||
if (c == '.') {
|
||||
if (dotFound) {
|
||||
return true;
|
||||
} else {
|
||||
dotFound = true;
|
||||
}
|
||||
} else {
|
||||
if (!isdigit(c)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
c = value[i];
|
||||
}
|
||||
return i < length;
|
||||
}
|
||||
|
||||
String getNumerical(const String& tBuf, NumericalType requestedType, NumericalType& detectedType) {
|
||||
detectedType = NumericalType::Unknown;
|
||||
const unsigned int bufLength = tBuf.length();
|
||||
unsigned int firstDec = 0;
|
||||
String result;
|
||||
@@ -170,12 +196,13 @@ String getNumerical(const String& tBuf, NumericalType requestedType, NumericalTy
|
||||
|
||||
if (firstDec >= bufLength) { return result; }
|
||||
bool decPt = false;
|
||||
|
||||
detectedType = NumericalType::Integer;
|
||||
char c = tBuf.charAt(firstDec);
|
||||
|
||||
if ((c == '+') || (c == '-')) {
|
||||
if ((requestedType != NumericalType::HexadecimalUInt) &&
|
||||
(requestedType != NumericalType::BinaryUint)) {
|
||||
detectedType = NumericalType::Integer;
|
||||
if (c == '-') {
|
||||
result += c;
|
||||
}
|
||||
@@ -187,54 +214,37 @@ String getNumerical(const String& tBuf, NumericalType requestedType, NumericalTy
|
||||
}
|
||||
if (c == '0') {
|
||||
++firstDec;
|
||||
result += c;
|
||||
|
||||
if (firstDec < bufLength) {
|
||||
c = tBuf.charAt(firstDec);
|
||||
|
||||
if ((c == 'x') || (c == 'X')) {
|
||||
++firstDec;
|
||||
result += '0';
|
||||
result += c;
|
||||
detectedType = NumericalType::HexadecimalUInt;
|
||||
} else if ((c == 'b') || (c == 'B')) {
|
||||
++firstDec;
|
||||
result += '0';
|
||||
result += c;
|
||||
detectedType = NumericalType::BinaryUint;
|
||||
} else if (NumericalType::Integer == requestedType) {
|
||||
// Allow leading zeroes in Integer types (e.g. in time notation)
|
||||
detectedType = NumericalType::Integer;
|
||||
while (c == '0' && firstDec < bufLength) {
|
||||
// N.B. intentional "reverse order" of reading char and ++firstDec
|
||||
c = tBuf.charAt(firstDec);
|
||||
++firstDec;
|
||||
}
|
||||
if (firstDec >= bufLength) {
|
||||
result += '0';
|
||||
}
|
||||
}
|
||||
} else if (NumericalType::FloatingPoint == requestedType && c == '.') {
|
||||
// Only floating point numbers should start with '0.'
|
||||
// All other combinations are not valid.
|
||||
++firstDec;
|
||||
result += '0';
|
||||
result += c;
|
||||
decPt = true;
|
||||
detectedType = NumericalType::FloatingPoint;
|
||||
} else {
|
||||
detectedType = NumericalType::Integer;
|
||||
result += '0';
|
||||
return result;
|
||||
}
|
||||
}
|
||||
} else if (NumericalType::Unknown == detectedType) {
|
||||
if (NumericalType::HexadecimalUInt == requestedType && isxdigit(c)) {
|
||||
// Should be careful here, as we're patching a string,
|
||||
// which may yield different result when the requested type is not specifically hex.
|
||||
detectedType = NumericalType::HexadecimalUInt;
|
||||
result = F("0x");
|
||||
} else if (isdigit(c)) {
|
||||
detectedType = NumericalType::Integer;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int x = firstDec; x < bufLength; ++x) {
|
||||
@@ -270,9 +280,6 @@ String getNumerical(const String& tBuf, NumericalType requestedType, NumericalTy
|
||||
return result;
|
||||
}
|
||||
break;
|
||||
case NumericalType::Unknown:
|
||||
// If we still have no clue what it is by now, return it.
|
||||
return result;
|
||||
}
|
||||
}
|
||||
result += c;
|
||||
@@ -283,8 +290,17 @@ String getNumerical(const String& tBuf, NumericalType requestedType, NumericalTy
|
||||
bool isNumerical(const String& tBuf, NumericalType& detectedType) {
|
||||
NumericalType requestedType = NumericalType::FloatingPoint;
|
||||
const String result = getNumerical(tBuf, requestedType, detectedType);
|
||||
if (NumericalType::Unknown == detectedType) {
|
||||
return false;
|
||||
if (result.length() > 0)
|
||||
{
|
||||
String tmp(tBuf);
|
||||
tmp.trim(); // remove leading and trailing spaces
|
||||
|
||||
// Resulting size should be the same size as the given string.
|
||||
// Not sure if it is possible to have a longer result, but better be sure to also allow for larger resulting strings.
|
||||
// For example ".123" -> "0.123"
|
||||
return result.length() >= tmp.length();
|
||||
}
|
||||
|
||||
|
||||
return result.length() > 0;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ bool validDoubleFromString(const String& tBuf, double& result);
|
||||
|
||||
// Numerical types sorted from least specific to most specific.
|
||||
enum class NumericalType {
|
||||
Unknown,
|
||||
FloatingPoint,
|
||||
Integer,
|
||||
HexadecimalUInt,
|
||||
@@ -31,6 +30,7 @@ enum class NumericalType {
|
||||
};
|
||||
|
||||
bool mustConsiderAsString(NumericalType detectedType);
|
||||
bool mustConsiderAsString(const String& value);
|
||||
|
||||
String getNumerical(const String& tBuf, NumericalType requestedType, NumericalType& detectedType);
|
||||
|
||||
|
||||
@@ -165,7 +165,16 @@ String getPinStateJSON(bool search, uint32_t key, const String& log, int16_t noS
|
||||
String reply;
|
||||
reply.reserve(128);
|
||||
reply += F("{\n\"log\": \"");
|
||||
reply += log.substring(7, 32); // truncate to 25 chars, max MQTT message size = 128 including header...
|
||||
{
|
||||
// truncate to 25 chars, max MQTT message size = 128 including header...
|
||||
int colonPos = log.indexOf(':');
|
||||
if (colonPos == -1) {
|
||||
colonPos = 0;
|
||||
}
|
||||
String tmp = log.substring(colonPos, colonPos + 25);
|
||||
tmp.trim();
|
||||
reply += tmp;
|
||||
}
|
||||
reply += F("\",\n\"plugin\": ");
|
||||
reply += getPluginFromKey(key);
|
||||
reply += F(",\n\"pin\": ");
|
||||
|
||||
@@ -241,6 +241,18 @@ String doFormatUserVar(struct EventStruct *event, byte rel_index, bool mustCheck
|
||||
return "0";
|
||||
}
|
||||
|
||||
{
|
||||
// First try to format using the plugin specific formatting.
|
||||
String result;
|
||||
EventStruct tempEvent(*event);
|
||||
tempEvent.idx = rel_index;
|
||||
PluginCall(PLUGIN_FORMAT_USERVAR, &tempEvent, result);
|
||||
if (result.length() > 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const byte valueCount = getValueCountForTask(event->TaskIndex);
|
||||
Sensor_VType sensorType = event->getSensorType();
|
||||
|
||||
@@ -264,7 +276,7 @@ String doFormatUserVar(struct EventStruct *event, byte rel_index, bool mustCheck
|
||||
|
||||
switch (sensorType) {
|
||||
case Sensor_VType::SENSOR_TYPE_LONG:
|
||||
return String((unsigned long)UserVar[event->BaseVarIndex] + ((unsigned long)UserVar[event->BaseVarIndex + 1] << 16));
|
||||
return String(UserVar.getSensorTypeLong(event->TaskIndex));
|
||||
case Sensor_VType::SENSOR_TYPE_STRING:
|
||||
return event->String2;
|
||||
|
||||
@@ -386,10 +398,7 @@ String to_json_object_value(const String& object, const String& value) {
|
||||
result += F("\"\"");
|
||||
return result;
|
||||
}
|
||||
NumericalType detectedType;
|
||||
bool isNum = isNumerical(value, detectedType);
|
||||
|
||||
if (!isNum || mustConsiderAsString(detectedType)) {
|
||||
if (mustConsiderAsString(value)) {
|
||||
// Is not a numerical value, or BIN/HEX notation, thus wrap with quotes
|
||||
if ((value.indexOf('\n') != -1) || (value.indexOf('\r') != -1) || (value.indexOf('"') != -1)) {
|
||||
// Must replace characters, so make a deepcopy
|
||||
@@ -461,13 +470,13 @@ bool safe_strncpy(char *dest, const char *source, size_t max_size) {
|
||||
bool result = true;
|
||||
|
||||
memset(dest, 0, max_size);
|
||||
size_t str_length = strlen(source);
|
||||
size_t str_length = strlen_P(source);
|
||||
|
||||
if (str_length >= max_size) {
|
||||
str_length = max_size;
|
||||
result = false;
|
||||
}
|
||||
strncpy(dest, source, str_length);
|
||||
strncpy_P(dest, source, str_length);
|
||||
dest[max_size - 1] = 0;
|
||||
return result;
|
||||
}
|
||||
@@ -768,7 +777,7 @@ void parseEventVariables(String& s, struct EventStruct *event, boolean useURLenc
|
||||
if (validTaskIndex(event->TaskIndex)) {
|
||||
if (s.indexOf(F("%val")) != -1) {
|
||||
if (event->getSensorType() == Sensor_VType::SENSOR_TYPE_LONG) {
|
||||
SMART_REPL(F("%val1%"), String((unsigned long)UserVar[event->BaseVarIndex] + ((unsigned long)UserVar[event->BaseVarIndex + 1] << 16)))
|
||||
SMART_REPL(F("%val1%"), String(UserVar.getSensorTypeLong(event->TaskIndex)))
|
||||
} else {
|
||||
for (byte i = 0; i < getValueCountForTask(event->TaskIndex); ++i) {
|
||||
String valstr = F("%val");
|
||||
|
||||
@@ -105,7 +105,9 @@ bool WiFi_AP_CandidatesList::getNext() {
|
||||
|
||||
if (mustPop) {
|
||||
known_it = known.begin();
|
||||
candidates.pop_front();
|
||||
if (!candidates.empty()) {
|
||||
candidates.pop_front();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -176,30 +178,26 @@ void WiFi_AP_CandidatesList::addFromRTC() {
|
||||
return;
|
||||
}
|
||||
|
||||
WiFi_AP_Candidate tmp(RTC.lastWiFiSettingsIndex, ssid, key);
|
||||
candidates.emplace_front(RTC.lastWiFiSettingsIndex, ssid, key);
|
||||
candidates.front().setBSSID(RTC.lastBSSID);
|
||||
candidates.front().rssi = -1; // Set to best possible RSSI so it is tried first.
|
||||
candidates.front().channel = RTC.lastWiFiChannel;
|
||||
|
||||
tmp.setBSSID(RTC.lastBSSID);
|
||||
if (!tmp.bssid_set()) return;
|
||||
if (!candidates.front().usable() || !candidates.front().allowQuickConnect()) {
|
||||
candidates.pop_front();
|
||||
return;
|
||||
}
|
||||
|
||||
// This is not taken from a scan, so no idea of the used encryption.
|
||||
// Try to find a matching BSSID to get the encryption.
|
||||
bool matchfound = false;
|
||||
for (auto it = candidates.begin(); !matchfound && it != candidates.end(); ++it) {
|
||||
if (tmp == *it) {
|
||||
matchfound = true;
|
||||
tmp = *it;
|
||||
for (auto it = candidates.begin(); it != candidates.end(); ++it) {
|
||||
if ((it->rssi != -1) && candidates.front() == *it) {
|
||||
candidates.front().enc_type = it->enc_type;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!matchfound) {
|
||||
if (currentCandidate == tmp) {
|
||||
tmp = currentCandidate;
|
||||
}
|
||||
}
|
||||
|
||||
tmp.channel = RTC.lastWiFiChannel;
|
||||
tmp.rssi = -1; // Set to best possible RSSI so it is tried first.
|
||||
if (tmp.usable() && tmp.allowQuickConnect()) {
|
||||
candidates.push_front(tmp);
|
||||
if (currentCandidate == candidates.front()) {
|
||||
candidates.front().enc_type = currentCandidate.enc_type;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ String formatDomoticzSensorType(struct EventStruct *event) {
|
||||
values = formatUserVarDomoticz(event, 0);
|
||||
break;
|
||||
case Sensor_VType::SENSOR_TYPE_LONG: // single LONG value, stored in two floats (rfid tags)
|
||||
values = (unsigned long)UserVar[event->BaseVarIndex] + ((unsigned long)UserVar[event->BaseVarIndex + 1] << 16);
|
||||
values = UserVar.getSensorTypeLong(event->TaskIndex);
|
||||
break;
|
||||
case Sensor_VType::SENSOR_TYPE_DUAL: // any sensor that uses two simple values
|
||||
values = formatUserVarDomoticz(event, 0);
|
||||
|
||||
@@ -44,7 +44,7 @@ String getPackedFromPlugin(struct EventStruct *event, uint8_t sampleSetCount)
|
||||
{
|
||||
case Sensor_VType::SENSOR_TYPE_LONG:
|
||||
{
|
||||
unsigned long longval = (unsigned long)UserVar[event->BaseVarIndex] + ((unsigned long)UserVar[event->BaseVarIndex + 1] << 16);
|
||||
unsigned long longval = UserVar.getSensorTypeLong(event->TaskIndex);
|
||||
packed += LoRa_addInt(longval, PackedData_uint32);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -161,8 +161,8 @@ bool P082_data_struct::getDateTime(struct tm& dateTime, uint32_t& age, bool& pps
|
||||
if (!gps->date.isValid() || !gps->time.isValid()) {
|
||||
return false;
|
||||
}
|
||||
dateTime.tm_year = gps->date.year() - 1970;
|
||||
dateTime.tm_mon = gps->date.month();
|
||||
dateTime.tm_year = gps->date.year() - 1900;
|
||||
dateTime.tm_mon = gps->date.month() - 1; // GPS month starts at 1, tm_mon at 0
|
||||
dateTime.tm_mday = gps->date.day();
|
||||
|
||||
dateTime.tm_hour = gps->time.hour();
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -310,10 +310,16 @@ void handle_json()
|
||||
for (byte x = 0; x < valueCount; x++)
|
||||
{
|
||||
addHtml('{');
|
||||
const String value = formatUserVarNoCheck(TaskIndex, x);
|
||||
byte nrDecimals = ExtraTaskSettings.TaskDeviceValueDecimals[x];
|
||||
if (mustConsiderAsString(value)) {
|
||||
// Flag as not to treat as a float
|
||||
nrDecimals = 255;
|
||||
}
|
||||
stream_next_json_object_value(F("ValueNumber"), String(x + 1));
|
||||
stream_next_json_object_value(F("Name"), String(ExtraTaskSettings.TaskDeviceValueNames[x]));
|
||||
stream_next_json_object_value(F("NrDecimals"), String(ExtraTaskSettings.TaskDeviceValueDecimals[x]));
|
||||
stream_last_json_object_value(F("Value"), formatUserVarNoCheck(TaskIndex, x));
|
||||
stream_next_json_object_value(F("NrDecimals"), String(nrDecimals));
|
||||
stream_last_json_object_value(F("Value"), value);
|
||||
|
||||
if (x < (valueCount - 1)) {
|
||||
addHtml(F(",\n"));
|
||||
|
||||
+12
-8
File diff suppressed because one or more lines are too long
@@ -41,7 +41,9 @@ function loopDeLoop(timeForNext, activeRequests) {
|
||||
if (valueEntry !== 'TypeError') {
|
||||
tempValue = data.Sensors[c].TaskValues[k].Value;
|
||||
decimalsValue = data.Sensors[c].TaskValues[k].NrDecimals;
|
||||
tempValue = parseFloat(tempValue).toFixed(decimalsValue);
|
||||
if (decimalsValue < 255) {
|
||||
tempValue = parseFloat(tempValue).toFixed(decimalsValue);
|
||||
}
|
||||
var valueID = 'value_' + (data.Sensors[c].TaskNumber - 1) + '_' + (data.Sensors[c].TaskValues[k].ValueNumber - 1);
|
||||
var valueNameID = 'valuename_' + (data.Sensors[c].TaskNumber - 1) + '_' + (data.Sensors[c].TaskValues[k].ValueNumber - 1);
|
||||
var valueElement = document.getElementById(valueID);
|
||||
@@ -72,4 +74,4 @@ function loopDeLoop(timeForNext, activeRequests) {
|
||||
check = 1;
|
||||
}
|
||||
}, timeForNext);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,14 @@
|
||||
Import("env")
|
||||
import os
|
||||
import glob
|
||||
import filecmp
|
||||
|
||||
def do_concat_cpp_files(cpp_files, output_file):
|
||||
with open(output_file, 'wb') as newf:
|
||||
for filename in cpp_files:
|
||||
with open(filename, 'rb') as hf:
|
||||
newf.write(hf.read())
|
||||
newf.write(os.linesep.encode()) # append newline to separate files.
|
||||
|
||||
|
||||
def concat_cpp_files(path_to_concat):
|
||||
@@ -15,13 +23,11 @@ def concat_cpp_files(path_to_concat):
|
||||
os.makedirs(cpp_path_out)
|
||||
|
||||
tmp_cpp_file = os.path.join(cpp_path_out, '__tmpfile.cpp')
|
||||
tmp2_cpp_file = os.path.join(cpp_path_out, '__tmpfile.cpp.test')
|
||||
|
||||
print("\u001b[32m Concat {}/*.cpp to {} \u001b[0m".format(cpp_path, tmp_cpp_file))
|
||||
|
||||
|
||||
if os.path.exists(tmp_cpp_file):
|
||||
os.remove(tmp_cpp_file)
|
||||
|
||||
for root, dirs, files in os.walk(cpp_path):
|
||||
for file in files:
|
||||
if file.endswith('.cpp'):
|
||||
@@ -29,13 +35,18 @@ def concat_cpp_files(path_to_concat):
|
||||
cpp_files.append(fullname)
|
||||
print("\u001b[33m Add: \u001b[0m {}".format(fullname))
|
||||
|
||||
if os.path.exists(tmp_cpp_file):
|
||||
do_concat_cpp_files(cpp_files, tmp2_cpp_file)
|
||||
|
||||
if filecmp.cmp(tmp_cpp_file, tmp2_cpp_file):
|
||||
print("\u001b[32m Files not changed, will not touch __tmpfile.cpp \u001b[0m")
|
||||
os.remove(tmp2_cpp_file)
|
||||
else:
|
||||
os.remove(tmp_cpp_file)
|
||||
os.rename(tmp2_cpp_file, tmp_cpp_file)
|
||||
else:
|
||||
do_concat_cpp_files(cpp_files, tmp_cpp_file)
|
||||
|
||||
with open(tmp_cpp_file,'wb') as newf:
|
||||
for filename in cpp_files:
|
||||
with open(filename,'rb') as hf:
|
||||
newf.write(hf.read())
|
||||
newf.write(os.linesep.encode()) #append newline to separate files.
|
||||
|
||||
print("\u001b[32m ------------------------------- \u001b[0m")
|
||||
|
||||
|
||||
|
||||
@@ -24,4 +24,4 @@ def clear_all_concat_cpp_files(source, target, env):
|
||||
print("\u001b[32m ------------------------------ \u001b[0m")
|
||||
|
||||
|
||||
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", [clear_all_concat_cpp_files])
|
||||
#env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", [clear_all_concat_cpp_files])
|
||||
Reference in New Issue
Block a user