mirror of https://github.com/esphome/esphome.git
Merge 74964694c3
into c7c0d97a5e
This commit is contained in:
commit
d548cbb6f4
|
@ -197,6 +197,7 @@ esphome/components/lilygo_t5_47/touchscreen/* @jesserockz
|
||||||
esphome/components/lock/* @esphome/core
|
esphome/components/lock/* @esphome/core
|
||||||
esphome/components/logger/* @esphome/core
|
esphome/components/logger/* @esphome/core
|
||||||
esphome/components/ltr390/* @sjtrny
|
esphome/components/ltr390/* @sjtrny
|
||||||
|
esphome/components/m5stack4relay/* @KoenBreeman
|
||||||
esphome/components/matrix_keypad/* @ssieb
|
esphome/components/matrix_keypad/* @ssieb
|
||||||
esphome/components/max31865/* @DAVe3283
|
esphome/components/max31865/* @DAVe3283
|
||||||
esphome/components/max44009/* @berfenger
|
esphome/components/max44009/* @berfenger
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import i2c
|
||||||
|
from esphome.const import CONF_ID
|
||||||
|
|
||||||
|
CODEOWNERS = ["@KoenBreeman"]
|
||||||
|
DEPENDENCIES = ["i2c"]
|
||||||
|
|
||||||
|
MULTI_CONF = True
|
||||||
|
|
||||||
|
CONF_M5STACK4RELAY_ID = "m5stack4relay_id"
|
||||||
|
|
||||||
|
m5stack4relay_ns = cg.esphome_ns.namespace("m5stack4relay")
|
||||||
|
M5Stack4Relay = m5stack4relay_ns.class_("M5Stack4Relay", cg.Component, i2c.I2CDevice)
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = (
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(M5Stack4Relay),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.extend(cv.COMPONENT_SCHEMA)
|
||||||
|
.extend(i2c.i2c_device_schema(0x26))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
await i2c.register_i2c_device(var, config)
|
|
@ -0,0 +1,65 @@
|
||||||
|
#include "m5stack4relay.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace m5stack4relay {
|
||||||
|
|
||||||
|
static const char *const TAG = "m5stack_4_relay";
|
||||||
|
|
||||||
|
void M5Stack4Relay::dump_config() {
|
||||||
|
ESP_LOGCONFIG(TAG, "M5Stack 4 Relays:");
|
||||||
|
LOG_I2C_DEVICE(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! @brief Setting the mode of the device, and turn off all relays.
|
||||||
|
* @param mode Async = 0, Sync = 1. */
|
||||||
|
void M5Stack4Relay::init_(bool mode) {
|
||||||
|
this->write1_byte_(UNIT_4RELAY_REG, mode);
|
||||||
|
this->write1_byte_(UNIT_4RELAY_RELAY_REG, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! @brief Read a certain length of data to the specified register address. */
|
||||||
|
uint8_t M5Stack4Relay::read1_byte_(uint8_t register_address) {
|
||||||
|
uint8_t data;
|
||||||
|
if (!this->read_byte(register_address, &data)) {
|
||||||
|
ESP_LOGW(TAG, "Read from relay failed!");
|
||||||
|
this->status_set_warning();
|
||||||
|
return uint8_t(0);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! @brief Control the on/off of the specified relay.
|
||||||
|
* @param number Bit number of relay (0~3).
|
||||||
|
@param state OFF = 0, ON = 1 . */
|
||||||
|
void M5Stack4Relay::relay_write(uint8_t number, bool state) {
|
||||||
|
uint8_t state_from_device = this->read1_byte_(UNIT_4RELAY_RELAY_REG);
|
||||||
|
if (state == 0) {
|
||||||
|
state_from_device &= ~(0x01 << number);
|
||||||
|
} else {
|
||||||
|
state_from_device |= (0x01 << number);
|
||||||
|
}
|
||||||
|
this->write1_byte_(UNIT_4RELAY_RELAY_REG, state_from_device);
|
||||||
|
}
|
||||||
|
|
||||||
|
void M5Stack4Relay::setup() {
|
||||||
|
ESP_LOGCONFIG(TAG, "Setting up M5Stack_4_Relays...");
|
||||||
|
uint8_t setupmode = 1;
|
||||||
|
this->init_(setupmode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! @brief Setting the mode of the device.
|
||||||
|
* @param mode Async = 0, Sync = 1. */
|
||||||
|
void M5Stack4Relay::set_switch_mode(bool mode) { this->write1_byte_(UNIT_4RELAY_REG, mode); }
|
||||||
|
|
||||||
|
/*! @brief Write a certain length of data to the specified register address. */
|
||||||
|
void M5Stack4Relay::write1_byte_(uint8_t register_address, uint8_t data) {
|
||||||
|
if (!this->write_byte(register_address, data)) {
|
||||||
|
ESP_LOGW(TAG, "Write to relay failed!");
|
||||||
|
this->status_set_warning();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace m5stack4relay
|
||||||
|
} // namespace esphome
|
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/components/i2c/i2c.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace m5stack4relay {
|
||||||
|
|
||||||
|
static constexpr uint8_t UNIT_4RELAY_REG = 0X10;
|
||||||
|
static constexpr uint8_t UNIT_4RELAY_RELAY_REG = 0X11;
|
||||||
|
|
||||||
|
enum class RelayBit : uint8_t { RELAY1 = 0, RELAY2 = 1, RELAY3 = 2, RELAY4 = 3 };
|
||||||
|
|
||||||
|
class M5Stack4Relay : public Component, public i2c::I2CDevice {
|
||||||
|
public:
|
||||||
|
void set_switch_mode(bool mode);
|
||||||
|
|
||||||
|
void relay_write(uint8_t number, bool state);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void write1_byte_(uint8_t register_address, uint8_t data);
|
||||||
|
uint8_t read1_byte_(uint8_t register_address);
|
||||||
|
|
||||||
|
void dump_config() override;
|
||||||
|
|
||||||
|
void init_(bool mode);
|
||||||
|
|
||||||
|
void setup() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace m5stack4relay
|
||||||
|
} // namespace esphome
|
|
@ -0,0 +1,63 @@
|
||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import i2c, switch
|
||||||
|
from esphome.const import CONF_CHANNEL, CONF_INTERLOCK # , CONF_ID,
|
||||||
|
|
||||||
|
from .. import m5stack4relay_ns, M5Stack4Relay, CONF_M5STACK4RELAY_ID
|
||||||
|
|
||||||
|
DEPENDENCIES = ["m5stack4relay"]
|
||||||
|
|
||||||
|
M5StackSwitch = m5stack4relay_ns.class_(
|
||||||
|
"M5Stack4RelaySwitch", cg.Component, i2c.I2CDevice, switch.Switch
|
||||||
|
)
|
||||||
|
|
||||||
|
CONF_INTERLOCK_WAIT_TIME = "interlock_wait_time"
|
||||||
|
|
||||||
|
CONF_Relay_1 = 1
|
||||||
|
CONF_Relay_2 = 2
|
||||||
|
CONF_Relay_3 = 3
|
||||||
|
CONF_Relay_4 = 4
|
||||||
|
|
||||||
|
CONF_INTERLOCK_WAIT_TIME = "interlock_wait_time"
|
||||||
|
|
||||||
|
RelayBit_ = m5stack4relay_ns.enum("RelayBit", is_class=True)
|
||||||
|
|
||||||
|
SWITCH_MAP = {
|
||||||
|
CONF_Relay_1: RelayBit_.RELAY1,
|
||||||
|
CONF_Relay_2: RelayBit_.RELAY2,
|
||||||
|
CONF_Relay_3: RelayBit_.RELAY3,
|
||||||
|
CONF_Relay_4: RelayBit_.RELAY4,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = (
|
||||||
|
switch.switch_schema(M5StackSwitch)
|
||||||
|
.extend(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(M5StackSwitch),
|
||||||
|
cv.GenerateID(CONF_M5STACK4RELAY_ID): cv.use_id(M5Stack4Relay),
|
||||||
|
cv.Required(CONF_CHANNEL): cv.enum(SWITCH_MAP),
|
||||||
|
cv.Optional(CONF_INTERLOCK): cv.ensure_list(cv.use_id(switch.Switch)),
|
||||||
|
cv.Optional(
|
||||||
|
CONF_INTERLOCK_WAIT_TIME, default="0ms"
|
||||||
|
): cv.positive_time_period_milliseconds,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.extend(cv.COMPONENT_SCHEMA)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
var = await switch.new_switch(config)
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
await cg.register_parented(var, config[CONF_M5STACK4RELAY_ID])
|
||||||
|
|
||||||
|
cg.add(var.set_channel(config[CONF_CHANNEL]))
|
||||||
|
|
||||||
|
if CONF_INTERLOCK in config:
|
||||||
|
interlock = []
|
||||||
|
for it in config[CONF_INTERLOCK]:
|
||||||
|
lock = await cg.get_variable(it)
|
||||||
|
interlock.append(lock)
|
||||||
|
cg.add(var.set_interlock(interlock))
|
||||||
|
cg.add(var.set_interlock_wait_time(config[CONF_INTERLOCK_WAIT_TIME]))
|
|
@ -0,0 +1,75 @@
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
#include "m5stack4relay_switch.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace m5stack4relay {
|
||||||
|
|
||||||
|
static const char *const TAG = "switch.M5Stack_4_Relay";
|
||||||
|
|
||||||
|
float M5Stack4RelaySwitch::get_setup_priority() const { return setup_priority::HARDWARE; }
|
||||||
|
|
||||||
|
void M5Stack4RelaySwitch::setup() {
|
||||||
|
ESP_LOGCONFIG(TAG, "Setting up M5Stack_4_relay Switch '%s'...", this->name_.c_str());
|
||||||
|
|
||||||
|
bool initial_state = this->get_initial_state_with_restore_mode().value_or(false);
|
||||||
|
|
||||||
|
// write state before setup
|
||||||
|
if (initial_state) {
|
||||||
|
this->turn_on();
|
||||||
|
} else {
|
||||||
|
this->turn_off();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void M5Stack4RelaySwitch::dump_config() {
|
||||||
|
LOG_SWITCH("", "M5Stack4Relay Switch", this);
|
||||||
|
|
||||||
|
if (!this->interlock_.empty()) {
|
||||||
|
ESP_LOGCONFIG(TAG, " Interlocks:");
|
||||||
|
for (auto *lock : this->interlock_) {
|
||||||
|
if (lock == this)
|
||||||
|
continue;
|
||||||
|
ESP_LOGCONFIG(TAG, " %s", lock->get_name().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void M5Stack4RelaySwitch::write_state(bool state) {
|
||||||
|
if (state != this->inverted_) {
|
||||||
|
// Turning ON, check interlocking
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
for (auto *lock : this->interlock_) {
|
||||||
|
if (lock == this)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (lock->state) {
|
||||||
|
lock->turn_off();
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found && this->interlock_wait_time_ != 0) {
|
||||||
|
this->set_timeout("interlock", this->interlock_wait_time_, [this, state] {
|
||||||
|
// Don't write directly, call the function again
|
||||||
|
// (some other switch may have changed state while we were waiting)
|
||||||
|
this->write_state(state);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (this->interlock_wait_time_ != 0) {
|
||||||
|
// If we are switched off during the interlock wait time, cancel any pending
|
||||||
|
// re-activations
|
||||||
|
this->cancel_timeout("interlock");
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will be called every time the user requests a state change.
|
||||||
|
this->parent_->relay_write(this->channel_, state);
|
||||||
|
|
||||||
|
// Acknowledge new state by publishing it
|
||||||
|
this->publish_state(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void M5Stack4RelaySwitch::set_interlock(const std::vector<Switch *> &interlock) { this->interlock_ = interlock; }
|
||||||
|
|
||||||
|
} // namespace m5stack4relay
|
||||||
|
} // namespace esphome
|
|
@ -0,0 +1,31 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/components/switch/switch.h"
|
||||||
|
|
||||||
|
#include "esphome/components/m5stack4relay/m5stack4relay.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace m5stack4relay {
|
||||||
|
|
||||||
|
class M5Stack4RelaySwitch : public Component, public switch_::Switch, public Parented<M5Stack4Relay> {
|
||||||
|
public:
|
||||||
|
float get_setup_priority() const override;
|
||||||
|
|
||||||
|
void setup() override;
|
||||||
|
void dump_config() override;
|
||||||
|
void write_state(bool state) override;
|
||||||
|
|
||||||
|
void set_channel(RelayBit channel) { this->channel_ = (uint8_t) channel; }
|
||||||
|
|
||||||
|
void set_interlock(const std::vector<Switch *> &interlock);
|
||||||
|
void set_interlock_wait_time(uint32_t interlock_wait_time) { interlock_wait_time_ = interlock_wait_time; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint8_t channel_;
|
||||||
|
std::vector<Switch *> interlock_;
|
||||||
|
uint32_t interlock_wait_time_{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace m5stack4relay
|
||||||
|
} // namespace esphome
|
|
@ -58,6 +58,9 @@ i2c:
|
||||||
number: 22
|
number: 22
|
||||||
frequency: 100khz
|
frequency: 100khz
|
||||||
|
|
||||||
|
m5stack4relay:
|
||||||
|
id: M5stackrelay_ID1
|
||||||
|
|
||||||
modbus:
|
modbus:
|
||||||
uart_id: uart_1
|
uart_id: uart_1
|
||||||
flow_control_pin:
|
flow_control_pin:
|
||||||
|
@ -641,6 +644,30 @@ switch:
|
||||||
led: 3
|
led: 3
|
||||||
name: TM1638Led3
|
name: TM1638Led3
|
||||||
|
|
||||||
|
- platform: m5stack4relay
|
||||||
|
id: m5stack4relay_1
|
||||||
|
name: m5stack4relay1
|
||||||
|
channel: 1
|
||||||
|
m5stack4relay_id: M5stackrelay_ID1
|
||||||
|
|
||||||
|
- platform: m5stack4relay
|
||||||
|
id: m5stack4relay_2
|
||||||
|
name: m5stack4relay2
|
||||||
|
channel: 2
|
||||||
|
m5stack4relay_id: M5stackrelay_ID1
|
||||||
|
|
||||||
|
- platform: m5stack4relay
|
||||||
|
id: m5stack4relay_3
|
||||||
|
name: m5stack4relay3
|
||||||
|
channel: 3
|
||||||
|
m5stack4relay_id: M5stackrelay_ID1
|
||||||
|
|
||||||
|
- platform: m5stack4relay
|
||||||
|
id: m5stack4relay_4
|
||||||
|
name: m5stack4relay4
|
||||||
|
channel: 4
|
||||||
|
m5stack4relay_id: M5stackrelay_ID1
|
||||||
|
|
||||||
display:
|
display:
|
||||||
- platform: tm1638
|
- platform: tm1638
|
||||||
id: primarydisplay
|
id: primarydisplay
|
||||||
|
|
Loading…
Reference in New Issue