Skip to content

Commit 9ab4f1e

Browse files
authored
Merge pull request #147 from MathewHDYT/master
Backport bugfixes from v0.12.0
2 parents 5a5d27a + 6f20f76 commit 9ab4f1e

5 files changed

Lines changed: 56 additions & 34 deletions

File tree

library.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"arduino-libraries/ArduinoHttpClient" : "^0.4.0",
1313
"bblanchon/StreamUtils" : "^1.7.3"
1414
},
15-
"version": "0.11.0",
15+
"version": "0.11.1",
1616
"examples": "examples/*/*.ino",
1717
"frameworks": "arduino",
1818
"license": "MIT"

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=ThingsBoard
2-
version=0.11.0
2+
version=0.11.1
33
author=ThingsBoard Team
44
maintainer=ThingsBoard Team
55
sentence=ThingsBoard library for Arduino.

src/OTA_Handler.h

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,6 @@
1919
#include "OTA_Update_Callback.h"
2020
#include "OTA_Failure_Response.h"
2121

22-
// Library include.
23-
#ifdef ESP8266
24-
#include <Updater.h>
25-
#else
26-
#ifdef ESP32
27-
#include <Update.h>
28-
#endif // ESP32
29-
#endif // ESP8266
3022

3123
/// ---------------------------------
3224
/// Constant strings in flash memory.
@@ -69,7 +61,7 @@ constexpr char RECEIVED_UNEXPECTED_CHUNK[] = "Received chunk (%u), not the same
6961
constexpr char ERROR_UPDATE_BEGIN[] = "Failed to initalize flash updater";
7062
constexpr char ERROR_UPDATE_WRITE[] = "Only wrote (%u) bytes of binary data to flash memory instead of expected (%u)";
7163
constexpr char UPDATING_HASH_FAILED[] = "Updating hash failed";
72-
constexpr char ERROR_UPDATE_END[] = "Error (%u) during flash updater not all bytes written";
64+
constexpr char ERROR_UPDATE_END[] = "Error during flash updater not all bytes written";
7365
constexpr char CHKS_VER_FAILED[] = "Checksum verification failed";
7466
constexpr char FW_CHUNK[] = "Receive chunk (%i), with size (%u) bytes";
7567
constexpr char HASH_ACTUAL[] = "(%s) actual checksum: (%s)";
@@ -79,6 +71,7 @@ constexpr char FW_UPDATE_ABORTED[] = "Firmware update aborted";
7971
constexpr char FW_UPDATE_SUCCESS[] = "Update success";
8072
#endif // THINGSBOARD_ENABLE_PROGMEM
8173

