ESP_IOT v2.5
IOT ESP Coding
Update.h
Go to the documentation of this file.
1#ifdef NOT_FOR_SHOW_ONLY
2
3
4#ifndef ESP8266UPDATER_H
5#define ESP8266UPDATER_H
6
7#include <Arduino.h>
8#include <MD5Builder.h>
9#include <functional>
10#include "esp_partition.h"
11
12#define UPDATE_ERROR_OK (0)
13#define UPDATE_ERROR_WRITE (1)
14#define UPDATE_ERROR_ERASE (2)
15#define UPDATE_ERROR_READ (3)
16#define UPDATE_ERROR_SPACE (4)
17#define UPDATE_ERROR_SIZE (5)
18#define UPDATE_ERROR_STREAM (6)
19#define UPDATE_ERROR_MD5 (7)
20#define UPDATE_ERROR_MAGIC_BYTE (8)
21#define UPDATE_ERROR_ACTIVATE (9)
22#define UPDATE_ERROR_NO_PARTITION (10)
23#define UPDATE_ERROR_BAD_ARGUMENT (11)
24#define UPDATE_ERROR_ABORT (12)
25
26#define UPDATE_SIZE_UNKNOWN 0xFFFFFFFF
27
28#define U_FLASH 0
29#define U_SPIFFS 100
30#define U_AUTH 200
31
32#define ENCRYPTED_BLOCK_SIZE 16
33
34class UpdateClass {
35 public:
36 typedef std::function<void(size_t, size_t)> THandlerFunction_Progress;
37
38 UpdateClass();
39
40 /*
41 This callback will be called when Update is receiving data
42 */
43 UpdateClass& onProgress(THandlerFunction_Progress fn);
44
45 /*
46 Call this to check the space needed for the update
47 Will return false if there is not enough space
48 */
49 bool begin(size_t size=UPDATE_SIZE_UNKNOWN, int command = U_FLASH, int ledPin = -1, uint8_t ledOn = LOW, const char *label = NULL);
50
51 /*
52 Writes a buffer to the flash and increments the address
53 Returns the amount written
54 */
55 size_t write(uint8_t *data, size_t len);
56
57 /*
58 Writes the remaining bytes from the Stream to the flash
59 Uses readBytes() and sets UPDATE_ERROR_STREAM on timeout
60 Returns the bytes written
61 Should be equal to the remaining bytes when called
62 Usable for slow streams like Serial
63 */
64 size_t writeStream(Stream &data);
65
66 /*
67 If all bytes are written
68 this call will write the config to eboot
69 and return true
70 If there is already an update running but is not finished and !evenIfRemaining
71 or there is an error
72 this will clear everything and return false
73 the last error is available through getError()
74 evenIfRemaining is helpfull when you update without knowing the final size first
75 */
76 bool end(bool evenIfRemaining = false);
77
78 /*
79 Aborts the running update
80 */
81 void abort();
82
83 /*
84 Prints the last error to an output stream
85 */
86 void printError(Print &out);
87
88 const char * errorString();
89
90 /*
91 sets the expected MD5 for the firmware (hexString)
92 */
93 bool setMD5(const char * expected_md5);
94
95 /*
96 returns the MD5 String of the successfully ended firmware
97 */
98 String md5String(void){ return _md5.toString(); }
99
100 /*
101 populated the result with the md5 bytes of the successfully ended firmware
102 */
103 void md5(uint8_t * result){ return _md5.getBytes(result); }
104
105 //Helpers
106 uint8_t getError(){ return _error; }
107 void clearError(){ _error = UPDATE_ERROR_OK; }
108 bool hasError(){ return _error != UPDATE_ERROR_OK; }
109 bool isRunning(){ return _size > 0; }
110 bool isFinished(){ return _progress == _size; }
111 size_t size(){ return _size; }
112 size_t progress(){ return _progress; }
113 size_t remaining(){ return _size - _progress; }
114
115 /*
116 Template to write from objects that expose
117 available() and read(uint8_t*, size_t) methods
118 faster than the writeStream method
119 writes only what is available
120 */
121 template<typename T>
122 size_t write(T &data){
123 size_t written = 0;
124 if (hasError() || !isRunning())
125 return 0;
126
127 size_t available = data.available();
128 while(available) {
129 if(_bufferLen + available > remaining()){
130 available = remaining() - _bufferLen;
131 }
132 if(_bufferLen + available > 4096) {
133 size_t toBuff = 4096 - _bufferLen;
134 data.read(_buffer + _bufferLen, toBuff);
135 _bufferLen += toBuff;
136 if(!_writeBuffer())
137 return written;
138 written += toBuff;
139 } else {
140 data.read(_buffer + _bufferLen, available);
141 _bufferLen += available;
142 written += available;
143 if(_bufferLen == remaining()) {
144 if(!_writeBuffer()) {
145 return written;
146 }
147 }
148 }
149 if(remaining() == 0)
150 return written;
151 available = data.available();
152 }
153 return written;
154 }
155
156 /*
157 check if there is a firmware on the other OTA partition that you can bootinto
158 */
159 bool canRollBack();
160 /*
161 set the other OTA partition as bootable (reboot to enable)
162 */
163 bool rollBack();
164
165 private:
166 void _reset();
167 void _abort(uint8_t err);
168 bool _writeBuffer();
169 bool _verifyHeader(uint8_t data);
170 bool _verifyEnd();
171 bool _enablePartition(const esp_partition_t* partition);
172
173
174 uint8_t _error;
175 uint8_t *_buffer;
176 uint8_t *_skipBuffer;
177 size_t _bufferLen;
178 size_t _size;
179 THandlerFunction_Progress _progress_callback;
180 uint32_t _progress;
181 uint32_t _command;
182 const esp_partition_t* _partition;
183
184 String _target_md5;
185 MD5Builder _md5;
186
187 int _ledPin;
188 uint8_t _ledOn;
189};
190
191extern UpdateClass Update;
192
193#endif
194
195#endif