49static const char *
const TAG =
"sonoff_d1";
52static constexpr size_t SONOFF_D1_ACK_SIZE = 7;
53static constexpr size_t SONOFF_D1_MAX_CMD_SIZE = 17;
57 for (
size_t i = 2; i <
len - 1; i++) {
72 uint8_t value = this->
read();
73 ESP_LOGW(TAG,
"[%04d] Skip %02d: 0x%02x from the dimmer", this->
write_count_, garbage, value);
79 ESP_LOGW(TAG,
"[%04d] Skip %d bytes from the dimmer", this->
write_count_, garbage);
86 if (cmd ==
nullptr ||
len < 7) {
87 ESP_LOGW(TAG,
"[%04d] Too short command buffer (actual len is %d bytes, minimal is 7)", this->
write_count_, len);
93#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
98 if (cmd[0] != 0xAA || cmd[1] != 0x55) {
99 ESP_LOGW(TAG,
"[%04d] RX: wrong header (%x%x, must be AA55)", this->
write_count_, cmd[0], cmd[1]);
103 if ((cmd[5] + 7 ) >
len) {
104 ESP_LOGW(TAG,
"[%04d] RX: Payload length is unexpected (%d, max expected %d)", this->
write_count_, cmd[5],
110#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
117 if (valid_checksum != cmd[cmd[5] + 7 - 1]) {
118 ESP_LOGW(TAG,
"[%04d] RX: checksum mismatch (%d, expected %d)", this->
write_count_, cmd[cmd[5] + 7 - 1],
130 ESP_LOGW(TAG,
"[%04d] RX: feedback timeout", this->
write_count_);
138 uint8_t ref_buffer[7] = {0xAA, 0x55, cmd[2], cmd[3], 0x00, 0x00, 0x00};
139 uint8_t buffer[
sizeof(ref_buffer)] = {0};
141 size_t buf_len =
sizeof(ref_buffer);
150 while (
pos <
sizeof(ref_buffer) && ref_buffer[
pos] == buffer[
pos]) {
153 if (
pos ==
sizeof(ref_buffer)) {
154 ESP_LOGD(TAG,
"[%04d] Acknowledge received", this->
write_count_);
158 ESP_LOGW(TAG,
"[%04d] Unexpected acknowledge received (possible clash of RF/HA commands), expected ack was:",
168 ESP_LOGW(TAG,
"[%04d] Too short command (actual len is %d bytes, minimal is 7)", this->
write_count_, len);
171 if (cmd[0] != 0xAA || cmd[1] != 0x55) {
172 ESP_LOGW(TAG,
"[%04d] Wrong header (%x%x, must be AA55)", this->
write_count_, cmd[0], cmd[1]);
175 if ((cmd[5] + 7 ) !=
len) {
176 ESP_LOGW(TAG,
"[%04d] Payload length field does not match packet length (%d, expected %d)", this->
write_count_,
187#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
201 ESP_LOGE(TAG,
"[%04d] Unable to write to the dimmer", this->
write_count_);
209 uint8_t cmd[17] = {0xAA, 0x55, 0x01, 0x04, 0x00, 0x0A, 0x00, 0x00, 0xFF,
211 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
215 ESP_LOGI(TAG,
"[%04d] Setting dimmer state to %s, raw brightness=%d", this->
write_count_, ONOFF(binary), cmd[7]);
220 if (cmd[2] == 0x01 && cmd[3] == 0x04 && cmd[4] == 0x00 && cmd[5] == 0x0A) {
221 uint8_t ack_buffer[7] = {0xAA, 0x55, cmd[2], cmd[3], 0x00, 0x00, 0x00};
224 ESP_LOGI(TAG,
"[%04d] RF sets dimmer state to %s, raw brightness=%d", this->
write_count_, ONOFF(cmd[6]), cmd[7]);
226 const bool new_state = cmd[6];
236 ESP_LOGI(TAG,
"[%04d] Ghost command from RF detected, reverted", this->
write_count_);
242 ESP_LOGW(TAG,
"[%04d] Unexpected command received", this->
write_count_);
248 ESP_LOGV(TAG,
"Publishing new state: %s, brightness=%d", ONOFF(is_on), brightness);
251 if (brightness != 0) {
257 call.set_brightness((
float) brightness / 100.0f);
275 state->current_values_as_binary(&binary);
276 state->current_values_as_brightness(&brightness);
279 const uint8_t calculated_brightness = (uint8_t) roundf(brightness * 100);
281 if (calculated_brightness == 0) {
294 ESP_LOGW(TAG,
"Failed to update the dimmer, publishing the previous state");
302 "Sonoff D1 Dimmer: '%s'\n"
303 " Use RM433 Remote: %s\n"
304 " Minimal brightness: %d\n"
305 " Maximal brightness: %d",
314 ESP_LOGV(TAG,
"Have some UART data in loop()");
315 uint8_t buffer[17] = {0};
316 size_t len =
sizeof(buffer);
const StringRef & get_name() const
constexpr const char * c_str() const
LightCall & set_state(optional< bool > state)
Set the binary ON/OFF state of the light.
This class represents the communication layer between the front-end MQTT layer and the hardware outpu...
This class is used to represent the capabilities of a light.
bool read_command_(uint8_t *cmd, size_t &len)
void process_command_(const uint8_t *cmd, size_t len)
uint8_t calc_checksum_(const uint8_t *cmd, size_t len)
bool control_dimmer_(bool binary, uint8_t brightness)
void populate_checksum_(uint8_t *cmd, size_t len)
void dump_config() override
light::LightState * light_state_
void write_state(light::LightState *state) override
void publish_state_(bool is_on, uint8_t brightness)
bool read_ack_(const uint8_t *cmd, size_t len)
light::LightTraits get_traits() override
bool write_command_(uint8_t *cmd, size_t len, bool needs_ack=true)
optional< std::array< uint8_t, N > > read_array()
void write_array(const uint8_t *data, size_t len)
@ BRIGHTNESS
Dimmable light.
char * format_hex_pretty_to(char *buffer, size_t buffer_size, const uint8_t *data, size_t length, char separator)
Format byte array as uppercase hex to buffer (base implementation).
constexpr size_t format_hex_pretty_size(size_t byte_count)
Calculate buffer size needed for format_hex_pretty_to with separator: "XX:XX:...:XX\0".
T remap(U value, U min, U max, T min_out, T max_out)
Remap value from the range (min, max) to (min_out, max_out).