74+
8275
/// @brief Handles actually writing the received firmware packets into flash memory
8376
/// @tparam Logger Logging class that should be used to print messages generated by ThingsBoard
8477
template<typename Logger>
@@ -119,8 +112,9 @@ class OTA_Handler {
119112
m_fw_algorithm = fw_algorithm;
120113
m_fw_checksum = fw_checksum;
121114
m_fw_checksum_algorithm = fw_checksum_algorithm;
115+
m_fw_updater = m_fw_callback->Get_Updater();
122116

123-
if (!m_publish_callback || !m_send_fw_state_callback || !m_finish_callback) {
117+
if (!m_publish_callback || !m_send_fw_state_callback || !m_finish_callback || !m_fw_updater) {
124118
Logger::log(OTA_CB_IS_NULL);
125119
(void)m_send_fw_state_callback(FW_STATE_FAILED, OTA_CB_IS_NULL);
126120
return Handle_Failure(OTA_Failure_Response::RETRY_NOTHING);
@@ -131,9 +125,7 @@ class OTA_Handler {
131125
/// @brief Stops the firmware update
132126
inline void Stop_Firmware_Update() {
133127
m_watchdog.detach();
134-
#ifdef ESP32
135-
Update.abort();
136-
#endif
128+
m_fw_updater->reset();
137129
Logger::log(FW_UPDATE_ABORTED);
138130
(void)m_send_fw_state_callback(FW_STATE_FAILED, FW_UPDATE_ABORTED);
139131
Handle_Failure(OTA_Failure_Response::RETRY_NOTHING);
@@ -145,7 +137,7 @@ class OTA_Handler {
145137
/// @param current_chunk Index of the chunk we recieved the binary data for
146138
/// @param payload Firmware packet data of the current chunk
147139
/// @param total_bytes Amount of bytes in the current firmware packet data
148-
inline void Process_Firmware_Packet(const uint32_t& current_chunk, uint8_t *payload, const uint32_t& total_bytes) {
140+
inline void Process_Firmware_Packet(const uint32_t& current_chunk, uint8_t *payload, const unsigned int& total_bytes) {
149141
(void)m_send_fw_state_callback(FW_STATE_DOWNLOADING, nullptr);
150142

151143
if (current_chunk != m_requested_chunks) {
@@ -163,15 +155,15 @@ class OTA_Handler {
163155

164156
if (current_chunk == 0U) {
165157
// Initialize Flash
166-
if (!Update.begin(m_fw_size)) {
158+
if (!m_fw_updater->begin(m_fw_size)) {
167159
Logger::log(ERROR_UPDATE_BEGIN);
168160
(void)m_send_fw_state_callback(FW_STATE_FAILED, ERROR_UPDATE_BEGIN);
169161
return Handle_Failure(OTA_Failure_Response::RETRY_UPDATE);
170162
}
171163
}
172164

173165
// Write received binary data to flash partition
174-
const size_t written_bytes = Update.write(payload, total_bytes);
166+
const size_t written_bytes = m_fw_updater->write(payload, total_bytes);
175167
if (written_bytes != total_bytes) {
176168
char message[Helper::detectSize(ERROR_UPDATE_WRITE, written_bytes, total_bytes)];
177169
snprintf_P(message, sizeof(message), ERROR_UPDATE_WRITE, written_bytes, total_bytes);
@@ -211,6 +203,7 @@ class OTA_Handler {
211203
std::string m_fw_algorithm;
212204
std::string m_fw_checksum;
213205
mbedtls_md_type_t m_fw_checksum_algorithm;
206+
IUpdater *m_fw_updater;
214207
HashGenerator m_hash;
215208
uint32_t m_total_chunks;
216209
uint32_t m_requested_chunks;
@@ -222,9 +215,7 @@ class OTA_Handler {
222215
m_retries = m_fw_callback->Get_Chunk_Retries();
223216
m_hash.start(m_fw_checksum_algorithm);
224217
m_watchdog.detach();
225-
#ifdef ESP32
226-
Update.abort();
227-
#endif
218+
m_fw_updater->reset();
228219
Request_Next_Firmware_Packet();
229220
}
230221

@@ -240,7 +231,7 @@ class OTA_Handler {
240231
(void)m_send_fw_state_callback(FW_STATE_FAILED, UNABLE_TO_REQUEST_CHUNCKS);
241232
}
242233

243-
// Watchdog gets started no matter if publishing request was successfull or not in hopes,
234+
// Watchdog gets started no matter if publishing request was successful or not in hopes,
244235
// that after the given timeout the callback calls this method again and can then publish the request successfully.
245236
m_watchdog.once(m_fw_callback->Get_Timeout());
246237
}
@@ -267,12 +258,9 @@ class OTA_Handler {
267258

268259
Logger::log(CHKS_VER_SUCCESS);
269260

270-
if (!Update.end()) {
271-
const uint8_t error = Update.getError();
272-
char message[Helper::detectSize(ERROR_UPDATE_END, error)];
273-
snprintf_P(message, sizeof(message), ERROR_UPDATE_END, error);
274-
Logger::log(message);
275-
(void)m_send_fw_state_callback(FW_STATE_FAILED, message);
261+
if (!m_fw_updater->end()) {
262+
Logger::log(ERROR_UPDATE_END);
263+
(void)m_send_fw_state_callback(FW_STATE_FAILED, ERROR_UPDATE_END);
276264
return Handle_Failure(OTA_Failure_Response::RETRY_UPDATE);
277265
}
278266

src/ThingsBoard.h

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,6 +1041,30 @@ class ThingsBoardSized {
10411041
return m_client.unsubscribe(ATTRIBUTE_TOPIC);
10421042
}
10431043

1044+
/// @brief Clears all currently subscribed callbacks and unsubscribed from all
1045+
/// currently subscribed MQTT topics, any response that will stil be received is discarded
1046+
/// and any ongoing firmware update is aborted and will not be finished.
1047+
/// Was previously done automatically in the connect() method, but is not done anymore,
1048+
/// because connect() method now reconencts to all previously subscribed MQTT topics instead,
1049+
/// therefore there is no need anymore to discard all previously subscribed callbacks and letting the user resubscribe
1050+
inline void Cleanup_Subscriptions() {
1051+
// Cleanup all server-side RPC subscriptions
1052+
this->RPC_Unsubscribe();
1053+
// Cleanup all client-side RPC requests
1054+
this->RPC_Request_Unsubscribe();
1055+
// Cleanup all shared attributes subscriptions
1056+
this->Shared_Attributes_Unsubscribe();
1057+
// Cleanup all client-side or shared attributes requests
1058+
this->Attributes_Request_Unsubscribe();
1059+
// Cleanup all provision requests
1060+
this->Provision_Unsubscribe();
1061+
// Stop any ongoing Firmware update,
1062+
// which will in turn cleanup the internal member variables of the OTAHandler class
1063+
// as well as all firmware subscriptions
1064+
// and inform the user of the failed firmware update
1065+
this->Stop_Firmware_Update();
1066+
}
1067+
10441068
private:
10451069

10461070
#if THINGSBOARD_ENABLE_STREAM_UTILS
@@ -1369,20 +1393,30 @@ class ThingsBoardSized {
13691393
/// @return Whether connecting to ThingsBoard was successful or not
13701394
inline bool connect_to_host(const char *access_token, const char *client_id, const char *password) {
13711395
const bool connection_result = m_client.connect(client_id, access_token, password);
1396+
13721397
if (!connection_result) {
13731398
Logger::log(CONNECT_FAILED);
13741399
return connection_result;
13751400
}
13761401

1377-
this->RPC_Unsubscribe(); // Cleanup all server-side RPC subscriptions
1378-
this->RPC_Request_Unsubscribe(); // Cleanup all client-side RPC requests
1379-
this->Shared_Attributes_Unsubscribe(); // Cleanup all shared attributes subscriptions
1380-
this->Attributes_Request_Unsubscribe(); // Cleanup all client-side or shared attributes requests
1381-
this->Provision_Unsubscribe(); // Cleanup all provision subscriptions
1382-
// Firmware subscriptions are not cleaned up to ensure that it can be continued if the connection drops while the update is ongoing
1402+
// Only attempt to resubscribe if we connected successfully
1403+
Resubscribe_Topics();
13831404
return connection_result;
13841405
}
13851406

1407+
/// @brief Resubscribes to topics that establish a permanent connection with MQTT, meaning they may receive more than one event over their lifetime,
1408+
/// whereas other events that are only ever called once and then deleted after they have been handled are not resubscribed.
1409+
/// This is done, because the chance of disconnecting the moment when a request event (provisioning, attribute request, client-side rpc) was sent
1410+
/// and then reconnecting and resubscribing to that topic fast enough to still receive the message is not feasible
1411+
inline void Resubscribe_Topics() {
1412+
if (!m_rpc_callbacks.empty()) {
1413+
m_client.subscribe(RPC_SUBSCRIBE_TOPIC);
1414+
}
1415+
if (!m_shared_attribute_update_callbacks.empty()) {
1416+
m_client.subscribe(ATTRIBUTE_TOPIC);
1417+
}
1418+
}
1419+
13861420
#if !THINGSBOARD_ENABLE_DYNAMIC
13871421
/// @brief Reserves size for the given amount of items in our internal callback vectors beforehand for performance reasons,
13881422
/// this ensures the internal memory blocks do not have to move if new data is inserted,

0 commit comments

Comments
 (0)