Anova fahrenheit support (#2126)

Co-authored-by: Ben Buxton <bb@cactii.net>
This commit is contained in:
buxtronix 2021-08-09 06:05:36 +10:00 committed by GitHub
parent 29f72037fe
commit fe7af21c91
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 50 additions and 8 deletions

View file

@ -90,19 +90,24 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
if (this->codec_->has_running()) {
this->mode = this->codec_->running_ ? climate::CLIMATE_MODE_HEAT : climate::CLIMATE_MODE_OFF;
}
if (this->codec_->has_unit()) {
this->fahrenheit_ = (this->codec_->unit_ == 'f');
ESP_LOGD(TAG, "Anova units is %s", this->fahrenheit_ ? "fahrenheit" : "celcius");
this->current_request_++;
}
this->publish_state();
if (this->current_request_ > 0) {
if (this->current_request_ > 1) {
AnovaPacket *pkt = nullptr;
switch (this->current_request_++) {
case 1:
case 2:
pkt = this->codec_->get_read_target_temp_request();
break;
case 2:
case 3:
pkt = this->codec_->get_read_current_temp_request();
break;
default:
this->current_request_ = 0;
this->current_request_ = 1;
break;
}
if (pkt != nullptr) {
@ -121,12 +126,16 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
}
}
void Anova::set_unit_of_measurement(const char *unit) { this->fahrenheit_ = !strncmp(unit, "f", 1); }
void Anova::update() {
if (this->node_state != espbt::ClientState::Established)
return;
if (this->current_request_ == 0) {
if (this->current_request_ < 2) {
auto pkt = this->codec_->get_read_device_status_request();
if (this->current_request_ == 0)
auto pkt = this->codec_->get_set_unit_request(this->fahrenheit_ ? 'f' : 'c');
auto status = esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_,
pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
if (status)

View file

@ -36,12 +36,14 @@ class Anova : public climate::Climate, public esphome::ble_client::BLEClientNode
traits.set_visual_temperature_step(0.1);
return traits;
}
void set_unit_of_measurement(const char *);
protected:
AnovaCodec *codec_;
void control(const climate::ClimateCall &call) override;
uint16_t char_handle_;
uint8_t current_request_;
bool fahrenheit_;
};
} // namespace anova

View file

@ -3,6 +3,10 @@
namespace esphome {
namespace anova {
float ftoc(float f) { return (f - 32.0) * (5.0f / 9.0f); }
float ctof(float c) { return (c * 9.0f / 5.0f) + 32.0; }
AnovaPacket *AnovaCodec::clean_packet_() {
this->packet_.length = strlen((char *) this->packet_.data);
this->packet_.data[this->packet_.length] = '\0';
@ -42,6 +46,8 @@ AnovaPacket *AnovaCodec::get_read_data_request() {
AnovaPacket *AnovaCodec::get_set_target_temp_request(float temperature) {
this->current_query_ = SET_TARGET_TEMPERATURE;
if (this->fahrenheit_)
temperature = ctof(temperature);
sprintf((char *) this->packet_.data, CMD_SET_TARGET_TEMP, temperature);
return this->clean_packet_();
}
@ -67,7 +73,6 @@ AnovaPacket *AnovaCodec::get_stop_request() {
void AnovaCodec::decode(const uint8_t *data, uint16_t length) {
memset(this->buf_, 0, 32);
strncpy(this->buf_, (char *) data, length);
ESP_LOGV("anova", "Received: %s\n", this->buf_);
this->has_target_temp_ = this->has_current_temp_ = this->has_unit_ = this->has_running_ = false;
switch (this->current_query_) {
case READ_DEVICE_STATUS: {
@ -97,19 +102,32 @@ void AnovaCodec::decode(const uint8_t *data, uint16_t length) {
}
case READ_TARGET_TEMPERATURE: {
this->target_temp_ = strtof(this->buf_, nullptr);
if (this->fahrenheit_)
this->target_temp_ = ftoc(this->target_temp_);
this->has_target_temp_ = true;
break;
}
case SET_TARGET_TEMPERATURE: {
this->target_temp_ = strtof(this->buf_, nullptr);
if (this->fahrenheit_)
this->target_temp_ = ftoc(this->target_temp_);
this->has_target_temp_ = true;
break;
}
case READ_CURRENT_TEMPERATURE: {
this->current_temp_ = strtof(this->buf_, nullptr);
if (this->fahrenheit_)
this->current_temp_ = ftoc(this->current_temp_);
this->has_current_temp_ = true;
break;
}
case SET_UNIT:
case READ_UNIT: {
this->unit_ = this->buf_[0];
this->fahrenheit_ = this->buf_[0] == 'f';
this->has_unit_ = true;
break;
}
default:
break;
}

View file

@ -71,6 +71,7 @@ class AnovaCodec {
bool has_unit_;
bool has_running_;
char buf_[32];
bool fahrenheit_;
CurrentQuery current_query_;
};

View file

@ -1,7 +1,12 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import climate, ble_client
from esphome.const import CONF_ID
from esphome.const import CONF_ID, CONF_UNIT_OF_MEASUREMENT
UNITS = {
"f": "f",
"c": "c",
}
CODEOWNERS = ["@buxtronix"]
DEPENDENCIES = ["ble_client"]
@ -12,7 +17,12 @@ Anova = anova_ns.class_(
)
CONFIG_SCHEMA = (
climate.CLIMATE_SCHEMA.extend({cv.GenerateID(): cv.declare_id(Anova)})
climate.CLIMATE_SCHEMA.extend(
{
cv.GenerateID(): cv.declare_id(Anova),
cv.Required(CONF_UNIT_OF_MEASUREMENT): cv.enum(UNITS),
}
)
.extend(ble_client.BLE_CLIENT_SCHEMA)
.extend(cv.polling_component_schema("60s"))
)
@ -23,3 +33,4 @@ async def to_code(config):
await cg.register_component(var, config)
await climate.register_climate(var, config)
await ble_client.register_ble_node(var, config)
cg.add(var.set_unit_of_measurement(config[CONF_UNIT_OF_MEASUREMENT]))

View file

@ -1566,6 +1566,7 @@ climate:
- platform: anova
name: Anova cooker
ble_client_id: ble_blah
unit_of_measurement: c
midea_dongle:
uart_id: uart0