OTA Subroutine
This commit is contained in:
parent
142f0dd2e2
commit
1ecd97d821
|
@ -9,6 +9,11 @@ bool ESPMegaDisplay::recieveSerialCommand(bool process)
|
||||||
{
|
{
|
||||||
bool dataRecieved = false;
|
bool dataRecieved = false;
|
||||||
// Read the serial buffer if available
|
// Read the serial buffer if available
|
||||||
|
if (xSemaphoreTake(this->serialMutex, DISPLAY_MUTEX_TAKE_TIMEOUT) == pdFALSE)
|
||||||
|
{
|
||||||
|
ESP_LOGI("ESPMegaDisplay", "Failed to take serial mutex");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
while (displayAdapter->available())
|
while (displayAdapter->available())
|
||||||
{
|
{
|
||||||
rx_buffer[rx_buffer_index] = displayAdapter->read();
|
rx_buffer[rx_buffer_index] = displayAdapter->read();
|
||||||
|
@ -22,6 +27,7 @@ bool ESPMegaDisplay::recieveSerialCommand(bool process)
|
||||||
this->processSerialCommand();
|
this->processSerialCommand();
|
||||||
dataRecieved = true;
|
dataRecieved = true;
|
||||||
}
|
}
|
||||||
|
xSemaphoreGive(this->serialMutex);
|
||||||
return dataRecieved;
|
return dataRecieved;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,13 +64,15 @@ void ESPMegaDisplay::processSerialCommand()
|
||||||
{
|
{
|
||||||
processPageReportPayload();
|
processPageReportPayload();
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
// The payload does not match any of the expected payload types
|
// The payload does not match any of the expected payload types
|
||||||
// Pass the payload to the payload callbacks
|
// Pass the payload to the payload callbacks
|
||||||
// type, payload, length
|
// type, payload, length
|
||||||
for (auto const &callback : payload_callbacks)
|
for (auto const &callback : payload_callbacks)
|
||||||
{
|
{
|
||||||
callback.second(rx_buffer[0], reinterpret_cast<unsigned char*>(&rx_buffer[1]), rx_buffer_index - 4);;
|
callback.second(rx_buffer[0], reinterpret_cast<unsigned char *>(&rx_buffer[1]), rx_buffer_index - 4);
|
||||||
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->rx_buffer_index = 0;
|
this->rx_buffer_index = 0;
|
||||||
|
@ -115,6 +123,8 @@ void ESPMegaDisplay::processPageReportPayload()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sends stop bytes to the display adapter.
|
* @brief Sends stop bytes to the display adapter.
|
||||||
|
*
|
||||||
|
* @note This function does not take the serial mutex, it is assumed that the caller has already taken the mutex.
|
||||||
*/
|
*/
|
||||||
void ESPMegaDisplay::sendStopBytes()
|
void ESPMegaDisplay::sendStopBytes()
|
||||||
{
|
{
|
||||||
|
@ -129,8 +139,14 @@ void ESPMegaDisplay::sendStopBytes()
|
||||||
*/
|
*/
|
||||||
void ESPMegaDisplay::sendCommand(char *command)
|
void ESPMegaDisplay::sendCommand(char *command)
|
||||||
{
|
{
|
||||||
|
if (xSemaphoreTake(this->serialMutex, DISPLAY_MUTEX_TAKE_TIMEOUT) == pdFALSE)
|
||||||
|
{
|
||||||
|
ESP_LOGI("ESPMegaDisplay", "Failed to take serial mutex");
|
||||||
|
return;
|
||||||
|
}
|
||||||
displayAdapter->print(command);
|
displayAdapter->print(command);
|
||||||
sendStopBytes();
|
sendStopBytes();
|
||||||
|
xSemaphoreGive(this->serialMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -139,9 +155,15 @@ void ESPMegaDisplay::sendCommand(char *command)
|
||||||
*/
|
*/
|
||||||
void ESPMegaDisplay::jumpToPage(int page)
|
void ESPMegaDisplay::jumpToPage(int page)
|
||||||
{
|
{
|
||||||
|
if (xSemaphoreTake(this->serialMutex, DISPLAY_MUTEX_TAKE_TIMEOUT) == pdFALSE)
|
||||||
|
{
|
||||||
|
ESP_LOGI("ESPMegaDisplay", "Failed to take serial mutex");
|
||||||
|
return;
|
||||||
|
}
|
||||||
this->displayAdapter->print("page ");
|
this->displayAdapter->print("page ");
|
||||||
this->displayAdapter->print(page);
|
this->displayAdapter->print(page);
|
||||||
sendStopBytes();
|
sendStopBytes();
|
||||||
|
xSemaphoreGive(this->serialMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -151,10 +173,16 @@ void ESPMegaDisplay::jumpToPage(int page)
|
||||||
*/
|
*/
|
||||||
void ESPMegaDisplay::setNumber(const char *component, int value)
|
void ESPMegaDisplay::setNumber(const char *component, int value)
|
||||||
{
|
{
|
||||||
|
if (xSemaphoreTake(this->serialMutex, DISPLAY_MUTEX_TAKE_TIMEOUT) == pdFALSE)
|
||||||
|
{
|
||||||
|
ESP_LOGI("ESPMegaDisplay", "Failed to take serial mutex");
|
||||||
|
return;
|
||||||
|
}
|
||||||
this->displayAdapter->print(component);
|
this->displayAdapter->print(component);
|
||||||
this->displayAdapter->print("=");
|
this->displayAdapter->print("=");
|
||||||
this->displayAdapter->print(value);
|
this->displayAdapter->print(value);
|
||||||
sendStopBytes();
|
sendStopBytes();
|
||||||
|
xSemaphoreGive(this->serialMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -164,11 +192,17 @@ void ESPMegaDisplay::setNumber(const char *component, int value)
|
||||||
*/
|
*/
|
||||||
void ESPMegaDisplay::setString(const char *component, const char *value)
|
void ESPMegaDisplay::setString(const char *component, const char *value)
|
||||||
{
|
{
|
||||||
|
if (xSemaphoreTake(this->serialMutex, DISPLAY_MUTEX_TAKE_TIMEOUT) == pdFALSE)
|
||||||
|
{
|
||||||
|
ESP_LOGI("ESPMegaDisplay", "Failed to take serial mutex");
|
||||||
|
return;
|
||||||
|
}
|
||||||
this->displayAdapter->print(component);
|
this->displayAdapter->print(component);
|
||||||
this->displayAdapter->print("=\"");
|
this->displayAdapter->print("=\"");
|
||||||
this->displayAdapter->print(value);
|
this->displayAdapter->print(value);
|
||||||
this->displayAdapter->print("\"");
|
this->displayAdapter->print("\"");
|
||||||
sendStopBytes();
|
sendStopBytes();
|
||||||
|
xSemaphoreGive(this->serialMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -185,9 +219,15 @@ uint32_t ESPMegaDisplay::getNumber(const char *component)
|
||||||
this->rx_buffer_index = 0;
|
this->rx_buffer_index = 0;
|
||||||
uint32_t start = millis();
|
uint32_t start = millis();
|
||||||
// Send the get command
|
// Send the get command
|
||||||
|
if (xSemaphoreTake(this->serialMutex, DISPLAY_MUTEX_TAKE_TIMEOUT) == pdFALSE)
|
||||||
|
{
|
||||||
|
ESP_LOGI("ESPMegaDisplay", "Failed to take serial mutex");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
this->displayAdapter->print("get ");
|
this->displayAdapter->print("get ");
|
||||||
this->displayAdapter->print(component);
|
this->displayAdapter->print(component);
|
||||||
sendStopBytes();
|
sendStopBytes();
|
||||||
|
xSemaphoreGive(this->serialMutex);
|
||||||
// Try to get a valid payload DISPLAY_FETCH_RETRY_COUNT times
|
// Try to get a valid payload DISPLAY_FETCH_RETRY_COUNT times
|
||||||
// Wait for the response
|
// Wait for the response
|
||||||
bool validPayload = false;
|
bool validPayload = false;
|
||||||
|
@ -246,9 +286,15 @@ const char *ESPMegaDisplay::getString(const char *component)
|
||||||
this->rx_buffer_index = 0;
|
this->rx_buffer_index = 0;
|
||||||
uint32_t start = millis();
|
uint32_t start = millis();
|
||||||
// Send the get command
|
// Send the get command
|
||||||
|
if (xSemaphoreTake(this->serialMutex, DISPLAY_MUTEX_TAKE_TIMEOUT) == pdFALSE)
|
||||||
|
{
|
||||||
|
ESP_LOGI("ESPMegaDisplay", "Failed to take serial mutex");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
this->displayAdapter->print("get ");
|
this->displayAdapter->print("get ");
|
||||||
this->displayAdapter->print(component);
|
this->displayAdapter->print(component);
|
||||||
sendStopBytes();
|
sendStopBytes();
|
||||||
|
xSemaphoreGive(this->serialMutex);
|
||||||
// Wait for the response
|
// Wait for the response
|
||||||
// Try to get a valid payload DISPLAY_FETCH_RETRY_COUNT times
|
// Try to get a valid payload DISPLAY_FETCH_RETRY_COUNT times
|
||||||
// Wait for the response
|
// Wait for the response
|
||||||
|
@ -307,9 +353,15 @@ bool ESPMegaDisplay::getStringToBuffer(const char *component, char *buffer, uint
|
||||||
this->rx_buffer_index = 0;
|
this->rx_buffer_index = 0;
|
||||||
uint32_t start = millis();
|
uint32_t start = millis();
|
||||||
// Send the get command
|
// Send the get command
|
||||||
|
if (xSemaphoreTake(this->serialMutex, DISPLAY_MUTEX_TAKE_TIMEOUT) == pdFALSE)
|
||||||
|
{
|
||||||
|
ESP_LOGI("ESPMegaDisplay", "Failed to take serial mutex");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
this->displayAdapter->print("get ");
|
this->displayAdapter->print("get ");
|
||||||
this->displayAdapter->print(component);
|
this->displayAdapter->print(component);
|
||||||
sendStopBytes();
|
sendStopBytes();
|
||||||
|
xSemaphoreGive(this->serialMutex);
|
||||||
// Wait for the response
|
// Wait for the response
|
||||||
// Try to get a valid payload DISPLAY_FETCH_RETRY_COUNT times
|
// Try to get a valid payload DISPLAY_FETCH_RETRY_COUNT times
|
||||||
// Wait for the response
|
// Wait for the response
|
||||||
|
@ -404,9 +456,15 @@ bool ESPMegaDisplay::payloadIsValid()
|
||||||
*/
|
*/
|
||||||
void ESPMegaDisplay::setBrightness(int value)
|
void ESPMegaDisplay::setBrightness(int value)
|
||||||
{
|
{
|
||||||
|
if (xSemaphoreTake(this->serialMutex, DISPLAY_MUTEX_TAKE_TIMEOUT) == pdFALSE)
|
||||||
|
{
|
||||||
|
ESP_LOGI("ESPMegaDisplay", "Failed to take serial mutex");
|
||||||
|
return;
|
||||||
|
}
|
||||||
this->displayAdapter->print("dim=");
|
this->displayAdapter->print("dim=");
|
||||||
this->displayAdapter->print(value);
|
this->displayAdapter->print(value);
|
||||||
sendStopBytes();
|
sendStopBytes();
|
||||||
|
xSemaphoreGive(this->serialMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -415,9 +473,15 @@ void ESPMegaDisplay::setBrightness(int value)
|
||||||
*/
|
*/
|
||||||
void ESPMegaDisplay::setVolume(int value)
|
void ESPMegaDisplay::setVolume(int value)
|
||||||
{
|
{
|
||||||
|
if (xSemaphoreTake(this->serialMutex, DISPLAY_MUTEX_TAKE_TIMEOUT) == pdFALSE)
|
||||||
|
{
|
||||||
|
ESP_LOGI("ESPMegaDisplay", "Failed to take serial mutex");
|
||||||
|
return;
|
||||||
|
}
|
||||||
this->displayAdapter->print("vol=");
|
this->displayAdapter->print("vol=");
|
||||||
this->displayAdapter->print(value);
|
this->displayAdapter->print(value);
|
||||||
sendStopBytes();
|
sendStopBytes();
|
||||||
|
xSemaphoreGive(this->serialMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -427,9 +491,15 @@ void ESPMegaDisplay::reset()
|
||||||
{
|
{
|
||||||
// First we send a stop bytes to clear the serial buffer
|
// First we send a stop bytes to clear the serial buffer
|
||||||
// This ensures that the display is ready to receive the reset command
|
// This ensures that the display is ready to receive the reset command
|
||||||
|
if (xSemaphoreTake(this->serialMutex, DISPLAY_MUTEX_TAKE_TIMEOUT) == pdFALSE)
|
||||||
|
{
|
||||||
|
ESP_LOGI("ESPMegaDisplay", "Failed to take serial mutex");
|
||||||
|
return;
|
||||||
|
}
|
||||||
sendStopBytes();
|
sendStopBytes();
|
||||||
this->displayAdapter->print("rest");
|
this->displayAdapter->print("rest");
|
||||||
sendStopBytes();
|
sendStopBytes();
|
||||||
|
xSemaphoreGive(this->serialMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -448,8 +518,14 @@ ESPMegaDisplay::ESPMegaDisplay(HardwareSerial *displayAdapter)
|
||||||
*/
|
*/
|
||||||
void ESPMegaDisplay::begin()
|
void ESPMegaDisplay::begin()
|
||||||
{
|
{
|
||||||
|
if (xSemaphoreTake(this->serialMutex, DISPLAY_MUTEX_TAKE_TIMEOUT) == pdFALSE)
|
||||||
|
{
|
||||||
|
ESP_LOGE("ESPMegaDisplay", "Failed to take serial mutex");
|
||||||
|
return;
|
||||||
|
}
|
||||||
this->displayAdapter->setTimeout(100);
|
this->displayAdapter->setTimeout(100);
|
||||||
this->displayAdapter->flush();
|
this->displayAdapter->flush();
|
||||||
|
xSemaphoreGive(this->serialMutex);
|
||||||
this->reset();
|
this->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,7 +586,7 @@ void ESPMegaDisplay::unregisterPageChangeCallback(uint16_t handle)
|
||||||
* @param callback The callback function.
|
* @param callback The callback function.
|
||||||
* @return The handle of the callback function.
|
* @return The handle of the callback function.
|
||||||
*/
|
*/
|
||||||
uint16_t ESPMegaDisplay::registerPayloadCallback(std::function<void(uint8_t, uint8_t*, uint8_t)> callback)
|
uint16_t ESPMegaDisplay::registerPayloadCallback(std::function<void(uint8_t, uint8_t *, uint8_t)> callback)
|
||||||
{
|
{
|
||||||
uint16_t handle = payload_callbacks.size();
|
uint16_t handle = payload_callbacks.size();
|
||||||
payload_callbacks[handle] = callback;
|
payload_callbacks[handle] = callback;
|
||||||
|
@ -525,3 +601,119 @@ void ESPMegaDisplay::unregisterPayloadCallback(uint16_t handle)
|
||||||
{
|
{
|
||||||
payload_callbacks.erase(handle);
|
payload_callbacks.erase(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Takes the serial mutex.
|
||||||
|
*/
|
||||||
|
void ESPMegaDisplay::takeSerialMutex()
|
||||||
|
{
|
||||||
|
xSemaphoreTake(this->serialMutex, DISPLAY_MUTEX_TAKE_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gives the serial mutex.
|
||||||
|
*/
|
||||||
|
void ESPMegaDisplay::giveSerialMutex()
|
||||||
|
{
|
||||||
|
xSemaphoreGive(this->serialMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Starts an OTA update.
|
||||||
|
* @param size The size of the update.
|
||||||
|
* @return True if the OTA update is started, false otherwise.
|
||||||
|
*/
|
||||||
|
bool ESPMegaDisplay::beginOTA(size_t size)
|
||||||
|
{
|
||||||
|
if (xSemaphoreTake(this->serialMutex, DISPLAY_MUTEX_TAKE_TIMEOUT) == pdFALSE)
|
||||||
|
{
|
||||||
|
ESP_LOGI("ESPMegaDisplay", "Failed to take serial mutex");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ESP_LOGD("ESPMegaDisplay", "LCD OTA Subroutine has taken the serial mutex, all other tasks will be blocked until the OTA update is complete.");
|
||||||
|
// We have taken the serial mutex, all helper functions will be blocked until the OTA update is complete
|
||||||
|
// Thus, we have to interact directly with the display adapter
|
||||||
|
this->sendStopBytes();
|
||||||
|
this->displayAdapter->print("rest");
|
||||||
|
this->sendStopBytes();
|
||||||
|
delay(500);
|
||||||
|
this->displayAdapter->print("connect");
|
||||||
|
this->sendStopBytes();
|
||||||
|
delay(1000);
|
||||||
|
// Flush the serial recieve buffer
|
||||||
|
while (this->displayAdapter->available())
|
||||||
|
this->displayAdapter->read();
|
||||||
|
this->displayAdapter->print("whmi-wri ");
|
||||||
|
this->displayAdapter->print(size);
|
||||||
|
this->displayAdapter->print(",115200,res0");
|
||||||
|
this->sendStopBytes();
|
||||||
|
delay(1000);
|
||||||
|
// If the display is ready, it will send a 0x05 byte
|
||||||
|
// If it does, return true, otherwise return false
|
||||||
|
unsigned long startTime = millis();
|
||||||
|
while (millis() - startTime < OTA_WAIT_TIMEOUT)
|
||||||
|
{
|
||||||
|
if (this->displayAdapter->available())
|
||||||
|
{
|
||||||
|
if (this->displayAdapter->read() == 0x05)
|
||||||
|
{
|
||||||
|
ESP_LOGV("ESPMegaDisplay", "LCD OTA Subroutine is ready to receive data.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// FLush the serial recieve buffer
|
||||||
|
while (this->displayAdapter->available())
|
||||||
|
this->displayAdapter->read();
|
||||||
|
ESP_LOGE("ESPMegaDisplay", "LCD OTA Subroutine failed to initialize.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Writes data to the display during an OTA update.
|
||||||
|
* @param data The data to write.
|
||||||
|
* @param size The size of the data.
|
||||||
|
* @return True if the data is written, false otherwise.
|
||||||
|
*/
|
||||||
|
bool ESPMegaDisplay::writeOTA(uint8_t *data, size_t size)
|
||||||
|
{
|
||||||
|
// Check if the data size is too large
|
||||||
|
if(size>4096)
|
||||||
|
{
|
||||||
|
ESP_LOGE("ESPMegaDisplay", "LCD OTA Subroutine failed to write data, data size is too large.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Flush the serial recieve buffer
|
||||||
|
while (this->displayAdapter->available())
|
||||||
|
this->displayAdapter->read();
|
||||||
|
// Write the data
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
this->displayAdapter->write(data[i]);
|
||||||
|
// After writing the data, the display will send a 0x05 byte
|
||||||
|
// If it does, return true, otherwise return false
|
||||||
|
unsigned long startTime = millis();
|
||||||
|
while (millis() - startTime < OTA_WAIT_TIMEOUT)
|
||||||
|
{
|
||||||
|
if (this->displayAdapter->available())
|
||||||
|
{
|
||||||
|
if (this->displayAdapter->read() == 0x05)
|
||||||
|
{
|
||||||
|
ESP_LOGV("ESPMegaDisplay", "LCD OTA Subroutine is ready to receive data.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ESP_LOGE("ESPMegaDisplay", "LCD OTA Subroutine failed to write data.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Ends an LCD OTA update.
|
||||||
|
*/
|
||||||
|
void ESPMegaDisplay::endOTA()
|
||||||
|
{
|
||||||
|
xSemaphoreGive(this->serialMutex);
|
||||||
|
this->reset();
|
||||||
|
delay(500);
|
||||||
|
this->begin();
|
||||||
|
}
|
|
@ -2,6 +2,9 @@
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#define DISPLAY_MUTEX_TAKE_TIMEOUT 1000 // ms
|
||||||
|
#define OTA_WAIT_TIMEOUT 1000 // ms
|
||||||
|
|
||||||
#define DISPLAY_FETCH_TIMEOUT 100 // ms
|
#define DISPLAY_FETCH_TIMEOUT 100 // ms
|
||||||
#define DISPLAY_FETCH_RETRY_COUNT 5
|
#define DISPLAY_FETCH_RETRY_COUNT 5
|
||||||
|
|
||||||
|
@ -32,8 +35,13 @@ class ESPMegaDisplay
|
||||||
void unregisterPageChangeCallback(uint16_t handle);
|
void unregisterPageChangeCallback(uint16_t handle);
|
||||||
uint16_t registerPayloadCallback(std::function<void(uint8_t, uint8_t*, uint8_t)> callback);
|
uint16_t registerPayloadCallback(std::function<void(uint8_t, uint8_t*, uint8_t)> callback);
|
||||||
void unregisterPayloadCallback(uint16_t handle);
|
void unregisterPayloadCallback(uint16_t handle);
|
||||||
|
void takeSerialMutex();
|
||||||
|
void giveSerialMutex();
|
||||||
|
bool beginOTA(size_t size);
|
||||||
|
bool writeOTA(uint8_t* data, size_t size);
|
||||||
|
void endOTA();
|
||||||
protected:
|
protected:
|
||||||
|
SemaphoreHandle_t serialMutex;
|
||||||
uint8_t currentPage;
|
uint8_t currentPage;
|
||||||
uint8_t rx_buffer_index;
|
uint8_t rx_buffer_index;
|
||||||
char rx_buffer[256];
|
char rx_buffer[256];
|
||||||
|
|
Loading…
Reference in New Issue