50static const char *
const TAG =
"sonoff_d1";
53static constexpr size_t SONOFF_D1_ACK_SIZE = 7;
54static constexpr size_t SONOFF_D1_MAX_CMD_SIZE = 17;
58 for (
size_t i = 2; i <
len - 1; i++) {
73 uint8_t value = this->
read();
74 ESP_LOGW(TAG,
"[%04d] Skip %02d: 0x%02x from the dimmer", this->
write_count_, garbage, value);
80 ESP_LOGW(TAG,
"[%04d] Skip %d bytes from the dimmer", this->
write_count_, garbage);
87 if (cmd ==
nullptr ||
len < 7) {
88 ESP_LOGW(TAG,
"[%04d] Too short command buffer (actual len is %d bytes, minimal is 7)", this->
write_count_, len);
94#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
99 if (cmd[0] != 0xAA || cmd[1] != 0x55) {
100 ESP_LOGW(TAG,
"[%04d] RX: wrong header (%x%x, must be AA55)", this->
write_count_, cmd[0], cmd[1]);
104 if ((cmd[5] + 7 ) >
len) {
105 ESP_LOGW(TAG,
"[%04d] RX: Payload length is unexpected (%d, max expected %d)", this->
write_count_, cmd[5],
111#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
118 if (valid_checksum != cmd[cmd[5] + 7 - 1]) {
119 ESP_LOGW(TAG,
"[%04d] RX: checksum mismatch (%d, expected %d)", this->
write_count_, cmd[cmd[5] + 7 - 1],
131 ESP_LOGW(TAG,
"[%04d] RX: feedback timeout", this->
write_count_);
139 uint8_t ref_buffer[7] = {0xAA, 0x55, cmd[2], cmd[3], 0x00, 0x00, 0x00};
140 uint8_t buffer[
sizeof(ref_buffer)] = {0};
142 size_t buf_len =
sizeof(ref_buffer);
151 while (
pos <
sizeof(ref_buffer) && ref_buffer[
pos] == buffer[
pos]) {
154 if (
pos ==
sizeof(ref_buffer)) {
155 ESP_LOGD(TAG,
"[%04d] Acknowledge received", this->
write_count_);
159 ESP_LOGW(TAG,
"[%04d] Unexpected acknowledge received (possible clash of RF/HA commands), expected ack was:",
169 ESP_LOGW(TAG,
"[%04d] Too short command (actual len is %d bytes, minimal is 7)", this->
write_count_, len);
172 if (cmd[0] != 0xAA || cmd[1] != 0x55) {
173 ESP_LOGW(TAG,
"[%04d] Wrong header (%x%x, must be AA55)", this->
write_count_, cmd[0], cmd[1]);
176 if ((cmd[5] + 7 ) !=
len) {
177 ESP_LOGW(TAG,
"[%04d] Payload length field does not match packet length (%d, expected %d)", this->
write_count_,
186 uint32_t retries = 10;
188#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
202 ESP_LOGE(TAG,
"[%04d] Unable to write to the dimmer", this->
write_count_);
210 uint8_t cmd[17] = {0xAA, 0x55, 0x01, 0x04, 0x00, 0x0A, 0x00, 0x00, 0xFF,
212 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
216 ESP_LOGI(TAG,
"[%04d] Setting dimmer state to %s, raw brightness=%d", this->
write_count_, ONOFF(binary), cmd[7]);
221 if (cmd[2] == 0x01 && cmd[3] == 0x04 && cmd[4] == 0x00 && cmd[5] == 0x0A) {
222 uint8_t ack_buffer[7] = {0xAA, 0x55, cmd[2], cmd[3], 0x00, 0x00, 0x00};
225 ESP_LOGI(TAG,
"[%04d] RF sets dimmer state to %s, raw brightness=%d", this->
write_count_, ONOFF(cmd[6]), cmd[7]);
227 const bool new_state = cmd[6];
237 ESP_LOGI(TAG,
"[%04d] Ghost command from RF detected, reverted", this->
write_count_);
243 ESP_LOGW(TAG,
"[%04d] Unexpected command received", this->
write_count_);
249 ESP_LOGV(TAG,
"Publishing new state: %s, brightness=%d", ONOFF(is_on), brightness);
252 if (brightness != 0) {
258 call.set_brightness((
float) brightness / 100.0f);
276 state->current_values_as_binary(&binary);
277 state->current_values_as_brightness(&brightness);
280 const uint8_t calculated_brightness = (uint8_t) roundf(brightness * 100);
282 if (calculated_brightness == 0) {
295 ESP_LOGW(TAG,
"Failed to update the dimmer, publishing the previous state");
303 "Sonoff D1 Dimmer: '%s'\n"
304 " Use RM433 Remote: %s\n"
305 " Minimal brightness: %d\n"
306 " Maximal brightness: %d",
315 ESP_LOGV(TAG,
"Have some UART data in loop()");
316 uint8_t buffer[17] = {0};
317 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.
Providing packet encoding functions for exchanging data with a remote host.
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).