mirror of
https://github.com/geoffdavis/esphome-mitsubishiheatpump
synced 2025-07-25 02:53:59 +00:00
Merge branch 'release/1.0.0'
This commit is contained in:
124
README.md
124
README.md
@ -9,9 +9,34 @@ Wirelessly control your Mitsubishi Comfort HeatPump with an ESP8266 or ESP32 usi
|
||||
* Uses the [SwiCago/HeatPump](https://github.com/SwiCago/HeatPump) Arduino libary to talk to the unit directly via the internal J105 header.
|
||||
* NOTE: REQUIRES SEVERAL FIXES - SEE https://github.com/SwiCago/HeatPump/pull/155
|
||||
|
||||
## Supported Microcontrollers
|
||||
This library should work on most ESP8266 or ESP32 platforms. It has been tested with the following:
|
||||
* Generic ESP-01S board (ESP8266)
|
||||
* WeMos D1 Mini (ESP8266)
|
||||
* Generic ESP32 Dev Kit (ESP32)
|
||||
|
||||
## Supported Mitsubishi Climate Units
|
||||
The underlying HeatPump library works with a number of Mitsubishi HeatPump units. Basically, if the unit has a J105 header on the main board, it should work with this library.
|
||||
|
||||
The whole integration with this libary and the underlying HeatPump has been
|
||||
tested by the author on the following units:
|
||||
* MSZ-GL06NA
|
||||
* MFZ-KA09NA
|
||||
|
||||
## Usage
|
||||
### Build a control circuit as detailed in the SwiCago/HeatPump README.
|
||||
You can use either an ESP8266 or an ESP32.
|
||||
You can use either an ESP8266 or an ESP32 for this.
|
||||
|
||||
### Clone this repository into your ESPHome configuration directory
|
||||
|
||||
This repository needs to live in your ESPHome configuration directory, as it doesn't work correctly when used as a Platform.IO library, and there doesn't seem to be an analog for that functionality for esphome code.
|
||||
|
||||
On Hass.IO, you'll want to do something like:
|
||||
|
||||
* Change directories to your esphome configuration directory.
|
||||
* `mkdir -p src`
|
||||
* `cd src`
|
||||
* `git clone https://github.com/geoffdavis/esphome-mitsubishiheatpump.git`
|
||||
|
||||
### Configure your ESPHome device with YAML
|
||||
|
||||
@ -26,30 +51,107 @@ the `HardwareSerial` handle within the ESPHome framework.
|
||||
Create an ESPHome YAML configuration with the following sections:
|
||||
* `esphome: libraries:`
|
||||
* `climate:` - set up a custom climate, change the Serial port as needed.
|
||||
* ESP8266 only: `logger: baud\_rate: 0` - disables serial port logging on sole hardware UART
|
||||
* ESP8266 only: `logger: baud\_rate: 0` - disables serial port logging on the
|
||||
sole ESP8266 hardware UART
|
||||
|
||||
```yaml
|
||||
esphome:
|
||||
name: denheatpump
|
||||
platform: ESP8266
|
||||
board: esp01_1m
|
||||
# Boards tested: ESP-01S (ESP8266), Wemos D1 Mini (ESP8266); ESP32 Wifi-DevKit2
|
||||
|
||||
libraries:
|
||||
- https://github.com/geoffdavis/HeatPump#init_fix
|
||||
- https://github.com/geoffdavis/esphome-mitsubishiheatpump
|
||||
#- SwiCago/HeatPump
|
||||
- https://github.com/geoffdavis/HeatPump#init_fix
|
||||
|
||||
includes:
|
||||
- src/esphome-mitsubishiheatpump
|
||||
|
||||
wifi:
|
||||
ssid: !secret wifi_ssid
|
||||
password: !secret wifi_password
|
||||
|
||||
# Enable fallback hotspot (captive portal) in case wifi connection fails
|
||||
ap:
|
||||
ssid: "Denheatpump Fallback Hotspot"
|
||||
password: !secret fallback_password
|
||||
|
||||
captive_portal:
|
||||
|
||||
# Enable logging
|
||||
logger:
|
||||
# ESP8266 ONLY:
|
||||
# disable serial port logging, as the HeatPump component needs
|
||||
# the sole hardware UART on the ESP8266
|
||||
baud_rate: 0
|
||||
# ESP8266 only - disable serial port logging, as the HeatPump component
|
||||
# needs the sole hardware UART on the ESP8266
|
||||
baud_rate: 0
|
||||
|
||||
# Enable Home Assistant API
|
||||
api:
|
||||
|
||||
ota:
|
||||
|
||||
# Enable Web server.
|
||||
web_server:
|
||||
port: 80
|
||||
|
||||
# Sync time with Home Assistant.
|
||||
time:
|
||||
- platform: homeassistant
|
||||
id: homeassistant_time
|
||||
|
||||
# Text sensors with general information.
|
||||
text_sensor:
|
||||
# Expose ESPHome version as sensor.
|
||||
- platform: version
|
||||
name: denheatpump ESPHome Version
|
||||
# Expose WiFi information as sensors.
|
||||
- platform: wifi_info
|
||||
ip_address:
|
||||
name: denheatpump IP
|
||||
ssid:
|
||||
name: denheatpump SSID
|
||||
bssid:
|
||||
name: denheatpump BSSID
|
||||
|
||||
# Sensors with general information.
|
||||
sensor:
|
||||
# Uptime sensor.
|
||||
- platform: uptime
|
||||
name: denheatpump Uptime
|
||||
|
||||
# WiFi Signal sensor.
|
||||
- platform: wifi_signal
|
||||
name: denheatpump WiFi Signal
|
||||
update_interval: 60s
|
||||
|
||||
|
||||
climate:
|
||||
- platform: custom
|
||||
# ESP32 only - change &Serial to &Serial1 or &Serial2 and remove the
|
||||
# logging:baud_rate above to allow the built-in UART0 to function for
|
||||
# logging.
|
||||
lambda: |-
|
||||
auto my_heatpump = new MitsubishiHeatPump(&Serial);
|
||||
App.register_component(my_heatpump);
|
||||
return {my_heatpump};
|
||||
|
||||
climates:
|
||||
- name: "My Heat Pump"
|
||||
- name: "Den Heat Pump"
|
||||
```
|
||||
|
||||
Note that you can change the &
|
||||
# See Also
|
||||
|
||||
The [gysmo38/mitsubishi2MQTT](https://github.com/gysmo38/mitsubishi2MQTT)
|
||||
Arduino sketch also uses the `SwiCago/HeatPump`
|
||||
library, and works with MQTT directly. I found it's WiFi stack to not be
|
||||
particularly robust, but the controls worked fine. Like this ESPHome
|
||||
repository, it will automatically register the device in your HomeAssistant
|
||||
instance if you have HA configured to do so.
|
||||
|
||||
There's also the built-in to ESPHome [Mitsubishi]
|
||||
(https://github.com/esphome/esphome/blob/dev/esphome/components/mitsubishi/mitsubishi.h)
|
||||
climate component. It's only in the `dev` branch at the moment (2020-03-11).
|
||||
The big drawback with the built-in component is that it uses Infrared Remote
|
||||
commands to talk to the Heat Pump. By contrast, the approach used by this
|
||||
repository and it's underlying `HeatPump` library allows bi-directional
|
||||
communication with the Mitsubishi system, and can detect when someone changes
|
||||
the settings via an IR remote.
|
||||
|
90
espmhp.cpp
90
espmhp.cpp
@ -9,32 +9,47 @@
|
||||
*
|
||||
* Requirements:
|
||||
* - https://github.com/geoffdavis/HeatPump#init_fix (until upstream is fixed)
|
||||
* - ESPHome 1.5.0-dev or greater
|
||||
* - ESPHome 1.15.0-dev or greater
|
||||
*/
|
||||
|
||||
|
||||
#include "espmhp.h"
|
||||
using namespace esphome;
|
||||
|
||||
/**
|
||||
* Create a new MitsubishiHeatPump object
|
||||
*
|
||||
* Args:
|
||||
* hw_serial: pointer to an Arduino HardwareSerial instance
|
||||
* poll_interval: polling interval in milliseconds
|
||||
*/
|
||||
MitsubishiHeatPump::MitsubishiHeatPump(
|
||||
HardwareSerial* hw_serial,
|
||||
uint32_t poll_interval
|
||||
) :
|
||||
PollingComponent{poll_interval}, // member initializers list
|
||||
hw_serial_{hw_serial}
|
||||
{ }
|
||||
|
||||
void MitsubishiHeatPump::check_logger_conflict_() {
|
||||
#ifdef USE_LOGGER
|
||||
if (this->get_hw_serial_() == logger::global_logger->get_hw_serial()) {
|
||||
ESP_LOGW(TAG, " You're using the same serial port for logging"
|
||||
" and the MitsubishiHeatPump component. Please disable"
|
||||
" logging over the serial port by setting"
|
||||
" logger:baud_rate to 0.");
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_LOGGER
|
||||
if (this->get_hw_serial_() == logger::global_logger->get_hw_serial()) {
|
||||
ESP_LOGW(TAG, " You're using the same serial port for logging"
|
||||
" and the MitsubishiHeatPump component. Please disable"
|
||||
" logging over the serial port by setting"
|
||||
" logger:baud_rate to 0.");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void MitsubishiHeatPump::update() {
|
||||
// This will be called every "update_interval" milliseconds.
|
||||
//this->dump_config();
|
||||
hp->sync();
|
||||
#ifndef USE_CALLBACKS
|
||||
this->hpSettingsChanged();
|
||||
heatpumpStatus currentStatus = hp->getStatus();
|
||||
this->hpStatusChanged(currentStatus);
|
||||
#endif
|
||||
this->hp->sync();
|
||||
#ifndef USE_CALLBACKS
|
||||
this->hpSettingsChanged();
|
||||
heatpumpStatus currentStatus = hp->getStatus();
|
||||
this->hpStatusChanged(currentStatus);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@ -45,7 +60,7 @@ void MitsubishiHeatPump::update() {
|
||||
* ESPHome, particularly the Dry operation mode, and several of the fan modes.
|
||||
*
|
||||
* Returns:
|
||||
* This class' supported ESPHome climate::ClimateTraits.
|
||||
* This class' supported climate::ClimateTraits.
|
||||
*/
|
||||
climate::ClimateTraits MitsubishiHeatPump::traits() {
|
||||
auto traits = climate::ClimateTraits();
|
||||
@ -122,8 +137,10 @@ void MitsubishiHeatPump::control(const climate::ClimateCall &call) {
|
||||
}
|
||||
|
||||
if (call.get_target_temperature().has_value()){
|
||||
ESP_LOGV("control", "Sending target temp: %.1f",
|
||||
*call.get_target_temperature())
|
||||
ESP_LOGV(
|
||||
"control", "Sending target temp: %.1f",
|
||||
*call.get_target_temperature()
|
||||
)
|
||||
hp->setTemperature(*call.get_target_temperature());
|
||||
updated = true;
|
||||
}
|
||||
@ -187,9 +204,6 @@ void MitsubishiHeatPump::control(const climate::ClimateCall &call) {
|
||||
}
|
||||
ESP_LOGD(TAG, "control - Was HeatPump updated? %s", YESNO(updated));
|
||||
hp->update();
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void MitsubishiHeatPump::hpSettingsChanged() {
|
||||
@ -216,15 +230,15 @@ void MitsubishiHeatPump::hpSettingsChanged() {
|
||||
*/
|
||||
if (strcmp(currentSettings.power, "ON") == 0) {
|
||||
if (strcmp(currentSettings.mode, "HEAT") == 0) {
|
||||
this->mode = CLIMATE_MODE_HEAT;
|
||||
this->mode = climate::CLIMATE_MODE_HEAT;
|
||||
} else if (strcmp(currentSettings.mode, "DRY") == 0) {
|
||||
this->mode = CLIMATE_MODE_DRY;
|
||||
this->mode = climate::CLIMATE_MODE_DRY;
|
||||
} else if (strcmp(currentSettings.mode, "COOL") == 0) {
|
||||
this->mode = CLIMATE_MODE_COOL;
|
||||
this->mode = climate::CLIMATE_MODE_COOL;
|
||||
} else if (strcmp(currentSettings.mode, "FAN") == 0) {
|
||||
this->mode = CLIMATE_MODE_FAN_ONLY;
|
||||
this->mode = climate::CLIMATE_MODE_FAN_ONLY;
|
||||
} else if (strcmp(currentSettings.mode, "AUTO") == 0) {
|
||||
this->mode = CLIMATE_MODE_AUTO;
|
||||
this->mode = climate::CLIMATE_MODE_AUTO;
|
||||
} else {
|
||||
ESP_LOGW(
|
||||
TAG,
|
||||
@ -233,7 +247,7 @@ void MitsubishiHeatPump::hpSettingsChanged() {
|
||||
);
|
||||
}
|
||||
} else {
|
||||
this->mode = CLIMATE_MODE_OFF;
|
||||
this->mode = climate::CLIMATE_MODE_OFF;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Climate mode is: %i", this->mode);
|
||||
@ -244,17 +258,17 @@ void MitsubishiHeatPump::hpSettingsChanged() {
|
||||
* const char* FAN_MAP[6] = {"AUTO", "QUIET", "1", "2", "3", "4"};
|
||||
*/
|
||||
if (strcmp(currentSettings.fan, "QUIET") == 0) {
|
||||
this->fan_mode = CLIMATE_FAN_DIFFUSE;
|
||||
this->fan_mode = climate::CLIMATE_FAN_DIFFUSE;
|
||||
} else if (strcmp(currentSettings.fan, "1") == 0) {
|
||||
this->fan_mode = CLIMATE_FAN_LOW;
|
||||
this->fan_mode = climate::CLIMATE_FAN_LOW;
|
||||
} else if (strcmp(currentSettings.fan, "2") == 0) {
|
||||
this->fan_mode = CLIMATE_FAN_MEDIUM;
|
||||
this->fan_mode = climate::CLIMATE_FAN_MEDIUM;
|
||||
} else if (strcmp(currentSettings.fan, "3") == 0) {
|
||||
this->fan_mode = CLIMATE_FAN_MIDDLE;
|
||||
this->fan_mode = climate::CLIMATE_FAN_MIDDLE;
|
||||
} else if (strcmp(currentSettings.fan, "4") == 0) {
|
||||
this->fan_mode = CLIMATE_FAN_HIGH;
|
||||
this->fan_mode = climate::CLIMATE_FAN_HIGH;
|
||||
} else { //case "AUTO" or default:
|
||||
this->fan_mode = CLIMATE_FAN_AUTO;
|
||||
this->fan_mode = climate::CLIMATE_FAN_AUTO;
|
||||
}
|
||||
ESP_LOGI(TAG, "Fan mode is: %i", this->fan_mode);
|
||||
|
||||
@ -265,10 +279,10 @@ void MitsubishiHeatPump::hpSettingsChanged() {
|
||||
(strcmp(currentSettings.vane, "AUTO") == 0)
|
||||
|| (strcmp(currentSettings.vane, "SWING") == 0)
|
||||
) {
|
||||
this->swing_mode = CLIMATE_SWING_VERTICAL;
|
||||
this->swing_mode = climate::CLIMATE_SWING_VERTICAL;
|
||||
}
|
||||
else {
|
||||
this->swing_mode = CLIMATE_SWING_OFF;
|
||||
this->swing_mode = climate::CLIMATE_SWING_OFF;
|
||||
}
|
||||
ESP_LOGI(TAG, "Swing mode is: %i", this->swing_mode);
|
||||
|
||||
@ -313,7 +327,7 @@ void MitsubishiHeatPump::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Intializing new HeatPump object.");
|
||||
this->hp = new HeatPump();
|
||||
|
||||
#ifdef USE_CALLBACKS
|
||||
#ifdef USE_CALLBACKS
|
||||
hp->setSettingsChangedCallback(
|
||||
[this]() {
|
||||
this->hpSettingsChanged();
|
||||
@ -325,7 +339,7 @@ void MitsubishiHeatPump::setup() {
|
||||
this->hpStatusChanged(currentStatus);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ESP_LOGCONFIG(
|
||||
TAG,
|
||||
|
32
espmhp.h
32
espmhp.h
@ -9,23 +9,22 @@
|
||||
*
|
||||
* Requirements:
|
||||
* - https://github.com/geoffdavis/HeatPump#init_fix (until upstream is fixed)
|
||||
* - ESPHome 1.5.0-dev or greater
|
||||
* - ESPHome 1.15.0-dev or greater
|
||||
*/
|
||||
|
||||
// Uncomment to use HeatPump callback functions (broken, causes boot failures)
|
||||
//#define USE_CALLBACKS
|
||||
#pragma once
|
||||
|
||||
#include "esphome/components/climate.h"
|
||||
#include "esphome/components/climate_traits.h"
|
||||
#include "esphome/components/climate_mode.h"
|
||||
#include "esphome/core/component.h"
|
||||
|
||||
#include "esphome.h"
|
||||
#include "HeatPump.h"
|
||||
using namespace esphome;
|
||||
|
||||
static const char *TAG = "MitsubishiHeatPump"; // Logging tag
|
||||
#ifndef ESPMHP_H
|
||||
#define ESPMHP_H
|
||||
|
||||
static const char *ESPMHP_VERSION = "1.0.0-dev";
|
||||
static const char* TAG = "MitsubishiHeatPump"; // Logging tag
|
||||
|
||||
static const char* ESPMHP_VERSION = "1.0.0";
|
||||
|
||||
/* If polling interval is greater than 9 seconds, the HeatPump
|
||||
library reconnects, but doesn't then follow up with our data request.*/
|
||||
@ -38,11 +37,11 @@ static const uint8_t ESPMHP_MAX_TEMPERATURE = 31; // degrees C,
|
||||
static const uint8_t ESPMHP_TEMPERATURE_STEP = 0.5; // temperature setting step,
|
||||
// in degrees C
|
||||
|
||||
|
||||
class MitsubishiHeatPump : public PollingComponent, public climate::Climate {
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Create a new MitsubishiHeatPump object
|
||||
*
|
||||
@ -51,16 +50,15 @@ class MitsubishiHeatPump : public PollingComponent, public climate::Climate {
|
||||
* poll_interval: polling interval in milliseconds
|
||||
*/
|
||||
MitsubishiHeatPump(
|
||||
HardwareSerial * hw_serial, uint32_t
|
||||
poll_interval=ESPMHP_POLL_INTERVAL_DEFAULT
|
||||
) : PollingComponent(poll_interval) {
|
||||
this->hw_serial_ = hw_serial;
|
||||
}
|
||||
HardwareSerial* hw_serial,
|
||||
uint32_t poll_interval=ESPMHP_POLL_INTERVAL_DEFAULT
|
||||
);
|
||||
|
||||
// Print a banner with library information.
|
||||
void banner() {
|
||||
ESP_LOGI(TAG, "ESPHome MitsubishiHeatPump version %s",
|
||||
ESPMHP_VERSION);
|
||||
}
|
||||
|
||||
// print the current configuration
|
||||
void dump_config() override;
|
||||
@ -104,6 +102,8 @@ class MitsubishiHeatPump : public PollingComponent, public climate::Climate {
|
||||
|
||||
private:
|
||||
// Retrieve the HardwareSerial pointer from friend and subclasses.
|
||||
HardwareSerial *hw_serial_{nullptr};
|
||||
HardwareSerial *hw_serial_;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user