Add MitsibishiAC

This commit is contained in:
2022-06-25 16:09:41 +03:00
parent 4b7e1b00d7
commit f3221660ce
22 changed files with 4152 additions and 0 deletions

448
MitsubishiAC/src/main.cpp Normal file
View File

@@ -0,0 +1,448 @@
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <Ticker.h>
#include <AsyncMqttClient.h>
//#include <ArduinoJson.h>
#include <HeatPump.h>
#define HOST_NAME "MitsubishiAC"
#define OTA_USE
//#define RDEB
//#define SDEB
#ifdef RDEB
#include <RemoteDebug.h>
#endif
#ifdef OTA_USE
#include <ArduinoOTA.h>
#endif
#define MAIN_TOPIC "home/bigroom/ac/"
#define SET_TOPIC "/set"
#define DEBUG_TOPIC "debug"
#define TIMERS_TOPIC "/timers"
#define STATUS_TOPIC "/status"
const char* ssid = "wf-home";
const char* password = "0ndthnrf";
const char* mqtt_server = "192.168.1.111";
unsigned long cRun = millis();
bool _debugMode;
HeatPump hp;
AsyncMqttClient mqttClient;
Ticker mqttReconnectTimer;
WiFiEventHandler wifiConnectHandler;
WiFiEventHandler wifiDisconnectHandler;
Ticker wifiReconnectTimer;
#ifdef RDEB
RemoteDebug Debug;
#endif
void connectToWifi();
void connectToMqtt();
void onWifiConnect(const WiFiEventStationModeGotIP& event);
void onWifiDisconnect(const WiFiEventStationModeDisconnected& event);
void onMqttConnect(bool sessionPresent);
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason);
void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total);
void hpSettingsChanged();
void hpStatusChanged(heatpumpStatus currentStatus);
void hpPacketDebug(byte* packet, unsigned int length, char* packetDirection);
void setup(){
#ifdef SDEB
Serial.begin(9600);
#endif
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
WiFi.mode(WIFI_STA);
WiFi.hostname(HOST_NAME);
// ArduinoOTA.onStart([]() {
// Serial1.println("Start Update"); // "Начало OTA-апдейта"
// });
// ArduinoOTA.onEnd([]() {
// Serial1.println("\nEnd Update"); // "Завершение OTA-апдейта"
// });
// ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
// //Serial1.printf("Progress: %u%%\r", (progress / (total / 100)));
// });
// ArduinoOTA.onError([](ota_error_t error) {
// Serial1.printf("Error[%u]: ", error);
// if (error == OTA_AUTH_ERROR) Serial1.println("Auth Failed");
// // "Ошибка при аутентификации"
// else if (error == OTA_BEGIN_ERROR) Serial1.println("Begin Failed");
// // "Ошибка при начале OTA-апдейта"
// else if (error == OTA_CONNECT_ERROR) Serial1.println("Connect Failed");
// // "Ошибка при подключении"
// else if (error == OTA_RECEIVE_ERROR) Serial1.println("Receive Failed");
// // "Ошибка при получении данных"
// else if (error == OTA_END_ERROR) Serial1.println("End Failed");
// // "Ошибка при завершении OTA-апдейта"
// });
wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect);
wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect);
mqttClient.onConnect(onMqttConnect);
mqttClient.onDisconnect(onMqttDisconnect);
mqttClient.onMessage(onMqttMessage);
mqttClient.setServer(mqtt_server, 1883);
mqttClient.setClientId(HOST_NAME);
#ifdef OTA_USE
ArduinoOTA.begin();
#endif
#ifdef RDEB
Debug.begin(HOST_NAME); // Initialize the WiFi server
Debug.setResetCmdEnabled(true); // Enable the reset command
Debug.showProfiler(true); // Profiler (Good to measure times, to optimize codes)
Debug.showColors(true); // Colors
#endif
hp.setSettingsChangedCallback(hpSettingsChanged);
hp.setStatusChangedCallback(hpStatusChanged);
hp.setPacketCallback(hpPacketDebug);
#ifndef SDEB
hp.connect(&Serial);
hp.enableAutoUpdate();
hp.enableExternalUpdate();
#else
Serial.println(F("Connect WIFI"));
#endif
connectToWifi();
}
void loop(){
#ifndef SDEB
hp.sync();
#endif
#ifdef OTA_USE
if(WiFi.isConnected())
ArduinoOTA.handle();
#endif
if((cRun + 4999) < millis()){
#ifdef SDEB
Serial.println(millis());
#else
hpStatusChanged(hp.getStatus());
#endif
cRun = millis();
#ifdef RDEB
debugD("$ul Loop Topic %s", cRun, MAIN_TOPIC TIMERS_TOPIC);
#endif
}
#ifdef RDEB
Debug.handle();
#endif
//yield();
}
void connectToWifi() {
#ifdef SDEB
Serial.println(F("Connecting to Wi-Fi..."));
#endif
WiFi.begin(ssid, password);
}
void connectToMqtt() {
#ifdef SDEB
Serial.println(F("Connecting to MQTT..."));
#endif
mqttClient.connect();
}
void onWifiConnect(const WiFiEventStationModeGotIP& event) {
#ifdef SDEB
Serial.println(F("Connected to Wi-Fi."));
Serial.print(F("IP: "));
Serial.println(WiFi.localIP());
#endif
digitalWrite(LED_BUILTIN, LOW);
connectToMqtt();
}
void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) {
#ifdef SDEB
Serial.println(F("Disconnected from Wi-Fi."));
#endif
mqttReconnectTimer.detach(); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
wifiReconnectTimer.once(2, connectToWifi);
digitalWrite(LED_BUILTIN, HIGH);
}
void onMqttConnect(bool sessionPresent) {
#ifdef SDEB
Serial.println(F("Connected to MQTT..."));
#endif
// mqttClient.publish(MAIN_TOPIC "power_set", 1, false, "");
// mqttClient.publish(MAIN_TOPIC "mode_set", 1, false, "");
// mqttClient.publish(MAIN_TOPIC "temp_set", 1, false, "");
// mqttClient.publish(MAIN_TOPIC "fan_set", 1, false, "");
// mqttClient.publish(MAIN_TOPIC "vane_set", 1, false, "");
// mqttClient.publish(MAIN_TOPIC "widevane_set", 1, false, "");
//mqttClient.publish(MAIN_TOPIC DEBUG_TOPIC, 1, false, "");
mqttClient.subscribe(MAIN_TOPIC "power_set", 1);
mqttClient.subscribe(MAIN_TOPIC "mode_set", 1);
mqttClient.subscribe(MAIN_TOPIC "temp_set", 1);
mqttClient.subscribe(MAIN_TOPIC "fan_set", 1);
mqttClient.subscribe(MAIN_TOPIC "vane_set", 1);
mqttClient.subscribe(MAIN_TOPIC "widevane_set", 1);
#ifdef RDEB
debugD("MQTT Connect");
#endif
}
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
if (WiFi.isConnected()) {
mqttReconnectTimer.once(2, connectToMqtt);
}
#ifdef RDEB
debugD("MQTT DisConnect");
#endif
}
void hpSettingsChanged() {
// const size_t bufferSize = JSON_OBJECT_SIZE(6);
// DynamicJsonDocument root(bufferSize);
heatpumpSettings currentSettings = hp.getSettings();
// root["power"] = currentSettings.power;
// root["mode"] = currentSettings.mode;
// root["temperature"] = currentSettings.temperature;
// root["fan"] = currentSettings.fan;
// root["vane"] = currentSettings.vane;
// root["wideVane"] = currentSettings.wideVane;
mqttClient.publish(MAIN_TOPIC "power", 1, false, currentSettings.power);
mqttClient.publish(MAIN_TOPIC "mode", 1, false, currentSettings.mode);
char t[5];
dtostrf(currentSettings.temperature, 4, 1, t);
mqttClient.publish(MAIN_TOPIC "temp", 1, false, t);
mqttClient.publish(MAIN_TOPIC "fan", 1, false, currentSettings.fan);
mqttClient.publish(MAIN_TOPIC "vane", 1, false, currentSettings.vane);
mqttClient.publish(MAIN_TOPIC "wideVane", 1, false, currentSettings.wideVane);
//root["iSee"] = currentSettings.iSee;
// char buffer[512];
// serializeJson(root, buffer);
#ifdef RDEB
debugD("SettingsChanged %s", buffer);
#endif
#ifdef SDEB
Serial.print(F("SettChgd: "));
// Serial.println(buffer);
#endif
//bool retain = true;
//mqttClient.publish(MAIN_TOPIC, 1, false, buffer);
// if (!mqtt_client.publish(heatpump_topic, buffer, retain)) {
// mqtt_client.publish(heatpump_debug_topic, "failed to publish to heatpump topic");
// }
}
void hpStatusChanged(heatpumpStatus currentStatus) {
// send room temp and operating info
// const size_t bufferSizeInfo = JSON_OBJECT_SIZE(2);
// DynamicJsonDocument rootInfo(bufferSizeInfo);
// rootInfo["roomTemperature"] = currentStatus.roomTemperature;
// rootInfo["operating"] = currentStatus.operating;
// char bufferInfo[512];
// serializeJson(rootInfo, bufferInfo);
// #ifdef SDEB
// Serial.print(F("StatChgd: "));
// Serial.println(bufferInfo);
// #endif
// #ifdef RDEB
// debugD("StatusSend %s", bufferInfo);
// #endif
char t[5];
dtostrf(currentStatus.roomTemperature, 4, 1, t);
mqttClient.publish(MAIN_TOPIC "temperature", 1, false, t);
mqttClient.publish(MAIN_TOPIC "operating", 1, false, currentStatus.operating == false ? "OFF" : "ON");
//mqttClient.publish(MAIN_TOPIC STATUS_TOPIC, 1, false, bufferInfo);
// if (!mqtt_client.publish(heatpump_status_topic, bufferInfo, true)) {
// mqtt_client.publish(heatpump_debug_topic, "failed to publish to room temp and operation status to heatpump/status topic");
// }
// send the timer info
// const size_t bufferSizeTimers = JSON_OBJECT_SIZE(5);
// DynamicJsonDocument rootTimers(bufferSizeTimers);
// rootTimers["mode"] = currentStatus.timers.mode;
// rootTimers["onMins"] = currentStatus.timers.onMinutesSet;
// rootTimers["onRemainMins"] = currentStatus.timers.onMinutesRemaining;
// rootTimers["offMins"] = currentStatus.timers.offMinutesSet;
// rootTimers["offRemainMins"] = currentStatus.timers.offMinutesRemaining;
// char bufferTimers[512];
// serializeJson(rootTimers, bufferTimers);
#ifdef RDEB
debugD("TimersSend %s", bufferTimers);
#endif
mqttClient.publish(MAIN_TOPIC "timerMode", 1, false, currentStatus.timers.mode);
itoa(currentStatus.timers.onMinutesSet, t, 10);
mqttClient.publish(MAIN_TOPIC "timerOnMinSet", 1, false, t);
itoa(currentStatus.timers.onMinutesRemaining, t, 10);
mqttClient.publish(MAIN_TOPIC "timerOnMinRem", 1, false, t);
itoa(currentStatus.timers.offMinutesSet, t, 10);
mqttClient.publish(MAIN_TOPIC "timerOffMinSet", 1, false, t);
itoa(currentStatus.timers.offMinutesRemaining, t, 10);
mqttClient.publish(MAIN_TOPIC "timerOffMinRem", 1, false, t);
//mqttClient.publish(MAIN_TOPIC TIMERS_TOPIC, 1, false, bufferTimers);
// if (!mqtt_client.publish(heatpump_timers_topic, bufferTimers, true)) {
// mqtt_client.publish(heatpump_debug_topic, "failed to publish timer info to heatpump/status topic");
// }
}
void hpPacketDebug(byte* packet, unsigned int length, char* packetDirection) {
if (_debugMode) {
String message = packetDirection;
message += " ";
for (unsigned int idx = 0; idx < length; idx++) {
if (packet[idx] < 16) {
message += "0"; // pad single hex digits with a 0
}
message += String(packet[idx], HEX) + " ";
}
// const size_t bufferSize = JSON_OBJECT_SIZE(6);
// DynamicJsonDocument root(bufferSize);
// root[packetDirection] = message;
// char buffer[512];
// serializeJson(root, buffer);
// #ifdef RDEB
// debugD("DebugSend %s", buffer);
// #endif
mqttClient.publish(MAIN_TOPIC DEBUG_TOPIC, 1, false, message.c_str());
// if (!mqtt_client.publish(heatpump_debug_topic, buffer)) {
// mqtt_client.publish(heatpump_debug_topic, "failed to publish to heatpump/debug topic");
// }
}
}
void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
char message[len + 1];
for (size_t i = 0; i < len; i++) {
message[i] = (char)payload[i];
}
message[len] = '\0';
String mqtt = "Topic:";
mqtt += topic;
mqtt += " Payload:";
mqtt += String(message);
mqttClient.publish(MAIN_TOPIC "debug_mqtt", 1, false, mqtt.c_str());
#ifdef SDEB
Serial.print(F("MQTT msg: "));
Serial.println(message);
#endif
#ifdef RDEB
debugD("MQTT Message %s", message);
#endif
if (strcmp(topic, MAIN_TOPIC "power_set") == 0) {
mqttClient.publish(MAIN_TOPIC "debug", 1, false, (String("Power set:") + String(message)).c_str());
#ifdef SDEB
Serial.print(F("Setpower: "));
Serial.println(message);
#else
hp.setPowerSetting(atoi(message) == 1 ? "ON" : "OFF");
#endif
#ifdef RDEB
debugD("SET Power %s", power);
#endif
}
if (strcmp(topic, MAIN_TOPIC "mode_set") == 0) {
mqttClient.publish(MAIN_TOPIC "debug", 1, false, (String("Mode set:") + String(message)).c_str());
#ifdef RDEB
debugD("SET Mode %s", mode);
#endif
#ifdef SDEB
Serial.print(F("SetMode: "));
Serial.println(message);
#else
hp.setModeSetting(message);
#endif
}
if (strcmp(topic, MAIN_TOPIC "temp_set") == 0) {
float temperature = atof(message);
mqttClient.publish(MAIN_TOPIC "debug", 1, false, (String("Temp set:") + String(message)).c_str());
#ifdef RDEB
debugD("SET Temp %f", temperature);
#endif
#ifdef SDEB
Serial.print(F("SetTemp: "));
Serial.println(temperature);
#else
hp.setTemperature(temperature);
#endif
}
if (strcmp(topic, MAIN_TOPIC "fan_set") == 0) {
mqttClient.publish(MAIN_TOPIC "debug", 1, false, (String("Fan set:") + String(message)).c_str());
#ifdef RDEB
debugD("SET Fan %s", fan);
#endif
#ifdef SDEB
Serial.print(F("SetFan: "));
Serial.println(message);
#else
hp.setFanSpeed(message);
#endif
}
if (strcmp(topic, MAIN_TOPIC "vane_set") == 0) {
mqttClient.publish(MAIN_TOPIC "debug", 1, false, (String("Vane set:") + String(message)).c_str());
#ifdef RDEB
debugD("SET Vane %s", vane);
#endif
#ifdef SDEB
Serial.print(F("SetVane: "));
Serial.println(message);
#else
hp.setVaneSetting(message);
#endif
}
if (strcmp(topic, MAIN_TOPIC "wideVane_set") == 0) {
#ifdef SDEB
Serial.print(F("SetwideVane: "));
Serial.println(message);
#else
hp.setWideVaneSetting(message);
#endif
}
if (strcmp(topic, MAIN_TOPIC "remoteTemperature_set") == 0) {
float temperature = atof(message);
#ifdef RDEB
debugD("SET RemTemp %f", temperature);
#endif
#ifdef SDEB
Serial.print(F("SetTemp: "));
Serial.println(temperature);
#else
hp.setRemoteTemperature(temperature);
#endif
}
#ifndef SDEB
// bool result = hp.update();
// if (!result) {
// mqttClient.publish(MAIN_TOPIC DEBUG_TOPIC, 1, false, "heatpump: update() failed");
// }
#endif
}