OTA Subroutine
This commit is contained in:
parent
142f0dd2e2
commit
1ecd97d821
|
@ -9,6 +9,11 @@ bool ESPMegaDisplay::recieveSerialCommand(bool process)
|
|||
{
|
||||
bool dataRecieved = false;
|
||||
// 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())
|
||||
{
|
||||
rx_buffer[rx_buffer_index] = displayAdapter->read();
|
||||
|
@ -22,6 +27,7 @@ bool ESPMegaDisplay::recieveSerialCommand(bool process)
|
|||
this->processSerialCommand();
|
||||
dataRecieved = true;
|
||||
}
|
||||
xSemaphoreGive(this->serialMutex);
|
||||
return dataRecieved;
|
||||
}
|
||||
|
||||
|
@ -58,13 +64,15 @@ void ESPMegaDisplay::processSerialCommand()
|
|||
{
|
||||
processPageReportPayload();
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
// The payload does not match any of the expected payload types
|
||||
// Pass the payload to the payload callbacks
|
||||
// type, payload, length
|
||||
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;
|
||||
|
@ -115,6 +123,8 @@ void ESPMegaDisplay::processPageReportPayload()
|
|||
|
||||
/**
|
||||
* @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()
|
||||
{
|
||||
|
@ -129,8 +139,14 @@ void ESPMegaDisplay::sendStopBytes()
|
|||
*/
|
||||
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);
|
||||
sendStopBytes();
|
||||
xSemaphoreGive(this->serialMutex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -139,9 +155,15 @@ void ESPMegaDisplay::sendCommand(char *command)
|
|||
*/
|
||||
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);
|
||||
sendStopBytes();
|
||||
xSemaphoreGive(this->serialMutex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -151,10 +173,16 @@ void ESPMegaDisplay::jumpToPage(int page)
|
|||
*/
|
||||
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("=");
|
||||
this->displayAdapter->print(value);
|
||||
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)
|
||||
{
|
||||
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("=\"");
|
||||
this->displayAdapter->print(value);
|
||||
this->displayAdapter->print("\"");
|
||||
sendStopBytes();
|
||||
xSemaphoreGive(this->serialMutex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -185,9 +219,15 @@ uint32_t ESPMegaDisplay::getNumber(const char *component)
|
|||
this->rx_buffer_index = 0;
|
||||
uint32_t start = millis();
|
||||
// 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(component);
|
||||
sendStopBytes();
|
||||
xSemaphoreGive(this->serialMutex);
|
||||
// Try to get a valid payload DISPLAY_FETCH_RETRY_COUNT times
|
||||
// Wait for the response
|
||||
bool validPayload = false;
|
||||
|
@ -246,9 +286,15 @@ const char *ESPMegaDisplay::getString(const char *component)
|
|||
this->rx_buffer_index = 0;
|
||||
uint32_t start = millis();
|
||||
// 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(component);
|
||||
sendStopBytes();
|
||||
xSemaphoreGive(this->serialMutex);
|
||||
// Wait for the response
|
||||
// Try to get a valid payload DISPLAY_FETCH_RETRY_COUNT times
|
||||
// Wait for the response
|
||||
|
@ -307,9 +353,15 @@ bool ESPMegaDisplay::getStringToBuffer(const char *component, char *buffer, uint
|
|||
this->rx_buffer_index = 0;
|
||||
uint32_t start = millis();
|
||||
// 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(component);
|
||||
sendStopBytes();
|
||||
xSemaphoreGive(this->serialMutex);
|
||||
// Wait for the response
|
||||
// Try to get a valid payload DISPLAY_FETCH_RETRY_COUNT times
|
||||
// Wait for the response
|
||||
|
@ -404,9 +456,15 @@ bool ESPMegaDisplay::payloadIsValid()
|
|||
*/
|
||||
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(value);
|
||||
sendStopBytes();
|
||||
xSemaphoreGive(this->serialMutex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -415,9 +473,15 @@ void ESPMegaDisplay::setBrightness(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(value);
|
||||
sendStopBytes();
|
||||
xSemaphoreGive(this->serialMutex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -427,9 +491,15 @@ void ESPMegaDisplay::reset()
|
|||
{
|
||||
// First we send a stop bytes to clear the serial buffer
|
||||
// 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();
|
||||
this->displayAdapter->print("rest");
|
||||
sendStopBytes();
|
||||
xSemaphoreGive(this->serialMutex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -448,8 +518,14 @@ ESPMegaDisplay::ESPMegaDisplay(HardwareSerial *displayAdapter)
|
|||
*/
|
||||
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->flush();
|
||||
xSemaphoreGive(this->serialMutex);
|
||||
this->reset();
|
||||
}
|
||||
|
||||
|
@ -510,7 +586,7 @@ void ESPMegaDisplay::unregisterPageChangeCallback(uint16_t handle)
|
|||
* @param callback 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();
|
||||
payload_callbacks[handle] = callback;
|
||||
|
@ -524,4 +600,120 @@ uint16_t ESPMegaDisplay::registerPayloadCallback(std::function<void(uint8_t, uin
|
|||
void ESPMegaDisplay::unregisterPayloadCallback(uint16_t 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 <map>
|
||||
|
||||
#define DISPLAY_MUTEX_TAKE_TIMEOUT 1000 // ms
|
||||
#define OTA_WAIT_TIMEOUT 1000 // ms
|
||||
|
||||
#define DISPLAY_FETCH_TIMEOUT 100 // ms
|
||||
#define DISPLAY_FETCH_RETRY_COUNT 5
|
||||
|
||||
|
@ -32,8 +35,13 @@ class ESPMegaDisplay
|
|||
void unregisterPageChangeCallback(uint16_t handle);
|
||||
uint16_t registerPayloadCallback(std::function<void(uint8_t, uint8_t*, uint8_t)> callback);
|
||||
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:
|
||||
SemaphoreHandle_t serialMutex;
|
||||
uint8_t currentPage;
|
||||
uint8_t rx_buffer_index;
|
||||
char rx_buffer[256];
|
||||
|
|
Loading…
Reference in New Issue