Skip to content

Commit

Permalink
Merge pull request #18 from KazWolfe/feat/error-codes
Browse files Browse the repository at this point in the history
feat: Add error code sensor
  • Loading branch information
Sammy1Am authored Apr 2, 2024
2 parents cb78e3e + b1f66f7 commit 0fa7c68
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 13 deletions.
12 changes: 9 additions & 3 deletions components/mitsubishi_uart/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import climate, uart, sensor, binary_sensor, select, switch
from esphome.components import climate, uart, sensor, binary_sensor, text_sensor, select, switch
from esphome.core import CORE
from esphome.const import (
CONF_ID,
Expand All @@ -19,14 +19,15 @@
)
from esphome.core import coroutine

AUTO_LOAD = ["climate", "select", "sensor", "binary_sensor", "switch"]
DEPENDENCIES = ["uart", "climate", "sensor", "binary_sensor", "select", "switch"]
AUTO_LOAD = ["climate", "select", "sensor", "binary_sensor", "text_sensor", "switch"]
DEPENDENCIES = ["uart", "climate", "sensor", "binary_sensor", "text_sensor", "select", "switch"]

CONF_HP_UART = "heatpump_uart"
CONF_TS_UART = "thermostat_uart"

CONF_SENSORS = "sensors"
CONF_SENSORS_THERMOSTAT_TEMP = "thermostat_temperature"
CONF_SENSORS_ERROR_CODE = "error_code"

CONF_SELECTS = "selects"
CONF_TEMPERATURE_SOURCE_SELECT = "temperature_source_select" # This is to create a Select object for selecting a source
Expand Down Expand Up @@ -125,6 +126,11 @@
binary_sensor.binary_sensor_schema(),
binary_sensor.register_binary_sensor
),
CONF_SENSORS_ERROR_CODE: (
"Error Code",
text_sensor.text_sensor_schema(),
text_sensor.register_text_sensor
)
}

SENSORS_SCHEMA = cv.All({
Expand Down
26 changes: 22 additions & 4 deletions components/mitsubishi_uart/mitsubishi_uart-packetprocessing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,13 +285,31 @@ void MitsubishiUART::processPacket(const StandbyGetResponsePacket &packet) {
}

//TODO: Not sure what AutoMode does yet
};
}

void MitsubishiUART::processPacket(const ErrorStateGetResponsePacket &packet) {
ESP_LOGV(TAG, "Processing %s", packet.to_string().c_str());
routePacket(packet);
// TODO: The MHK2 thermostat often asks for this, but the response is usually just all zeros. Could be be checking for
// errors / messages / warnings. Should check when e.g. the filter life runs out.
};

std::string oldErrorCode = error_code_sensor->raw_state;

// TODO: Include friendly text from JSON, somehow.
if (!packet.errorPresent()) {
error_code_sensor->raw_state = "No Error Reported";
} else if (auto rawCode = packet.getRawShortCode() != 0x00) {
// Not that it matters, but good for validation I guess.
if ((rawCode & 0x1F) > 0x15) {
ESP_LOGW(TAG, "Error short code %x had invalid low bits. This is an IT protocol violation!", rawCode);
}

error_code_sensor->raw_state = "Error " + packet.getShortCode();
} else {
error_code_sensor->raw_state = "Error " + to_string(packet.getErrorCode());
}

publishOnUpdate |= (oldErrorCode != error_code_sensor->raw_state);
}

