mirror of
https://github.com/esphome/esphome.git
synced 2024-11-22 23:18:10 +01:00
commit
ff72d6a146
10 changed files with 108 additions and 97 deletions
|
@ -117,7 +117,7 @@ void Bedjet::control(const ClimateCall &call) {
|
||||||
pkt = this->codec_->get_button_request(BTN_OFF);
|
pkt = this->codec_->get_button_request(BTN_OFF);
|
||||||
break;
|
break;
|
||||||
case climate::CLIMATE_MODE_HEAT:
|
case climate::CLIMATE_MODE_HEAT:
|
||||||
pkt = this->codec_->get_button_request(BTN_EXTHT);
|
pkt = this->codec_->get_button_request(BTN_HEAT);
|
||||||
break;
|
break;
|
||||||
case climate::CLIMATE_MODE_FAN_ONLY:
|
case climate::CLIMATE_MODE_FAN_ONLY:
|
||||||
pkt = this->codec_->get_button_request(BTN_COOL);
|
pkt = this->codec_->get_button_request(BTN_COOL);
|
||||||
|
@ -137,7 +137,7 @@ void Bedjet::control(const ClimateCall &call) {
|
||||||
} else {
|
} else {
|
||||||
this->force_refresh_ = true;
|
this->force_refresh_ = true;
|
||||||
this->mode = mode;
|
this->mode = mode;
|
||||||
// We're using (custom) preset for Turbo & M1-3 presets, so changing climate mode will clear those
|
// We're using (custom) preset for Turbo, EXT HT, & M1-3 presets, so changing climate mode will clear those
|
||||||
this->custom_preset.reset();
|
this->custom_preset.reset();
|
||||||
this->preset.reset();
|
this->preset.reset();
|
||||||
}
|
}
|
||||||
|
@ -186,6 +186,8 @@ void Bedjet::control(const ClimateCall &call) {
|
||||||
pkt = this->codec_->get_button_request(BTN_M2);
|
pkt = this->codec_->get_button_request(BTN_M2);
|
||||||
} else if (preset == "M3") {
|
} else if (preset == "M3") {
|
||||||
pkt = this->codec_->get_button_request(BTN_M3);
|
pkt = this->codec_->get_button_request(BTN_M3);
|
||||||
|
} else if (preset == "EXT HT") {
|
||||||
|
pkt = this->codec_->get_button_request(BTN_EXTHT);
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGW(TAG, "Unsupported preset: %s", preset.c_str());
|
ESP_LOGW(TAG, "Unsupported preset: %s", preset.c_str());
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -67,6 +67,8 @@ class Bedjet : public climate::Climate, public esphome::ble_client::BLEClientNod
|
||||||
// We could fetch biodata from bedjet and set these names that way.
|
// We could fetch biodata from bedjet and set these names that way.
|
||||||
// But then we have to invert the lookup in order to send the right preset.
|
// But then we have to invert the lookup in order to send the right preset.
|
||||||
// For now, we can leave them as M1-3 to match the remote buttons.
|
// For now, we can leave them as M1-3 to match the remote buttons.
|
||||||
|
// EXT HT added to match remote button.
|
||||||
|
"EXT HT",
|
||||||
"M1",
|
"M1",
|
||||||
"M2",
|
"M2",
|
||||||
"M3",
|
"M3",
|
||||||
|
|
|
@ -39,17 +39,7 @@ class CaptivePortal : public AsyncWebHandler, public Component {
|
||||||
if (request->method() == HTTP_GET) {
|
if (request->method() == HTTP_GET) {
|
||||||
if (request->url() == "/")
|
if (request->url() == "/")
|
||||||
return true;
|
return true;
|
||||||
if (request->url() == "/stylesheet.css")
|
if (request->url() == "/config.json")
|
||||||
return true;
|
|
||||||
if (request->url() == "/wifi-strength-1.svg")
|
|
||||||
return true;
|
|
||||||
if (request->url() == "/wifi-strength-2.svg")
|
|
||||||
return true;
|
|
||||||
if (request->url() == "/wifi-strength-3.svg")
|
|
||||||
return true;
|
|
||||||
if (request->url() == "/wifi-strength-4.svg")
|
|
||||||
return true;
|
|
||||||
if (request->url() == "/lock.svg")
|
|
||||||
return true;
|
return true;
|
||||||
if (request->url() == "/wifisave")
|
if (request->url() == "/wifisave")
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -287,9 +287,11 @@ CLIMATE_CONTROL_ACTION_SCHEMA = cv.Schema(
|
||||||
cv.Exclusive(CONF_FAN_MODE, "fan_mode"): cv.templatable(
|
cv.Exclusive(CONF_FAN_MODE, "fan_mode"): cv.templatable(
|
||||||
validate_climate_fan_mode
|
validate_climate_fan_mode
|
||||||
),
|
),
|
||||||
cv.Exclusive(CONF_CUSTOM_FAN_MODE, "fan_mode"): cv.string_strict,
|
cv.Exclusive(CONF_CUSTOM_FAN_MODE, "fan_mode"): cv.templatable(
|
||||||
|
cv.string_strict
|
||||||
|
),
|
||||||
cv.Exclusive(CONF_PRESET, "preset"): cv.templatable(validate_climate_preset),
|
cv.Exclusive(CONF_PRESET, "preset"): cv.templatable(validate_climate_preset),
|
||||||
cv.Exclusive(CONF_CUSTOM_PRESET, "preset"): cv.string_strict,
|
cv.Exclusive(CONF_CUSTOM_PRESET, "preset"): cv.templatable(cv.string_strict),
|
||||||
cv.Optional(CONF_SWING_MODE): cv.templatable(validate_climate_swing_mode),
|
cv.Optional(CONF_SWING_MODE): cv.templatable(validate_climate_swing_mode),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -324,13 +326,17 @@ async def climate_control_to_code(config, action_id, template_arg, args):
|
||||||
template_ = await cg.templatable(config[CONF_FAN_MODE], args, ClimateFanMode)
|
template_ = await cg.templatable(config[CONF_FAN_MODE], args, ClimateFanMode)
|
||||||
cg.add(var.set_fan_mode(template_))
|
cg.add(var.set_fan_mode(template_))
|
||||||
if CONF_CUSTOM_FAN_MODE in config:
|
if CONF_CUSTOM_FAN_MODE in config:
|
||||||
template_ = await cg.templatable(config[CONF_CUSTOM_FAN_MODE], args, str)
|
template_ = await cg.templatable(
|
||||||
|
config[CONF_CUSTOM_FAN_MODE], args, cg.std_string
|
||||||
|
)
|
||||||
cg.add(var.set_custom_fan_mode(template_))
|
cg.add(var.set_custom_fan_mode(template_))
|
||||||
if CONF_PRESET in config:
|
if CONF_PRESET in config:
|
||||||
template_ = await cg.templatable(config[CONF_PRESET], args, ClimatePreset)
|
template_ = await cg.templatable(config[CONF_PRESET], args, ClimatePreset)
|
||||||
cg.add(var.set_preset(template_))
|
cg.add(var.set_preset(template_))
|
||||||
if CONF_CUSTOM_PRESET in config:
|
if CONF_CUSTOM_PRESET in config:
|
||||||
template_ = await cg.templatable(config[CONF_CUSTOM_PRESET], args, str)
|
template_ = await cg.templatable(
|
||||||
|
config[CONF_CUSTOM_PRESET], args, cg.std_string
|
||||||
|
)
|
||||||
cg.add(var.set_custom_preset(template_))
|
cg.add(var.set_custom_preset(template_))
|
||||||
if CONF_SWING_MODE in config:
|
if CONF_SWING_MODE in config:
|
||||||
template_ = await cg.templatable(
|
template_ = await cg.templatable(
|
||||||
|
|
|
@ -158,11 +158,8 @@ bool ShellyDimmer::upgrade_firmware_() {
|
||||||
ESP_LOGW(TAG, "Starting STM32 firmware upgrade");
|
ESP_LOGW(TAG, "Starting STM32 firmware upgrade");
|
||||||
this->reset_dfu_boot_();
|
this->reset_dfu_boot_();
|
||||||
|
|
||||||
// Could be constexpr in c++17
|
|
||||||
static const auto CLOSE = [](stm32_t *stm32) { stm32_close(stm32); };
|
|
||||||
|
|
||||||
// Cleanup with RAII
|
// Cleanup with RAII
|
||||||
std::unique_ptr<stm32_t, decltype(CLOSE)> stm32{stm32_init(this, STREAM_SERIAL, 1), CLOSE};
|
auto stm32 = stm32_init(this, STREAM_SERIAL, 1);
|
||||||
|
|
||||||
if (!stm32) {
|
if (!stm32) {
|
||||||
ESP_LOGW(TAG, "Failed to initialize STM32");
|
ESP_LOGW(TAG, "Failed to initialize STM32");
|
||||||
|
@ -170,7 +167,7 @@ bool ShellyDimmer::upgrade_firmware_() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Erase STM32 flash.
|
// Erase STM32 flash.
|
||||||
if (stm32_erase_memory(stm32.get(), 0, STM32_MASS_ERASE) != STM32_ERR_OK) {
|
if (stm32_erase_memory(stm32, 0, STM32_MASS_ERASE) != STM32_ERR_OK) {
|
||||||
ESP_LOGW(TAG, "Failed to erase STM32 flash memory");
|
ESP_LOGW(TAG, "Failed to erase STM32 flash memory");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -196,7 +193,7 @@ bool ShellyDimmer::upgrade_firmware_() {
|
||||||
std::memcpy(buffer, p, BUFFER_SIZE);
|
std::memcpy(buffer, p, BUFFER_SIZE);
|
||||||
p += BUFFER_SIZE;
|
p += BUFFER_SIZE;
|
||||||
|
|
||||||
if (stm32_write_memory(stm32.get(), addr, buffer, len) != STM32_ERR_OK) {
|
if (stm32_write_memory(stm32, addr, buffer, len) != STM32_ERR_OK) {
|
||||||
ESP_LOGW(TAG, "Failed to write to STM32 flash memory");
|
ESP_LOGW(TAG, "Failed to write to STM32 flash memory");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ namespace shelly_dimmer {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
int flash_addr_to_page_ceil(const stm32_t *stm, uint32_t addr) {
|
int flash_addr_to_page_ceil(const stm32_unique_ptr &stm, uint32_t addr) {
|
||||||
if (!(addr >= stm->dev->fl_start && addr <= stm->dev->fl_end))
|
if (!(addr >= stm->dev->fl_start && addr <= stm->dev->fl_end))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ int flash_addr_to_page_ceil(const stm32_t *stm, uint32_t addr) {
|
||||||
return addr ? page + 1 : page;
|
return addr ? page + 1 : page;
|
||||||
}
|
}
|
||||||
|
|
||||||
stm32_err_t stm32_get_ack_timeout(const stm32_t *stm, uint32_t timeout) {
|
stm32_err_t stm32_get_ack_timeout(const stm32_unique_ptr &stm, uint32_t timeout) {
|
||||||
auto *stream = stm->stream;
|
auto *stream = stm->stream;
|
||||||
uint8_t rxbyte;
|
uint8_t rxbyte;
|
||||||
|
|
||||||
|
@ -168,9 +168,9 @@ stm32_err_t stm32_get_ack_timeout(const stm32_t *stm, uint32_t timeout) {
|
||||||
} while (true);
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
stm32_err_t stm32_get_ack(const stm32_t *stm) { return stm32_get_ack_timeout(stm, 0); }
|
stm32_err_t stm32_get_ack(const stm32_unique_ptr &stm) { return stm32_get_ack_timeout(stm, 0); }
|
||||||
|
|
||||||
stm32_err_t stm32_send_command_timeout(const stm32_t *stm, const uint8_t cmd, const uint32_t timeout) {
|
stm32_err_t stm32_send_command_timeout(const stm32_unique_ptr &stm, const uint8_t cmd, const uint32_t timeout) {
|
||||||
auto *const stream = stm->stream;
|
auto *const stream = stm->stream;
|
||||||
|
|
||||||
static constexpr auto BUFFER_SIZE = 2;
|
static constexpr auto BUFFER_SIZE = 2;
|
||||||
|
@ -194,12 +194,12 @@ stm32_err_t stm32_send_command_timeout(const stm32_t *stm, const uint8_t cmd, co
|
||||||
return STM32_ERR_UNKNOWN;
|
return STM32_ERR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
stm32_err_t stm32_send_command(const stm32_t *stm, const uint8_t cmd) {
|
stm32_err_t stm32_send_command(const stm32_unique_ptr &stm, const uint8_t cmd) {
|
||||||
return stm32_send_command_timeout(stm, cmd, 0);
|
return stm32_send_command_timeout(stm, cmd, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we have lost sync, send a wrong command and expect a NACK */
|
/* if we have lost sync, send a wrong command and expect a NACK */
|
||||||
stm32_err_t stm32_resync(const stm32_t *stm) {
|
stm32_err_t stm32_resync(const stm32_unique_ptr &stm) {
|
||||||
auto *const stream = stm->stream;
|
auto *const stream = stm->stream;
|
||||||
uint32_t t0 = millis();
|
uint32_t t0 = millis();
|
||||||
auto t1 = t0;
|
auto t1 = t0;
|
||||||
|
@ -238,7 +238,7 @@ stm32_err_t stm32_resync(const stm32_t *stm) {
|
||||||
*
|
*
|
||||||
* len is value of the first byte in the frame.
|
* len is value of the first byte in the frame.
|
||||||
*/
|
*/
|
||||||
stm32_err_t stm32_guess_len_cmd(const stm32_t *stm, const uint8_t cmd, uint8_t *const data, unsigned int len) {
|
stm32_err_t stm32_guess_len_cmd(const stm32_unique_ptr &stm, const uint8_t cmd, uint8_t *const data, unsigned int len) {
|
||||||
auto *const stream = stm->stream;
|
auto *const stream = stm->stream;
|
||||||
|
|
||||||
if (stm32_send_command(stm, cmd) != STM32_ERR_OK)
|
if (stm32_send_command(stm, cmd) != STM32_ERR_OK)
|
||||||
|
@ -286,7 +286,7 @@ stm32_err_t stm32_guess_len_cmd(const stm32_t *stm, const uint8_t cmd, uint8_t *
|
||||||
* This function sends the init sequence and, in case of timeout, recovers
|
* This function sends the init sequence and, in case of timeout, recovers
|
||||||
* the interface.
|
* the interface.
|
||||||
*/
|
*/
|
||||||
stm32_err_t stm32_send_init_seq(const stm32_t *stm) {
|
stm32_err_t stm32_send_init_seq(const stm32_unique_ptr &stm) {
|
||||||
auto *const stream = stm->stream;
|
auto *const stream = stm->stream;
|
||||||
|
|
||||||
stream->write_array(&STM32_CMD_INIT, 1);
|
stream->write_array(&STM32_CMD_INIT, 1);
|
||||||
|
@ -320,7 +320,7 @@ stm32_err_t stm32_send_init_seq(const stm32_t *stm) {
|
||||||
return STM32_ERR_UNKNOWN;
|
return STM32_ERR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
stm32_err_t stm32_mass_erase(const stm32_t *stm) {
|
stm32_err_t stm32_mass_erase(const stm32_unique_ptr &stm) {
|
||||||
auto *const stream = stm->stream;
|
auto *const stream = stm->stream;
|
||||||
|
|
||||||
if (stm32_send_command(stm, stm->cmd->er) != STM32_ERR_OK) {
|
if (stm32_send_command(stm, stm->cmd->er) != STM32_ERR_OK) {
|
||||||
|
@ -364,7 +364,7 @@ template<typename T> std::unique_ptr<T[], void (*)(T *memory)> malloc_array_raii
|
||||||
DELETOR};
|
DELETOR};
|
||||||
}
|
}
|
||||||
|
|
||||||
stm32_err_t stm32_pages_erase(const stm32_t *stm, const uint32_t spage, const uint32_t pages) {
|
stm32_err_t stm32_pages_erase(const stm32_unique_ptr &stm, const uint32_t spage, const uint32_t pages) {
|
||||||
auto *const stream = stm->stream;
|
auto *const stream = stm->stream;
|
||||||
uint8_t cs = 0;
|
uint8_t cs = 0;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -474,6 +474,18 @@ template<size_t N> void populate_buffer_with_address(uint8_t (&buffer)[N], uint3
|
||||||
buffer[4] = static_cast<uint8_t>(buffer[0] ^ buffer[1] ^ buffer[2] ^ buffer[3]);
|
buffer[4] = static_cast<uint8_t>(buffer[0] ^ buffer[1] ^ buffer[2] ^ buffer[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T> stm32_unique_ptr make_stm32_with_deletor(T ptr) {
|
||||||
|
static const auto CLOSE = [](stm32_t *stm32) {
|
||||||
|
if (stm32) {
|
||||||
|
free(stm32->cmd); // NOLINT
|
||||||
|
}
|
||||||
|
free(stm32); // NOLINT
|
||||||
|
};
|
||||||
|
|
||||||
|
// Cleanup with RAII
|
||||||
|
return std::unique_ptr<stm32_t, decltype(CLOSE)>{ptr, CLOSE};
|
||||||
|
}
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
} // namespace shelly_dimmer
|
} // namespace shelly_dimmer
|
||||||
|
@ -485,48 +497,44 @@ namespace shelly_dimmer {
|
||||||
/* find newer command by higher code */
|
/* find newer command by higher code */
|
||||||
#define newer(prev, a) (((prev) == STM32_CMD_ERR) ? (a) : (((prev) > (a)) ? (prev) : (a)))
|
#define newer(prev, a) (((prev) == STM32_CMD_ERR) ? (a) : (((prev) > (a)) ? (prev) : (a)))
|
||||||
|
|
||||||
stm32_t *stm32_init(uart::UARTDevice *stream, const uint8_t flags, const char init) {
|
stm32_unique_ptr stm32_init(uart::UARTDevice *stream, const uint8_t flags, const char init) {
|
||||||
uint8_t buf[257];
|
uint8_t buf[257];
|
||||||
|
|
||||||
// Could be constexpr in c++17
|
auto stm = make_stm32_with_deletor(static_cast<stm32_t *>(calloc(sizeof(stm32_t), 1))); // NOLINT
|
||||||
static const auto CLOSE = [](stm32_t *stm32) { stm32_close(stm32); };
|
|
||||||
|
|
||||||
// Cleanup with RAII
|
|
||||||
std::unique_ptr<stm32_t, decltype(CLOSE)> stm{static_cast<stm32_t *>(calloc(sizeof(stm32_t), 1)), // NOLINT
|
|
||||||
CLOSE};
|
|
||||||
|
|
||||||
if (!stm) {
|
if (!stm) {
|
||||||
return nullptr;
|
return make_stm32_with_deletor(nullptr);
|
||||||
}
|
}
|
||||||
stm->stream = stream;
|
stm->stream = stream;
|
||||||
stm->flags = flags;
|
stm->flags = flags;
|
||||||
|
|
||||||
stm->cmd = static_cast<stm32_cmd_t *>(malloc(sizeof(stm32_cmd_t))); // NOLINT
|
stm->cmd = static_cast<stm32_cmd_t *>(malloc(sizeof(stm32_cmd_t))); // NOLINT
|
||||||
if (!stm->cmd) {
|
if (!stm->cmd) {
|
||||||
return nullptr;
|
return make_stm32_with_deletor(nullptr);
|
||||||
}
|
}
|
||||||
memset(stm->cmd, STM32_CMD_ERR, sizeof(stm32_cmd_t));
|
memset(stm->cmd, STM32_CMD_ERR, sizeof(stm32_cmd_t));
|
||||||
|
|
||||||
if ((stm->flags & STREAM_OPT_CMD_INIT) && init) {
|
if ((stm->flags & STREAM_OPT_CMD_INIT) && init) {
|
||||||
if (stm32_send_init_seq(stm.get()) != STM32_ERR_OK)
|
if (stm32_send_init_seq(stm) != STM32_ERR_OK)
|
||||||
return nullptr; // NOLINT
|
return make_stm32_with_deletor(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the version and read protection status */
|
/* get the version and read protection status */
|
||||||
if (stm32_send_command(stm.get(), STM32_CMD_GVR) != STM32_ERR_OK) {
|
if (stm32_send_command(stm, STM32_CMD_GVR) != STM32_ERR_OK) {
|
||||||
return nullptr; // NOLINT
|
return make_stm32_with_deletor(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* From AN, only UART bootloader returns 3 bytes */
|
/* From AN, only UART bootloader returns 3 bytes */
|
||||||
{
|
{
|
||||||
const auto len = (stm->flags & STREAM_OPT_GVR_ETX) ? 3 : 1;
|
const auto len = (stm->flags & STREAM_OPT_GVR_ETX) ? 3 : 1;
|
||||||
if (!stream->read_array(buf, len))
|
if (!stream->read_array(buf, len))
|
||||||
return nullptr; // NOLINT
|
return make_stm32_with_deletor(nullptr);
|
||||||
|
|
||||||
stm->version = buf[0];
|
stm->version = buf[0];
|
||||||
stm->option1 = (stm->flags & STREAM_OPT_GVR_ETX) ? buf[1] : 0;
|
stm->option1 = (stm->flags & STREAM_OPT_GVR_ETX) ? buf[1] : 0;
|
||||||
stm->option2 = (stm->flags & STREAM_OPT_GVR_ETX) ? buf[2] : 0;
|
stm->option2 = (stm->flags & STREAM_OPT_GVR_ETX) ? buf[2] : 0;
|
||||||
if (stm32_get_ack(stm.get()) != STM32_ERR_OK) {
|
if (stm32_get_ack(stm) != STM32_ERR_OK) {
|
||||||
return nullptr;
|
return make_stm32_with_deletor(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,8 +552,8 @@ stm32_t *stm32_init(uart::UARTDevice *stream, const uint8_t flags, const char in
|
||||||
return STM32_CMD_GET_LENGTH;
|
return STM32_CMD_GET_LENGTH;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
if (stm32_guess_len_cmd(stm.get(), STM32_CMD_GET, buf, len) != STM32_ERR_OK)
|
if (stm32_guess_len_cmd(stm, STM32_CMD_GET, buf, len) != STM32_ERR_OK)
|
||||||
return nullptr;
|
return make_stm32_with_deletor(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto stop = buf[0] + 1;
|
const auto stop = buf[0] + 1;
|
||||||
|
@ -607,23 +615,23 @@ stm32_t *stm32_init(uart::UARTDevice *stream, const uint8_t flags, const char in
|
||||||
}
|
}
|
||||||
if (new_cmds)
|
if (new_cmds)
|
||||||
ESP_LOGD(TAG, ")");
|
ESP_LOGD(TAG, ")");
|
||||||
if (stm32_get_ack(stm.get()) != STM32_ERR_OK) {
|
if (stm32_get_ack(stm) != STM32_ERR_OK) {
|
||||||
return nullptr;
|
return make_stm32_with_deletor(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stm->cmd->get == STM32_CMD_ERR || stm->cmd->gvr == STM32_CMD_ERR || stm->cmd->gid == STM32_CMD_ERR) {
|
if (stm->cmd->get == STM32_CMD_ERR || stm->cmd->gvr == STM32_CMD_ERR || stm->cmd->gid == STM32_CMD_ERR) {
|
||||||
ESP_LOGD(TAG, "Error: bootloader did not returned correct information from GET command");
|
ESP_LOGD(TAG, "Error: bootloader did not returned correct information from GET command");
|
||||||
return nullptr;
|
return make_stm32_with_deletor(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the device ID */
|
/* get the device ID */
|
||||||
if (stm32_guess_len_cmd(stm.get(), stm->cmd->gid, buf, 1) != STM32_ERR_OK) {
|
if (stm32_guess_len_cmd(stm, stm->cmd->gid, buf, 1) != STM32_ERR_OK) {
|
||||||
return nullptr;
|
return make_stm32_with_deletor(nullptr);
|
||||||
}
|
}
|
||||||
const auto returned = buf[0] + 1;
|
const auto returned = buf[0] + 1;
|
||||||
if (returned < 2) {
|
if (returned < 2) {
|
||||||
ESP_LOGD(TAG, "Only %d bytes sent in the PID, unknown/unsupported device", returned);
|
ESP_LOGD(TAG, "Only %d bytes sent in the PID, unknown/unsupported device", returned);
|
||||||
return nullptr;
|
return make_stm32_with_deletor(nullptr);
|
||||||
}
|
}
|
||||||
stm->pid = (buf[1] << 8) | buf[2];
|
stm->pid = (buf[1] << 8) | buf[2];
|
||||||
if (returned > 2) {
|
if (returned > 2) {
|
||||||
|
@ -631,8 +639,8 @@ stm32_t *stm32_init(uart::UARTDevice *stream, const uint8_t flags, const char in
|
||||||
for (auto i = 2; i <= returned; i++)
|
for (auto i = 2; i <= returned; i++)
|
||||||
ESP_LOGD(TAG, " %02x", buf[i]);
|
ESP_LOGD(TAG, " %02x", buf[i]);
|
||||||
}
|
}
|
||||||
if (stm32_get_ack(stm.get()) != STM32_ERR_OK) {
|
if (stm32_get_ack(stm) != STM32_ERR_OK) {
|
||||||
return nullptr;
|
return make_stm32_with_deletor(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
stm->dev = DEVICES;
|
stm->dev = DEVICES;
|
||||||
|
@ -641,21 +649,14 @@ stm32_t *stm32_init(uart::UARTDevice *stream, const uint8_t flags, const char in
|
||||||
|
|
||||||
if (!stm->dev->id) {
|
if (!stm->dev->id) {
|
||||||
ESP_LOGD(TAG, "Unknown/unsupported device (Device ID: 0x%03x)", stm->pid);
|
ESP_LOGD(TAG, "Unknown/unsupported device (Device ID: 0x%03x)", stm->pid);
|
||||||
return nullptr;
|
return make_stm32_with_deletor(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Would be much better if the unique_ptr was returned from this function
|
return stm;
|
||||||
// Release ownership of unique_ptr
|
|
||||||
return stm.release(); // NOLINT
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void stm32_close(stm32_t *stm) {
|
stm32_err_t stm32_read_memory(const stm32_unique_ptr &stm, const uint32_t address, uint8_t *data,
|
||||||
if (stm)
|
const unsigned int len) {
|
||||||
free(stm->cmd); // NOLINT
|
|
||||||
free(stm); // NOLINT
|
|
||||||
}
|
|
||||||
|
|
||||||
stm32_err_t stm32_read_memory(const stm32_t *stm, const uint32_t address, uint8_t *data, const unsigned int len) {
|
|
||||||
auto *const stream = stm->stream;
|
auto *const stream = stm->stream;
|
||||||
|
|
||||||
if (!len)
|
if (!len)
|
||||||
|
@ -693,7 +694,8 @@ stm32_err_t stm32_read_memory(const stm32_t *stm, const uint32_t address, uint8_
|
||||||
return STM32_ERR_OK;
|
return STM32_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
stm32_err_t stm32_write_memory(const stm32_t *stm, uint32_t address, const uint8_t *data, const unsigned int len) {
|
stm32_err_t stm32_write_memory(const stm32_unique_ptr &stm, uint32_t address, const uint8_t *data,
|
||||||
|
const unsigned int len) {
|
||||||
auto *const stream = stm->stream;
|
auto *const stream = stm->stream;
|
||||||
|
|
||||||
if (!len)
|
if (!len)
|
||||||
|
@ -753,7 +755,7 @@ stm32_err_t stm32_write_memory(const stm32_t *stm, uint32_t address, const uint8
|
||||||
return STM32_ERR_OK;
|
return STM32_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
stm32_err_t stm32_wunprot_memory(const stm32_t *stm) {
|
stm32_err_t stm32_wunprot_memory(const stm32_unique_ptr &stm) {
|
||||||
if (stm->cmd->uw == STM32_CMD_ERR) {
|
if (stm->cmd->uw == STM32_CMD_ERR) {
|
||||||
ESP_LOGD(TAG, "Error: WRITE UNPROTECT command not implemented in bootloader.");
|
ESP_LOGD(TAG, "Error: WRITE UNPROTECT command not implemented in bootloader.");
|
||||||
return STM32_ERR_NO_CMD;
|
return STM32_ERR_NO_CMD;
|
||||||
|
@ -766,7 +768,7 @@ stm32_err_t stm32_wunprot_memory(const stm32_t *stm) {
|
||||||
[]() { ESP_LOGD(TAG, "Error: Failed to WRITE UNPROTECT"); });
|
[]() { ESP_LOGD(TAG, "Error: Failed to WRITE UNPROTECT"); });
|
||||||
}
|
}
|
||||||
|
|
||||||
stm32_err_t stm32_wprot_memory(const stm32_t *stm) {
|
stm32_err_t stm32_wprot_memory(const stm32_unique_ptr &stm) {
|
||||||
if (stm->cmd->wp == STM32_CMD_ERR) {
|
if (stm->cmd->wp == STM32_CMD_ERR) {
|
||||||
ESP_LOGD(TAG, "Error: WRITE PROTECT command not implemented in bootloader.");
|
ESP_LOGD(TAG, "Error: WRITE PROTECT command not implemented in bootloader.");
|
||||||
return STM32_ERR_NO_CMD;
|
return STM32_ERR_NO_CMD;
|
||||||
|
@ -779,7 +781,7 @@ stm32_err_t stm32_wprot_memory(const stm32_t *stm) {
|
||||||
[]() { ESP_LOGD(TAG, "Error: Failed to WRITE PROTECT"); });
|
[]() { ESP_LOGD(TAG, "Error: Failed to WRITE PROTECT"); });
|
||||||
}
|
}
|
||||||
|
|
||||||
stm32_err_t stm32_runprot_memory(const stm32_t *stm) {
|
stm32_err_t stm32_runprot_memory(const stm32_unique_ptr &stm) {
|
||||||
if (stm->cmd->ur == STM32_CMD_ERR) {
|
if (stm->cmd->ur == STM32_CMD_ERR) {
|
||||||
ESP_LOGD(TAG, "Error: READOUT UNPROTECT command not implemented in bootloader.");
|
ESP_LOGD(TAG, "Error: READOUT UNPROTECT command not implemented in bootloader.");
|
||||||
return STM32_ERR_NO_CMD;
|
return STM32_ERR_NO_CMD;
|
||||||
|
@ -792,7 +794,7 @@ stm32_err_t stm32_runprot_memory(const stm32_t *stm) {
|
||||||
[]() { ESP_LOGD(TAG, "Error: Failed to READOUT UNPROTECT"); });
|
[]() { ESP_LOGD(TAG, "Error: Failed to READOUT UNPROTECT"); });
|
||||||
}
|
}
|
||||||
|
|
||||||
stm32_err_t stm32_readprot_memory(const stm32_t *stm) {
|
stm32_err_t stm32_readprot_memory(const stm32_unique_ptr &stm) {
|
||||||
if (stm->cmd->rp == STM32_CMD_ERR) {
|
if (stm->cmd->rp == STM32_CMD_ERR) {
|
||||||
ESP_LOGD(TAG, "Error: READOUT PROTECT command not implemented in bootloader.");
|
ESP_LOGD(TAG, "Error: READOUT PROTECT command not implemented in bootloader.");
|
||||||
return STM32_ERR_NO_CMD;
|
return STM32_ERR_NO_CMD;
|
||||||
|
@ -805,7 +807,7 @@ stm32_err_t stm32_readprot_memory(const stm32_t *stm) {
|
||||||
[]() { ESP_LOGD(TAG, "Error: Failed to READOUT PROTECT"); });
|
[]() { ESP_LOGD(TAG, "Error: Failed to READOUT PROTECT"); });
|
||||||
}
|
}
|
||||||
|
|
||||||
stm32_err_t stm32_erase_memory(const stm32_t *stm, uint32_t spage, uint32_t pages) {
|
stm32_err_t stm32_erase_memory(const stm32_unique_ptr &stm, uint32_t spage, uint32_t pages) {
|
||||||
if (!pages || spage > STM32_MAX_PAGES || ((pages != STM32_MASS_ERASE) && ((spage + pages) > STM32_MAX_PAGES)))
|
if (!pages || spage > STM32_MAX_PAGES || ((pages != STM32_MASS_ERASE) && ((spage + pages) > STM32_MAX_PAGES)))
|
||||||
return STM32_ERR_OK;
|
return STM32_ERR_OK;
|
||||||
|
|
||||||
|
@ -847,7 +849,7 @@ stm32_err_t stm32_erase_memory(const stm32_t *stm, uint32_t spage, uint32_t page
|
||||||
return STM32_ERR_OK;
|
return STM32_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static stm32_err_t stm32_run_raw_code(const stm32_t *stm, uint32_t target_address, const uint8_t *code,
|
static stm32_err_t stm32_run_raw_code(const stm32_unique_ptr &stm, uint32_t target_address, const uint8_t *code,
|
||||||
uint32_t code_size) {
|
uint32_t code_size) {
|
||||||
static constexpr uint32_t BUFFER_SIZE = 256;
|
static constexpr uint32_t BUFFER_SIZE = 256;
|
||||||
|
|
||||||
|
@ -893,7 +895,7 @@ static stm32_err_t stm32_run_raw_code(const stm32_t *stm, uint32_t target_addres
|
||||||
return stm32_go(stm, target_address);
|
return stm32_go(stm, target_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
stm32_err_t stm32_go(const stm32_t *stm, const uint32_t address) {
|
stm32_err_t stm32_go(const stm32_unique_ptr &stm, const uint32_t address) {
|
||||||
auto *const stream = stm->stream;
|
auto *const stream = stm->stream;
|
||||||
|
|
||||||
if (stm->cmd->go == STM32_CMD_ERR) {
|
if (stm->cmd->go == STM32_CMD_ERR) {
|
||||||
|
@ -916,7 +918,7 @@ stm32_err_t stm32_go(const stm32_t *stm, const uint32_t address) {
|
||||||
return STM32_ERR_OK;
|
return STM32_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
stm32_err_t stm32_reset_device(const stm32_t *stm) {
|
stm32_err_t stm32_reset_device(const stm32_unique_ptr &stm) {
|
||||||
const auto target_address = stm->dev->ram_start;
|
const auto target_address = stm->dev->ram_start;
|
||||||
|
|
||||||
if (stm->dev->flags & F_OBLL) {
|
if (stm->dev->flags & F_OBLL) {
|
||||||
|
@ -927,7 +929,8 @@ stm32_err_t stm32_reset_device(const stm32_t *stm) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stm32_err_t stm32_crc_memory(const stm32_t *stm, const uint32_t address, const uint32_t length, uint32_t *const crc) {
|
stm32_err_t stm32_crc_memory(const stm32_unique_ptr &stm, const uint32_t address, const uint32_t length,
|
||||||
|
uint32_t *const crc) {
|
||||||
static constexpr auto BUFFER_SIZE = 5;
|
static constexpr auto BUFFER_SIZE = 5;
|
||||||
auto *const stream = stm->stream;
|
auto *const stream = stm->stream;
|
||||||
|
|
||||||
|
@ -1022,7 +1025,7 @@ uint32_t stm32_sw_crc(uint32_t crc, uint8_t *buf, unsigned int len) {
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
stm32_err_t stm32_crc_wrapper(const stm32_t *stm, uint32_t address, uint32_t length, uint32_t *crc) {
|
stm32_err_t stm32_crc_wrapper(const stm32_unique_ptr &stm, uint32_t address, uint32_t length, uint32_t *crc) {
|
||||||
static constexpr uint32_t CRC_INIT_VALUE = 0xFFFFFFFF;
|
static constexpr uint32_t CRC_INIT_VALUE = 0xFFFFFFFF;
|
||||||
static constexpr uint32_t BUFFER_SIZE = 256;
|
static constexpr uint32_t BUFFER_SIZE = 256;
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#ifdef USE_SHD_FIRMWARE_DATA
|
#ifdef USE_SHD_FIRMWARE_DATA
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
#include "esphome/components/uart/uart.h"
|
#include "esphome/components/uart/uart.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
|
@ -108,19 +109,20 @@ struct VarlenCmd {
|
||||||
uint8_t length;
|
uint8_t length;
|
||||||
};
|
};
|
||||||
|
|
||||||
stm32_t *stm32_init(uart::UARTDevice *stream, uint8_t flags, char init);
|
using stm32_unique_ptr = std::unique_ptr<stm32_t, void (*)(stm32_t *)>;
|
||||||
void stm32_close(stm32_t *stm);
|
|
||||||
stm32_err_t stm32_read_memory(const stm32_t *stm, uint32_t address, uint8_t *data, unsigned int len);
|
stm32_unique_ptr stm32_init(uart::UARTDevice *stream, uint8_t flags, char init);
|
||||||
stm32_err_t stm32_write_memory(const stm32_t *stm, uint32_t address, const uint8_t *data, unsigned int len);
|
stm32_err_t stm32_read_memory(const stm32_unique_ptr &stm, uint32_t address, uint8_t *data, unsigned int len);
|
||||||
stm32_err_t stm32_wunprot_memory(const stm32_t *stm);
|
stm32_err_t stm32_write_memory(const stm32_unique_ptr &stm, uint32_t address, const uint8_t *data, unsigned int len);
|
||||||
stm32_err_t stm32_wprot_memory(const stm32_t *stm);
|
stm32_err_t stm32_wunprot_memory(const stm32_unique_ptr &stm);
|
||||||
stm32_err_t stm32_erase_memory(const stm32_t *stm, uint32_t spage, uint32_t pages);
|
stm32_err_t stm32_wprot_memory(const stm32_unique_ptr &stm);
|
||||||
stm32_err_t stm32_go(const stm32_t *stm, uint32_t address);
|
stm32_err_t stm32_erase_memory(const stm32_unique_ptr &stm, uint32_t spage, uint32_t pages);
|
||||||
stm32_err_t stm32_reset_device(const stm32_t *stm);
|
stm32_err_t stm32_go(const stm32_unique_ptr &stm, uint32_t address);
|
||||||
stm32_err_t stm32_readprot_memory(const stm32_t *stm);
|
stm32_err_t stm32_reset_device(const stm32_unique_ptr &stm);
|
||||||
stm32_err_t stm32_runprot_memory(const stm32_t *stm);
|
stm32_err_t stm32_readprot_memory(const stm32_unique_ptr &stm);
|
||||||
stm32_err_t stm32_crc_memory(const stm32_t *stm, uint32_t address, uint32_t length, uint32_t *crc);
|
stm32_err_t stm32_runprot_memory(const stm32_unique_ptr &stm);
|
||||||
stm32_err_t stm32_crc_wrapper(const stm32_t *stm, uint32_t address, uint32_t length, uint32_t *crc);
|
stm32_err_t stm32_crc_memory(const stm32_unique_ptr &stm, uint32_t address, uint32_t length, uint32_t *crc);
|
||||||
|
stm32_err_t stm32_crc_wrapper(const stm32_unique_ptr &stm, uint32_t address, uint32_t length, uint32_t *crc);
|
||||||
uint32_t stm32_sw_crc(uint32_t crc, uint8_t *buf, unsigned int len);
|
uint32_t stm32_sw_crc(uint32_t crc, uint8_t *buf, unsigned int len);
|
||||||
|
|
||||||
} // namespace shelly_dimmer
|
} // namespace shelly_dimmer
|
||||||
|
|
|
@ -13,11 +13,11 @@ static const char *const TAG = "time";
|
||||||
|
|
||||||
RealTimeClock::RealTimeClock() = default;
|
RealTimeClock::RealTimeClock() = default;
|
||||||
void RealTimeClock::call_setup() {
|
void RealTimeClock::call_setup() {
|
||||||
setenv("TZ", this->timezone_.c_str(), 1);
|
this->apply_timezone_();
|
||||||
tzset();
|
|
||||||
PollingComponent::call_setup();
|
PollingComponent::call_setup();
|
||||||
}
|
}
|
||||||
void RealTimeClock::synchronize_epoch_(uint32_t epoch) {
|
void RealTimeClock::synchronize_epoch_(uint32_t epoch) {
|
||||||
|
// Update UTC epoch time.
|
||||||
struct timeval timev {
|
struct timeval timev {
|
||||||
.tv_sec = static_cast<time_t>(epoch), .tv_usec = 0,
|
.tv_sec = static_cast<time_t>(epoch), .tv_usec = 0,
|
||||||
};
|
};
|
||||||
|
@ -30,6 +30,9 @@ void RealTimeClock::synchronize_epoch_(uint32_t epoch) {
|
||||||
ret = settimeofday(&timev, nullptr);
|
ret = settimeofday(&timev, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Move timezone back to local timezone.
|
||||||
|
this->apply_timezone_();
|
||||||
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
ESP_LOGW(TAG, "setimeofday() failed with code %d", ret);
|
ESP_LOGW(TAG, "setimeofday() failed with code %d", ret);
|
||||||
}
|
}
|
||||||
|
@ -41,6 +44,11 @@ void RealTimeClock::synchronize_epoch_(uint32_t epoch) {
|
||||||
this->time_sync_callback_.call();
|
this->time_sync_callback_.call();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RealTimeClock::apply_timezone_() {
|
||||||
|
setenv("TZ", this->timezone_.c_str(), 1);
|
||||||
|
tzset();
|
||||||
|
}
|
||||||
|
|
||||||
size_t ESPTime::strftime(char *buffer, size_t buffer_len, const char *format) {
|
size_t ESPTime::strftime(char *buffer, size_t buffer_len, const char *format) {
|
||||||
struct tm c_tm = this->to_c_tm();
|
struct tm c_tm = this->to_c_tm();
|
||||||
return ::strftime(buffer, buffer_len, format, &c_tm);
|
return ::strftime(buffer, buffer_len, format, &c_tm);
|
||||||
|
|
|
@ -137,6 +137,7 @@ class RealTimeClock : public PollingComponent {
|
||||||
void synchronize_epoch_(uint32_t epoch);
|
void synchronize_epoch_(uint32_t epoch);
|
||||||
|
|
||||||
std::string timezone_{};
|
std::string timezone_{};
|
||||||
|
void apply_timezone_();
|
||||||
|
|
||||||
CallbackManager<void()> time_sync_callback_;
|
CallbackManager<void()> time_sync_callback_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""Constants used by esphome."""
|
"""Constants used by esphome."""
|
||||||
|
|
||||||
__version__ = "2022.5.0b1"
|
__version__ = "2022.5.0b2"
|
||||||
|
|
||||||
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue