-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathFailSafe.h
168 lines (139 loc) · 5.36 KB
/
FailSafe.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/**
* @file FailSafe.h
* @version 0.2.3
* @date 18/12/2020
* @author German Martin
* @brief Library to add a simple fail safe mode to any ESP32 or ESP8266 project
*/
#ifndef _BOOTCHECK_h
#define _BOOTCHECK_h
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <ArduinoOTA.h>
#include "FS.h"
#if !defined FS_USE_FLASH || __DOXYGEN__
#define FS_USE_FLASH 0 /**< Set to 1 to use File System. Set to 0 to use RTC memory. Only for ESP8266. Does not work with power off.*/
#endif // FS_USE_FLASH
#if FS_USE_FLASH || __DOXYGEN__
#if !defined FS_USE_LITTLEFS || __DOXYGEN__
#define FS_USE_LITTLEFS 0 /**< Set to 0 to use SPIFFS (Default). Set to 1 to use LittleFS (Recommended). Only for ESP8266, ESP32 always uses SPIFFS*/
#endif // FS_USE_LITTLEFS
#endif // FS_USE_FLASH
#ifdef ESP32
#undef FS_USE_FLASH
#undef FS_USE_LITTLEFS
#define FS_USE_FLASH 1 // Do not modify
#define FS_USE_LITTLEFS 0 // Do not modify
#include <SPIFFS.h>
#include "Update.h"
#endif // ESP32
#ifndef FAIL_SAFE_DEBUG
#define FAIL_SAFE_DEBUG 0 /**< Set to 1 to enable log. If using ESP32 you need to set core log level to WARN at least */
#endif
#if FAIL_SAFE_DEBUG
#ifdef ESP8266
#define DEBUG_INTERFACE Serial
#ifdef DEBUG_INTERFACE
const char* extractFileName (const char* path);
#define DEBUG_LINE_PREFIX() DEBUG_INTERFACE.printf_P (PSTR("[%lu][%s:%d] %s() Heap: %lu | "),millis(),extractFileName(__FILE__),__LINE__,__FUNCTION__,(unsigned long)ESP.getFreeHeap())
#define fsDebug(text,...) DEBUG_LINE_PREFIX();DEBUG_INTERFACE.printf_P(PSTR(text),##__VA_ARGS__);DEBUG_INTERFACE.println()
#endif // DEBUG_INTERFACE
#else // ESP32
#define DEFAULT_LOG_TAG "FailSafe"
#define fsDebug(format,...) ESP_LOGW (DEFAULT_LOG_TAG,"%d Heap: %6d. " format, millis(), ESP.getFreeHeap(), ##__VA_ARGS__)
#endif // ESP8266
#else
#define fsDebug(text,...)
#endif // FAIL_SAFE_DEBUG
#if defined ESP32 || FS_USE_FLASH || __DOXYGEN__
constexpr auto FILENAME = "/failsafe.bin";
#endif
#define DEFAULT_BOOT_FLAG_TIMEOUT 10000 /**< Boot flag is reset this time after boot */
#define DEFAULT_OFFSET 0 /**< If RTC is used this is offset. Modify it if your project uses RTC memory too */
#define DEFAULT_MAX_BOOT_CYCLES 3 /**< Number of quick boot loops on which fail safe mode is started */
constexpr auto PASSWD = "laplacian"; /**< Fail Safe mode WiFi AP password */
enum failSafeMode_t {
OFF = 0, /**< Normal mode */
TRIGGERED = 1, /**< Fail safe mode triggered, not started yet */
RUNNING = 2 /**< Fail safe mode active */
};
struct bootFlag_t {
#if !FS_USE_FLASH || __DOXYGEN__
uint32_t crc; /**< If RTC is used this field is used to check data integrify */
#endif // FS_USE_FLASH
int32_t bootCycles; /**< Booth cycle counter */
};
#if defined ESP8266 || __DOXYGEN__
/**
* @brief Extract filename fom a path, to use it in debug messages
* @param path Complete file path
* @return file name without path
*/
const char* IRAM_ATTR extractFileName (const char* path);
#endif
class FailSafeClass
{
protected:
bootFlag_t bootFlag; /**< Boot counter */
uint32_t offset; /**< RTC memory offset */
failSafeMode_t failSafe = OFF; /**< Current fail safe mode status */
int indicatorLed; /**< LED to show fail safe mode status. Normally off (= HIGH) */
/**
* @brief Save boot flag on persistent storage (RTC or SPIFFS)
* @return Save result, false in case of error
*/
bool saveFlag ();
/**
* @brief Load last boot counter from storage (RTC or SPIFFS)
* @return Save result, false in case of error
*/
bool loadFlag ();
/**
* @brief Internal setup method for fail safe mode
*/
void failSafeModeSetup ();
/**
* @brief Internal loop method in fail safe mode
*/
void failSafeModeLoop ();
public:
/**
* @brief Reset boot counter to 0 and update storage
*/
void resetFlag ();
/**
* @brief Checks if fail safe mode should be activated. This should be called at the beginning of main setup function
* @param maxBootCycles Number of cycles after device enters in Fail Safe mode
* @param led Indicates Fail Safe mode status. Normally off (= HIGH)
* @param memOffset RTC memory offset. This is not used if storage is SPIFFS
*/
void checkBoot (int maxBootCycles = DEFAULT_MAX_BOOT_CYCLES, int led = -1, uint32_t memOffset = DEFAULT_OFFSET);
/**
* @brief Triggers fail safe mode manually from user code. IT can be used if WiFi cannot connect, for instance
*/
void startFailSafe () {
failSafe = TRIGGERED;
}
/**
* @brief Checks if fail safe mode is active to help controlling user code
* @return Fail Safe mode status
*/
failSafeMode_t isActive () {
return failSafe;
}
/**
* @brief Internal loop should be called on every main code loop
* @param timeout Boot flag is reset this time after boot
*/
void loop (uint32_t timeout = DEFAULT_BOOT_FLAG_TIMEOUT);
/**
* @brief Converts current status to a char string
* @return Textual Fail Safe mode status
*/
const char* toString ();
};
extern FailSafeClass FailSafe; /**< Static instance */
#endif