void MitsubishiUART::processPacket(const RemoteTemperatureSetRequestPacket &packet) {
ESP_LOGV(TAG, "Processing %s", packet.to_string().c_str());

Expand Down
9 changes: 8 additions & 1 deletion components/mitsubishi_uart/mitsubishi_uart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ be about `update_interval` late from their actual time. Generally the update in
(default is 5seconds) this won't pose a practical problem.
*/
void MitsubishiUART::update() {

// TODO: Temporarily wait 5 seconds on startup to help with viewing logs
if (millis() < 5000) {
return;
Expand All @@ -128,10 +127,14 @@ void MitsubishiUART::update() {

IFACTIVE(
// Request an update from the heatpump
// TODO: This isn't a problem *yet*, but sending all these packets every loop might start to cause some issues in
// certain configurations or setups. We may want to consider only asking for certain packets on a rarer cadence,
// depending on their utility (e.g. we dont need to check for errors every loop).
hp_bridge.sendPacket(GetRequestPacket::getSettingsInstance()); // Needs to be done before status packet for mode logic to work
hp_bridge.sendPacket(GetRequestPacket::getStandbyInstance());
hp_bridge.sendPacket(GetRequestPacket::getStatusInstance());
hp_bridge.sendPacket(GetRequestPacket::getCurrentTempInstance());
hp_bridge.sendPacket(GetRequestPacket::getErrorInfoInstance());
)
}

Expand All @@ -157,6 +160,10 @@ void MitsubishiUART::doPublish() {
ESP_LOGI(TAG, "Actual fan speed differs, do publish");
actual_fan_sensor->publish_state(actual_fan_sensor->raw_state);
}
if (error_code_sensor && (error_code_sensor->raw_state != error_code_sensor->state)) {
ESP_LOGI(TAG, "Error code state differs, do publish");
error_code_sensor->publish_state(error_code_sensor->raw_state);
}

// Binary sensors automatically dedup publishes (I think) and so will only actually publish on change
service_filter_sensor->publish_state(service_filter_sensor->state);
Expand Down
2 changes: 2 additions & 0 deletions components/mitsubishi_uart/mitsubishi_uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class MitsubishiUART : public PollingComponent, public climate::Climate, public
void set_defrost_sensor(binary_sensor::BinarySensor *sensor) {defrost_sensor = sensor;};
void set_hot_adjust_sensor(binary_sensor::BinarySensor *sensor) {hot_adjust_sensor = sensor;};
void set_standby_sensor(binary_sensor::BinarySensor *sensor) {standby_sensor = sensor;};
void set_error_code_sensor(text_sensor::TextSensor *sensor) { error_code_sensor = sensor; };

// Select setters
void set_temperature_source_select(select::Select *select) {temperature_source_select = select;};
Expand Down Expand Up @@ -155,6 +156,7 @@ class MitsubishiUART : public PollingComponent, public climate::Climate, public
binary_sensor::BinarySensor *defrost_sensor = nullptr;
binary_sensor::BinarySensor *hot_adjust_sensor = nullptr;
binary_sensor::BinarySensor *standby_sensor = nullptr;
text_sensor::TextSensor *error_code_sensor = nullptr;

// Selects
select::Select *temperature_source_select;
Expand Down
2 changes: 1 addition & 1 deletion components/mitsubishi_uart/muart_bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ void MUARTBridge::classifyAndProcessRawPacket(RawPacket &pkt) const {
case GetCommand::current_temp :
processRawPacket<CurrentTempGetResponsePacket>(pkt, false);
break;
case GetCommand::four :
case GetCommand::error_info :
processRawPacket<ErrorStateGetResponsePacket>(pkt, false);
break;
case GetCommand::standby :
Expand Down
22 changes: 20 additions & 2 deletions components/mitsubishi_uart/muart_packet-derived.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "muart_packet.h"
#include "muart_utils.h"
#include "mitsubishi_uart.h"

namespace esphome {
namespace mitsubishi_uart {
Expand Down Expand Up @@ -75,8 +76,9 @@ std::string StatusGetResponsePacket::to_string() const {
std::string ErrorStateGetResponsePacket::to_string() const {
return ("Error State Response: " + Packet::to_string()
+ CONSOLE_COLOR_PURPLE
+ "\n ErrorCode: " + format_hex(getErrorCode())
+ " ShortCode: " + format_hex(getShortCode()) // TODO: This can be converted to a code string
+ "\n Error State: " + (errorPresent() ? "Yes" : "No")
+ " ErrorCode: " + format_hex(getErrorCode())
+ " ShortCode: " + getShortCode() + "(" + format_hex(getRawShortCode()) + ")"
);
}
std::string RemoteTemperatureSetRequestPacket::to_string() const {
Expand Down Expand Up @@ -202,5 +204,21 @@ std::string ThermostatHelloRequestPacket::getThermostatVersionString() const {
return buf;
}

// ErrorStateGetResponsePacket functions
std::string ErrorStateGetResponsePacket::getShortCode() const {
const char* upperAlphabet = "AbEFJLPU";
const char* lowerAlphabet = "0123456789ABCDEFOHJLPU";
const uint8_t errorCode = this->getRawShortCode();

uint8_t lowBits = errorCode & 0x1F;
if (lowBits > 0x15) {
char buf[7];
sprintf(buf, "ERR_%x", errorCode);
return buf;
}

return {upperAlphabet[(errorCode & 0xE0) >> 5], lowerAlphabet[lowBits]};
}

} // namespace mitsubishi_uart
} // namespace esphome
9 changes: 8 additions & 1 deletion components/mitsubishi_uart/muart_packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,10 @@ class GetRequestPacket : public Packet {
static GetRequestPacket INSTANCE = GetRequestPacket(GetCommand::status);
return INSTANCE;
}
static GetRequestPacket& getErrorInfoInstance() {
static GetRequestPacket INSTANCE = GetRequestPacket(GetCommand::error_info);
return INSTANCE;
}
using Packet::Packet;

private:
Expand Down Expand Up @@ -257,7 +261,10 @@ class ErrorStateGetResponsePacket : public Packet {
using Packet::Packet;
public:
uint16_t getErrorCode() const {return pkt_.getPayloadByte(4) << 8 | pkt_.getPayloadByte(5);}
uint8_t getShortCode() const {return pkt_.getPayloadByte(6);}
uint8_t getRawShortCode() const {return pkt_.getPayloadByte(6);}
std::string getShortCode() const;

bool errorPresent() const { return getErrorCode() != 0x8000 || getRawShortCode() != 0x00; }

std::string to_string() const override;
};
Expand Down
2 changes: 1 addition & 1 deletion components/mitsubishi_uart/muart_rawpacket.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ enum class PacketType : uint8_t {
enum class GetCommand : uint8_t {
settings = 0x02,
current_temp = 0x03,
four = 0x04,
error_info = 0x04,
status = 0x06,
standby = 0x09,
a_9 = 0xa9
Expand Down

0 comments on commit 0fa7c68

Please sign in to comment.