mirror of
https://github.com/arendst/Tasmota.git
synced 2025-04-25 07:17:16 +00:00
Add demo for driver/sensor settings file storage (#10786)
This commit is contained in:
parent
d46d28c2e1
commit
7561647dce
@ -486,6 +486,8 @@ void SettingsSave(uint8_t rotate) {
|
|||||||
* stop_flash_rotate 1 = Allow only eeprom flash slot use (SetOption12 1)
|
* stop_flash_rotate 1 = Allow only eeprom flash slot use (SetOption12 1)
|
||||||
*/
|
*/
|
||||||
#ifndef FIRMWARE_MINIMAL
|
#ifndef FIRMWARE_MINIMAL
|
||||||
|
XsnsCall(FUNC_SAVE_SETTINGS);
|
||||||
|
XdrvCall(FUNC_SAVE_SETTINGS);
|
||||||
UpdateBackwardCompatibility();
|
UpdateBackwardCompatibility();
|
||||||
if ((GetSettingsCrc32() != settings_crc32) || rotate) {
|
if ((GetSettingsCrc32() != settings_crc32) || rotate) {
|
||||||
if (1 == rotate) { // Use eeprom flash slot only and disable flash rotate from now on (upgrade)
|
if (1 == rotate) { // Use eeprom flash slot only and disable flash rotate from now on (upgrade)
|
||||||
|
@ -270,7 +270,7 @@ enum LightTypes { LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT
|
|||||||
|
|
||||||
enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_PIN_STATE, FUNC_MODULE_INIT, FUNC_PRE_INIT, FUNC_INIT,
|
enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_PIN_STATE, FUNC_MODULE_INIT, FUNC_PRE_INIT, FUNC_INIT,
|
||||||
FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND,
|
FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND,
|
||||||
FUNC_SAVE_AT_MIDNIGHT, FUNC_SAVE_BEFORE_RESTART,
|
FUNC_SAVE_SETTINGS, FUNC_SAVE_AT_MIDNIGHT, FUNC_SAVE_BEFORE_RESTART,
|
||||||
FUNC_AFTER_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_SENSOR, FUNC_COMMAND, FUNC_COMMAND_SENSOR, FUNC_COMMAND_DRIVER,
|
FUNC_AFTER_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_SENSOR, FUNC_COMMAND, FUNC_COMMAND_SENSOR, FUNC_COMMAND_DRIVER,
|
||||||
FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA,
|
FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA,
|
||||||
FUNC_SET_POWER, FUNC_SET_DEVICE_POWER, FUNC_SHOW_SENSOR, FUNC_ANY_KEY,
|
FUNC_SET_POWER, FUNC_SET_DEVICE_POWER, FUNC_SHOW_SENSOR, FUNC_ANY_KEY,
|
||||||
|
@ -233,6 +233,8 @@ const uint16_t LOG_BUFFER_SIZE = 4000; // Max number of characters in lo
|
|||||||
|
|
||||||
#define TASM_FILE_SETTINGS "/.settings" // Settings binary blob
|
#define TASM_FILE_SETTINGS "/.settings" // Settings binary blob
|
||||||
#define TASM_FILE_SETTINGS_LKG "/.settings.lkg" // Last Known Good Settings binary blob
|
#define TASM_FILE_SETTINGS_LKG "/.settings.lkg" // Last Known Good Settings binary blob
|
||||||
|
#define TASM_FILE_DRIVER "/.drvset%03d"
|
||||||
|
#define TASM_FILE_SENSOR "/.snsset%03d"
|
||||||
#define TASM_FILE_ZIGBEE "/zb" // Zigbee settings blob as used by CC2530 on ESP32
|
#define TASM_FILE_ZIGBEE "/zb" // Zigbee settings blob as used by CC2530 on ESP32
|
||||||
|
|
||||||
#ifndef MQTT_MAX_PACKET_SIZE
|
#ifndef MQTT_MAX_PACKET_SIZE
|
||||||
@ -475,18 +477,18 @@ bool first_device_group_is_local = true;
|
|||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Macro for SetOption synonyms
|
* Macro for SetOption synonyms
|
||||||
*
|
*
|
||||||
* SetOption synonyms come first in the list of commands, right after the prefix.
|
* SetOption synonyms come first in the list of commands, right after the prefix.
|
||||||
* They don't need any matching function pointer, since they are handled internally.
|
* They don't need any matching function pointer, since they are handled internally.
|
||||||
* So don't forget to NOT put pointers in the functions pointers list.
|
* So don't forget to NOT put pointers in the functions pointers list.
|
||||||
*
|
*
|
||||||
* The additionnal list of unsigned bytes contains the Option numbers of each synonyms
|
* The additionnal list of unsigned bytes contains the Option numbers of each synonyms
|
||||||
* in the same order. The first byte of the list contains the number of synonyms
|
* in the same order. The first byte of the list contains the number of synonyms
|
||||||
* (not including the number itself). The is the number of names to skip to find the first command.
|
* (not including the number itself). The is the number of names to skip to find the first command.
|
||||||
*
|
*
|
||||||
* As it si cumbersome to calculate the first byte (number of synonyms), we provide the following
|
* As it si cumbersome to calculate the first byte (number of synonyms), we provide the following
|
||||||
* macro `SO_SYNONYMS(<name>, <list of bytes>)`
|
* macro `SO_SYNONYMS(<name>, <list of bytes>)`
|
||||||
*
|
*
|
||||||
* For example:
|
* For example:
|
||||||
* ```
|
* ```
|
||||||
* SO_SYNONYMS(kLightSynonyms,
|
* SO_SYNONYMS(kLightSynonyms,
|
||||||
@ -494,7 +496,7 @@ bool first_device_group_is_local = true;
|
|||||||
* 106,
|
* 106,
|
||||||
* );
|
* );
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* is equivalent to:
|
* is equivalent to:
|
||||||
* ```
|
* ```
|
||||||
* const static uint8_t kLightSynonyms[] PROGMEM = {
|
* const static uint8_t kLightSynonyms[] PROGMEM = {
|
||||||
@ -503,7 +505,7 @@ bool first_device_group_is_local = true;
|
|||||||
* 106,
|
* 106,
|
||||||
* };
|
* };
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* This comes very handy if you need to adjust the number of synonyms depending on #defines
|
* This comes very handy if you need to adjust the number of synonyms depending on #defines
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
@ -85,10 +85,6 @@ uint8_t ufs_type;
|
|||||||
uint8_t ffs_type;
|
uint8_t ffs_type;
|
||||||
bool download_busy;
|
bool download_busy;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************************************/
|
/*********************************************************************************************/
|
||||||
|
|
||||||
// Init flash file system
|
// Init flash file system
|
||||||
|
186
tasmota/xdrv_98_file_settings_demo.ino
Normal file
186
tasmota/xdrv_98_file_settings_demo.ino
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
xdrv_98_file_settings_demo.ino - Demo for Tasmota
|
||||||
|
|
||||||
|
Copyright (C) 2021 Theo Arends
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Enable this define to use this demo
|
||||||
|
//#define USE_DRV_FILE_DEMO
|
||||||
|
|
||||||
|
#ifdef USE_DRV_FILE_DEMO
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Settings load and save demo using Tasmota file system
|
||||||
|
*
|
||||||
|
* To test this file:
|
||||||
|
* - Have hardware with at least 2M flash
|
||||||
|
* - Enable a build.ldscript with at least 256k filesystem in platform_override.ini
|
||||||
|
* - Enable define USE_UFILESYS in user_config_override.h
|
||||||
|
\*********************************************************************************************/
|
||||||
|
#warning **** USE_DRV_FILE_DEMO is enabled ****
|
||||||
|
|
||||||
|
#define XDRV_98 98
|
||||||
|
|
||||||
|
#define DRV98_MAX_DRV_TEXT 16
|
||||||
|
|
||||||
|
const uint32_t DRV98_VERSION = 0x01010101; // Latest driver version (See settings deltas below)
|
||||||
|
|
||||||
|
// Demo command line commands
|
||||||
|
const char kDrvDemoCommands[] PROGMEM = "Drv|" // Prefix
|
||||||
|
"Text";
|
||||||
|
|
||||||
|
void (* const DrvDemoCommand[])(void) PROGMEM = {
|
||||||
|
&CmndDrvText };
|
||||||
|
|
||||||
|
// Global structure containing driver saved variables
|
||||||
|
struct {
|
||||||
|
uint32_t crc32; // To detect file changes
|
||||||
|
uint32_t version; // To detect driver function changes
|
||||||
|
char drv_text[DRV98_MAX_DRV_TEXT -1][10];
|
||||||
|
} Drv98Settings;
|
||||||
|
|
||||||
|
// Global structure containing driver non-saved variables
|
||||||
|
struct {
|
||||||
|
uint32_t any_value;
|
||||||
|
} Drv98Global;
|
||||||
|
|
||||||
|
void CmndDrvText(void) {
|
||||||
|
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= DRV98_MAX_DRV_TEXT)) {
|
||||||
|
if (!XdrvMailbox.usridx) {
|
||||||
|
// Command DrvText
|
||||||
|
for (uint32_t i = 0; i < DRV98_MAX_DRV_TEXT; i++) {
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("DRV: DrvText%02d %s"), i, Drv98Settings.drv_text[i]);
|
||||||
|
}
|
||||||
|
ResponseCmndDone();
|
||||||
|
} else {
|
||||||
|
// Command DrvText<index> <text>
|
||||||
|
uint32_t index = XdrvMailbox.index -1;
|
||||||
|
if (XdrvMailbox.data_len > 0) {
|
||||||
|
snprintf_P(Drv98Settings.drv_text[index], sizeof(Drv98Settings.drv_text[index]), XdrvMailbox.data);
|
||||||
|
}
|
||||||
|
ResponseCmndIdxChar(Drv98Settings.drv_text[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Driver Settings load and save
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
uint32_t GetDrvDemoSettingsCrc32(void) {
|
||||||
|
// Use Tasmota CRC calculation function
|
||||||
|
return GetCfgCrc32((uint8_t*)&Drv98Settings +4, sizeof(Drv98Settings) -4); // Skip crc32
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrvDemoPreInit(void) {
|
||||||
|
// Init default values in case file is not found
|
||||||
|
memset(&Drv98Settings, 0x00, sizeof(Drv98Settings));
|
||||||
|
Drv98Settings.version = DRV98_VERSION;
|
||||||
|
// Init any other parameter in struct Drv98Settings
|
||||||
|
snprintf_P(Drv98Settings.drv_text[0], sizeof(Drv98Settings.drv_text[0]), PSTR("Azalea"));
|
||||||
|
|
||||||
|
// Try to load file /drvset098
|
||||||
|
char filename[20];
|
||||||
|
// Use for sensors:
|
||||||
|
// snprintf_P(filename, sizeof(filename), PSTR(TASM_FILE_SENSOR), XSNS_98);
|
||||||
|
// Use for drivers:
|
||||||
|
snprintf_P(filename, sizeof(filename), PSTR(TASM_FILE_DRIVER), XDRV_98);
|
||||||
|
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("DRV: About to load settings from file %s"), filename);
|
||||||
|
|
||||||
|
#ifdef USE_UFILESYS
|
||||||
|
|
||||||
|
bool result = TfsLoadFile(filename, (uint8_t*)&Drv98Settings, sizeof(Drv98Settings));
|
||||||
|
if (result) {
|
||||||
|
// Fix possible setting deltas
|
||||||
|
if (Drv98Settings.version != DRV98_VERSION) { // Fix version dependent changes
|
||||||
|
|
||||||
|
if (Settings.version < 0x01010100) {
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("DRV: Update oldest version restore"));
|
||||||
|
|
||||||
|
}
|
||||||
|
if (Settings.version < 0x01010101) {
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("DRV: Update old version restore"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set current version and save settings
|
||||||
|
Drv98Settings.version = DRV98_VERSION;
|
||||||
|
DrvDemoSettingsSave();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// File system not ready: No flash space reserved for file system
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("DRV: ERROR File system not ready or file not found"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("DRV: ERROR File system not enabled"));
|
||||||
|
|
||||||
|
#endif // USE_UFILESYS
|
||||||
|
Drv98Settings.crc32 = GetDrvDemoSettingsCrc32();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrvDemoSettingsSave(void) {
|
||||||
|
if (GetDrvDemoSettingsCrc32() != Drv98Settings.crc32) {
|
||||||
|
// Try to save file /drvset098
|
||||||
|
Drv98Settings.crc32 = GetDrvDemoSettingsCrc32();
|
||||||
|
char filename[20];
|
||||||
|
// Use for sensors:
|
||||||
|
// snprintf_P(filename, sizeof(filename), PSTR(TASM_FILE_SENSOR), XSNS_98);
|
||||||
|
// Use for drivers:
|
||||||
|
snprintf_P(filename, sizeof(filename), PSTR(TASM_FILE_DRIVER), XDRV_98);
|
||||||
|
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("DRV: About to save settings to file %s"), filename);
|
||||||
|
|
||||||
|
#ifdef USE_UFILESYS
|
||||||
|
bool result = TfsSaveFile(filename, (const uint8_t*)&Drv98Settings, sizeof(Drv98Settings));
|
||||||
|
if (!result) {
|
||||||
|
// File system not ready: No flash space reserved for file system
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("DRV: ERROR File system not ready or unable to save file"));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("DRV: ERROR File system not enabled"));
|
||||||
|
|
||||||
|
#endif // USE_UFILESYS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Interface
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
bool Xdrv98(uint8_t function) {
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
switch (function) {
|
||||||
|
case FUNC_COMMAND:
|
||||||
|
result = DecodeCommand(kDrvDemoCommands, DrvDemoCommand);
|
||||||
|
break;
|
||||||
|
case FUNC_SAVE_SETTINGS:
|
||||||
|
DrvDemoSettingsSave();
|
||||||
|
break;
|
||||||
|
case FUNC_PRE_INIT:
|
||||||
|
DrvDemoPreInit();
|
||||||
|
break;
|
||||||
|
case FUNC_SAVE_BEFORE_RESTART:
|
||||||
|
// !!! DO NOT USE AS IT'S FUNCTION IS BETTER HANDLED BY FUNC_SAVE_SETTINGS !!!
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_DRV_FILE_DEMO
|
Loading…
x
Reference in New Issue
Block a user