mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-28 04:07:47 +00:00
Compare commits
14
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
41341b46de | ||
|
|
3574517014 | ||
|
|
cca785e1f0 | ||
|
|
4215e058d0 | ||
|
|
2f91fbe931 | ||
|
|
90febfd46f | ||
|
|
ccc5b68111 | ||
|
|
07f6b86138 | ||
|
|
7b2667feaa | ||
|
|
48bd7b334d | ||
|
|
9dd4242590 | ||
|
|
ac8c29e9c5 | ||
|
|
387b0f68a8 | ||
|
|
fa130bf649 |
Vendored
+23
@@ -1,3 +1,26 @@
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20180801 (since mega-20180723)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Wed Aug 1 04:00:18 CEST 2018
|
||||
|
||||
Edwin Eefting (1):
|
||||
Power down PN532 after reading. Saves power and reduces interference with Wifi.
|
||||
|
||||
TD-er (11):
|
||||
[ExtraTaskSettings] Added some comments & clarifications
|
||||
[ExtraTaskSettings] Added extra clear functions and checks
|
||||
[ExtraTaskSettings] Keep ExtraTaskSettings actualized for plugin calls
|
||||
[meminfodetail] Add command `meminfodetail`
|
||||
[FileHandling] Write some log indicating file operation
|
||||
[compiler fix] Forgot to declare String
|
||||
[Storage] Split storage related functions to new file
|
||||
[Storage] Simplify settings I/O error handling
|
||||
[#882] Add checks on names in task setup
|
||||
[#1379] Check for "forbidden" characters in names.
|
||||
[#1306] Added %R% and %N% for literals \r and \n
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20180723 (since mega-20180722)
|
||||
-------------------------------------------------
|
||||
|
||||
+2
-1
@@ -85,7 +85,8 @@ bool doExecuteCommand(const char * cmd, struct EventStruct *event, const char* l
|
||||
}
|
||||
case 'm': {
|
||||
COMMAND_CASE("malloc" , Command_Malloc); // Diagnostic.h
|
||||
COMMAND_CASE("meminfo" , Command_MenInfo); // Diagnostic.h
|
||||
COMMAND_CASE("meminfo" , Command_MemInfo); // Diagnostic.h
|
||||
COMMAND_CASE("meminfodetail" , Command_MemInfo_detail); // Diagnostic.h
|
||||
COMMAND_CASE("messagedelay" , Command_MQTT_messageDelay); // MQTT.h
|
||||
COMMAND_CASE("mqttretainflag" , Command_MQTT_Retain); // MQTT.h
|
||||
break;
|
||||
|
||||
@@ -38,20 +38,50 @@ bool Command_SerialFloat(struct EventStruct *event, const char* Line)
|
||||
return success;
|
||||
}
|
||||
|
||||
bool Command_MenInfo(struct EventStruct *event, const char* Line)
|
||||
bool Command_MemInfo(struct EventStruct *event, const char* Line)
|
||||
{
|
||||
bool success = true;
|
||||
Serial.print(F("SecurityStruct : "));
|
||||
Serial.print(F("SecurityStruct | "));
|
||||
Serial.println(sizeof(SecuritySettings));
|
||||
Serial.print(F("SettingsStruct : "));
|
||||
Serial.print(F("SettingsStruct | "));
|
||||
Serial.println(sizeof(Settings));
|
||||
Serial.print(F("ExtraTaskSettingsStruct: "));
|
||||
Serial.print(F("ExtraTaskSettingsStruct| "));
|
||||
Serial.println(sizeof(ExtraTaskSettings));
|
||||
Serial.print(F("DeviceStruct: "));
|
||||
Serial.print(F("DeviceStruct | "));
|
||||
Serial.println(sizeof(Device));
|
||||
return success;
|
||||
}
|
||||
|
||||
bool Command_MemInfo_detail(struct EventStruct *event, const char* Line)
|
||||
{
|
||||
bool success = true;
|
||||
Command_MemInfo(event, Line);
|
||||
for (int st = 0; st < SettingsType_MAX; ++st) {
|
||||
SettingsType settingsType = static_cast<SettingsType>(st);
|
||||
int max_index, offset, max_size;
|
||||
int struct_size = 0;
|
||||
Serial.println();
|
||||
Serial.print(getSettingsTypeString(settingsType));
|
||||
Serial.println(F(" | start | end | max_size | struct_size"));
|
||||
Serial.println(F("--- | --- | --- | --- | ---"));
|
||||
getSettingsParameters(settingsType, 0, max_index, offset, max_size, struct_size);
|
||||
for (int i = 0; i < max_index; ++i) {
|
||||
getSettingsParameters(settingsType, i, offset, max_size);
|
||||
Serial.print(i);
|
||||
Serial.print('|');
|
||||
Serial.print(offset);
|
||||
Serial.print('|');
|
||||
Serial.print(offset + max_size);
|
||||
Serial.print('|');
|
||||
Serial.print(max_size);
|
||||
Serial.print('|');
|
||||
Serial.println(struct_size);
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool Command_Background(struct EventStruct *event, const char* Line)
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
bool Command_Task_Clear(struct EventStruct *event, const char* Line)
|
||||
{
|
||||
bool success = true;
|
||||
// Par1 is here for 1 ... TASKS_MAX
|
||||
taskClear(event->Par1 - 1, true);
|
||||
return success;
|
||||
}
|
||||
@@ -12,13 +13,13 @@ bool Command_Task_Clear(struct EventStruct *event, const char* Line)
|
||||
bool Command_Task_ClearAll(struct EventStruct *event, const char* Line)
|
||||
{
|
||||
bool success = true;
|
||||
for (byte t=0; t<TASKS_MAX; t++)
|
||||
for (byte t = 0; t < TASKS_MAX; t++)
|
||||
taskClear(t, false);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool Command_Task_ValueSet(struct EventStruct *event, const char* Line)
|
||||
{
|
||||
{
|
||||
bool success = true;
|
||||
char TmpStr1[INPUT_COMMAND_SIZE];
|
||||
if (GetArgv(Line, TmpStr1, 4))
|
||||
@@ -29,14 +30,14 @@ bool Command_Task_ValueSet(struct EventStruct *event, const char* Line)
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO: Get Task description and var name
|
||||
//TODO: Get Task description and var name
|
||||
Serial.println(UserVar[(VARS_PER_TASK * (event->Par1 - 1)) + event->Par2 - 1]);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool Command_Task_ValueSetAndRun(struct EventStruct *event, const char* Line)
|
||||
{
|
||||
{
|
||||
bool success = true;
|
||||
char TmpStr1[INPUT_COMMAND_SIZE];
|
||||
if (GetArgv(Line, TmpStr1, 4))
|
||||
@@ -50,7 +51,7 @@ bool Command_Task_ValueSetAndRun(struct EventStruct *event, const char* Line)
|
||||
}
|
||||
|
||||
bool Command_Task_Run(struct EventStruct *event, const char* Line)
|
||||
{
|
||||
{
|
||||
bool success = true;
|
||||
SensorSendTask(event->Par1 - 1);
|
||||
return success;
|
||||
@@ -64,4 +65,4 @@ bool Command_Task_RemoteConfig(struct EventStruct *event, const char* Line)
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // COMMAND_TASKS_H
|
||||
#endif // COMMAND_TASKS_H
|
||||
|
||||
+191
-66
@@ -302,6 +302,7 @@
|
||||
#define RULES_MAX_NESTING_LEVEL 3
|
||||
#define RULESETS_MAX 4
|
||||
#define RULES_BUFFER_SIZE 64
|
||||
#define NAME_FORMULA_LENGTH_MAX 40
|
||||
|
||||
#define PIN_MODE_UNDEFINED 0
|
||||
#define PIN_MODE_INPUT 1
|
||||
@@ -344,8 +345,9 @@
|
||||
#define BOOT_CAUSE_DEEP_SLEEP 2
|
||||
#define BOOT_CAUSE_EXT_WD 10
|
||||
|
||||
#define DAT_TASKS_SIZE 2048
|
||||
#define DAT_TASKS_CUSTOM_OFFSET 1024
|
||||
#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
|
||||
@@ -364,6 +366,30 @@
|
||||
#define CONFIG_FILE_SIZE 131072
|
||||
#endif
|
||||
|
||||
enum SettingsType {
|
||||
TaskSettings_Type = 0,
|
||||
CustomTaskSettings_Type,
|
||||
ControllerSettings_Type,
|
||||
CustomControllerSettings_Type,
|
||||
NotificationSettings_Type,
|
||||
|
||||
SettingsType_MAX
|
||||
|
||||
};
|
||||
bool getSettingsParameters(SettingsType settingsType, int index, int& offset, int& max_size);
|
||||
String getSettingsTypeString(SettingsType settingsType) {
|
||||
switch (settingsType) {
|
||||
case TaskSettings_Type: return F("TaskSettings");
|
||||
case CustomTaskSettings_Type: return F("CustomTaskSettings");
|
||||
case ControllerSettings_Type: return F("ControllerSettings");
|
||||
case CustomControllerSettings_Type: return F("CustomControllerSettings");
|
||||
case NotificationSettings_Type: return F("NotificationSettings");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return String();
|
||||
}
|
||||
|
||||
/*
|
||||
To modify the stock configuration without changing this repo file :
|
||||
- define USE_CUSTOM_H as a build flags. ie : export PLATFORMIO_BUILD_FLAGS="'-DUSE_CUSTOM_H'"
|
||||
@@ -581,48 +607,94 @@ struct SecurityStruct
|
||||
|
||||
struct SettingsStruct
|
||||
{
|
||||
SettingsStruct() :
|
||||
PID(0), Version(0), Build(0), IP_Octet(0), Unit(0), Delay(0),
|
||||
Pin_i2c_sda(-1), Pin_i2c_scl(-1), Pin_status_led(-1), Pin_sd_cs(-1),
|
||||
UDPPort(0), SyslogLevel(0), SerialLogLevel(0), WebLogLevel(0), SDLogLevel(0),
|
||||
BaudRate(0), MessageDelay(0), deepSleep(0),
|
||||
CustomCSS(false), DST(false), WDI2CAddress(0),
|
||||
UseRules(false), UseSerial(false), UseSSDP(false), UseNTP(false),
|
||||
WireClockStretchLimit(0), GlobalSync(false), ConnectionFailuresThreshold(0),
|
||||
TimeZone(0), MQTTRetainFlag(false), InitSPI(false),
|
||||
Pin_status_led_Inversed(false), deepSleepOnFail(false), UseValueLogger(false),
|
||||
DST_Start(0), DST_End(0), UseRTOSMultitasking(false), Pin_Reset(-1),
|
||||
SyslogFacility(DEFAULT_SYSLOG_FACILITY), StructSize(0), MQTTUseUnitNameAsClientId(0)
|
||||
{
|
||||
for (byte i = 0; i < CONTROLLER_MAX; ++i) {
|
||||
Protocol[i] = 0;
|
||||
ControllerEnabled[i] = false;
|
||||
for (byte task = 0; task < TASKS_MAX; ++task) {
|
||||
TaskDeviceID[i][task] = 0;
|
||||
TaskDeviceSendData[i][task] = false;
|
||||
}
|
||||
}
|
||||
for (byte task = 0; task < TASKS_MAX; ++task) {
|
||||
TaskDeviceNumber[task] = 0;
|
||||
OLD_TaskDeviceID[task] = 0;
|
||||
TaskDevicePin1PullUp[task] = false;
|
||||
for (byte cv = 0; cv < PLUGIN_CONFIGVAR_MAX; ++cv) {
|
||||
TaskDevicePluginConfig[task][cv] = 0;
|
||||
}
|
||||
TaskDevicePin1Inversed[task] = false;
|
||||
for (byte cv = 0; cv < PLUGIN_CONFIGFLOATVAR_MAX; ++cv) {
|
||||
TaskDevicePluginConfigFloat[task][cv] = 0.0;
|
||||
}
|
||||
for (byte cv = 0; cv < PLUGIN_CONFIGLONGVAR_MAX; ++cv) {
|
||||
TaskDevicePluginConfigLong[task][cv] = 0;
|
||||
}
|
||||
OLD_TaskDeviceSendData[task] = false;
|
||||
TaskDeviceGlobalSync[task] = false;
|
||||
TaskDeviceDataFeed[task] = 0;
|
||||
TaskDeviceTimer[task] = 0;
|
||||
TaskDeviceEnabled[task] = false;
|
||||
}
|
||||
SettingsStruct() {
|
||||
clearAll();
|
||||
}
|
||||
|
||||
void clearAll() {
|
||||
PID = 0;
|
||||
Version = 0;
|
||||
Build = 0;
|
||||
IP_Octet = 0;
|
||||
Unit = 0;
|
||||
Delay = 0;
|
||||
Pin_i2c_sda = -1;
|
||||
Pin_i2c_scl = -1;
|
||||
Pin_status_led = -1;
|
||||
Pin_sd_cs = -1;
|
||||
UDPPort = 0;
|
||||
SyslogLevel = 0;
|
||||
SerialLogLevel = 0;
|
||||
WebLogLevel = 0;
|
||||
SDLogLevel = 0;
|
||||
BaudRate = 0;
|
||||
MessageDelay = 0;
|
||||
deepSleep = 0;
|
||||
CustomCSS = false;
|
||||
DST = false;
|
||||
WDI2CAddress = 0;
|
||||
UseRules = false;
|
||||
UseSerial = false;
|
||||
UseSSDP = false;
|
||||
UseNTP = false;
|
||||
WireClockStretchLimit = 0;
|
||||
GlobalSync = false;
|
||||
ConnectionFailuresThreshold = 0;
|
||||
TimeZone = 0;
|
||||
MQTTRetainFlag = false;
|
||||
InitSPI = false;
|
||||
Pin_status_led_Inversed = false;
|
||||
deepSleepOnFail = false;
|
||||
UseValueLogger = false;
|
||||
DST_Start = 0;
|
||||
DST_End = 0;
|
||||
UseRTOSMultitasking = false;
|
||||
Pin_Reset = -1;
|
||||
SyslogFacility = DEFAULT_SYSLOG_FACILITY;
|
||||
StructSize = 0;
|
||||
MQTTUseUnitNameAsClientId = 0;
|
||||
|
||||
for (byte i = 0; i < CONTROLLER_MAX; ++i) {
|
||||
Protocol[i] = 0;
|
||||
ControllerEnabled[i] = false;
|
||||
}
|
||||
for (byte i = 0; i < NOTIFICATION_MAX; ++i) {
|
||||
Notification[i] = 0;
|
||||
NotificationEnabled[i] = false;
|
||||
}
|
||||
for (byte task = 0; task < TASKS_MAX; ++task) {
|
||||
clearTask(task);
|
||||
}
|
||||
}
|
||||
|
||||
void clearTask(byte task) {
|
||||
for (byte i = 0; i < CONTROLLER_MAX; ++i) {
|
||||
TaskDeviceID[i][task] = 0;
|
||||
TaskDeviceSendData[i][task] = false;
|
||||
}
|
||||
TaskDeviceNumber[task] = 0;
|
||||
OLD_TaskDeviceID[task] = 0;
|
||||
TaskDevicePin1[task] = -1;
|
||||
TaskDevicePin2[task] = -1;
|
||||
TaskDevicePin3[task] = -1;
|
||||
TaskDevicePort[task] = 0;
|
||||
TaskDevicePin1PullUp[task] = false;
|
||||
for (byte cv = 0; cv < PLUGIN_CONFIGVAR_MAX; ++cv) {
|
||||
TaskDevicePluginConfig[task][cv] = 0;
|
||||
}
|
||||
TaskDevicePin1Inversed[task] = false;
|
||||
for (byte cv = 0; cv < PLUGIN_CONFIGFLOATVAR_MAX; ++cv) {
|
||||
TaskDevicePluginConfigFloat[task][cv] = 0.0;
|
||||
}
|
||||
for (byte cv = 0; cv < PLUGIN_CONFIGLONGVAR_MAX; ++cv) {
|
||||
TaskDevicePluginConfigLong[task][cv] = 0;
|
||||
}
|
||||
OLD_TaskDeviceSendData[task] = false;
|
||||
TaskDeviceGlobalSync[task] = false;
|
||||
TaskDeviceDataFeed[task] = 0;
|
||||
TaskDeviceTimer[task] = 0;
|
||||
TaskDeviceEnabled[task] = false;
|
||||
}
|
||||
|
||||
unsigned long PID;
|
||||
int Version;
|
||||
@@ -683,12 +755,12 @@ struct SettingsStruct
|
||||
long TaskDevicePluginConfigLong[TASKS_MAX][PLUGIN_CONFIGLONGVAR_MAX];
|
||||
boolean OLD_TaskDeviceSendData[TASKS_MAX];
|
||||
boolean TaskDeviceGlobalSync[TASKS_MAX];
|
||||
byte TaskDeviceDataFeed[TASKS_MAX];
|
||||
byte TaskDeviceDataFeed[TASKS_MAX]; // When set to 0, only read local connected sensorsfeeds
|
||||
unsigned long TaskDeviceTimer[TASKS_MAX];
|
||||
boolean TaskDeviceEnabled[TASKS_MAX];
|
||||
boolean ControllerEnabled[CONTROLLER_MAX];
|
||||
boolean NotificationEnabled[NOTIFICATION_MAX];
|
||||
unsigned int TaskDeviceID[CONTROLLER_MAX][TASKS_MAX];
|
||||
unsigned int TaskDeviceID[CONTROLLER_MAX][TASKS_MAX]; // IDX number (mainly used by Domoticz)
|
||||
boolean TaskDeviceSendData[CONTROLLER_MAX][TASKS_MAX];
|
||||
boolean Pin_status_led_Inversed;
|
||||
boolean deepSleepOnFail;
|
||||
@@ -860,15 +932,26 @@ struct NotificationSettingsStruct
|
||||
//its safe to extend this struct, up to 4096 bytes, default values in config are 0
|
||||
};
|
||||
|
||||
// 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() : TaskIndex(0) {
|
||||
TaskDeviceName[0] = 0;
|
||||
ExtraTaskSettingsStruct() : TaskIndex(TASKS_MAX) {
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
TaskIndex = TASKS_MAX;
|
||||
for (byte j = 0; j < (NAME_FORMULA_LENGTH_MAX + 1); ++j) {
|
||||
TaskDeviceName[j] = 0;
|
||||
}
|
||||
for (byte i = 0; i < VARS_PER_TASK; ++i) {
|
||||
for (byte j = 0; j < 41; ++j) {
|
||||
for (byte j = 0; j < (NAME_FORMULA_LENGTH_MAX + 1); ++j) {
|
||||
TaskDeviceFormula[i][j] = 0;
|
||||
TaskDeviceValueNames[i][j] = 0;
|
||||
TaskDeviceValueDecimals[i] = 0;
|
||||
TaskDeviceValueDecimals[i] = 2;
|
||||
}
|
||||
}
|
||||
for (byte i = 0; i < PLUGIN_EXTRACONFIGVAR_MAX; ++i) {
|
||||
@@ -877,10 +960,46 @@ struct ExtraTaskSettingsStruct
|
||||
}
|
||||
}
|
||||
|
||||
byte TaskIndex;
|
||||
char TaskDeviceName[41];
|
||||
char TaskDeviceFormula[VARS_PER_TASK][41];
|
||||
char TaskDeviceValueNames[VARS_PER_TASK][41];
|
||||
bool checkUniqueValueNames() {
|
||||
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;
|
||||
}
|
||||
|
||||
bool checkInvalidCharInNames(const char* name) {
|
||||
int pos = 0;
|
||||
while (*(name+pos) != 0) {
|
||||
switch (*(name+pos)) {
|
||||
case ',':
|
||||
case ' ':
|
||||
case '#':
|
||||
case '[':
|
||||
case ']':
|
||||
return false;
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool checkInvalidCharInNames() {
|
||||
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;
|
||||
}
|
||||
|
||||
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];
|
||||
@@ -1053,20 +1172,26 @@ struct DeviceStruct
|
||||
PullUpOption(false), InverseLogicOption(false), FormulaOption(false),
|
||||
ValueCount(0), Custom(false), SendDataOption(false), GlobalSyncOption(false),
|
||||
TimerOption(false), TimerOptional(false), DecimalsOnly(false) {}
|
||||
byte Number;
|
||||
byte Type;
|
||||
byte VType;
|
||||
byte Ports;
|
||||
boolean PullUpOption;
|
||||
boolean InverseLogicOption;
|
||||
boolean FormulaOption;
|
||||
byte ValueCount;
|
||||
|
||||
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)
|
||||
boolean PullUpOption; // Allow to set internal pull-up resistors.
|
||||
boolean InverseLogicOption; // Allow to invert the boolean state (e.g. a switch)
|
||||
boolean FormulaOption; // Allow to enter a formula to convert values during read. (not possible with Custom enabled)
|
||||
byte ValueCount; // The number of output values of a plugin. The value should match the number of keys PLUGIN_VALUENAME1_xxx
|
||||
boolean Custom;
|
||||
boolean SendDataOption;
|
||||
boolean GlobalSyncOption;
|
||||
boolean TimerOption;
|
||||
boolean TimerOptional;
|
||||
boolean DecimalsOnly;
|
||||
boolean SendDataOption; // Allow to send data to a controller.
|
||||
boolean GlobalSyncOption; // No longer used. Was used for ESPeasy values sync between nodes
|
||||
boolean TimerOption; // Allow to set the "Interval" timer for the plugin.
|
||||
boolean TimerOptional; // When taskdevice timer is not set and not optional, use default "Interval" delay (Settings.Delay)
|
||||
boolean DecimalsOnly; // Allow to set the number of decimals (otherwise treated a 0 decimals)
|
||||
} Device[DEVICES_MAX + 1]; // 1 more because first device is empty device
|
||||
|
||||
struct ProtocolStruct
|
||||
|
||||
@@ -195,8 +195,6 @@ void setup()
|
||||
// setWifiMode(WIFI_STA);
|
||||
checkRuleSets();
|
||||
|
||||
ExtraTaskSettings.TaskIndex = 255; // make sure this is an unused nr to prevent cache load on boot
|
||||
|
||||
// if different version, eeprom settings structure has changed. Full Reset needed
|
||||
// on a fresh ESP module eeprom values are set to 255. Version results into -1 (signed int)
|
||||
if (Settings.Version != VERSION || Settings.PID != ESP_PROJECT_PID)
|
||||
|
||||
@@ -0,0 +1,697 @@
|
||||
/********************************************************************************************\
|
||||
SPIFFS error handling
|
||||
Look here for error # reference: https://github.com/pellepl/spiffs/blob/master/src/spiffs.h
|
||||
\*********************************************************************************************/
|
||||
#define SPIFFS_CHECK(result, fname) if (!(result)) { return(FileError(__LINE__, fname)); }
|
||||
String FileError(int line, const char * fname)
|
||||
{
|
||||
String err = F("FS : Error while reading/writing ");
|
||||
err += fname;
|
||||
err += F(" in ");
|
||||
err += line;
|
||||
addLog(LOG_LEVEL_ERROR, err);
|
||||
return(err);
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Keep track of number of flash writes.
|
||||
\*********************************************************************************************/
|
||||
|
||||
void flashCount()
|
||||
{
|
||||
if (RTC.flashDayCounter <= MAX_FLASHWRITES_PER_DAY)
|
||||
RTC.flashDayCounter++;
|
||||
RTC.flashCounter++;
|
||||
saveToRTC();
|
||||
}
|
||||
|
||||
String flashGuard()
|
||||
{
|
||||
checkRAM(F("flashGuard"));
|
||||
if (RTC.flashDayCounter > MAX_FLASHWRITES_PER_DAY)
|
||||
{
|
||||
String log = F("FS : Daily flash write rate exceeded! (powercycle to reset this)");
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
return log;
|
||||
}
|
||||
flashCount();
|
||||
return(String());
|
||||
}
|
||||
|
||||
//use this in function that can return an error string. it automaticly returns with an error string if there where too many flash writes.
|
||||
#define FLASH_GUARD() { String flashErr=flashGuard(); if (flashErr.length()) return(flashErr); }
|
||||
|
||||
/********************************************************************************************\
|
||||
Fix stuff to clear out differences between releases
|
||||
\*********************************************************************************************/
|
||||
String BuildFixes()
|
||||
{
|
||||
checkRAM(F("BuildFixes"));
|
||||
Serial.println(F("\nBuild changed!"));
|
||||
|
||||
if (Settings.Build < 145)
|
||||
{
|
||||
String fname=F(FILE_NOTIFICATION);
|
||||
fs::File f = SPIFFS.open(fname, "w");
|
||||
SPIFFS_CHECK(f, fname.c_str());
|
||||
|
||||
if (f)
|
||||
{
|
||||
for (int x = 0; x < 4096; x++)
|
||||
{
|
||||
SPIFFS_CHECK(f.write(0), fname.c_str());
|
||||
}
|
||||
f.close();
|
||||
}
|
||||
}
|
||||
|
||||
if (Settings.Build < 20101)
|
||||
{
|
||||
Serial.println(F("Fix reset Pin"));
|
||||
Settings.Pin_Reset = -1;
|
||||
}
|
||||
if (Settings.Build < 20102) {
|
||||
// Settings were 'mangled' by using older version
|
||||
// Have to patch settings to make sure no bogus data is being used.
|
||||
Serial.println(F("Fix settings with uninitalized data or corrupted by switching between versions"));
|
||||
Settings.UseRTOSMultitasking = false;
|
||||
Settings.Pin_Reset = -1;
|
||||
Settings.SyslogFacility = DEFAULT_SYSLOG_FACILITY;
|
||||
Settings.MQTTUseUnitNameAsClientId = DEFAULT_MQTT_USE_UNITNANE_AS_CLIENTID;
|
||||
Settings.StructSize = sizeof(Settings);
|
||||
}
|
||||
|
||||
Settings.Build = BUILD;
|
||||
return(SaveSettings());
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Mount FS and check config.dat
|
||||
\*********************************************************************************************/
|
||||
void fileSystemCheck()
|
||||
{
|
||||
checkRAM(F("fileSystemCheck"));
|
||||
addLog(LOG_LEVEL_INFO, F("FS : Mounting..."));
|
||||
if (SPIFFS.begin())
|
||||
{
|
||||
#if defined(ESP8266)
|
||||
fs::FSInfo fs_info;
|
||||
SPIFFS.info(fs_info);
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
String log = F("FS : Mount successful, used ");
|
||||
log=log+fs_info.usedBytes;
|
||||
log=log+F(" bytes of ");
|
||||
log=log+fs_info.totalBytes;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
#endif
|
||||
|
||||
fs::File f = SPIFFS.open(FILE_CONFIG, "r");
|
||||
if (!f)
|
||||
{
|
||||
ResetFactory();
|
||||
}
|
||||
f.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
String log = F("FS : Mount failed");
|
||||
Serial.println(log);
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
ResetFactory();
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Save settings to SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String SaveSettings(void)
|
||||
{
|
||||
checkRAM(F("SaveSettings"));
|
||||
MD5Builder md5;
|
||||
uint8_t tmp_md5[16] = {0};
|
||||
String err;
|
||||
|
||||
Settings.StructSize = sizeof(struct SettingsStruct);
|
||||
|
||||
// FIXME @TD-er: As discussed in #1292, the CRC for the settings is now disabled.
|
||||
/*
|
||||
memcpy( Settings.ProgmemMd5, CRCValues.runTimeMD5, 16);
|
||||
md5.begin();
|
||||
md5.add((uint8_t *)&Settings, sizeof(Settings)-16);
|
||||
md5.calculate();
|
||||
md5.getBytes(tmp_md5);
|
||||
if (memcmp(tmp_md5, Settings.md5, 16) != 0) {
|
||||
// Settings have changed, save to file.
|
||||
memcpy(Settings.md5, tmp_md5, 16);
|
||||
*/
|
||||
err=SaveToFile((char*)FILE_CONFIG, 0, (byte*)&Settings, sizeof(Settings));
|
||||
if (err.length())
|
||||
return(err);
|
||||
// }
|
||||
|
||||
memcpy( SecuritySettings.ProgmemMd5, CRCValues.runTimeMD5, 16);
|
||||
md5.begin();
|
||||
md5.add((uint8_t *)&SecuritySettings, sizeof(SecuritySettings)-16);
|
||||
md5.calculate();
|
||||
md5.getBytes(tmp_md5);
|
||||
if (memcmp(tmp_md5, SecuritySettings.md5, 16) != 0) {
|
||||
// Settings have changed, save to file.
|
||||
memcpy(SecuritySettings.md5, tmp_md5, 16);
|
||||
err=SaveToFile((char*)FILE_SECURITY, 0, (byte*)&SecuritySettings, sizeof(SecuritySettings));
|
||||
if (WifiIsAP(WiFi.getMode())) {
|
||||
// Security settings are saved, may be update of WiFi settings or hostname.
|
||||
wifiSetupConnect = true;
|
||||
}
|
||||
}
|
||||
return (err);
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Load settings from SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String LoadSettings()
|
||||
{
|
||||
checkRAM(F("LoadSettings"));
|
||||
String err;
|
||||
uint8_t calculatedMd5[16];
|
||||
MD5Builder md5;
|
||||
|
||||
err=LoadFromFile((char*)FILE_CONFIG, 0, (byte*)&Settings, sizeof( SettingsStruct));
|
||||
if (err.length())
|
||||
return(err);
|
||||
|
||||
// FIXME @TD-er: As discussed in #1292, the CRC for the settings is now disabled.
|
||||
/*
|
||||
if (Settings.StructSize > 16) {
|
||||
md5.begin();
|
||||
md5.add((uint8_t *)&Settings, Settings.StructSize -16);
|
||||
md5.calculate();
|
||||
md5.getBytes(calculatedMd5);
|
||||
}
|
||||
if (memcmp (calculatedMd5, Settings.md5,16)==0){
|
||||
addLog(LOG_LEVEL_INFO, F("CRC : Settings CRC ...OK"));
|
||||
if (memcmp(Settings.ProgmemMd5, CRCValues.runTimeMD5, 16)!=0)
|
||||
addLog(LOG_LEVEL_INFO, F("CRC : binary has changed since last save of Settings"));
|
||||
}
|
||||
else{
|
||||
addLog(LOG_LEVEL_ERROR, F("CRC : Settings CRC ...FAIL"));
|
||||
}
|
||||
*/
|
||||
|
||||
err=LoadFromFile((char*)FILE_SECURITY, 0, (byte*)&SecuritySettings, sizeof( SecurityStruct));
|
||||
md5.begin();
|
||||
md5.add((uint8_t *)&SecuritySettings, sizeof(SecuritySettings)-16);
|
||||
md5.calculate();
|
||||
md5.getBytes(calculatedMd5);
|
||||
if (memcmp (calculatedMd5, SecuritySettings.md5, 16)==0){
|
||||
addLog(LOG_LEVEL_INFO, F("CRC : SecuritySettings CRC ...OK "));
|
||||
if (memcmp(SecuritySettings.ProgmemMd5,CRCValues.runTimeMD5, 16)!=0)
|
||||
addLog(LOG_LEVEL_INFO, F("CRC : binary has changed since last save of Settings"));
|
||||
}
|
||||
else{
|
||||
addLog(LOG_LEVEL_ERROR, F("CRC : SecuritySettings CRC ...FAIL"));
|
||||
}
|
||||
setUseStaticIP(useStaticIP());
|
||||
ExtraTaskSettings.clear(); // make sure these will not contain old settings.
|
||||
return(err);
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Offsets in settings files
|
||||
\*********************************************************************************************/
|
||||
bool getSettingsParameters(SettingsType settingsType, int index, int& max_index, int& offset, int& max_size, int& struct_size) {
|
||||
struct_size = 0;
|
||||
switch (settingsType) {
|
||||
case TaskSettings_Type:
|
||||
max_index = TASKS_MAX;
|
||||
offset = DAT_OFFSET_TASKS + (index * DAT_TASKS_DISTANCE);
|
||||
max_size = DAT_TASKS_SIZE;
|
||||
struct_size = sizeof(ExtraTaskSettingsStruct);
|
||||
break;
|
||||
case CustomTaskSettings_Type:
|
||||
max_index = TASKS_MAX;
|
||||
offset = DAT_OFFSET_TASKS + (index * DAT_TASKS_DISTANCE) + DAT_TASKS_CUSTOM_OFFSET;
|
||||
max_size = DAT_TASKS_CUSTOM_SIZE;
|
||||
// struct_size may differ.
|
||||
break;
|
||||
case ControllerSettings_Type:
|
||||
max_index = CONTROLLER_MAX;
|
||||
offset = DAT_OFFSET_CONTROLLER + (index * DAT_CONTROLLER_SIZE);
|
||||
max_size = DAT_CONTROLLER_SIZE;
|
||||
struct_size = sizeof(ControllerSettingsStruct);
|
||||
break;
|
||||
case CustomControllerSettings_Type:
|
||||
max_index = CONTROLLER_MAX;
|
||||
offset = DAT_OFFSET_CUSTOM_CONTROLLER + (index * DAT_CUSTOM_CONTROLLER_SIZE);
|
||||
max_size = DAT_CUSTOM_CONTROLLER_SIZE;
|
||||
// struct_size may differ.
|
||||
break;
|
||||
case NotificationSettings_Type:
|
||||
max_index = NOTIFICATION_MAX;
|
||||
offset = index * DAT_NOTIFICATION_SIZE;
|
||||
max_size = DAT_NOTIFICATION_SIZE;
|
||||
struct_size = sizeof(NotificationSettingsStruct);
|
||||
break;
|
||||
default:
|
||||
max_index = -1;
|
||||
offset = -1;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool getAndLogSettingsParameters(bool read, SettingsType settingsType, int index, int& offset, int& max_size) {
|
||||
if (loglevelActiveFor(LOG_LEVEL_DEBUG_DEV)) {
|
||||
String log = read ? F("Read") : F("Write");
|
||||
log += F(" settings: ");
|
||||
log += getSettingsTypeString(settingsType);
|
||||
log += F(" index: ");
|
||||
log += index;
|
||||
addLog(LOG_LEVEL_DEBUG_DEV, log);
|
||||
}
|
||||
return getSettingsParameters(settingsType, index, offset, max_size);
|
||||
}
|
||||
|
||||
bool getSettingsParameters(SettingsType settingsType, int index, int& offset, int& max_size) {
|
||||
int max_index = -1;
|
||||
int struct_size;
|
||||
if (!getSettingsParameters(settingsType, index, max_index, offset, max_size, struct_size))
|
||||
return false;
|
||||
if (index >= 0 && index < max_index) return true;
|
||||
offset = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Save Task settings to SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String SaveTaskSettings(byte TaskIndex)
|
||||
{
|
||||
checkRAM(F("SaveTaskSettings"));
|
||||
if (ExtraTaskSettings.TaskIndex != TaskIndex)
|
||||
return F("SaveTaskSettings taskIndex does not match");
|
||||
String err = SaveToFile(TaskSettings_Type, TaskIndex, (char*)FILE_CONFIG, (byte*)&ExtraTaskSettings, sizeof(struct ExtraTaskSettingsStruct));
|
||||
if (err.length() == 0)
|
||||
err = checkTaskSettings(TaskIndex);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Load Task settings from SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String LoadTaskSettings(byte TaskIndex)
|
||||
{
|
||||
checkRAM(F("LoadTaskSettings"));
|
||||
if (ExtraTaskSettings.TaskIndex == TaskIndex)
|
||||
return(String()); //already loaded
|
||||
ExtraTaskSettings.clear();
|
||||
String result = "";
|
||||
result = LoadFromFile(TaskSettings_Type, TaskIndex, (char*)FILE_CONFIG, (byte*)&ExtraTaskSettings, sizeof(struct ExtraTaskSettingsStruct));
|
||||
|
||||
// After loading, some settings may need patching.
|
||||
ExtraTaskSettings.TaskIndex = TaskIndex; // Needed when an empty task was requested
|
||||
if (ExtraTaskSettings.TaskDeviceValueNames[0][0] == 0) {
|
||||
// if field set empty, reload defaults
|
||||
struct EventStruct TempEvent;
|
||||
TempEvent.TaskIndex = TaskIndex;
|
||||
String dummyString;
|
||||
//the plugin call should populate ExtraTaskSettings with its default values.
|
||||
PluginCall(PLUGIN_GET_DEVICEVALUENAMES, &TempEvent, dummyString);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Save Custom Task settings to SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String SaveCustomTaskSettings(int TaskIndex, byte* memAddress, int datasize)
|
||||
{
|
||||
checkRAM(F("SaveCustomTaskSettings"));
|
||||
return(SaveToFile(CustomTaskSettings_Type, TaskIndex, (char*)FILE_CONFIG, memAddress, datasize));
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Clear custom task settings
|
||||
\*********************************************************************************************/
|
||||
String ClearCustomTaskSettings(int TaskIndex)
|
||||
{
|
||||
// addLog(LOG_LEVEL_DEBUG, F("Clearing custom task settings"));
|
||||
return(ClearInFile(CustomTaskSettings_Type, TaskIndex, (char*)FILE_CONFIG));
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Load Custom Task settings to SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String LoadCustomTaskSettings(int TaskIndex, byte* memAddress, int datasize)
|
||||
{
|
||||
checkRAM(F("LoadCustomTaskSettings"));
|
||||
return(LoadFromFile(CustomTaskSettings_Type, TaskIndex, (char*)FILE_CONFIG, memAddress, datasize));
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Save Controller settings to SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String SaveControllerSettings(int ControllerIndex, byte* memAddress, int datasize)
|
||||
{
|
||||
checkRAM(F("SaveControllerSettings"));
|
||||
return SaveToFile(ControllerSettings_Type, ControllerIndex, (char*)FILE_CONFIG, memAddress, datasize);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Load Controller settings to SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String LoadControllerSettings(int ControllerIndex, byte* memAddress, int datasize)
|
||||
{
|
||||
checkRAM(F("LoadControllerSettings"));
|
||||
return(LoadFromFile(ControllerSettings_Type, ControllerIndex, (char*)FILE_CONFIG, memAddress, datasize));
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Clear Custom Controller settings
|
||||
\*********************************************************************************************/
|
||||
String ClearCustomControllerSettings(int ControllerIndex)
|
||||
{
|
||||
checkRAM(F("ClearCustomControllerSettings"));
|
||||
// addLog(LOG_LEVEL_DEBUG, F("Clearing custom controller settings"));
|
||||
return(ClearInFile(CustomControllerSettings_Type, ControllerIndex, (char*)FILE_CONFIG));
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Save Custom Controller settings to SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String SaveCustomControllerSettings(int ControllerIndex,byte* memAddress, int datasize)
|
||||
{
|
||||
checkRAM(F("SaveCustomControllerSettings"));
|
||||
return SaveToFile(CustomControllerSettings_Type, ControllerIndex, (char*)FILE_CONFIG, memAddress, datasize);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Load Custom Controller settings to SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String LoadCustomControllerSettings(int ControllerIndex,byte* memAddress, int datasize)
|
||||
{
|
||||
checkRAM(F("LoadCustomControllerSettings"));
|
||||
return(LoadFromFile(CustomControllerSettings_Type, ControllerIndex, (char*)FILE_CONFIG, memAddress, datasize));
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Save Controller settings to SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String SaveNotificationSettings(int NotificationIndex, byte* memAddress, int datasize)
|
||||
{
|
||||
checkRAM(F("SaveNotificationSettings"));
|
||||
return SaveToFile(NotificationSettings_Type, NotificationIndex, (char*)FILE_NOTIFICATION, memAddress, datasize);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Load Controller settings to SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String LoadNotificationSettings(int NotificationIndex, byte* memAddress, int datasize)
|
||||
{
|
||||
checkRAM(F("LoadNotificationSettings"));
|
||||
return(LoadFromFile(NotificationSettings_Type, NotificationIndex, (char*)FILE_NOTIFICATION, memAddress, datasize));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Init a file with zeros on SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String InitFile(const char* fname, int datasize)
|
||||
{
|
||||
checkRAM(F("InitFile"));
|
||||
FLASH_GUARD();
|
||||
|
||||
fs::File f = SPIFFS.open(fname, "w");
|
||||
SPIFFS_CHECK(f, fname);
|
||||
|
||||
for (int x = 0; x < datasize ; x++)
|
||||
{
|
||||
SPIFFS_CHECK(f.write(0), fname);
|
||||
}
|
||||
f.close();
|
||||
|
||||
//OK
|
||||
return String();
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Save data into config file on SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String SaveToFile(char* fname, int index, byte* memAddress, int datasize)
|
||||
{
|
||||
if (index < 0) {
|
||||
String log = F("SaveToFile: ");
|
||||
log += fname;
|
||||
log += F(" ERROR, invalid position in file");
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
return log;
|
||||
}
|
||||
|
||||
checkRAM(F("SaveToFile"));
|
||||
FLASH_GUARD();
|
||||
|
||||
fs::File f = SPIFFS.open(fname, "r+");
|
||||
SPIFFS_CHECK(f, fname);
|
||||
|
||||
SPIFFS_CHECK(f.seek(index, fs::SeekSet), fname);
|
||||
byte *pointerToByteToSave = memAddress;
|
||||
for (int x = 0; x < datasize ; x++)
|
||||
{
|
||||
SPIFFS_CHECK(f.write(*pointerToByteToSave), fname);
|
||||
pointerToByteToSave++;
|
||||
}
|
||||
f.close();
|
||||
String log = F("FILE : Saved ");
|
||||
log=log+fname;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
//OK
|
||||
return String();
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Clear a certain area in a file (set to 0)
|
||||
\*********************************************************************************************/
|
||||
String ClearInFile(char* fname, int index, int datasize)
|
||||
{
|
||||
if (index < 0) {
|
||||
String log = F("ClearInFile: ");
|
||||
log += fname;
|
||||
log += F(" ERROR, invalid position in file");
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
return log;
|
||||
}
|
||||
|
||||
checkRAM(F("ClearInFile"));
|
||||
FLASH_GUARD();
|
||||
|
||||
fs::File f = SPIFFS.open(fname, "r+");
|
||||
SPIFFS_CHECK(f, fname);
|
||||
|
||||
SPIFFS_CHECK(f.seek(index, fs::SeekSet), fname);
|
||||
for (int x = 0; x < datasize ; x++)
|
||||
{
|
||||
SPIFFS_CHECK(f.write(0), fname);
|
||||
}
|
||||
f.close();
|
||||
|
||||
//OK
|
||||
return String();
|
||||
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Load data from config file on SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String LoadFromFile(char* fname, int offset, byte* memAddress, int datasize)
|
||||
{
|
||||
if (offset < 0) {
|
||||
String log = F("LoadFromFile: ");
|
||||
log += fname;
|
||||
log += F(" ERROR, invalid position in file");
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
return log;
|
||||
}
|
||||
START_TIMER;
|
||||
|
||||
checkRAM(F("LoadFromFile"));
|
||||
|
||||
fs::File f = SPIFFS.open(fname, "r+");
|
||||
SPIFFS_CHECK(f, fname);
|
||||
SPIFFS_CHECK(f.seek(offset, fs::SeekSet), fname);
|
||||
SPIFFS_CHECK(f.read(memAddress,datasize), fname);
|
||||
f.close();
|
||||
|
||||
STOP_TIMER(LOADFILE_STATS);
|
||||
|
||||
return(String());
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Wrapper functions to handle errors in accessing settings
|
||||
\*********************************************************************************************/
|
||||
String getSettingsFileIndexRangeError(bool read, SettingsType settingsType, int index) {
|
||||
if (settingsType >= SettingsType_MAX) {
|
||||
String error = F("Unknown settingsType: ");
|
||||
error += static_cast<int>(settingsType);
|
||||
return error;
|
||||
}
|
||||
String error = read ? F("Load") : F("Save");
|
||||
error += getSettingsTypeString(settingsType);
|
||||
error += F(" index out of range: ");
|
||||
error += index;
|
||||
return error;
|
||||
}
|
||||
|
||||
String getSettingsFileDatasizeError(bool read, SettingsType settingsType, int index, int datasize, int max_size) {
|
||||
String error = read ? F("Load") : F("Save");
|
||||
error += getSettingsTypeString(settingsType);
|
||||
error += '(';
|
||||
error += index;
|
||||
error += F(") datasize(");
|
||||
error += datasize;
|
||||
error += F(") > max_size(");
|
||||
error += max_size;
|
||||
error += ')';
|
||||
return error;
|
||||
}
|
||||
|
||||
String LoadFromFile(SettingsType settingsType, int index, char* fname, byte* memAddress, int datasize) {
|
||||
bool read = true;
|
||||
int offset, max_size;
|
||||
if (!getAndLogSettingsParameters(read, settingsType, index, offset, max_size)) {
|
||||
return getSettingsFileIndexRangeError(read, settingsType, index);
|
||||
}
|
||||
if (datasize > max_size)
|
||||
return getSettingsFileDatasizeError(read, settingsType, index, datasize, max_size);
|
||||
return(LoadFromFile(fname, offset, memAddress, datasize));
|
||||
}
|
||||
|
||||
String SaveToFile(SettingsType settingsType, int index, char* fname, byte* memAddress, int datasize) {
|
||||
bool read = false;
|
||||
int offset, max_size;
|
||||
if (!getAndLogSettingsParameters(read, settingsType, index, offset, max_size)) {
|
||||
return getSettingsFileIndexRangeError(read, settingsType, index);
|
||||
}
|
||||
if (datasize > max_size)
|
||||
return getSettingsFileDatasizeError(read, settingsType, index, datasize, max_size);
|
||||
return(SaveToFile(fname, offset, memAddress, datasize));
|
||||
}
|
||||
|
||||
String ClearInFile(SettingsType settingsType, int index, char* fname) {
|
||||
bool read = false;
|
||||
int offset, max_size;
|
||||
if (!getAndLogSettingsParameters(read, settingsType, index, offset, max_size)) {
|
||||
return getSettingsFileIndexRangeError(read, settingsType, index);
|
||||
}
|
||||
return(ClearInFile(fname, offset, max_size));
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Check SPIFFS area settings
|
||||
\*********************************************************************************************/
|
||||
int SpiffsSectors()
|
||||
{
|
||||
checkRAM(F("SpiffsSectors"));
|
||||
#if defined(ESP8266)
|
||||
uint32_t _sectorStart = ((uint32_t)&_SPIFFS_start - 0x40200000) / SPI_FLASH_SEC_SIZE;
|
||||
uint32_t _sectorEnd = ((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE;
|
||||
return _sectorEnd - _sectorStart;
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
return 32;
|
||||
#endif
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Get partition table information
|
||||
\*********************************************************************************************/
|
||||
#ifdef ESP32
|
||||
String getPartitionType(byte pType, byte pSubType) {
|
||||
esp_partition_type_t partitionType = static_cast<esp_partition_type_t>(pType);
|
||||
esp_partition_subtype_t partitionSubType = static_cast<esp_partition_subtype_t>(pSubType);
|
||||
if (partitionType == ESP_PARTITION_TYPE_APP) {
|
||||
if (partitionSubType >= ESP_PARTITION_SUBTYPE_APP_OTA_MIN &&
|
||||
partitionSubType < ESP_PARTITION_SUBTYPE_APP_OTA_MAX) {
|
||||
String result = F("OTA partition ");
|
||||
result += (partitionSubType - ESP_PARTITION_SUBTYPE_APP_OTA_MIN);
|
||||
return result;
|
||||
}
|
||||
|
||||
switch (partitionSubType) {
|
||||
case ESP_PARTITION_SUBTYPE_APP_FACTORY: return F("Factory app");
|
||||
case ESP_PARTITION_SUBTYPE_APP_TEST: return F("Test app");
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
if (partitionType == ESP_PARTITION_TYPE_DATA) {
|
||||
switch (partitionSubType) {
|
||||
case ESP_PARTITION_SUBTYPE_DATA_OTA: return F("OTA selection");
|
||||
case ESP_PARTITION_SUBTYPE_DATA_PHY: return F("PHY init data");
|
||||
case ESP_PARTITION_SUBTYPE_DATA_NVS: return F("NVS");
|
||||
case ESP_PARTITION_SUBTYPE_DATA_COREDUMP: return F("COREDUMP");
|
||||
case ESP_PARTITION_SUBTYPE_DATA_ESPHTTPD: return F("ESPHTTPD");
|
||||
case ESP_PARTITION_SUBTYPE_DATA_FAT: return F("FAT");
|
||||
case ESP_PARTITION_SUBTYPE_DATA_SPIFFS: return F("SPIFFS");
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
String result = F("Unknown(");
|
||||
result += partitionSubType;
|
||||
result += ')';
|
||||
return result;
|
||||
}
|
||||
|
||||
String getPartitionTableHeader(const String& itemSep, const String& lineEnd) {
|
||||
String result;
|
||||
result += F("Address");
|
||||
result += itemSep;
|
||||
result += F("Size");
|
||||
result += itemSep;
|
||||
result += F("Label");
|
||||
result += itemSep;
|
||||
result += F("Partition Type");
|
||||
result += itemSep;
|
||||
result += F("Encrypted");
|
||||
result += lineEnd;
|
||||
return result;
|
||||
}
|
||||
|
||||
String getPartitionTable(byte pType, const String& itemSep, const String& lineEnd) {
|
||||
esp_partition_type_t partitionType = static_cast<esp_partition_type_t>(pType);
|
||||
String result;
|
||||
const esp_partition_t * _mypart;
|
||||
esp_partition_iterator_t _mypartiterator = esp_partition_find(partitionType, ESP_PARTITION_SUBTYPE_ANY, NULL);
|
||||
if (_mypartiterator) {
|
||||
do {
|
||||
_mypart = esp_partition_get(_mypartiterator);
|
||||
result += formatToHex(_mypart->address);
|
||||
result += itemSep;
|
||||
result += formatToHex_decimal(_mypart->size, 1024);
|
||||
result += itemSep;
|
||||
result += _mypart->label;
|
||||
result += itemSep;
|
||||
result += getPartitionType(_mypart->type, _mypart->subtype);
|
||||
result += itemSep;
|
||||
result += (_mypart->encrypted ? F("Yes") : F("-"));
|
||||
result += lineEnd;
|
||||
} while ((_mypartiterator = esp_partition_next(_mypartiterator)) != NULL);
|
||||
}
|
||||
esp_partition_iterator_release(_mypartiterator);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
+43
-622
@@ -133,8 +133,8 @@ int8_t getTaskIndexByName(String TaskNameSearch)
|
||||
for (byte x = 0; x < TASKS_MAX; x++)
|
||||
{
|
||||
LoadTaskSettings(x);
|
||||
String TaskName = ExtraTaskSettings.TaskDeviceName;
|
||||
if ((ExtraTaskSettings.TaskDeviceName[0] != 0 ) && (TaskNameSearch.equalsIgnoreCase(TaskName)))
|
||||
String TaskName = getTaskDeviceName(x);
|
||||
if ((TaskName.length() != 0 ) && (TaskNameSearch.equalsIgnoreCase(TaskName)))
|
||||
{
|
||||
return x;
|
||||
}
|
||||
@@ -143,30 +143,6 @@ int8_t getTaskIndexByName(String TaskNameSearch)
|
||||
}
|
||||
|
||||
|
||||
void flashCount()
|
||||
{
|
||||
if (RTC.flashDayCounter <= MAX_FLASHWRITES_PER_DAY)
|
||||
RTC.flashDayCounter++;
|
||||
RTC.flashCounter++;
|
||||
saveToRTC();
|
||||
}
|
||||
|
||||
String flashGuard()
|
||||
{
|
||||
checkRAM(F("flashGuard"));
|
||||
if (RTC.flashDayCounter > MAX_FLASHWRITES_PER_DAY)
|
||||
{
|
||||
String log = F("FS : Daily flash write rate exceeded! (powercycle to reset this)");
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
return log;
|
||||
}
|
||||
flashCount();
|
||||
return(String());
|
||||
}
|
||||
|
||||
//use this in function that can return an error string. it automaticly returns with an error string if there where too many flash writes.
|
||||
#define FLASH_GUARD() { String flashErr=flashGuard(); if (flashErr.length()) return(flashErr); }
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
set pin mode & state (info table)
|
||||
@@ -402,145 +378,49 @@ void parseCommandString(struct EventStruct *event, const String& string)
|
||||
void taskClear(byte taskIndex, boolean save)
|
||||
{
|
||||
checkRAM(F("taskClear"));
|
||||
Settings.TaskDeviceNumber[taskIndex] = 0;
|
||||
ExtraTaskSettings.TaskDeviceName[0] = 0;
|
||||
Settings.TaskDeviceDataFeed[taskIndex] = 0;
|
||||
Settings.TaskDevicePin1[taskIndex] = -1;
|
||||
Settings.TaskDevicePin2[taskIndex] = -1;
|
||||
Settings.TaskDevicePin3[taskIndex] = -1;
|
||||
Settings.TaskDevicePort[taskIndex] = 0;
|
||||
Settings.TaskDeviceGlobalSync[taskIndex] = false;
|
||||
Settings.TaskDeviceTimer[taskIndex] = 0;
|
||||
Settings.TaskDeviceEnabled[taskIndex] = false;
|
||||
|
||||
for (byte controllerNr = 0; controllerNr < CONTROLLER_MAX; controllerNr++)
|
||||
{
|
||||
Settings.TaskDeviceID[controllerNr][taskIndex] = 0;
|
||||
Settings.TaskDeviceSendData[controllerNr][taskIndex] = true;
|
||||
}
|
||||
|
||||
for (byte x = 0; x < PLUGIN_CONFIGVAR_MAX; x++)
|
||||
Settings.TaskDevicePluginConfig[taskIndex][x] = 0;
|
||||
|
||||
for (byte varNr = 0; varNr < VARS_PER_TASK; varNr++)
|
||||
{
|
||||
ExtraTaskSettings.TaskDeviceFormula[varNr][0] = 0;
|
||||
ExtraTaskSettings.TaskDeviceValueNames[varNr][0] = 0;
|
||||
ExtraTaskSettings.TaskDeviceValueDecimals[varNr] = 2;
|
||||
}
|
||||
|
||||
for (byte varNr = 0; varNr < PLUGIN_EXTRACONFIGVAR_MAX; varNr++)
|
||||
{
|
||||
ExtraTaskSettings.TaskDevicePluginConfigLong[varNr] = 0;
|
||||
ExtraTaskSettings.TaskDevicePluginConfig[varNr] = 0;
|
||||
}
|
||||
|
||||
if (save)
|
||||
{
|
||||
Settings.clearTask(taskIndex);
|
||||
ExtraTaskSettings.clear(); // Invalidate any cached values.
|
||||
ExtraTaskSettings.TaskIndex = taskIndex;
|
||||
if (save) {
|
||||
SaveTaskSettings(taskIndex);
|
||||
SaveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
SPIFFS error handling
|
||||
Look here for error # reference: https://github.com/pellepl/spiffs/blob/master/src/spiffs.h
|
||||
\*********************************************************************************************/
|
||||
#define SPIFFS_CHECK(result, fname) if (!(result)) { return(FileError(__LINE__, fname)); }
|
||||
String FileError(int line, const char * fname)
|
||||
{
|
||||
String err = F("FS : Error while reading/writing ");
|
||||
err += fname;
|
||||
err += F(" in ");
|
||||
err += line;
|
||||
addLog(LOG_LEVEL_ERROR, err);
|
||||
return(err);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Fix stuff to clear out differences between releases
|
||||
\*********************************************************************************************/
|
||||
String BuildFixes()
|
||||
{
|
||||
checkRAM(F("BuildFixes"));
|
||||
Serial.println(F("\nBuild changed!"));
|
||||
|
||||
if (Settings.Build < 145)
|
||||
{
|
||||
String fname=F(FILE_NOTIFICATION);
|
||||
fs::File f = SPIFFS.open(fname, "w");
|
||||
SPIFFS_CHECK(f, fname.c_str());
|
||||
|
||||
if (f)
|
||||
{
|
||||
for (int x = 0; x < 4096; x++)
|
||||
{
|
||||
SPIFFS_CHECK(f.write(0), fname.c_str());
|
||||
String checkTaskSettings(byte taskIndex) {
|
||||
String err = LoadTaskSettings(taskIndex);
|
||||
if (err.length() > 0) return err;
|
||||
if (!ExtraTaskSettings.checkUniqueValueNames()) {
|
||||
return F("Use unique value names");
|
||||
}
|
||||
if (!ExtraTaskSettings.checkInvalidCharInNames()) {
|
||||
return F("Invalid character in names. Do not use ',#[]' or space.");
|
||||
}
|
||||
String deviceName = ExtraTaskSettings.TaskDeviceName;
|
||||
if (deviceName.length() == 0) {
|
||||
if (Settings.TaskDeviceEnabled[taskIndex]) {
|
||||
// Decide what to do here, for now give a warning when task is enabled.
|
||||
return F("Warning: Task Device Name is empty. It is adviced to give tasks an unique name");
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < TASKS_MAX; ++i) {
|
||||
if (i != taskIndex) {
|
||||
LoadTaskSettings(i);
|
||||
if (ExtraTaskSettings.TaskDeviceName[0] != 0) {
|
||||
if (strcasecmp(ExtraTaskSettings.TaskDeviceName, deviceName.c_str()) == 0) {
|
||||
err = F("Task Device Name is not unique, conflicts with task ID #");
|
||||
err += (i+1);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
f.close();
|
||||
}
|
||||
}
|
||||
|
||||
if (Settings.Build < 20101)
|
||||
{
|
||||
Serial.println(F("Fix reset Pin"));
|
||||
Settings.Pin_Reset = -1;
|
||||
}
|
||||
if (Settings.Build < 20102) {
|
||||
// Settings were 'mangled' by using older version
|
||||
// Have to patch settings to make sure no bogus data is being used.
|
||||
Serial.println(F("Fix settings with uninitalized data or corrupted by switching between versions"));
|
||||
Settings.UseRTOSMultitasking = false;
|
||||
Settings.Pin_Reset = -1;
|
||||
Settings.SyslogFacility = DEFAULT_SYSLOG_FACILITY;
|
||||
Settings.MQTTUseUnitNameAsClientId = DEFAULT_MQTT_USE_UNITNANE_AS_CLIENTID;
|
||||
Settings.StructSize = sizeof(Settings);
|
||||
}
|
||||
|
||||
Settings.Build = BUILD;
|
||||
return(SaveSettings());
|
||||
err = LoadTaskSettings(taskIndex);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Mount FS and check config.dat
|
||||
\*********************************************************************************************/
|
||||
void fileSystemCheck()
|
||||
{
|
||||
checkRAM(F("fileSystemCheck"));
|
||||
addLog(LOG_LEVEL_INFO, F("FS : Mounting..."));
|
||||
if (SPIFFS.begin())
|
||||
{
|
||||
#if defined(ESP8266)
|
||||
fs::FSInfo fs_info;
|
||||
SPIFFS.info(fs_info);
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
String log = F("FS : Mount successful, used ");
|
||||
log=log+fs_info.usedBytes;
|
||||
log=log+F(" bytes of ");
|
||||
log=log+fs_info.totalBytes;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
#endif
|
||||
|
||||
fs::File f = SPIFFS.open(FILE_CONFIG, "r");
|
||||
if (!f)
|
||||
{
|
||||
ResetFactory();
|
||||
}
|
||||
f.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
String log = F("FS : Mount failed");
|
||||
Serial.println(log);
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
ResetFactory();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Find device index corresponding to task number setting
|
||||
@@ -723,394 +603,12 @@ uint32_t progMemMD5check(){
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Save settings to SPIFFS
|
||||
Handler for keeping ExtraTaskSettings up to date using cache
|
||||
\*********************************************************************************************/
|
||||
String SaveSettings(void)
|
||||
{
|
||||
checkRAM(F("SaveSettings"));
|
||||
MD5Builder md5;
|
||||
uint8_t tmp_md5[16] = {0};
|
||||
String err;
|
||||
|
||||
Settings.StructSize = sizeof(struct SettingsStruct);
|
||||
|
||||
// FIXME @TD-er: As discussed in #1292, the CRC for the settings is now disabled.
|
||||
/*
|
||||
memcpy( Settings.ProgmemMd5, CRCValues.runTimeMD5, 16);
|
||||
md5.begin();
|
||||
md5.add((uint8_t *)&Settings, sizeof(Settings)-16);
|
||||
md5.calculate();
|
||||
md5.getBytes(tmp_md5);
|
||||
if (memcmp(tmp_md5, Settings.md5, 16) != 0) {
|
||||
// Settings have changed, save to file.
|
||||
memcpy(Settings.md5, tmp_md5, 16);
|
||||
*/
|
||||
err=SaveToFile((char*)FILE_CONFIG, 0, (byte*)&Settings, sizeof(Settings));
|
||||
if (err.length())
|
||||
return(err);
|
||||
// }
|
||||
|
||||
memcpy( SecuritySettings.ProgmemMd5, CRCValues.runTimeMD5, 16);
|
||||
md5.begin();
|
||||
md5.add((uint8_t *)&SecuritySettings, sizeof(SecuritySettings)-16);
|
||||
md5.calculate();
|
||||
md5.getBytes(tmp_md5);
|
||||
if (memcmp(tmp_md5, SecuritySettings.md5, 16) != 0) {
|
||||
// Settings have changed, save to file.
|
||||
memcpy(SecuritySettings.md5, tmp_md5, 16);
|
||||
err=SaveToFile((char*)FILE_SECURITY, 0, (byte*)&SecuritySettings, sizeof(SecuritySettings));
|
||||
if (WifiIsAP(WiFi.getMode())) {
|
||||
// Security settings are saved, may be update of WiFi settings or hostname.
|
||||
wifiSetupConnect = true;
|
||||
}
|
||||
}
|
||||
return (err);
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Load settings from SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String LoadSettings()
|
||||
{
|
||||
checkRAM(F("LoadSettings"));
|
||||
String err;
|
||||
uint8_t calculatedMd5[16];
|
||||
MD5Builder md5;
|
||||
|
||||
err=LoadFromFile((char*)FILE_CONFIG, 0, (byte*)&Settings, sizeof( SettingsStruct));
|
||||
if (err.length())
|
||||
return(err);
|
||||
|
||||
// FIXME @TD-er: As discussed in #1292, the CRC for the settings is now disabled.
|
||||
/*
|
||||
if (Settings.StructSize > 16) {
|
||||
md5.begin();
|
||||
md5.add((uint8_t *)&Settings, Settings.StructSize -16);
|
||||
md5.calculate();
|
||||
md5.getBytes(calculatedMd5);
|
||||
}
|
||||
if (memcmp (calculatedMd5, Settings.md5,16)==0){
|
||||
addLog(LOG_LEVEL_INFO, F("CRC : Settings CRC ...OK"));
|
||||
if (memcmp(Settings.ProgmemMd5, CRCValues.runTimeMD5, 16)!=0)
|
||||
addLog(LOG_LEVEL_INFO, F("CRC : binary has changed since last save of Settings"));
|
||||
}
|
||||
else{
|
||||
addLog(LOG_LEVEL_ERROR, F("CRC : Settings CRC ...FAIL"));
|
||||
}
|
||||
*/
|
||||
|
||||
err=LoadFromFile((char*)FILE_SECURITY, 0, (byte*)&SecuritySettings, sizeof( SecurityStruct));
|
||||
md5.begin();
|
||||
md5.add((uint8_t *)&SecuritySettings, sizeof(SecuritySettings)-16);
|
||||
md5.calculate();
|
||||
md5.getBytes(calculatedMd5);
|
||||
if (memcmp (calculatedMd5, SecuritySettings.md5, 16)==0){
|
||||
addLog(LOG_LEVEL_INFO, F("CRC : SecuritySettings CRC ...OK "));
|
||||
if (memcmp(SecuritySettings.ProgmemMd5,CRCValues.runTimeMD5, 16)!=0)
|
||||
addLog(LOG_LEVEL_INFO, F("CRC : binary has changed since last save of Settings"));
|
||||
}
|
||||
else{
|
||||
addLog(LOG_LEVEL_ERROR, F("CRC : SecuritySettings CRC ...FAIL"));
|
||||
}
|
||||
setUseStaticIP(useStaticIP());
|
||||
return(err);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Save Task settings to SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String SaveTaskSettings(byte TaskIndex)
|
||||
{
|
||||
checkRAM(F("SaveTaskSettings"));
|
||||
if (DAT_TASKS_SIZE < sizeof(struct ExtraTaskSettingsStruct))
|
||||
return F("SaveTaskSettings too big");
|
||||
if (TaskIndex >= TASKS_MAX)
|
||||
return F("SaveTaskSettings TaskIndex too big");
|
||||
|
||||
ExtraTaskSettings.TaskIndex = TaskIndex;
|
||||
return(SaveToFile((char*)FILE_CONFIG, DAT_OFFSET_TASKS + (TaskIndex * DAT_TASKS_SIZE), (byte*)&ExtraTaskSettings, sizeof(struct ExtraTaskSettingsStruct)));
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Load Task settings from SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String LoadTaskSettings(byte TaskIndex)
|
||||
{
|
||||
checkRAM(F("LoadTaskSettings"));
|
||||
//already loaded
|
||||
if (ExtraTaskSettings.TaskIndex == TaskIndex)
|
||||
return(String());
|
||||
if (TaskIndex >= TASKS_MAX)
|
||||
return F("LoadTaskSettings TaskIndex too big");
|
||||
|
||||
String result = "";
|
||||
result = LoadFromFile((char*)FILE_CONFIG, DAT_OFFSET_TASKS + (TaskIndex * DAT_TASKS_SIZE), (byte*)&ExtraTaskSettings, sizeof(struct ExtraTaskSettingsStruct));
|
||||
ExtraTaskSettings.TaskIndex = TaskIndex; // Needed when an empty task was requested
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Save Custom Task settings to SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String SaveCustomTaskSettings(int TaskIndex, byte* memAddress, int datasize)
|
||||
{
|
||||
checkRAM(F("SaveCustomTaskSettings"));
|
||||
if (datasize > DAT_TASKS_SIZE)
|
||||
return F("SaveCustomTaskSettings too big");
|
||||
if (TaskIndex >= TASKS_MAX)
|
||||
return F("SaveCustomTaskSettings TaskIndex too big");
|
||||
|
||||
return(SaveToFile((char*)FILE_CONFIG, DAT_OFFSET_TASKS + (TaskIndex * DAT_TASKS_SIZE) + DAT_TASKS_CUSTOM_OFFSET, memAddress, datasize));
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Clear custom task settings
|
||||
\*********************************************************************************************/
|
||||
String ClearCustomTaskSettings(int TaskIndex)
|
||||
{
|
||||
// addLog(LOG_LEVEL_DEBUG, F("Clearing custom task settings"));
|
||||
if (TaskIndex >= TASKS_MAX)
|
||||
return F("ClearCustomTaskSettings TaskIndex too big");
|
||||
return(ClearInFile((char*)FILE_CONFIG, DAT_OFFSET_TASKS + (TaskIndex * DAT_TASKS_SIZE) + DAT_TASKS_CUSTOM_OFFSET, DAT_TASKS_CUSTOM_SIZE));
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Load Custom Task settings to SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String LoadCustomTaskSettings(int TaskIndex, byte* memAddress, int datasize)
|
||||
{
|
||||
checkRAM(F("LoadCustomTaskSettings"));
|
||||
if (datasize > DAT_TASKS_SIZE)
|
||||
return (String(F("LoadCustomTaskSettings too big")));
|
||||
if (TaskIndex >= TASKS_MAX)
|
||||
return F("LoadCustomTaskSettings TaskIndex too big");
|
||||
|
||||
return(LoadFromFile((char*)FILE_CONFIG, DAT_OFFSET_TASKS + (TaskIndex * DAT_TASKS_SIZE) + DAT_TASKS_CUSTOM_OFFSET, memAddress, datasize));
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Save Controller settings to SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String SaveControllerSettings(int ControllerIndex, byte* memAddress, int datasize)
|
||||
{
|
||||
checkRAM(F("SaveControllerSettings"));
|
||||
if (datasize > DAT_CONTROLLER_SIZE)
|
||||
return F("SaveControllerSettings too big");
|
||||
return SaveToFile((char*)FILE_CONFIG, DAT_OFFSET_CONTROLLER + (ControllerIndex * DAT_CONTROLLER_SIZE), memAddress, datasize);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Load Controller settings to SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String LoadControllerSettings(int ControllerIndex, byte* memAddress, int datasize)
|
||||
{
|
||||
checkRAM(F("LoadControllerSettings"));
|
||||
if (datasize > DAT_CONTROLLER_SIZE)
|
||||
return F("LoadControllerSettings too big");
|
||||
|
||||
return(LoadFromFile((char*)FILE_CONFIG, DAT_OFFSET_CONTROLLER + (ControllerIndex * DAT_CONTROLLER_SIZE), memAddress, datasize));
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Clear Custom Controller settings
|
||||
\*********************************************************************************************/
|
||||
String ClearCustomControllerSettings(int ControllerIndex)
|
||||
{
|
||||
checkRAM(F("ClearCustomControllerSettings"));
|
||||
// addLog(LOG_LEVEL_DEBUG, F("Clearing custom controller settings"));
|
||||
return(ClearInFile((char*)FILE_CONFIG, DAT_OFFSET_CUSTOM_CONTROLLER + (ControllerIndex * DAT_CUSTOM_CONTROLLER_SIZE), DAT_CUSTOM_CONTROLLER_SIZE));
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Save Custom Controller settings to SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String SaveCustomControllerSettings(int ControllerIndex,byte* memAddress, int datasize)
|
||||
{
|
||||
checkRAM(F("SaveCustomControllerSettings"));
|
||||
if (datasize > DAT_CUSTOM_CONTROLLER_SIZE)
|
||||
return F("SaveCustomControllerSettings too big");
|
||||
return SaveToFile((char*)FILE_CONFIG, DAT_OFFSET_CUSTOM_CONTROLLER + (ControllerIndex * DAT_CUSTOM_CONTROLLER_SIZE), memAddress, datasize);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Load Custom Controller settings to SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String LoadCustomControllerSettings(int ControllerIndex,byte* memAddress, int datasize)
|
||||
{
|
||||
checkRAM(F("LoadCustomControllerSettings"));
|
||||
if (datasize > DAT_CUSTOM_CONTROLLER_SIZE)
|
||||
return(F("LoadCustomControllerSettings too big"));
|
||||
return(LoadFromFile((char*)FILE_CONFIG, DAT_OFFSET_CUSTOM_CONTROLLER + (ControllerIndex * DAT_CUSTOM_CONTROLLER_SIZE), memAddress, datasize));
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Save Controller settings to SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String SaveNotificationSettings(int NotificationIndex, byte* memAddress, int datasize)
|
||||
{
|
||||
checkRAM(F("SaveNotificationSettings"));
|
||||
if (datasize > DAT_NOTIFICATION_SIZE)
|
||||
return F("SaveNotificationSettings too big");
|
||||
return SaveToFile((char*)FILE_NOTIFICATION, NotificationIndex * DAT_NOTIFICATION_SIZE, memAddress, datasize);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Load Controller settings to SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String LoadNotificationSettings(int NotificationIndex, byte* memAddress, int datasize)
|
||||
{
|
||||
checkRAM(F("LoadNotificationSettings"));
|
||||
if (datasize > DAT_NOTIFICATION_SIZE)
|
||||
return(F("LoadNotificationSettings too big"));
|
||||
return(LoadFromFile((char*)FILE_NOTIFICATION, NotificationIndex * DAT_NOTIFICATION_SIZE, memAddress, datasize));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Init a file with zeros on SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String InitFile(const char* fname, int datasize)
|
||||
{
|
||||
checkRAM(F("InitFile"));
|
||||
FLASH_GUARD();
|
||||
|
||||
fs::File f = SPIFFS.open(fname, "w");
|
||||
SPIFFS_CHECK(f, fname);
|
||||
|
||||
for (int x = 0; x < datasize ; x++)
|
||||
{
|
||||
SPIFFS_CHECK(f.write(0), fname);
|
||||
}
|
||||
f.close();
|
||||
|
||||
//OK
|
||||
return String();
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Save data into config file on SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String SaveToFile(char* fname, int index, byte* memAddress, int datasize)
|
||||
{
|
||||
checkRAM(F("SaveToFile"));
|
||||
FLASH_GUARD();
|
||||
String log = F("SaveToFile: ");
|
||||
log += fname;
|
||||
log += F(" index: ");
|
||||
log += index;
|
||||
log += F(" datasize: ");
|
||||
log += datasize;
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
fs::File f = SPIFFS.open(fname, "r+");
|
||||
SPIFFS_CHECK(f, fname);
|
||||
|
||||
SPIFFS_CHECK(f.seek(index, fs::SeekSet), fname);
|
||||
byte *pointerToByteToSave = memAddress;
|
||||
for (int x = 0; x < datasize ; x++)
|
||||
{
|
||||
SPIFFS_CHECK(f.write(*pointerToByteToSave), fname);
|
||||
pointerToByteToSave++;
|
||||
}
|
||||
f.close();
|
||||
log = F("FILE : Saved ");
|
||||
log=log+fname;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
//OK
|
||||
return String();
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Clear a certain area in a file (set to 0)
|
||||
\*********************************************************************************************/
|
||||
String ClearInFile(char* fname, int index, int datasize)
|
||||
{
|
||||
checkRAM(F("ClearInFile"));
|
||||
FLASH_GUARD();
|
||||
|
||||
String log = F("ClearInFile: ");
|
||||
log += fname;
|
||||
log += F(" index: ");
|
||||
log += index;
|
||||
log += F(" datasize: ");
|
||||
log += datasize;
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
|
||||
fs::File f = SPIFFS.open(fname, "r+");
|
||||
SPIFFS_CHECK(f, fname);
|
||||
|
||||
SPIFFS_CHECK(f.seek(index, fs::SeekSet), fname);
|
||||
for (int x = 0; x < datasize ; x++)
|
||||
{
|
||||
SPIFFS_CHECK(f.write(0), fname);
|
||||
}
|
||||
f.close();
|
||||
|
||||
//OK
|
||||
return String();
|
||||
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
Load data from config file on SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String LoadFromFile(char* fname, int index, byte* memAddress, int datasize)
|
||||
{
|
||||
START_TIMER;
|
||||
|
||||
checkRAM(F("LoadFromFile"));
|
||||
if (loglevelActiveFor(LOG_LEVEL_DEBUG_DEV)) {
|
||||
String log = F("LoadFromFile: ");
|
||||
log += fname;
|
||||
log += F(" index: ");
|
||||
log += index;
|
||||
log += F(" datasize: ");
|
||||
log += datasize;
|
||||
addLog(LOG_LEVEL_DEBUG_DEV, log);
|
||||
}
|
||||
|
||||
fs::File f = SPIFFS.open(fname, "r+");
|
||||
SPIFFS_CHECK(f, fname);
|
||||
SPIFFS_CHECK(f.seek(index, fs::SeekSet), fname);
|
||||
SPIFFS_CHECK(f.read(memAddress,datasize), fname);
|
||||
f.close();
|
||||
|
||||
STOP_TIMER(LOADFILE_STATS);
|
||||
|
||||
return(String());
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Check SPIFFS area settings
|
||||
\*********************************************************************************************/
|
||||
int SpiffsSectors()
|
||||
{
|
||||
checkRAM(F("SpiffsSectors"));
|
||||
#if defined(ESP8266)
|
||||
uint32_t _sectorStart = ((uint32_t)&_SPIFFS_start - 0x40200000) / SPI_FLASH_SEC_SIZE;
|
||||
uint32_t _sectorEnd = ((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE;
|
||||
return _sectorEnd - _sectorStart;
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
return 32;
|
||||
#endif
|
||||
String getTaskDeviceName(byte TaskIndex) {
|
||||
LoadTaskSettings(TaskIndex);
|
||||
return ExtraTaskSettings.TaskDeviceName;
|
||||
}
|
||||
|
||||
|
||||
@@ -1171,7 +669,7 @@ void ResetFactory(void)
|
||||
fname=FILE_RULES;
|
||||
InitFile(fname.c_str(), 0);
|
||||
|
||||
LoadSettings();
|
||||
Settings.clearAll();
|
||||
// now we set all parameters that need to be non-zero as default value
|
||||
|
||||
#if DEFAULT_USE_STATIC_IP
|
||||
@@ -1445,84 +943,6 @@ String getLWIPversion() {
|
||||
#endif
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Get partition table information
|
||||
\*********************************************************************************************/
|
||||
#ifdef ESP32
|
||||
String getPartitionType(byte pType, byte pSubType) {
|
||||
esp_partition_type_t partitionType = static_cast<esp_partition_type_t>(pType);
|
||||
esp_partition_subtype_t partitionSubType = static_cast<esp_partition_subtype_t>(pSubType);
|
||||
if (partitionType == ESP_PARTITION_TYPE_APP) {
|
||||
if (partitionSubType >= ESP_PARTITION_SUBTYPE_APP_OTA_MIN &&
|
||||
partitionSubType < ESP_PARTITION_SUBTYPE_APP_OTA_MAX) {
|
||||
String result = F("OTA partition ");
|
||||
result += (partitionSubType - ESP_PARTITION_SUBTYPE_APP_OTA_MIN);
|
||||
return result;
|
||||
}
|
||||
|
||||
switch (partitionSubType) {
|
||||
case ESP_PARTITION_SUBTYPE_APP_FACTORY: return F("Factory app");
|
||||
case ESP_PARTITION_SUBTYPE_APP_TEST: return F("Test app");
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
if (partitionType == ESP_PARTITION_TYPE_DATA) {
|
||||
switch (partitionSubType) {
|
||||
case ESP_PARTITION_SUBTYPE_DATA_OTA: return F("OTA selection");
|
||||
case ESP_PARTITION_SUBTYPE_DATA_PHY: return F("PHY init data");
|
||||
case ESP_PARTITION_SUBTYPE_DATA_NVS: return F("NVS");
|
||||
case ESP_PARTITION_SUBTYPE_DATA_COREDUMP: return F("COREDUMP");
|
||||
case ESP_PARTITION_SUBTYPE_DATA_ESPHTTPD: return F("ESPHTTPD");
|
||||
case ESP_PARTITION_SUBTYPE_DATA_FAT: return F("FAT");
|
||||
case ESP_PARTITION_SUBTYPE_DATA_SPIFFS: return F("SPIFFS");
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
String result = F("Unknown(");
|
||||
result += partitionSubType;
|
||||
result += ')';
|
||||
return result;
|
||||
}
|
||||
|
||||
String getPartitionTableHeader(const String& itemSep, const String& lineEnd) {
|
||||
String result;
|
||||
result += F("Address");
|
||||
result += itemSep;
|
||||
result += F("Size");
|
||||
result += itemSep;
|
||||
result += F("Label");
|
||||
result += itemSep;
|
||||
result += F("Partition Type");
|
||||
result += itemSep;
|
||||
result += F("Encrypted");
|
||||
result += lineEnd;
|
||||
return result;
|
||||
}
|
||||
|
||||
String getPartitionTable(byte pType, const String& itemSep, const String& lineEnd) {
|
||||
esp_partition_type_t partitionType = static_cast<esp_partition_type_t>(pType);
|
||||
String result;
|
||||
const esp_partition_t * _mypart;
|
||||
esp_partition_iterator_t _mypartiterator = esp_partition_find(partitionType, ESP_PARTITION_SUBTYPE_ANY, NULL);
|
||||
if (_mypartiterator) {
|
||||
do {
|
||||
_mypart = esp_partition_get(_mypartiterator);
|
||||
result += formatToHex(_mypart->address);
|
||||
result += itemSep;
|
||||
result += formatToHex_decimal(_mypart->size, 1024);
|
||||
result += itemSep;
|
||||
result += _mypart->label;
|
||||
result += itemSep;
|
||||
result += getPartitionType(_mypart->type, _mypart->subtype);
|
||||
result += itemSep;
|
||||
result += (_mypart->encrypted ? F("Yes") : F("-"));
|
||||
result += lineEnd;
|
||||
} while ((_mypartiterator = esp_partition_next(_mypartiterator)) != NULL);
|
||||
}
|
||||
esp_partition_iterator_release(_mypartiterator);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
@@ -1946,9 +1366,10 @@ String parseTemplate(String &tmpString, byte lineSize)
|
||||
if (Settings.TaskDeviceEnabled[y])
|
||||
{
|
||||
LoadTaskSettings(y);
|
||||
if (ExtraTaskSettings.TaskDeviceName[0] != 0)
|
||||
String taskDeviceName = getTaskDeviceName(y);
|
||||
if (taskDeviceName.length() != 0)
|
||||
{
|
||||
if (deviceName.equalsIgnoreCase(ExtraTaskSettings.TaskDeviceName))
|
||||
if (deviceName.equalsIgnoreCase(taskDeviceName))
|
||||
{
|
||||
boolean match = false;
|
||||
for (byte z = 0; z < VARS_PER_TASK; z++)
|
||||
@@ -3089,7 +2510,7 @@ void createRuleEvents(byte TaskIndex)
|
||||
byte sensorType = Device[DeviceIndex].VType;
|
||||
for (byte varNr = 0; varNr < Device[DeviceIndex].ValueCount; varNr++)
|
||||
{
|
||||
String eventString = ExtraTaskSettings.TaskDeviceName;
|
||||
String eventString = getTaskDeviceName(TaskIndex);
|
||||
eventString += F("#");
|
||||
eventString += ExtraTaskSettings.TaskDeviceValueNames[varNr];
|
||||
eventString += F("=");
|
||||
@@ -3123,7 +2544,7 @@ void SendValueLogger(byte TaskIndex)
|
||||
logger += F(",");
|
||||
logger += Settings.Unit;
|
||||
logger += F(",");
|
||||
logger += ExtraTaskSettings.TaskDeviceName;
|
||||
logger += getTaskDeviceName(TaskIndex);
|
||||
logger += F(",");
|
||||
logger += ExtraTaskSettings.TaskDeviceValueNames[varNr];
|
||||
logger += F(",");
|
||||
|
||||
@@ -477,6 +477,8 @@ void parseSystemVariables(String& s, boolean useURLencode)
|
||||
repl(F("%CR%"), F("\r"), s, useURLencode);
|
||||
repl(F("%LF%"), F("\n"), s, useURLencode);
|
||||
repl(F("%SP%"), F(" "), s, useURLencode); //space
|
||||
repl(F("%R%"), F("\\r"), s, useURLencode);
|
||||
repl(F("%N%"), F("\\n"), s, useURLencode);
|
||||
SMART_REPL(F("%ip4%"),WiFi.localIP().toString().substring(WiFi.localIP().toString().lastIndexOf('.')+1)) //4th IP octet
|
||||
SMART_REPL(F("%ip%"),WiFi.localIP().toString())
|
||||
SMART_REPL(F("%rssi%"), String((wifiStatus == ESPEASY_WIFI_DISCONNECTED) ? 0 : WiFi.RSSI()))
|
||||
@@ -520,6 +522,7 @@ void parseSystemVariables(String& s, boolean useURLencode)
|
||||
SMART_REPL_T(F("%sunset"), replSunSetTimeString)
|
||||
SMART_REPL_T(F("%sunrise"), replSunRiseTimeString)
|
||||
|
||||
// FIXME TD-er: Must make sure LoadTaskSettings has been performed before this is called.
|
||||
repl(F("%tskname%"), ExtraTaskSettings.TaskDeviceName, s, useURLencode);
|
||||
if (s.indexOf(F("%vname")) != -1) {
|
||||
repl(F("%vname1%"), ExtraTaskSettings.TaskDeviceValueNames[0], s, useURLencode);
|
||||
|
||||
+27
-13
@@ -427,7 +427,13 @@ bool isFormItem(const String& id)
|
||||
void addHtmlError(String error){
|
||||
if (error.length()>0)
|
||||
{
|
||||
TXBuffer += F("<div class=\"alert\"><span class=\"closebtn\" onclick=\"this.parentElement.style.display='none';\">×</span>");
|
||||
TXBuffer += F("<div class=\"");
|
||||
if (error.startsWith(F("Warn"))) {
|
||||
TXBuffer += F("warning");
|
||||
} else {
|
||||
TXBuffer += F("alert");
|
||||
}
|
||||
TXBuffer += F("\"><span class=\"closebtn\" onclick=\"this.parentElement.style.display='none';\">×</span>");
|
||||
TXBuffer += error;
|
||||
TXBuffer += F("</div>");
|
||||
}
|
||||
@@ -1821,12 +1827,15 @@ void handle_devices() {
|
||||
}
|
||||
const int edit = getFormItemInt(F("edit"), 0);
|
||||
|
||||
// taskIndex in the URL is 1 ... TASKS_MAX
|
||||
// For use in other functions, set it to 0 ... (TASKS_MAX - 1)
|
||||
byte taskIndex = getFormItemInt(F("index"), 0);
|
||||
boolean taskIndexNotSet = taskIndex == 0;
|
||||
--taskIndex;
|
||||
|
||||
byte DeviceIndex = 0;
|
||||
|
||||
LoadTaskSettings(taskIndex); // Make sure ExtraTaskSettings are up-to-date
|
||||
// FIXME TD-er: Might have to clear any caches here.
|
||||
if (edit != 0 && !taskIndexNotSet) // when form submitted
|
||||
{
|
||||
if (Settings.TaskDeviceNumber[taskIndex] != taskdevicenumber) // change of device: cleanup old device and reset default settings
|
||||
@@ -1844,7 +1853,7 @@ void handle_devices() {
|
||||
if (ExtraTaskSettings.TaskDeviceValueNames[0][0] == 0) // if field set empty, reload defaults
|
||||
PluginCall(PLUGIN_GET_DEVICEVALUENAMES, &TempEvent, dummyString); //the plugin should populate ExtraTaskSettings with its default values.
|
||||
|
||||
ClearCustomTaskSettings(taskIndex);
|
||||
ClearCustomTaskSettings(taskIndex);
|
||||
}
|
||||
}
|
||||
else if (taskdevicenumber != 0) //save settings
|
||||
@@ -2121,13 +2130,16 @@ void handle_devices() {
|
||||
addFormNote(F("This plugin is only supported on task 1-4 for now"));
|
||||
}
|
||||
|
||||
addFormTextBox( F("Name"), F("TDN"), ExtraTaskSettings.TaskDeviceName, 40); //="taskdevicename"
|
||||
addFormTextBox( F("Name"), F("TDN"), ExtraTaskSettings.TaskDeviceName, NAME_FORMULA_LENGTH_MAX); //="taskdevicename"
|
||||
|
||||
addFormCheckBox(F("Enabled"), F("TDE"), Settings.TaskDeviceEnabled[taskIndex]); //="taskdeviceenabled"
|
||||
|
||||
// section: Sensor / Actuator
|
||||
if (!Device[DeviceIndex].Custom && Settings.TaskDeviceDataFeed[taskIndex] == 0 &&
|
||||
((Device[DeviceIndex].Ports != 0) || (Device[DeviceIndex].PullUpOption) || (Device[DeviceIndex].InverseLogicOption) || (Device[DeviceIndex].Type >= DEVICE_TYPE_SINGLE && Device[DeviceIndex].Type <= DEVICE_TYPE_TRIPLE)) )
|
||||
((Device[DeviceIndex].Ports != 0) ||
|
||||
(Device[DeviceIndex].PullUpOption) ||
|
||||
(Device[DeviceIndex].InverseLogicOption) ||
|
||||
(Device[DeviceIndex].connectedToGPIOpins())) )
|
||||
{
|
||||
addFormSubHeader((Device[DeviceIndex].SendDataOption) ? F("Sensor") : F("Actuator"));
|
||||
|
||||
@@ -2153,12 +2165,14 @@ void handle_devices() {
|
||||
TempEvent.String3 = F("3rd GPIO");
|
||||
PluginCall(PLUGIN_GET_DEVICEGPIONAMES, &TempEvent, dummyString);
|
||||
|
||||
if (Device[DeviceIndex].Type >= DEVICE_TYPE_SINGLE && Device[DeviceIndex].Type <= DEVICE_TYPE_TRIPLE)
|
||||
addFormPinSelect(TempEvent.String1, F("taskdevicepin1"), Settings.TaskDevicePin1[taskIndex]);
|
||||
if (Device[DeviceIndex].Type >= DEVICE_TYPE_DUAL && Device[DeviceIndex].Type <= DEVICE_TYPE_TRIPLE)
|
||||
addFormPinSelect( TempEvent.String2, F("taskdevicepin2"), Settings.TaskDevicePin2[taskIndex]);
|
||||
if (Device[DeviceIndex].Type == DEVICE_TYPE_TRIPLE)
|
||||
addFormPinSelect(TempEvent.String3, F("taskdevicepin3"), Settings.TaskDevicePin3[taskIndex]);
|
||||
if (Device[DeviceIndex].connectedToGPIOpins()) {
|
||||
if (Device[DeviceIndex].Type >= DEVICE_TYPE_SINGLE)
|
||||
addFormPinSelect(TempEvent.String1, F("taskdevicepin1"), Settings.TaskDevicePin1[taskIndex]);
|
||||
if (Device[DeviceIndex].Type >= DEVICE_TYPE_DUAL)
|
||||
addFormPinSelect( TempEvent.String2, F("taskdevicepin2"), Settings.TaskDevicePin2[taskIndex]);
|
||||
if (Device[DeviceIndex].Type == DEVICE_TYPE_TRIPLE)
|
||||
addFormPinSelect(TempEvent.String3, F("taskdevicepin3"), Settings.TaskDevicePin3[taskIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
//add plugins content
|
||||
@@ -2242,14 +2256,14 @@ void handle_devices() {
|
||||
TXBuffer += F("<TD>");
|
||||
String id = F("TDVN"); //="taskdevicevaluename"
|
||||
id += (varNr + 1);
|
||||
addTextBox(id, ExtraTaskSettings.TaskDeviceValueNames[varNr], 40);
|
||||
addTextBox(id, ExtraTaskSettings.TaskDeviceValueNames[varNr], NAME_FORMULA_LENGTH_MAX);
|
||||
|
||||
if (Device[DeviceIndex].FormulaOption)
|
||||
{
|
||||
TXBuffer += F("<TD>");
|
||||
String id = F("TDF"); //="taskdeviceformula"
|
||||
id += (varNr + 1);
|
||||
addTextBox(id, ExtraTaskSettings.TaskDeviceFormula[varNr], 40);
|
||||
addTextBox(id, ExtraTaskSettings.TaskDeviceFormula[varNr], NAME_FORMULA_LENGTH_MAX);
|
||||
}
|
||||
|
||||
if (Device[DeviceIndex].FormulaOption || Device[DeviceIndex].DecimalsOnly)
|
||||
|
||||
@@ -255,6 +255,7 @@ static const char pgDefaultCSS[] PROGMEM = {
|
||||
".div_br {clear: both; }"
|
||||
// The alert message box
|
||||
".alert {padding: 20px; background-color: #f44336; color: white; margin-bottom: 15px; }"
|
||||
".warning {padding: 20px; background-color: #ffca17; color: white; margin-bottom: 15px; }"
|
||||
// The close button
|
||||
".closebtn {margin-left: 15px; color: white; font-weight: bold; float: right; font-size: 22px; line-height: 20px; cursor: pointer; transition: 0.3s; }"
|
||||
// When moving the mouse over the close button
|
||||
|
||||
+1
-1
@@ -100,7 +100,7 @@ boolean CPlugin_009(byte function, struct EventStruct *event, String& string)
|
||||
// Each sensor value get an own object (0..n)
|
||||
// sprintf(itemNames[x],"%d",x);
|
||||
JsonObject& val = SENSOR.createNestedObject(String(x));
|
||||
val[F("deviceName")] = ExtraTaskSettings.TaskDeviceName;
|
||||
val[F("deviceName")] = getTaskDeviceName(event->TaskIndex);
|
||||
val[F("valueName")] = ExtraTaskSettings.TaskDeviceValueNames[x];
|
||||
val[F("type")] = event->sensorType;
|
||||
val[F("value")] = formatUserVarNoCheck(event, x);
|
||||
|
||||
+3
-1
@@ -117,7 +117,7 @@ void C013_SendUDPTaskInfo(byte destUnit, byte sourceTaskIndex, byte destTaskInde
|
||||
infoReply.destTaskIndex = destTaskIndex;
|
||||
LoadTaskSettings(infoReply.sourceTaskIndex);
|
||||
infoReply.deviceNumber = Settings.TaskDeviceNumber[infoReply.sourceTaskIndex];
|
||||
strcpy(infoReply.taskName, ExtraTaskSettings.TaskDeviceName);
|
||||
strcpy(infoReply.taskName, getTaskDeviceName(infoReply.sourceTaskIndex).c_str());
|
||||
for (byte x = 0; x < VARS_PER_TASK; x++)
|
||||
strcpy(infoReply.ValueNames[x], ExtraTaskSettings.TaskDeviceValueNames[x]);
|
||||
|
||||
@@ -228,6 +228,7 @@ void C013_Receive(struct EventStruct *event) {
|
||||
// so it will write only once and has to be cleared manually through webgui
|
||||
if (Settings.TaskDeviceNumber[infoReply.destTaskIndex] == 0)
|
||||
{
|
||||
taskClear(infoReply.destTaskIndex, false);
|
||||
Settings.TaskDeviceNumber[infoReply.destTaskIndex] = infoReply.deviceNumber;
|
||||
Settings.TaskDeviceDataFeed[infoReply.destTaskIndex] = 1; // remote feed
|
||||
for (byte x = 0; x < CONTROLLER_MAX; x++)
|
||||
@@ -235,6 +236,7 @@ void C013_Receive(struct EventStruct *event) {
|
||||
strcpy(ExtraTaskSettings.TaskDeviceName, infoReply.taskName);
|
||||
for (byte x = 0; x < VARS_PER_TASK; x++)
|
||||
strcpy( ExtraTaskSettings.TaskDeviceValueNames[x], infoReply.ValueNames[x]);
|
||||
ExtraTaskSettings.TaskIndex = infoReply.destTaskIndex;
|
||||
SaveTaskSettings(infoReply.destTaskIndex);
|
||||
SaveSettings();
|
||||
}
|
||||
|
||||
+25
-1
@@ -27,6 +27,7 @@
|
||||
#define PN532_COMMAND_INLISTPASSIVETARGET (0x4A)
|
||||
#define PN532_RESPONSE_INLISTPASSIVETARGET (0x4B)
|
||||
#define PN532_MIFARE_ISO14443A (0x00)
|
||||
#define PN532_COMMAND_POWERDOWN (0x16)
|
||||
|
||||
uint8_t Plugin_017_pn532_packetbuffer[64];
|
||||
uint8_t Plugin_017_command;
|
||||
@@ -95,7 +96,7 @@ boolean Plugin_017(byte function, struct EventStruct *event, String& string)
|
||||
static byte errorCount=0;
|
||||
|
||||
counter++;
|
||||
if (counter == 3)
|
||||
if (counter == 3 )
|
||||
{
|
||||
if (digitalRead(4) == 0 || digitalRead(5) == 0)
|
||||
{
|
||||
@@ -123,6 +124,7 @@ boolean Plugin_017(byte function, struct EventStruct *event, String& string)
|
||||
Plugin_017_Init(Settings.TaskDevicePin3[event->TaskIndex]);
|
||||
}
|
||||
|
||||
|
||||
if (error == 0) {
|
||||
unsigned long key = uid[0];
|
||||
for (uint8_t i = 1; i < 4; i++) {
|
||||
@@ -232,6 +234,23 @@ uint32_t getFirmwareVersion(void)
|
||||
}
|
||||
|
||||
|
||||
void Plugin_017_powerDown(void)
|
||||
{
|
||||
|
||||
Plugin_017_pn532_packetbuffer[0] = PN532_COMMAND_POWERDOWN;
|
||||
Plugin_017_pn532_packetbuffer[1] = 1 << 7; //allowed wakeup source is i2c
|
||||
|
||||
if (Plugin_017_writeCommand(Plugin_017_pn532_packetbuffer, 2)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// delay(50); // we can try to read faster, but it will only put extra load on the I2C bus...
|
||||
|
||||
// read and ignore response
|
||||
Plugin_017_readResponse(Plugin_017_pn532_packetbuffer, sizeof(Plugin_017_pn532_packetbuffer));
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
* PN532 read tag
|
||||
\*********************************************************************************************/
|
||||
@@ -273,6 +292,10 @@ byte Plugin_017_readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t
|
||||
uid[i] = Plugin_017_pn532_packetbuffer[6 + i];
|
||||
}
|
||||
|
||||
// Plugin_017_Init(-1);
|
||||
Plugin_017_powerDown();
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -325,6 +348,7 @@ int16_t Plugin_017_readResponse(uint8_t buf[], uint8_t len)
|
||||
if (!Wire.requestFrom(PN532_I2C_ADDRESS, len + 2))
|
||||
return -1;
|
||||
|
||||
|
||||
if (!(Wire.read() & 1))
|
||||
return -1;
|
||||
|
||||
|
||||
+12
-12
@@ -23,12 +23,12 @@
|
||||
#define PCA9685_ALLLED_REG (byte)0xFA
|
||||
|
||||
/*
|
||||
is bit flag any bit rapresent the initialization state of PCA9685
|
||||
is bit flag any bit rapresent the initialization state of PCA9685
|
||||
es: bit 3 is set 1 PCA9685 with address 0X40 + 0x03 is intin
|
||||
*/
|
||||
#define IS_INIT(state, bit) ((state & 1 << bit) == 1 << bit)
|
||||
#define SET_INIT(state, bit) (state|= 1 << bit)
|
||||
long long initializeState; //
|
||||
long long initializeState; //
|
||||
|
||||
boolean Plugin_022(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
@@ -85,7 +85,7 @@ boolean Plugin_022(byte function, struct EventStruct *event, String& string)
|
||||
Settings.TaskDevicePort[event->TaskIndex] = getFormItemInt(F("i2c_addr"));
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case PLUGIN_WRITE:
|
||||
{
|
||||
@@ -100,7 +100,7 @@ boolean Plugin_022(byte function, struct EventStruct *event, String& string)
|
||||
String name = line.substring(0,dotPos);
|
||||
name.replace(F("["),F(""));
|
||||
name.replace(F("]"),F(""));
|
||||
if(name.equalsIgnoreCase(ExtraTaskSettings.TaskDeviceName) == true)
|
||||
if(name.equalsIgnoreCase(getTaskDeviceName(event->TaskIndex)) == true)
|
||||
{
|
||||
line = line.substring(dotPos + 1);
|
||||
istanceCommand = true;
|
||||
@@ -121,7 +121,7 @@ boolean Plugin_022(byte function, struct EventStruct *event, String& string)
|
||||
if(event->Par2 >=0 && event->Par2 <= PCA9685_MAX_PWM)
|
||||
{
|
||||
if (!IS_INIT(initializeState, (address - PCA9685_ADDRESS))) Plugin_022_initialize(address);
|
||||
|
||||
|
||||
Plugin_022_Write(address, event->Par1, event->Par2);
|
||||
setPinState(PLUGIN_ID_022, event->Par1, PIN_MODE_PWM, event->Par2);
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
@@ -139,7 +139,7 @@ boolean Plugin_022(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
success = true;
|
||||
if(event->Par1 >= PCA9685_MIN_FREQUENCY && event->Par1 <= PCA9685_MAX_FREQUENCY)
|
||||
{
|
||||
{
|
||||
if (!IS_INIT(initializeState, (address - PCA9685_ADDRESS))) Plugin_022_initialize(address);
|
||||
|
||||
Plugin_022_Frequency(address, event->Par1);
|
||||
@@ -150,7 +150,7 @@ boolean Plugin_022(byte function, struct EventStruct *event, String& string)
|
||||
}
|
||||
else{
|
||||
addLog(LOG_LEVEL_ERROR,String(F("PCA ")) + String(address, HEX) + String(F(" The frequesncy ")) + String(event->Par1) + String(F(" is out of range.")));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ boolean Plugin_022(byte function, struct EventStruct *event, String& string)
|
||||
if(parseString(line,2) == "all")
|
||||
{
|
||||
pin = -1;
|
||||
log += String(F("all"));
|
||||
log += String(F("all"));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -189,10 +189,10 @@ boolean Plugin_022(byte function, struct EventStruct *event, String& string)
|
||||
else
|
||||
{
|
||||
log += F(" on");
|
||||
Plugin_022_On(address, pin);
|
||||
Plugin_022_On(address, pin);
|
||||
}
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
setPinState(PLUGIN_ID_022, pin, PIN_MODE_OUTPUT, event->Par2);
|
||||
setPinState(PLUGIN_ID_022, pin, PIN_MODE_OUTPUT, event->Par2);
|
||||
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_022, pin, log, 0));
|
||||
}
|
||||
else{
|
||||
@@ -237,7 +237,7 @@ boolean Plugin_022(byte function, struct EventStruct *event, String& string)
|
||||
log += String(autoreset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
setSystemTimer(event->Par3 , PLUGIN_ID_022
|
||||
, event->TaskIndex
|
||||
@@ -286,7 +286,7 @@ boolean Plugin_022(byte function, struct EventStruct *event, String& string)
|
||||
, autoreset);
|
||||
}
|
||||
setPinState(PLUGIN_ID_022, event->Par1, PIN_MODE_OUTPUT, event->Par2);
|
||||
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_022, event->Par1, log, 0));
|
||||
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_022, event->Par1, log, 0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -235,7 +235,7 @@ boolean Plugin_023(byte function, struct EventStruct *event, String& string)
|
||||
String name = arguments.substring(0,dotPos);
|
||||
name.replace(F("["),F(""));
|
||||
name.replace(F("]"),F(""));
|
||||
if(name.equalsIgnoreCase(ExtraTaskSettings.TaskDeviceName) == true)
|
||||
if(name.equalsIgnoreCase(getTaskDeviceName(event->TaskIndex)) == true)
|
||||
{
|
||||
arguments = arguments.substring(dotPos+1);
|
||||
}
|
||||
@@ -244,7 +244,7 @@ boolean Plugin_023(byte function, struct EventStruct *event, String& string)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int argIndex = arguments.indexOf(',');
|
||||
if (argIndex)
|
||||
arguments = arguments.substring(0, argIndex);
|
||||
@@ -492,7 +492,7 @@ void Plugin_023_reset_display(struct Plugin_023_OLED_SettingStruct &oled)
|
||||
|
||||
|
||||
void Plugin_023_StartUp_OLED(struct Plugin_023_OLED_SettingStruct &oled)
|
||||
{
|
||||
{
|
||||
Plugin_023_init_OLED(oled);
|
||||
Plugin_023_reset_display(oled);
|
||||
Plugin_023_displayOff(oled);
|
||||
@@ -644,7 +644,7 @@ void Plugin_023_init_OLED(struct Plugin_023_OLED_SettingStruct &oled)
|
||||
multiplex = 0x3F;
|
||||
compins = 0x12;
|
||||
}
|
||||
|
||||
|
||||
Plugin_023_sendcommand(address, 0xAE); //display off
|
||||
Plugin_023_sendcommand(address, 0xD5); //SETDISPLAYCLOCKDIV
|
||||
Plugin_023_sendcommand(address, 0x80); // the suggested ratio 0x80
|
||||
|
||||
@@ -200,7 +200,7 @@ boolean Plugin_037(byte function, struct EventStruct *event, String& string)
|
||||
log = F("ERR : Illegal Payload ");
|
||||
log += Payload;
|
||||
log += " ";
|
||||
log += ExtraTaskSettings.TaskDeviceName;
|
||||
log += getTaskDeviceName(event->TaskIndex);
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
success = false;
|
||||
break;
|
||||
@@ -227,7 +227,7 @@ boolean Plugin_037(byte function, struct EventStruct *event, String& string)
|
||||
// Log the event
|
||||
|
||||
String log = F("IMPT : [");
|
||||
log += ExtraTaskSettings.TaskDeviceName;
|
||||
log += getTaskDeviceName(event->TaskIndex);
|
||||
log += F("#");
|
||||
log += ExtraTaskSettings.TaskDeviceValueNames[x];
|
||||
log += F("] : ");
|
||||
@@ -239,7 +239,7 @@ boolean Plugin_037(byte function, struct EventStruct *event, String& string)
|
||||
if (Settings.UseRules)
|
||||
{
|
||||
String RuleEvent = F("");
|
||||
RuleEvent += ExtraTaskSettings.TaskDeviceName;
|
||||
RuleEvent += getTaskDeviceName(event->TaskIndex);
|
||||
RuleEvent += F("#");
|
||||
RuleEvent += ExtraTaskSettings.TaskDeviceValueNames[x];
|
||||
RuleEvent += F("=");
|
||||
@@ -287,7 +287,7 @@ boolean MQTTSubscribe_037()
|
||||
{
|
||||
String log = F("IMPT : [");
|
||||
LoadTaskSettings(y);
|
||||
log += ExtraTaskSettings.TaskDeviceName;
|
||||
log += getTaskDeviceName(y);
|
||||
log += F("#");
|
||||
log += ExtraTaskSettings.TaskDeviceValueNames[x];
|
||||
log += F("] subscribed to ");
|
||||
|
||||
@@ -317,7 +317,7 @@ boolean Plugin_044(byte function, struct EventStruct *event, String& string)
|
||||
if (Settings.UseRules)
|
||||
{
|
||||
LoadTaskSettings(event->TaskIndex);
|
||||
String eventString = ExtraTaskSettings.TaskDeviceName;
|
||||
String eventString = getTaskDeviceName(event->TaskIndex);
|
||||
eventString += F("#Data");
|
||||
rulesProcessing(eventString);
|
||||
}
|
||||
|
||||
@@ -1241,10 +1241,18 @@ byte PluginCall(byte Function, struct EventStruct *event, String& str)
|
||||
// Schedule the plugin to be read.
|
||||
schedule_task_device_timer_at_init(event->TaskIndex);
|
||||
}
|
||||
if (Function != PLUGIN_GET_DEVICEVALUENAMES) {
|
||||
// LoadTaskSettings may call PLUGIN_GET_DEVICEVALUENAMES.
|
||||
LoadTaskSettings(event->TaskIndex);
|
||||
}
|
||||
|
||||
event->BaseVarIndex = event->TaskIndex * VARS_PER_TASK;
|
||||
checkRAM(F("PluginCall_init"),x);
|
||||
START_TIMER;
|
||||
bool retval = Plugin_ptr[x](Function, event, str);
|
||||
if (Function == PLUGIN_GET_DEVICEVALUENAMES) {
|
||||
ExtraTaskSettings.TaskIndex = event->TaskIndex;
|
||||
}
|
||||
STOP_TIMER_TASK(x,Function);
|
||||
return retval;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user