ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
seeed_multi_channel_relay.cpp
Go to the documentation of this file.
3#include "esphome/core/log.h"
4
6
7ESPHOME_LOG_TAG(TAG, "seeed_multi_channel_relay");
8
9static constexpr uint8_t CMD_CHANNEL_CTRL = 0x10;
10static constexpr uint8_t CMD_SAVE_I2C_ADDR = 0x11;
11static constexpr uint8_t CMD_READ_FIRMWARE_VER = 0x13;
12
14 if (!this->read_byte(CMD_READ_FIRMWARE_VER, &this->firmware_version_)) {
15 this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
16 return;
17 }
18#ifdef USE_SWITCH
19 // channels_ owns all 8 relays and the board has no read-back: after an ESP-only reboot the board keeps its
20 // relays, so every channel is set from the switches' restore modes in one write, and a channel already on
21 // never drops out while the others are written; a power cycle starts with all off. A switch with restore_mode
22 // DISABLED is driven off too, so its state matches what the next write does
23 uint8_t value = 0;
24 for (uint8_t channel = 0; channel != this->switches_.size(); channel++) {
25 switch_::Switch *sw = this->switches_[channel];
26 if (sw == nullptr)
27 continue;
28 const bool on = sw->get_initial_state_with_restore_mode().value_or(sw->is_inverted()) != sw->is_inverted();
29 assign_bits(value, 1 << channel, on);
30 }
31 if (!this->status_comm_result(this->write_byte(CMD_CHANNEL_CTRL, value)))
32 return;
33 this->channels_ = value;
34 for (uint8_t channel = 0; channel != this->switches_.size(); channel++) {
35 if (this->switches_[channel] != nullptr)
36 this->switches_[channel]->publish_state((value >> channel) & 1);
37 }
38#endif
39}
40
42 if (this->is_failed())
43 return;
44 // A lambda bypasses the schema range; a reserved address would strand the board
46 ESP_LOGW(TAG, "I2C address 0x%02X is reserved; not stored", address);
47 return;
48 }
49 if (!this->status_comm_result(this->write_byte(CMD_SAVE_I2C_ADDR, address)))
50 return;
51 this->set_i2c_address(address);
52 ESP_LOGI(TAG, "Board now answers at 0x%02X; update address: in the configuration", address);
53}
54
56 ESP_LOGCONFIG(TAG,
57 "Seeed Multi Channel Relay:\n"
58 " Firmware version: %u",
59 this->firmware_version_);
60 LOG_I2C_DEVICE(this);
61}
62
63bool SeeedMultiChannelRelay::set_relay(uint8_t channel, bool on) {
64 if (this->is_failed())
65 return false;
66 uint8_t value = this->channels_;
67 assign_bits(value, 1 << channel, on);
68 if (!this->status_comm_result(this->write_byte(CMD_CHANNEL_CTRL, value)))
69 return false;
70 this->channels_ = value;
71#ifdef USE_SWITCH
72 if (this->switches_[channel] != nullptr)
73 this->switches_[channel]->publish_state(on);
74#endif
75 return true;
76}
77
78} // namespace esphome::seeed_multi_channel_relay
uint8_t address
Definition bl0906.h:4
void mark_failed()
Mark this component as failed.
bool is_failed() const
Definition component.h:274
bool status_comm_result(bool ok)
Clears the warning when ok, else sets it with message (default "Communication failed"); returns ok.
bool write_byte(uint8_t a_register, uint8_t data) const
Definition i2c.h:312
bool read_byte(uint8_t a_register, uint8_t *data)
Definition i2c.h:272
void set_i2c_address(uint8_t address)
We store the address of the device on the bus.
Definition i2c.h:151
void change_address(uint8_t address)
Store a new I2C address in the board's EEPROM and talk to it there from now on.
bool set_relay(uint8_t channel, bool on)
Switch relay channel (0-7) on or off; returns false when the write failed.
Base class for all switches.
Definition switch.h:43
optional< bool > get_initial_state_with_restore_mode()
Returns the initial state of the switch, after applying restore mode rules.
Definition switch.cpp:49
bool is_inverted() const
Definition switch.h:130
ESPHOME_LOG_TAG(TAG, "seeed_multi_channel_relay")
ESPHOME_ALWAYS_INLINE constexpr void assign_bits(T &value, std::type_identity_t< T > mask, bool on)
Set the bits of mask in value when on is true, clear them otherwise.
Definition helpers.h:1072