Merge branch 'release/1.0.0'

This commit is contained in:
Geoff Davis
2020-03-11 15:39:25 -07:00
3 changed files with 181 additions and 65 deletions

124
README.md
View File

@ -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.

View File

@ -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,

View File

@ -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