1

Compare commits

...

6 Commits

5 changed files with 61 additions and 35 deletions
+3 -2
View File
@@ -69,8 +69,9 @@ these can be configured in YAML.
Since a lot of new connections will need to be made to ground, I recommend using
something like a perforated prototype board and make a single connection to
ground from the prototype board to the front panel control board, then connect
all other grounds needed for the circuiti to each other using the prototype
board. A 2cm$\times$8cm board fits perfectly in the empty space below the front panel in the front panel assemple. I also made all connections to the back of
all other grounds needed for the circuit to each other using the prototype
board. A 2cm $\times$ 8cm board fits perfectly in the empty space below the front panel in the front panel assembly. I also made all connections to the
back of
the front panel control board with wires with female Dupont connectors, then
used male headers on the prototype board so that the additional circuitry can
easily be removed.
+4 -4
View File
@@ -1,7 +1,7 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import fan, output
from esphome.const import CONF_OUTPUT_ID
from esphome.const import CONF_ID
from . import (
HAUSLANE_SCHEMA,
CONF_HAUSLANE_ID,
@@ -16,14 +16,14 @@ HauslaneFan = hauslane_ns.class_(
)
CONFIG_SCHEMA = (
fan.FAN_SCHEMA.extend({
cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(HauslaneFan),
fan.fan_schema(HauslaneFan).extend({
cv.GenerateID(CONF_HAUSLANE_ID): cv.use_id(HauslaneFan),
})
.extend(HAUSLANE_SCHEMA)
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_OUTPUT_ID])
var = cg.new_Pvariable(config[CONF_ID])
await fan.register_fan(var,config)
paren = await cg.get_variable(config[CONF_HAUSLANE_ID])
+42 -23
View File
@@ -30,7 +30,9 @@ void Hauslane::setup() {
}
// register ESPHome API service named "command"
#if defined(USE_API)
register_service(&Hauslane::command, "command", {"command"});
#endif
}
void Hauslane::loop() {
@@ -49,6 +51,10 @@ void Hauslane::loop() {
} else {
pos++;
}
} else if (rx_message.size() > MAX_RX) {
parse_state();
reading = false;
pos = 0;
} else {
pos = 0;
}
@@ -94,27 +100,28 @@ void Hauslane::loop() {
button_press(pin_down, true);
}
} else if (this->light_cur != this->light_target) {
if (this->power) {
// press light button
button_press(pin_light, true);
} else {
// power on hood first
if (this->speed==0 && !this->light_target) {
// request light turn off and fan is off, so simply hit power button
button_press(pin_power, true);
} else if (!this->power && this->light_target) {
// request light on and fan off, so power on hood first
button_press(pin_power, true);
} else if (this->power) {
// press light button to toggle
button_press(pin_light, true);
}
} else {
// target already met, so reset flag
this->meet_target=false;
}
} else if (this->speed==0 && !this->light_cur) {
} else if (this->speed==0 && !this->light_cur && this->power) {
// reset power flag
if(this->power) {
this->power=false;
ESP_LOGD(TAG, "Hood power: %d", this->power);
}
}
}
}
}
// Components are required to dump their configuration using ESP_LOGCONFIG in
// the dump_config() method. This method is used exclusively to print values
@@ -142,7 +149,7 @@ void Hauslane::set_speed(int new_speed) {
// read message on rx line and turn into current state of fan and light
void Hauslane::parse_state() {
size_t len = rx_message.size()-4;
size_t len = rx_message.size()-END_LEN;
std::string msg;
std::vector<uint8_t> msg_hex;
@@ -158,20 +165,20 @@ void Hauslane::parse_state() {
// oscilloscope, but as there is only one-way communication from the front
// panel to the main controller board, this would only be useful if
// replacing the front panel entirely
const std::vector<uint8_t> off_0{0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce};
const std::vector<uint8_t> on_0{0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xc6};
const std::vector<uint8_t> off_1{0xce, 0xc6, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xc6, 0xce, 0xce};
const std::vector<uint8_t> on_1{0xce, 0xc6, 0xce, 0xce, 0xce, 0xce, 0xce};
const std::vector<uint8_t> off_2{0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xc6, 0xce, 0xce};
const std::vector<uint8_t> on_2{0xce, 0xc6, 0xce, 0xce, 0xce, 0xce, 0xce, 0xc6, 0xce, 0xc6};
const std::vector<uint8_t> off_3{0x38, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce};
const std::vector<uint8_t> on_3{0x38, 0xc6, 0xce, 0xce, 0xce, 0xce, 0xce};
const std::vector<uint8_t> off_4{0xc6, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xc6, 0xce, 0xce, 0xce};
const std::vector<uint8_t> on_4{0xc6, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce};
const std::vector<uint8_t> off_5{0xc6, 0xc6, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xc6, 0xc6, 0xce, 0xce};
const std::vector<uint8_t> on_5{0xc6, 0xc6, 0xce, 0xce, 0xce, 0xce, 0xc6};
const std::vector<uint8_t> off_6{0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0x38, 0xce, 0xce};
const std::vector<uint8_t> on_6{0xce, 0xc6, 0xce, 0xce, 0xce, 0xce, 0x38};
const std::vector<uint8_t> off_0{0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0x00};
const std::vector<uint8_t> on_0{0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xc6, 0xfe};
const std::vector<uint8_t> off_1{0xce, 0xc6, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xc6, 0xce, 0xce, 0xc0};
const std::vector<uint8_t> on_1{0xce, 0xc6, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xfe};
const std::vector<uint8_t> off_2{0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xc6, 0xce, 0xce, 0xfe};
const std::vector<uint8_t> on_2{0xce, 0xce, 0xc6, 0xce, 0xce, 0xce, 0xce, 0xce, 0xc6, 0xce, 0xc6, 0xfe};
const std::vector<uint8_t> off_3{0xce, 0x38, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xc6, 0xce, 0xce, 0x00};
const std::vector<uint8_t> on_3{0xce, 0x38, 0xc6, 0xce, 0xce, 0xce, 0xce, 0xce, 0xc6, 0xce, 0xfe};
const std::vector<uint8_t> off_4{0xc6, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xc6, 0xce, 0xce, 0xce, 0x00};
const std::vector<uint8_t> on_4{0xc6, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xfe};
const std::vector<uint8_t> off_5{0xc6, 0xc6, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xc6, 0xc6, 0xce, 0xce, 0x00};
const std::vector<uint8_t> on_5{0xc6, 0xc6, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xc6, 0xce, 0xfe};
const std::vector<uint8_t> off_6{0xc6, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0x38, 0xce, 0xce, 0x00};
const std::vector<uint8_t> on_6{0xc6, 0xce, 0xc6, 0xce, 0xce, 0xce, 0xce, 0xce, 0x38, 0xce, 0xfe};
// print out formatted hex string to log
char buf[5];
@@ -224,6 +231,10 @@ void Hauslane::set_state(bool set_light, uint8_t set_speed) {
// save current state of light in memory
ESP_LOGD(TAG, "Received light state: %d", set_light);
this->light_cur = set_light;
if (!this->meet_target) {
// sync target light state if changed by button press
this->light_target = set_light;
}
// send light state to API if it is active
if (this->send_light_state) {
ESP_LOGD(TAG, "Sending new light state.");
@@ -234,12 +245,20 @@ void Hauslane::set_state(bool set_light, uint8_t set_speed) {
// save current state of fan in memory
ESP_LOGD(TAG, "Received fan speed: %d", set_speed);
this->speed = set_speed;
if (!this->meet_target) {
// sync target fan state if changed by button press
this->speed_target = set_speed;
}
// send fan state to API if it is active
if (this->send_fan_speed) {
ESP_LOGD(TAG,"Sending new fan speed.");
this->send_fan_speed(set_speed);
}
}
if (!this->power && (set_speed > 0 || set_light)) {
// set power to on if light or fan are on
this->power = true;
}
}
// custom component API commands
+7 -4
View File
@@ -2,7 +2,9 @@
#include "esphome/core/component.h"
#include "esphome/components/uart/uart.h"
#ifdef USE_API
#include "esphome/components/api/custom_api_device.h"
#endif
#ifdef USE_LIGHT
#include "esphome/components/light/light_output.h"
#endif
@@ -13,10 +15,11 @@
namespace esphome {
namespace hauslane {
static const unsigned char MSG_START[] = {0x08, 0x08, 0x08, 0xfe, 0xc0};
static const unsigned char MSG_END[] = {0xc0, 0xce, 0xce, 0xce};
static const uint8_t START_LEN=5;
static const uint8_t END_LEN=4;
static const unsigned char MSG_START[] = {0x08, 0x08, 0x08, 0xfe, 0x00, 0xc0};
static const unsigned char MSG_END[] = {0xc0, 0xce, 0xce, 0xce, 0xc6};
static const uint8_t START_LEN=6;
static const uint8_t END_LEN=5;
static const size_t MAX_RX=30;
static const int DELAY=250; // how long to press/release buttons in ms
class Hauslane : public Component, public uart::UARTDevice, public api::CustomAPIDevice {
+3
View File
@@ -13,12 +13,15 @@ esphome:
esp32:
board: esp32-c3-devkitm-1
platform:
type: esp-idf
# Enable logging
logger:
level: DEBUG
api:
custom_services: true
password: !secret api_password
ota: