mirror of
https://github.com/arendst/Tasmota.git
synced 2025-04-26 15:57:16 +00:00
Initial support for SHD web gui firmware upload
Initial support for Shelly Dimmer web gui firmware upload when #define SHELLY_FW_UPGRADE2 is enabled. #define SHELLY_FW_UPGRADE must be disabled at that time
This commit is contained in:
parent
ccbf634966
commit
acf0e79acb
@ -44,7 +44,7 @@ const uint16_t HTTP_OTA_RESTART_RECONNECT_TIME = 20000; // milliseconds - Allow
|
|||||||
uint8_t *efm8bb1_update = nullptr;
|
uint8_t *efm8bb1_update = nullptr;
|
||||||
#endif // USE_RF_FLASH
|
#endif // USE_RF_FLASH
|
||||||
|
|
||||||
enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1, UPL_TASMOTACLIENT, UPL_EFR32 };
|
enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1, UPL_TASMOTACLIENT, UPL_EFR32, UPL_SHD };
|
||||||
|
|
||||||
#ifdef USE_UNISHOX_COMPRESSION
|
#ifdef USE_UNISHOX_COMPRESSION
|
||||||
#ifdef USE_JAVASCRIPT_ES6
|
#ifdef USE_JAVASCRIPT_ES6
|
||||||
@ -2569,6 +2569,42 @@ void HandleInformation(void)
|
|||||||
|
|
||||||
/*-------------------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if defined(SHELLY_FW_UPGRADE2)
|
||||||
|
|
||||||
|
struct {
|
||||||
|
size_t spi_hex_size;
|
||||||
|
size_t spi_sector_counter;
|
||||||
|
size_t spi_sector_cursor;
|
||||||
|
bool ready;
|
||||||
|
} BUpload;
|
||||||
|
|
||||||
|
uint32_t BUploadStartSector(void) {
|
||||||
|
return (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 2; // Stay on the safe side
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t BUploadInit(void) {
|
||||||
|
BUpload.spi_hex_size = 0;
|
||||||
|
BUpload.spi_sector_counter = BUploadStartSector();
|
||||||
|
BUpload.spi_sector_cursor = 0;
|
||||||
|
BUpload.ready = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BUploadWriteBuffer(uint8_t *buf, size_t size) {
|
||||||
|
if (0 == BUpload.spi_sector_cursor) { // Starting a new sector write so we need to erase it first
|
||||||
|
ESP.flashEraseSector(BUpload.spi_sector_counter);
|
||||||
|
}
|
||||||
|
BUpload.spi_sector_cursor++;
|
||||||
|
ESP.flashWrite((BUpload.spi_sector_counter * SPI_FLASH_SEC_SIZE) + ((BUpload.spi_sector_cursor -1) * 2048), (uint32_t*)buf, size);
|
||||||
|
BUpload.spi_hex_size += size;
|
||||||
|
if (2 == BUpload.spi_sector_cursor) { // The web upload sends 2048 bytes at a time so keep track of the cursor position to reset it for the next flash sector erase
|
||||||
|
BUpload.spi_sector_cursor = 0;
|
||||||
|
BUpload.spi_sector_counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_TASMOTA_CLIENT or SHELLY_FW_UPGRADE2
|
||||||
|
|
||||||
void HandleUpgradeFirmware(void)
|
void HandleUpgradeFirmware(void)
|
||||||
{
|
{
|
||||||
if (!HttpCheckPriviledgedAccess()) { return; }
|
if (!HttpCheckPriviledgedAccess()) { return; }
|
||||||
@ -2668,12 +2704,21 @@ void HandleUploadDone(void)
|
|||||||
} else {
|
} else {
|
||||||
WSContentSend_P(PSTR("%06x'>" D_SUCCESSFUL "</font></b><br>"), WebColor(COL_TEXT_SUCCESS));
|
WSContentSend_P(PSTR("%06x'>" D_SUCCESSFUL "</font></b><br>"), WebColor(COL_TEXT_SUCCESS));
|
||||||
TasmotaGlobal.restart_flag = 2; // Always restart to re-enable disabled features during update
|
TasmotaGlobal.restart_flag = 2; // Always restart to re-enable disabled features during update
|
||||||
|
|
||||||
|
#ifdef SHELLY_FW_UPGRADE2
|
||||||
|
if (BUpload.ready) {
|
||||||
|
WSContentSend_P(PSTR("<br><div style='text-align:center;'><b>" D_TRANSFER_STARTED " ...</b></div>"));
|
||||||
|
TasmotaGlobal.restart_flag = 0; // Hold restart as code still needs to be transferred to STM
|
||||||
|
}
|
||||||
|
#endif // SHELLY_FW_UPGRADE2
|
||||||
|
|
||||||
#ifdef USE_TASMOTA_CLIENT
|
#ifdef USE_TASMOTA_CLIENT
|
||||||
if (TasmotaClient_GetFlagFlashing()) {
|
if (TasmotaClient_GetFlagFlashing()) {
|
||||||
WSContentSend_P(PSTR("<br><div style='text-align:center;'><b>" D_TRANSFER_STARTED " ...</b></div>"));
|
WSContentSend_P(PSTR("<br><div style='text-align:center;'><b>" D_TRANSFER_STARTED " ...</b></div>"));
|
||||||
TasmotaGlobal.restart_flag = 0; // Hold restart as code still needs to be transferred to Atmega
|
TasmotaGlobal.restart_flag = 0; // Hold restart as code still needs to be transferred to Atmega
|
||||||
}
|
}
|
||||||
#endif // USE_TASMOTA_CLIENT
|
#endif // USE_TASMOTA_CLIENT
|
||||||
|
|
||||||
if (TasmotaGlobal.restart_flag) {
|
if (TasmotaGlobal.restart_flag) {
|
||||||
WSContentSend_P(HTTP_MSG_RSTRT);
|
WSContentSend_P(HTTP_MSG_RSTRT);
|
||||||
ShowWebSource(SRC_WEBGUI);
|
ShowWebSource(SRC_WEBGUI);
|
||||||
@ -2684,11 +2729,17 @@ void HandleUploadDone(void)
|
|||||||
WSContentSpaceButton(BUTTON_MAIN);
|
WSContentSpaceButton(BUTTON_MAIN);
|
||||||
WSContentStop();
|
WSContentStop();
|
||||||
|
|
||||||
|
#ifdef SHELLY_FW_UPGRADE2
|
||||||
|
if (BUpload.ready) {
|
||||||
|
ShdFlash(BUploadStartSector() * SPI_FLASH_SEC_SIZE, BUpload.spi_hex_size);
|
||||||
|
}
|
||||||
|
#endif // SHELLY_FW_UPGRADE2
|
||||||
|
|
||||||
#ifdef USE_TASMOTA_CLIENT
|
#ifdef USE_TASMOTA_CLIENT
|
||||||
if (TasmotaClient_GetFlagFlashing()) {
|
if (TasmotaClient_GetFlagFlashing()) {
|
||||||
TasmotaClient_Flash();
|
TasmotaClient_Flash();
|
||||||
}
|
}
|
||||||
#endif
|
#endif // USE_TASMOTA_CLIENT
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleUploadLoop(void)
|
void HandleUploadLoop(void)
|
||||||
@ -2776,6 +2827,15 @@ void HandleUploadLoop(void)
|
|||||||
if (Web.upload_error != 0) { return; }
|
if (Web.upload_error != 0) { return; }
|
||||||
} else
|
} else
|
||||||
#endif // USE_RF_FLASH
|
#endif // USE_RF_FLASH
|
||||||
|
#ifdef SHELLY_FW_UPGRADE2
|
||||||
|
if (ShdPresent() && (0x00 == upload.buf[0]) && (0x10 == upload.buf[1])) {
|
||||||
|
Update.end(); // End esp8266 update session
|
||||||
|
Web.upload_file_type = UPL_SHD;
|
||||||
|
|
||||||
|
Web.upload_error = BUploadInit();
|
||||||
|
if (Web.upload_error != 0) { return; }
|
||||||
|
} else
|
||||||
|
#endif // SHELLY_FW_UPGRADE2
|
||||||
#ifdef USE_TASMOTA_CLIENT
|
#ifdef USE_TASMOTA_CLIENT
|
||||||
if (TasmotaClient_Available() && (upload.buf[0] == ':')) { // Check if this is a ARDUINO CLIENT hex file
|
if (TasmotaClient_Available() && (upload.buf[0] == ':')) { // Check if this is a ARDUINO CLIENT hex file
|
||||||
Update.end(); // End esp8266 update session
|
Update.end(); // End esp8266 update session
|
||||||
@ -2855,6 +2915,12 @@ void HandleUploadLoop(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // USE_RF_FLASH
|
#endif // USE_RF_FLASH
|
||||||
|
#ifdef SHELLY_FW_UPGRADE2
|
||||||
|
else if (UPL_SHD == Web.upload_file_type) {
|
||||||
|
// Write a block
|
||||||
|
BUploadWriteBuffer(upload.buf, upload.currentSize);
|
||||||
|
}
|
||||||
|
#endif // SHELLY_FW_UPGRADE2
|
||||||
#ifdef USE_TASMOTA_CLIENT
|
#ifdef USE_TASMOTA_CLIENT
|
||||||
else if (UPL_TASMOTACLIENT == Web.upload_file_type) {
|
else if (UPL_TASMOTACLIENT == Web.upload_file_type) {
|
||||||
TasmotaClient_WriteBuffer(upload.buf, upload.currentSize);
|
TasmotaClient_WriteBuffer(upload.buf, upload.currentSize);
|
||||||
@ -2931,6 +2997,13 @@ void HandleUploadLoop(void)
|
|||||||
Web.upload_file_type = UPL_TASMOTA;
|
Web.upload_file_type = UPL_TASMOTA;
|
||||||
}
|
}
|
||||||
#endif // USE_RF_FLASH
|
#endif // USE_RF_FLASH
|
||||||
|
#ifdef SHELLY_FW_UPGRADE2
|
||||||
|
else if (UPL_SHD == Web.upload_file_type) {
|
||||||
|
// Done writing the hex to SPI flash
|
||||||
|
BUpload.ready = true; // So we know on upload success page if it needs to flash hex or do a normal restart
|
||||||
|
Web.upload_file_type = UPL_TASMOTA;
|
||||||
|
}
|
||||||
|
#endif // SHELLY_FW_UPGRADE2
|
||||||
#ifdef USE_TASMOTA_CLIENT
|
#ifdef USE_TASMOTA_CLIENT
|
||||||
else if (UPL_TASMOTACLIENT == Web.upload_file_type) {
|
else if (UPL_TASMOTACLIENT == Web.upload_file_type) {
|
||||||
// Done writing the hex to SPI flash
|
// Done writing the hex to SPI flash
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
* https://shelly.cloud/wifi-smart-home-automation-shelly-dimmer/
|
* https://shelly.cloud/wifi-smart-home-automation-shelly-dimmer/
|
||||||
* https://shelly.cloud/products/shelly-dimmer-2-smart-home-light-controller/
|
* https://shelly.cloud/products/shelly-dimmer-2-smart-home-light-controller/
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
// #define SHELLY_DIMMER_DEBUG
|
// #define SHELLY_DIMMER_DEBUG
|
||||||
// #define SHELLY_HW_DIMMING
|
// #define SHELLY_HW_DIMMING
|
||||||
|
|
||||||
@ -37,7 +38,7 @@
|
|||||||
#define SHD_DRIVER_MAJOR_VERSION 1
|
#define SHD_DRIVER_MAJOR_VERSION 1
|
||||||
#define SHD_DRIVER_MINOR_VERSION 4
|
#define SHD_DRIVER_MINOR_VERSION 4
|
||||||
|
|
||||||
#define SHD_LOGNAME "SHD"
|
#define SHD_LOGNAME "SHD: "
|
||||||
|
|
||||||
#ifdef SHELLY_CMDS
|
#ifdef SHELLY_CMDS
|
||||||
#define D_PRFX_SHD "Shd"
|
#define D_PRFX_SHD "Shd"
|
||||||
@ -72,6 +73,10 @@
|
|||||||
#include <fw/shelly/dimmer/stm_v51.4.h>
|
#include <fw/shelly/dimmer/stm_v51.4.h>
|
||||||
#endif // SHELLY_FW_UPGRADE
|
#endif // SHELLY_FW_UPGRADE
|
||||||
|
|
||||||
|
#ifdef SHELLY_FW_UPGRADE2
|
||||||
|
#include <stm32flash.h>
|
||||||
|
#endif // SHELLY_FW_UPGRADE2
|
||||||
|
|
||||||
#include <TasmotaSerial.h>
|
#include <TasmotaSerial.h>
|
||||||
|
|
||||||
TasmotaSerial *ShdSerial = nullptr;
|
TasmotaSerial *ShdSerial = nullptr;
|
||||||
@ -105,6 +110,117 @@ struct SHD
|
|||||||
bool present = false;
|
bool present = false;
|
||||||
} Shd;
|
} Shd;
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* SHD firmware update Functions - James
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
#if defined(SHELLY_FW_UPGRADE) || defined(SHELLY_FW_UPGRADE2)
|
||||||
|
|
||||||
|
void ShdResetToDFUMode()
|
||||||
|
{
|
||||||
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Request co-processor reset in dfu mode"));
|
||||||
|
|
||||||
|
pinMode(Pin(GPIO_SHELLY_DIMMER_RST_INV), OUTPUT);
|
||||||
|
digitalWrite(Pin(GPIO_SHELLY_DIMMER_RST_INV), LOW);
|
||||||
|
|
||||||
|
pinMode(Pin(GPIO_SHELLY_DIMMER_BOOT0), OUTPUT);
|
||||||
|
digitalWrite(Pin(GPIO_SHELLY_DIMMER_BOOT0), HIGH);
|
||||||
|
|
||||||
|
delay(50);
|
||||||
|
|
||||||
|
// clear in the receive buffer
|
||||||
|
while (Serial.available())
|
||||||
|
Serial.read();
|
||||||
|
|
||||||
|
digitalWrite(Pin(GPIO_SHELLY_DIMMER_RST_INV), HIGH); // pull out of reset
|
||||||
|
delay(50); // wait 50ms fot the co-processor to come online
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShdUpdateFirmware(const uint8_t data[], unsigned int size)
|
||||||
|
{
|
||||||
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Update firmware"));
|
||||||
|
bool ret = true;
|
||||||
|
stm32_t *stm = stm32_init(&Serial, STREAM_SERIAL, 1);
|
||||||
|
if (stm)
|
||||||
|
{
|
||||||
|
off_t offset = 0;
|
||||||
|
uint8_t buffer[256];
|
||||||
|
unsigned int len;
|
||||||
|
const uint8_t *p_st = data;
|
||||||
|
uint32_t addr, start, end;
|
||||||
|
stm32_err_t s_err;
|
||||||
|
|
||||||
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "STM32 erase memory"));
|
||||||
|
|
||||||
|
stm32_erase_memory(stm, 0, STM32_MASS_ERASE);
|
||||||
|
|
||||||
|
addr = stm->dev->fl_start;
|
||||||
|
end = addr + size;
|
||||||
|
while(addr < end && offset < size)
|
||||||
|
{
|
||||||
|
uint32_t left = end - addr;
|
||||||
|
len = sizeof(buffer) > left ? left : sizeof(buffer);
|
||||||
|
len = len > size - offset ? size - offset : len;
|
||||||
|
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// memcpy(buffer, p_st, len);
|
||||||
|
// p_st += len;
|
||||||
|
memcpy(buffer, p_st, sizeof(buffer)); // We need 4-byte bounadry flash access
|
||||||
|
p_st += sizeof(buffer);
|
||||||
|
|
||||||
|
s_err = stm32_write_memory(stm, addr, buffer, len);
|
||||||
|
if (s_err != STM32_ERR_OK)
|
||||||
|
{
|
||||||
|
ret = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr += len;
|
||||||
|
offset += len;
|
||||||
|
}
|
||||||
|
stm32_close(stm);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SHELLY_FW_UPGRADE
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* SHD firmware update Functions - Theo
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
#ifdef SHELLY_FW_UPGRADE2
|
||||||
|
|
||||||
|
bool ShdPresent(void) {
|
||||||
|
return Shd.present;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShdFlash(uint32_t data, size_t size) {
|
||||||
|
AddLog_P(LOG_LEVEL_INFO, PSTR(SHD_LOGNAME "Updating firmware v%u.%u with %u bytes"),
|
||||||
|
Shd.dimmer.version_major, Shd.dimmer.version_minor, size);
|
||||||
|
|
||||||
|
Serial.end();
|
||||||
|
Serial.begin(115200, SERIAL_8E1);
|
||||||
|
ShdResetToDFUMode();
|
||||||
|
// uint32_t* values = (uint32_t*)(0x40200000 + data);
|
||||||
|
// AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Flash 0x%08X"), values[0]);
|
||||||
|
ShdUpdateFirmware((uint8_t*)(0x40200000 + data), size); // Allow flash access without ESP.flashRead
|
||||||
|
Serial.end();
|
||||||
|
|
||||||
|
ShdResetToAppMode();
|
||||||
|
Serial.begin(115200, SERIAL_8N1);
|
||||||
|
|
||||||
|
ShdSendVersion();
|
||||||
|
|
||||||
|
TasmotaGlobal.restart_flag = 2; // Restart to re-init stopped services
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SHELLY_FW_UPGRADE2
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Helper Functions
|
* Helper Functions
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
@ -142,7 +258,7 @@ int check_byte()
|
|||||||
if (chksm != chksm_calc)
|
if (chksm != chksm_calc)
|
||||||
{
|
{
|
||||||
#ifdef SHELLY_DIMMER_DEBUG
|
#ifdef SHELLY_DIMMER_DEBUG
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME" checksum: %x calculated: %x"), chksm, chksm_calc);
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Checksum: %x calculated: %x"), chksm, chksm_calc);
|
||||||
#endif // SHELLY_DIMMER_DEBUG
|
#endif // SHELLY_DIMMER_DEBUG
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -165,7 +281,7 @@ bool ShdSerialSend(const uint8_t data[] = nullptr, uint16_t len = 0)
|
|||||||
int retries = 3;
|
int retries = 3;
|
||||||
|
|
||||||
#ifdef SHELLY_DIMMER_DEBUG
|
#ifdef SHELLY_DIMMER_DEBUG
|
||||||
snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR(SHD_LOGNAME" Tx Packet:"));
|
snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR(SHD_LOGNAME "Tx Packet:"));
|
||||||
for (uint32_t i = 0; i < len; i++)
|
for (uint32_t i = 0; i < len; i++)
|
||||||
snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s %02x"), TasmotaGlobal.log_data, data[i]);
|
snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s %02x"), TasmotaGlobal.log_data, data[i]);
|
||||||
AddLog(LOG_LEVEL_DEBUG_MORE);
|
AddLog(LOG_LEVEL_DEBUG_MORE);
|
||||||
@ -187,7 +303,7 @@ bool ShdSerialSend(const uint8_t data[] = nullptr, uint16_t len = 0)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// timeout
|
// timeout
|
||||||
AddLog_P(LOG_LEVEL_ERROR, PSTR(SHD_LOGNAME" serial send timeout"));
|
AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR(SHD_LOGNAME "Serial send timeout"));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -326,9 +442,9 @@ void ShdSendCalibration(uint16_t brightness, uint16_t func, uint16_t fade_rate)
|
|||||||
bool ShdSyncState()
|
bool ShdSyncState()
|
||||||
{
|
{
|
||||||
#ifdef SHELLY_DIMMER_DEBUG
|
#ifdef SHELLY_DIMMER_DEBUG
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME" Serial %p"), ShdSerial);
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Serial %p"), ShdSerial);
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME" Set Brightness Want %d, Is %d"), Shd.req_brightness, Shd.dimmer.brightness);
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Set Brightness Want %d, Is %d"), Shd.req_brightness, Shd.dimmer.brightness);
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME" Set Fade Want %d, Is %d"), Settings.light_speed, Shd.dimmer.fade_rate);
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Set Fade Want %d, Is %d"), Settings.light_speed, Shd.dimmer.fade_rate);
|
||||||
#endif // SHELLY_DIMMER_DEBUG
|
#endif // SHELLY_DIMMER_DEBUG
|
||||||
|
|
||||||
if (!ShdSerial)
|
if (!ShdSerial)
|
||||||
@ -356,7 +472,7 @@ bool ShdSyncState()
|
|||||||
void ShdDebugState()
|
void ShdDebugState()
|
||||||
{
|
{
|
||||||
#ifdef SHELLY_DIMMER_DEBUG
|
#ifdef SHELLY_DIMMER_DEBUG
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME" MCU v%d.%d, Brightness:%d(%d%%), Power:%d, Fade:%d"),
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "MCU v%d.%d, Brightness:%d(%d%%), Power:%d, Fade:%d"),
|
||||||
Shd.dimmer.version_major, Shd.dimmer.version_minor,
|
Shd.dimmer.version_major, Shd.dimmer.version_minor,
|
||||||
Shd.dimmer.brightness,
|
Shd.dimmer.brightness,
|
||||||
changeUIntScale(Shd.dimmer.brightness, 0, 1000, 0, 100),
|
changeUIntScale(Shd.dimmer.brightness, 0, 1000, 0, 100),
|
||||||
@ -438,7 +554,7 @@ bool ShdPacketProcess(void)
|
|||||||
{
|
{
|
||||||
float kWhused = (float)Energy.active_power[0] * (Rtc.utc_time - Shd.last_power_check) / 36;
|
float kWhused = (float)Energy.active_power[0] * (Rtc.utc_time - Shd.last_power_check) / 36;
|
||||||
#ifdef SHELLY_DIMMER_DEBUG
|
#ifdef SHELLY_DIMMER_DEBUG
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME" Adding %i mWh to todays usage from %lu to %lu"), (int)(kWhused * 10), Shd.last_power_check, Rtc.utc_time);
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Adding %i mWh to todays usage from %lu to %lu"), (int)(kWhused * 10), Shd.last_power_check, Rtc.utc_time);
|
||||||
#endif // USE_ENERGY_SENSOR
|
#endif // USE_ENERGY_SENSOR
|
||||||
Energy.kWhtoday += kWhused;
|
Energy.kWhtoday += kWhused;
|
||||||
EnergyUpdateToday();
|
EnergyUpdateToday();
|
||||||
@ -447,7 +563,7 @@ bool ShdPacketProcess(void)
|
|||||||
#endif // USE_ENERGY_SENSOR
|
#endif // USE_ENERGY_SENSOR
|
||||||
|
|
||||||
#ifdef SHELLY_DIMMER_DEBUG
|
#ifdef SHELLY_DIMMER_DEBUG
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME" ShdPacketProcess: Brightness:%d Power:%lu Voltage:%lu Current:%lu Fade:%d"), brightness, wattage_raw, voltage_raw, current_raw, fade_rate);
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "ShdPacketProcess: Brightness:%d Power:%lu Voltage:%lu Current:%lu Fade:%d"), brightness, wattage_raw, voltage_raw, current_raw, fade_rate);
|
||||||
#endif // SHELLY_DIMMER_DEBUG
|
#endif // SHELLY_DIMMER_DEBUG
|
||||||
Shd.dimmer.brightness = brightness;
|
Shd.dimmer.brightness = brightness;
|
||||||
Shd.dimmer.power = wattage_raw;
|
Shd.dimmer.power = wattage_raw;
|
||||||
@ -461,7 +577,7 @@ bool ShdPacketProcess(void)
|
|||||||
Shd.buffer[pos + 1] == SHD_FIRMWARE_MAJOR_VERSION;
|
Shd.buffer[pos + 1] == SHD_FIRMWARE_MAJOR_VERSION;
|
||||||
#endif // SHELLY_FW_UPGRADE
|
#endif // SHELLY_FW_UPGRADE
|
||||||
|
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME" ShdPacketProcess: Version: %u.%u"), Shd.buffer[pos + 1], Shd.buffer[pos]);
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "ShdPacketProcess: Version: %u.%u"), Shd.buffer[pos + 1], Shd.buffer[pos]);
|
||||||
Shd.dimmer.version_minor = Shd.buffer[pos];
|
Shd.dimmer.version_minor = Shd.buffer[pos];
|
||||||
Shd.dimmer.version_major = Shd.buffer[pos + 1];
|
Shd.dimmer.version_major = Shd.buffer[pos + 1];
|
||||||
}
|
}
|
||||||
@ -483,7 +599,7 @@ bool ShdPacketProcess(void)
|
|||||||
|
|
||||||
void ShdResetToAppMode()
|
void ShdResetToAppMode()
|
||||||
{
|
{
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME" Request co-processor reset in app mode"));
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Request co-processor reset in app mode"));
|
||||||
|
|
||||||
pinMode(Pin(GPIO_SHELLY_DIMMER_RST_INV), OUTPUT);
|
pinMode(Pin(GPIO_SHELLY_DIMMER_RST_INV), OUTPUT);
|
||||||
digitalWrite(Pin(GPIO_SHELLY_DIMMER_RST_INV), LOW);
|
digitalWrite(Pin(GPIO_SHELLY_DIMMER_RST_INV), LOW);
|
||||||
@ -501,83 +617,10 @@ void ShdResetToAppMode()
|
|||||||
delay(50); // wait 50ms fot the co-processor to come online
|
delay(50); // wait 50ms fot the co-processor to come online
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SHELLY_FW_UPGRADE
|
|
||||||
|
|
||||||
void ShdResetToDFUMode()
|
|
||||||
{
|
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME" Request co-processor reset in dfu mode"));
|
|
||||||
|
|
||||||
pinMode(Pin(GPIO_SHELLY_DIMMER_RST_INV), OUTPUT);
|
|
||||||
digitalWrite(Pin(GPIO_SHELLY_DIMMER_RST_INV), LOW);
|
|
||||||
|
|
||||||
pinMode(Pin(GPIO_SHELLY_DIMMER_BOOT0), OUTPUT);
|
|
||||||
digitalWrite(Pin(GPIO_SHELLY_DIMMER_BOOT0), HIGH);
|
|
||||||
|
|
||||||
delay(50);
|
|
||||||
|
|
||||||
// clear in the receive buffer
|
|
||||||
while (Serial.available())
|
|
||||||
Serial.read();
|
|
||||||
|
|
||||||
digitalWrite(Pin(GPIO_SHELLY_DIMMER_RST_INV), HIGH); // pull out of reset
|
|
||||||
delay(50); // wait 50ms fot the co-processor to come online
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ShdUpdateFirmware(const uint8_t data[], unsigned int size)
|
|
||||||
{
|
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME" Update firmware"));
|
|
||||||
bool ret = true;
|
|
||||||
stm32_t *stm = stm32_init(&Serial, STREAM_SERIAL, 1);
|
|
||||||
if (stm)
|
|
||||||
{
|
|
||||||
off_t offset = 0;
|
|
||||||
uint8_t buffer[256];
|
|
||||||
unsigned int len;
|
|
||||||
const uint8_t *p_st = data;
|
|
||||||
uint32_t addr, start, end;
|
|
||||||
stm32_err_t s_err;
|
|
||||||
|
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME" STM32 erase memory"));
|
|
||||||
|
|
||||||
stm32_erase_memory(stm, 0, STM32_MASS_ERASE);
|
|
||||||
|
|
||||||
addr = stm->dev->fl_start;
|
|
||||||
end = addr + size;
|
|
||||||
while(addr < end && offset < size)
|
|
||||||
{
|
|
||||||
uint32_t left = end - addr;
|
|
||||||
len = sizeof(buffer) > left ? left : sizeof(buffer);
|
|
||||||
len = len > size - offset ? size - offset : len;
|
|
||||||
|
|
||||||
if (len == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(buffer, p_st, len);
|
|
||||||
p_st += len;
|
|
||||||
|
|
||||||
s_err = stm32_write_memory(stm, addr, buffer, len);
|
|
||||||
if (s_err != STM32_ERR_OK)
|
|
||||||
{
|
|
||||||
ret = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr += len;
|
|
||||||
offset += len;
|
|
||||||
}
|
|
||||||
stm32_close(stm);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // SHELLY_FW_UPGRADE
|
|
||||||
|
|
||||||
void ShdPoll(void)
|
void ShdPoll(void)
|
||||||
{
|
{
|
||||||
#ifdef SHELLY_DIMMER_DEBUG
|
#ifdef SHELLY_DIMMER_DEBUG
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME" Poll"));
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Poll"));
|
||||||
#endif // SHELLY_DIMMER_DEBUG
|
#endif // SHELLY_DIMMER_DEBUG
|
||||||
|
|
||||||
if (!ShdSerial)
|
if (!ShdSerial)
|
||||||
@ -590,7 +633,7 @@ void ShdPoll(void)
|
|||||||
bool ShdSendVersion(void)
|
bool ShdSendVersion(void)
|
||||||
{
|
{
|
||||||
#ifdef SHELLY_DIMMER_DEBUG
|
#ifdef SHELLY_DIMMER_DEBUG
|
||||||
AddLog_P(LOG_LEVEL_INFO, PSTR(SHD_LOGNAME" Sending version command"));
|
AddLog_P(LOG_LEVEL_INFO, PSTR(SHD_LOGNAME "Sending version command"));
|
||||||
#endif // SHELLY_DIMMER_DEBUG
|
#endif // SHELLY_DIMMER_DEBUG
|
||||||
return ShdSendCmd(SHD_VERSION_CMD, 0, 0);
|
return ShdSendCmd(SHD_VERSION_CMD, 0, 0);
|
||||||
}
|
}
|
||||||
@ -606,7 +649,7 @@ void ShdGetSettings(void)
|
|||||||
if (strstr(SettingsText(SET_SHD_PARAM), ",") != nullptr)
|
if (strstr(SettingsText(SET_SHD_PARAM), ",") != nullptr)
|
||||||
{
|
{
|
||||||
#ifdef SHELLY_DIMMER_DEBUG
|
#ifdef SHELLY_DIMMER_DEBUG
|
||||||
AddLog_P(LOG_LEVEL_INFO, PSTR(SHD_LOGNAME" Loading params: %s"), SettingsText(SET_SHD_PARAM));
|
AddLog_P(LOG_LEVEL_INFO, PSTR(SHD_LOGNAME "Loading params: %s"), SettingsText(SET_SHD_PARAM));
|
||||||
#endif // SHELLY_DIMMER_DEBUG
|
#endif // SHELLY_DIMMER_DEBUG
|
||||||
Shd.req_brightness = atoi(subStr(parameters, SettingsText(SET_SHD_PARAM), ",", 1));
|
Shd.req_brightness = atoi(subStr(parameters, SettingsText(SET_SHD_PARAM), ",", 1));
|
||||||
Shd.leading_edge = atoi(subStr(parameters, SettingsText(SET_SHD_PARAM), ",", 2));
|
Shd.leading_edge = atoi(subStr(parameters, SettingsText(SET_SHD_PARAM), ",", 2));
|
||||||
@ -626,9 +669,9 @@ void ShdSaveSettings(void)
|
|||||||
|
|
||||||
void ShdInit(void)
|
void ShdInit(void)
|
||||||
{
|
{
|
||||||
AddLog_P(LOG_LEVEL_INFO, PSTR(SHD_LOGNAME" Shelly Dimmer Driver v%u.%u"), SHD_DRIVER_MAJOR_VERSION, SHD_DRIVER_MINOR_VERSION);
|
AddLog_P(LOG_LEVEL_INFO, PSTR(SHD_LOGNAME "Shelly Dimmer Driver v%u.%u"), SHD_DRIVER_MAJOR_VERSION, SHD_DRIVER_MINOR_VERSION);
|
||||||
#ifdef SHELLY_DIMMER_DEBUG
|
#ifdef SHELLY_DIMMER_DEBUG
|
||||||
AddLog_P(LOG_LEVEL_INFO, PSTR(SHD_LOGNAME" Starting Tx %d Rx %d"), Pin(GPIO_TXD), Pin(GPIO_RXD));
|
AddLog_P(LOG_LEVEL_INFO, PSTR(SHD_LOGNAME "Starting Tx %d Rx %d"), Pin(GPIO_TXD), Pin(GPIO_RXD));
|
||||||
#endif // SHELLY_DIMMER_DEBUG
|
#endif // SHELLY_DIMMER_DEBUG
|
||||||
|
|
||||||
Shd.buffer = (uint8_t *)malloc(SHD_BUFFER_SIZE);
|
Shd.buffer = (uint8_t *)malloc(SHD_BUFFER_SIZE);
|
||||||
@ -644,13 +687,13 @@ void ShdInit(void)
|
|||||||
|
|
||||||
ShdResetToAppMode();
|
ShdResetToAppMode();
|
||||||
bool got_version = ShdSendVersion();
|
bool got_version = ShdSendVersion();
|
||||||
AddLog_P(LOG_LEVEL_INFO, PSTR(SHD_LOGNAME" Shelly Dimmer Co-processor Version v%u.%u"), Shd.dimmer.version_major, Shd.dimmer.version_minor);
|
AddLog_P(LOG_LEVEL_INFO, PSTR(SHD_LOGNAME "Shelly Dimmer Co-processor Version v%u.%u"), Shd.dimmer.version_major, Shd.dimmer.version_minor);
|
||||||
#ifdef SHELLY_FW_UPGRADE
|
#ifdef SHELLY_FW_UPGRADE
|
||||||
if (!got_version || (got_version &&
|
if (!got_version || (got_version &&
|
||||||
(Shd.dimmer.version_minor != SHD_FIRMWARE_MINOR_VERSION ||
|
(Shd.dimmer.version_minor != SHD_FIRMWARE_MINOR_VERSION ||
|
||||||
Shd.dimmer.version_major != SHD_FIRMWARE_MAJOR_VERSION)))
|
Shd.dimmer.version_major != SHD_FIRMWARE_MAJOR_VERSION)))
|
||||||
{
|
{
|
||||||
AddLog_P(LOG_LEVEL_INFO, PSTR(SHD_LOGNAME" Updating firmware from v%u.%u to v%u.%u with %u bytes"), Shd.dimmer.version_major, Shd.dimmer.version_minor, SHD_FIRMWARE_MAJOR_VERSION, SHD_FIRMWARE_MINOR_VERSION, sizeof(stm_firmware));
|
AddLog_P(LOG_LEVEL_INFO, PSTR(SHD_LOGNAME "Updating firmware from v%u.%u to v%u.%u with %u bytes"), Shd.dimmer.version_major, Shd.dimmer.version_minor, SHD_FIRMWARE_MAJOR_VERSION, SHD_FIRMWARE_MINOR_VERSION, sizeof(stm_firmware));
|
||||||
|
|
||||||
Serial.end();
|
Serial.end();
|
||||||
Serial.begin(115200, SERIAL_8E1);
|
Serial.begin(115200, SERIAL_8E1);
|
||||||
@ -688,7 +731,7 @@ bool ShdSerialInput(void)
|
|||||||
// finished
|
// finished
|
||||||
#ifdef SHELLY_DIMMER_DEBUG
|
#ifdef SHELLY_DIMMER_DEBUG
|
||||||
Shd.byte_counter++;
|
Shd.byte_counter++;
|
||||||
snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR(SHD_LOGNAME" RX Packet:"));
|
snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR(SHD_LOGNAME "RX Packet:"));
|
||||||
for (uint32_t i = 0; i < Shd.byte_counter; i++)
|
for (uint32_t i = 0; i < Shd.byte_counter; i++)
|
||||||
snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s %02x"), TasmotaGlobal.log_data, Shd.buffer[i]);
|
snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s %02x"), TasmotaGlobal.log_data, Shd.buffer[i]);
|
||||||
AddLog(LOG_LEVEL_DEBUG_MORE);
|
AddLog(LOG_LEVEL_DEBUG_MORE);
|
||||||
@ -702,9 +745,9 @@ bool ShdSerialInput(void)
|
|||||||
else if (check == 0)
|
else if (check == 0)
|
||||||
{
|
{
|
||||||
// wrong data
|
// wrong data
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME" Byte %i of received data frame is invalid"), Shd.byte_counter);
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Byte %i of received data frame is invalid"), Shd.byte_counter);
|
||||||
Shd.byte_counter++;
|
Shd.byte_counter++;
|
||||||
snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR(SHD_LOGNAME" RX Packet:"));
|
snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR(SHD_LOGNAME "RX Packet:"));
|
||||||
for (uint32_t i = 0; i < Shd.byte_counter; i++)
|
for (uint32_t i = 0; i < Shd.byte_counter; i++)
|
||||||
snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s %02x"), TasmotaGlobal.log_data, Shd.buffer[i]);
|
snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s %02x"), TasmotaGlobal.log_data, Shd.buffer[i]);
|
||||||
AddLog(LOG_LEVEL_DEBUG_MORE);
|
AddLog(LOG_LEVEL_DEBUG_MORE);
|
||||||
@ -736,7 +779,7 @@ bool ShdModuleSelected(void) {
|
|||||||
bool ShdSetChannels(void)
|
bool ShdSetChannels(void)
|
||||||
{
|
{
|
||||||
#ifdef SHELLY_DIMMER_DEBUG
|
#ifdef SHELLY_DIMMER_DEBUG
|
||||||
snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR(SHD_LOGNAME" SetChannels: \""));
|
snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR(SHD_LOGNAME "SetChannels: \""));
|
||||||
for (int i = 0; i < XdrvMailbox.data_len; i++)
|
for (int i = 0; i < XdrvMailbox.data_len; i++)
|
||||||
snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s%02x"), TasmotaGlobal.log_data, ((uint8_t *)XdrvMailbox.data)[i]);
|
snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s%02x"), TasmotaGlobal.log_data, ((uint8_t *)XdrvMailbox.data)[i]);
|
||||||
snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s\""), TasmotaGlobal.log_data);
|
snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s\""), TasmotaGlobal.log_data);
|
||||||
@ -756,7 +799,7 @@ bool ShdSetChannels(void)
|
|||||||
|
|
||||||
bool ShdSetPower(void)
|
bool ShdSetPower(void)
|
||||||
{
|
{
|
||||||
AddLog_P(LOG_LEVEL_INFO, PSTR("EXS: Set Power, Power 0x%02x"), XdrvMailbox.index);
|
AddLog_P(LOG_LEVEL_INFO, PSTR(SHD_LOGNAME "Set Power, Power 0x%02x"), XdrvMailbox.index);
|
||||||
|
|
||||||
Shd.req_on = (bool)XdrvMailbox.index;
|
Shd.req_on = (bool)XdrvMailbox.index;
|
||||||
return ShdSyncState();
|
return ShdSyncState();
|
||||||
@ -781,9 +824,9 @@ void CmndShdLeadingEdge(void)
|
|||||||
Shd.leading_edge = 2 - XdrvMailbox.payload;
|
Shd.leading_edge = 2 - XdrvMailbox.payload;
|
||||||
Settings.shd_leading_edge = XdrvMailbox.payload;
|
Settings.shd_leading_edge = XdrvMailbox.payload;
|
||||||
if (Shd.leading_edge == 1)
|
if (Shd.leading_edge == 1)
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME" Set to trailing edge"));
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Set to trailing edge"));
|
||||||
else
|
else
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME" Set to leading edge"));
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Set to leading edge"));
|
||||||
ShdSendSettings();
|
ShdSendSettings();
|
||||||
}
|
}
|
||||||
ShdSaveSettings();
|
ShdSaveSettings();
|
||||||
@ -796,7 +839,7 @@ void CmndShdWarmupBrightness(void)
|
|||||||
{
|
{
|
||||||
Shd.warmup_brightness = XdrvMailbox.payload * 10;
|
Shd.warmup_brightness = XdrvMailbox.payload * 10;
|
||||||
Settings.shd_warmup_brightness = XdrvMailbox.payload;
|
Settings.shd_warmup_brightness = XdrvMailbox.payload;
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME" Set warmup brightness to %d%%"), XdrvMailbox.payload);
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Set warmup brightness to %d%%"), XdrvMailbox.payload);
|
||||||
ShdSendSettings();
|
ShdSendSettings();
|
||||||
}
|
}
|
||||||
ShdSaveSettings();
|
ShdSaveSettings();
|
||||||
@ -809,7 +852,7 @@ void CmndShdWarmupTime(void)
|
|||||||
{
|
{
|
||||||
Shd.warmup_time = XdrvMailbox.payload;
|
Shd.warmup_time = XdrvMailbox.payload;
|
||||||
Settings.shd_warmup_time = XdrvMailbox.payload;
|
Settings.shd_warmup_time = XdrvMailbox.payload;
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME" Set warmup time to %dms"), XdrvMailbox.payload);
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Set warmup time to %dms"), XdrvMailbox.payload);
|
||||||
ShdSendSettings();
|
ShdSendSettings();
|
||||||
}
|
}
|
||||||
ShdSaveSettings();
|
ShdSaveSettings();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user