mirror of
https://github.com/GrKoR/esphome_aux_ac_component.git
synced 2025-12-06 11:36:55 +03:00
Compare commits
77 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
efa0991dd0 | ||
|
|
2e0c421c9f | ||
|
|
53414d8ab4 | ||
|
|
5a165d3a3d | ||
|
|
02887baa04 | ||
|
|
5f9d2c0c0f | ||
|
|
7a4bacfb9a | ||
|
|
c959d7be7e | ||
|
|
60d6f56fcf | ||
|
|
a8eba8882e | ||
|
|
96455e5882 | ||
|
|
89db23434b | ||
|
|
945d2603f1 | ||
|
|
6291828cec | ||
|
|
8dc9f0f478 | ||
|
|
03e0ee0d9a | ||
|
|
848fd8f6c1 | ||
|
|
e77d49c52a | ||
|
|
42fd8d5ba1 | ||
|
|
00aa426bfc | ||
|
|
029d92be96 | ||
|
|
d1e64af8a4 | ||
|
|
d238c8b661 | ||
|
|
140447ceab | ||
|
|
6920102969 | ||
|
|
f20f89cb93 | ||
|
|
6a98c47ada | ||
|
|
b5e88f7abc | ||
|
|
a166d18ede | ||
|
|
7de56fb656 | ||
|
|
cf5c88662d | ||
|
|
a7d2a73802 | ||
|
|
078a6b20cf | ||
|
|
69eebdb8c8 | ||
|
|
fe00198764 | ||
|
|
da5fcd5848 | ||
|
|
9d4930d290 | ||
|
|
26ae9c248c | ||
|
|
e67898997d | ||
|
|
e158586268 | ||
|
|
2d446f88e4 | ||
|
|
5591b91f7b | ||
|
|
551c476549 | ||
|
|
bdbd1478b7 | ||
|
|
9c2daf0615 | ||
|
|
3ca873450d | ||
|
|
5e1b78df9f | ||
|
|
7a252e5955 | ||
|
|
79f23c341d | ||
|
|
360d274088 | ||
|
|
973f961e5f | ||
|
|
cf990eb467 | ||
|
|
1c6575a264 | ||
|
|
7f68f3fdac | ||
|
|
e7bca33f35 | ||
|
|
f859e656a4 | ||
|
|
5b229da380 | ||
|
|
656344dda6 | ||
|
|
b10a2f5dab | ||
|
|
b80f4972f0 | ||
|
|
2a38208628 | ||
|
|
07a98e5789 | ||
|
|
fe323a6f65 | ||
|
|
584ef0d57a | ||
|
|
d15272f437 | ||
|
|
23584bf53a | ||
|
|
1b3bcdfa0f | ||
|
|
558922047e | ||
|
|
9f362f475b | ||
|
|
dad7025632 | ||
|
|
16824c10cc | ||
|
|
f31cfb3c16 | ||
|
|
35d0364655 | ||
|
|
25ab6feb4f | ||
|
|
3f1b31bb52 | ||
|
|
06388ebb2c | ||
|
|
1f11db4ae0 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -12,6 +12,6 @@
|
||||
**/livingroom_ac/
|
||||
**/kitchen_ac/
|
||||
/examples/*/*.h
|
||||
**/tests/test_*
|
||||
**/__pycache__
|
||||
**/private/
|
||||
**/private/
|
||||
**/tests
|
||||
@@ -36,7 +36,7 @@ The best way to report about your test results is writing a message in the [tele
|
||||
For correct component operation, you need hardware and firmware. The hardware description is located [in a separate file](docs/HARDWARE-EN.md).
|
||||
|
||||
### Firmware: Integration aux_ac to your configuration ###
|
||||
You need [ESPHome](https://esphome.io) v.1.18.0 or above. `External_components` have appeared in this version. But it is better to use ESPHome v.1.20.4 or above, cause there were a lot of `external_components` errors corrected before this version.
|
||||
You need [ESPHome](https://esphome.io) v.2025.2.0 or above. You can try esphome before 2025.2.0 but I can't guarantee error-free compilation of the examples.
|
||||
|
||||
## Installing ##
|
||||
1. Declare external component. Read [the manual](https://esphome.io/components/external_components.html?highlight=external) for details.
|
||||
|
||||
@@ -43,7 +43,7 @@ AUX - это один из нескольких OEM-производителей
|
||||
Для работы с кондиционером понадобится "железо" и прошивка. Описание электроники вынесено [в отдельный файл](docs/HARDWARE.md).
|
||||
|
||||
### Прошивка: интеграция aux_ac в вашу конфигурацию ESPHome ###
|
||||
Для использования требуется [ESPHome](https://esphome.io) версией не ниже 1.18.0. Именно в этой версии появились `external_components`. Но лучше использовать версию 1.20.4 или старше, так как до этой версии массированно исправлялись ошибки в механизме подключения внешних компонентов.<br />
|
||||
Для использования требуется [ESPHome](https://esphome.io) версией не ниже 2025.2.0. Работа с более ранними версиями возможна, но не гарантируется.<br />
|
||||
|
||||
## Установка ##
|
||||
1. Подключите компонент.
|
||||
|
||||
@@ -4,183 +4,238 @@
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/core/component.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace aux_ac {
|
||||
namespace esphome
|
||||
{
|
||||
namespace aux_ac
|
||||
{
|
||||
|
||||
// **************************************** DISPLAY ACTIONS ****************************************
|
||||
template <typename... Ts>
|
||||
class AirConDisplayOffAction : public Action<Ts...> {
|
||||
public:
|
||||
explicit AirConDisplayOffAction(AirCon *ac) : ac_(ac) {}
|
||||
// **************************************** DISPLAY ACTIONS ****************************************
|
||||
template <typename... Ts>
|
||||
class AirConDisplayOffAction : public Action<Ts...>
|
||||
{
|
||||
public:
|
||||
explicit AirConDisplayOffAction(AirCon *ac) : ac_(ac) {}
|
||||
|
||||
void play(Ts... x) override { this->ac_->displayOffSequence(); }
|
||||
void play(const Ts &...x) override
|
||||
{
|
||||
this->ac_->displayOffSequence();
|
||||
}
|
||||
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
};
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
};
|
||||
|
||||
template <typename... Ts>
|
||||
class AirConDisplayOnAction : public Action<Ts...> {
|
||||
public:
|
||||
explicit AirConDisplayOnAction(AirCon *ac) : ac_(ac) {}
|
||||
template <typename... Ts>
|
||||
class AirConDisplayOnAction : public Action<Ts...>
|
||||
{
|
||||
public:
|
||||
explicit AirConDisplayOnAction(AirCon *ac) : ac_(ac) {}
|
||||
|
||||
void play(Ts... x) override { this->ac_->displayOnSequence(); }
|
||||
void play(const Ts &...x) override
|
||||
{
|
||||
this->ac_->displayOnSequence();
|
||||
}
|
||||
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
};
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
};
|
||||
|
||||
// **************************************** VERTICAL LOUVER ACTIONS ****************************************
|
||||
template <typename... Ts>
|
||||
class AirConVLouverSwingAction : public Action<Ts...> {
|
||||
public:
|
||||
explicit AirConVLouverSwingAction(AirCon *ac) : ac_(ac) {}
|
||||
// **************************************** VERTICAL LOUVER ACTIONS ****************************************
|
||||
template <typename... Ts>
|
||||
class AirConVLouverSwingAction : public Action<Ts...>
|
||||
{
|
||||
public:
|
||||
explicit AirConVLouverSwingAction(AirCon *ac) : ac_(ac) {}
|
||||
|
||||
void play(Ts... x) override { this->ac_->setVLouverSwingSequence(); }
|
||||
void play(const Ts &...x) override
|
||||
{
|
||||
this->ac_->setVLouverSwingSequence();
|
||||
}
|
||||
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
};
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
};
|
||||
|
||||
template <typename... Ts>
|
||||
class AirConVLouverStopAction : public Action<Ts...> {
|
||||
public:
|
||||
explicit AirConVLouverStopAction(AirCon *ac) : ac_(ac) {}
|
||||
template <typename... Ts>
|
||||
class AirConVLouverStopAction : public Action<Ts...>
|
||||
{
|
||||
public:
|
||||
explicit AirConVLouverStopAction(AirCon *ac) : ac_(ac) {}
|
||||
|
||||
void play(Ts... x) override { this->ac_->setVLouverStopSequence(); }
|
||||
void play(const Ts &...x) override
|
||||
{
|
||||
this->ac_->setVLouverStopSequence();
|
||||
}
|
||||
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
};
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
};
|
||||
|
||||
template <typename... Ts>
|
||||
class AirConVLouverTopAction : public Action<Ts...> {
|
||||
public:
|
||||
explicit AirConVLouverTopAction(AirCon *ac) : ac_(ac) {}
|
||||
template <typename... Ts>
|
||||
class AirConVLouverTopAction : public Action<Ts...>
|
||||
{
|
||||
public:
|
||||
explicit AirConVLouverTopAction(AirCon *ac) : ac_(ac) {}
|
||||
|
||||
void play(Ts... x) override { this->ac_->setVLouverTopSequence(); }
|
||||
void play(const Ts &...x) override
|
||||
{
|
||||
this->ac_->setVLouverTopSequence();
|
||||
}
|
||||
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
};
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
};
|
||||
|
||||
template <typename... Ts>
|
||||
class AirConVLouverMiddleAboveAction : public Action<Ts...> {
|
||||
public:
|
||||
explicit AirConVLouverMiddleAboveAction(AirCon *ac) : ac_(ac) {}
|
||||
template <typename... Ts>
|
||||
class AirConVLouverMiddleAboveAction : public Action<Ts...>
|
||||
{
|
||||
public:
|
||||
explicit AirConVLouverMiddleAboveAction(AirCon *ac) : ac_(ac) {}
|
||||
|
||||
void play(Ts... x) override { this->ac_->setVLouverMiddleAboveSequence(); }
|
||||
void play(const Ts &...x) override
|
||||
{
|
||||
this->ac_->setVLouverMiddleAboveSequence();
|
||||
}
|
||||
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
};
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
};
|
||||
|
||||
template <typename... Ts>
|
||||
class AirConVLouverMiddleAction : public Action<Ts...> {
|
||||
public:
|
||||
explicit AirConVLouverMiddleAction(AirCon *ac) : ac_(ac) {}
|
||||
template <typename... Ts>
|
||||
class AirConVLouverMiddleAction : public Action<Ts...>
|
||||
{
|
||||
public:
|
||||
explicit AirConVLouverMiddleAction(AirCon *ac) : ac_(ac) {}
|
||||
|
||||
void play(Ts... x) override { this->ac_->setVLouverMiddleSequence(); }
|
||||
void play(const Ts &...x) override
|
||||
{
|
||||
this->ac_->setVLouverMiddleSequence();
|
||||
}
|
||||
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
};
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
};
|
||||
|
||||
template <typename... Ts>
|
||||
class AirConVLouverMiddleBelowAction : public Action<Ts...> {
|
||||
public:
|
||||
explicit AirConVLouverMiddleBelowAction(AirCon *ac) : ac_(ac) {}
|
||||
template <typename... Ts>
|
||||
class AirConVLouverMiddleBelowAction : public Action<Ts...>
|
||||
{
|
||||
public:
|
||||
explicit AirConVLouverMiddleBelowAction(AirCon *ac) : ac_(ac) {}
|
||||
|
||||
void play(Ts... x) override { this->ac_->setVLouverMiddleBelowSequence(); }
|
||||
void play(const Ts &...x) override
|
||||
{
|
||||
this->ac_->setVLouverMiddleBelowSequence();
|
||||
}
|
||||
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
};
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
};
|
||||
|
||||
template <typename... Ts>
|
||||
class AirConVLouverBottomAction : public Action<Ts...> {
|
||||
public:
|
||||
explicit AirConVLouverBottomAction(AirCon *ac) : ac_(ac) {}
|
||||
template <typename... Ts>
|
||||
class AirConVLouverBottomAction : public Action<Ts...>
|
||||
{
|
||||
public:
|
||||
explicit AirConVLouverBottomAction(AirCon *ac) : ac_(ac) {}
|
||||
|
||||
void play(Ts... x) override { this->ac_->setVLouverBottomSequence(); }
|
||||
void play(const Ts &...x) override
|
||||
{
|
||||
this->ac_->setVLouverBottomSequence();
|
||||
}
|
||||
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
};
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
};
|
||||
|
||||
template <typename... Ts>
|
||||
class AirConVLouverSetAction : public Action<Ts...> {
|
||||
public:
|
||||
AirConVLouverSetAction(AirCon *ac) : ac_(ac) {}
|
||||
TEMPLATABLE_VALUE(uint8_t, value);
|
||||
template <typename... Ts>
|
||||
class AirConVLouverSetAction : public Action<Ts...>
|
||||
{
|
||||
public:
|
||||
TEMPLATABLE_VALUE(uint8_t, value);
|
||||
|
||||
void play(Ts... x) {
|
||||
vlpos_ = this->value_.value(x...);
|
||||
this->ac_->setVLouverFrontendSequence((ac_vlouver_frontend)vlpos_);
|
||||
}
|
||||
AirConVLouverSetAction(AirCon *ac) : ac_(ac) {};
|
||||
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
uint8_t vlpos_;
|
||||
};
|
||||
void play(const Ts &...x) override
|
||||
{
|
||||
vlpos_ = this->value_.value(x...);
|
||||
this->ac_->setVLouverFrontendSequence((ac_vlouver_frontend)vlpos_);
|
||||
};
|
||||
|
||||
// **************************************** SEND TEST PACKET ACTION ****************************************
|
||||
template <typename... Ts>
|
||||
class AirConSendTestPacketAction : public Action<Ts...> {
|
||||
public:
|
||||
explicit AirConSendTestPacketAction(AirCon *ac) : ac_(ac) {}
|
||||
void set_data_template(std::function<std::vector<uint8_t>(Ts...)> func) {
|
||||
this->data_func_ = func;
|
||||
this->static_ = false;
|
||||
}
|
||||
void set_data_static(const std::vector<uint8_t> &data) {
|
||||
this->data_static_ = data;
|
||||
this->static_ = true;
|
||||
}
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
uint8_t vlpos_;
|
||||
};
|
||||
|
||||
void play(Ts... x) override {
|
||||
if (this->static_) {
|
||||
this->ac_->sendTestPacket(this->data_static_);
|
||||
} else {
|
||||
auto val = this->data_func_(x...);
|
||||
this->ac_->sendTestPacket(val);
|
||||
}
|
||||
}
|
||||
// **************************************** SEND TEST PACKET ACTION ****************************************
|
||||
template <typename... Ts>
|
||||
class AirConSendTestPacketAction : public Action<Ts...>
|
||||
{
|
||||
public:
|
||||
explicit AirConSendTestPacketAction(AirCon *ac) : ac_(ac) {}
|
||||
void set_data_template(std::function<std::vector<uint8_t>(Ts...)> func)
|
||||
{
|
||||
this->data_func_ = func;
|
||||
this->static_ = false;
|
||||
}
|
||||
void set_data_static(const std::vector<uint8_t> &data)
|
||||
{
|
||||
this->data_static_ = data;
|
||||
this->static_ = true;
|
||||
}
|
||||
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
bool static_{false};
|
||||
std::function<std::vector<uint8_t>(Ts...)> data_func_{};
|
||||
std::vector<uint8_t> data_static_{};
|
||||
};
|
||||
void play(const Ts &...x) override
|
||||
{
|
||||
if (this->static_)
|
||||
{
|
||||
this->ac_->sendTestPacket(this->data_static_);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto val = this->data_func_(x...);
|
||||
this->ac_->sendTestPacket(val);
|
||||
}
|
||||
}
|
||||
|
||||
// **************************************** POWER LIMITATION ACTIONS ****************************************
|
||||
template <typename... Ts>
|
||||
class AirConPowerLimitationOffAction : public Action<Ts...> {
|
||||
public:
|
||||
explicit AirConPowerLimitationOffAction(AirCon *ac) : ac_(ac) {}
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
bool static_{false};
|
||||
std::function<std::vector<uint8_t>(Ts...)> data_func_{};
|
||||
std::vector<uint8_t> data_static_{};
|
||||
};
|
||||
|
||||
void play(Ts... x) override { this->ac_->powerLimitationOffSequence(); }
|
||||
// **************************************** POWER LIMITATION ACTIONS ****************************************
|
||||
template <typename... Ts>
|
||||
class AirConPowerLimitationOffAction : public Action<Ts...>
|
||||
{
|
||||
public:
|
||||
explicit AirConPowerLimitationOffAction(AirCon *ac) : ac_(ac) {}
|
||||
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
};
|
||||
void play(const Ts &...x) override
|
||||
{
|
||||
this->ac_->powerLimitationOffSequence();
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
class AirConPowerLimitationOnAction : public Action<Ts...> {
|
||||
public:
|
||||
AirConPowerLimitationOnAction(AirCon *ac) : ac_(ac) {}
|
||||
TEMPLATABLE_VALUE(uint8_t, value);
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
};
|
||||
|
||||
void play(Ts... x) {
|
||||
this->pwr_lim_ = this->value_.value(x...);
|
||||
this->ac_->powerLimitationOnSequence(this->pwr_lim_);
|
||||
}
|
||||
template <typename... Ts>
|
||||
class AirConPowerLimitationOnAction : public Action<Ts...>
|
||||
{
|
||||
public:
|
||||
TEMPLATABLE_VALUE(uint8_t, value);
|
||||
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
uint8_t pwr_lim_;
|
||||
};
|
||||
AirConPowerLimitationOnAction(AirCon *ac) : ac_(ac) {};
|
||||
|
||||
} // namespace aux_ac
|
||||
} // namespace esphome
|
||||
void play(const Ts &...x) override
|
||||
{
|
||||
this->pwr_lim_ = this->value_.value(x...);
|
||||
this->ac_->powerLimitationOnSequence(this->pwr_lim_);
|
||||
}
|
||||
|
||||
protected:
|
||||
AirCon *ac_;
|
||||
uint8_t pwr_lim_;
|
||||
};
|
||||
|
||||
} // namespace aux_ac
|
||||
} // namespace esphome
|
||||
@@ -4,8 +4,8 @@
|
||||
/// немного переработанная версия старого компонента
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <stdarg.h>
|
||||
#include <cinttypes>
|
||||
|
||||
#include "esphome.h"
|
||||
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||
@@ -15,6 +15,12 @@
|
||||
#include "esphome/components/uart/uart.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/version.h"
|
||||
|
||||
#ifndef USE_ARDUINO
|
||||
using String = std::string;
|
||||
#define F(string_literal) (string_literal)
|
||||
#endif
|
||||
|
||||
// весь функционал сохранения пресетов прячу под дефайн
|
||||
// #define PRESETS_SAVING
|
||||
@@ -38,6 +44,11 @@ namespace esphome
|
||||
using climate::ClimatePreset;
|
||||
using climate::ClimateSwingMode;
|
||||
using climate::ClimateTraits;
|
||||
#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0)
|
||||
using climate::ClimateModeMask;
|
||||
using climate::ClimateSwingModeMask;
|
||||
using climate::ClimatePresetMask;
|
||||
#endif
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
//**************************************************** Packet logger configuration *******************************************************************
|
||||
@@ -710,16 +721,16 @@ namespace esphome
|
||||
{
|
||||
AC_COMMAND_BASE;
|
||||
ac_health_status health_status;
|
||||
float temp_ambient; // внутренняя температура
|
||||
int8_t temp_outdoor; // внешняя температура
|
||||
int8_t temp_inbound; // температура входящая
|
||||
int8_t temp_outbound; // температура исходящая
|
||||
int8_t temp_compressor; // температура компрессора
|
||||
ac_realFan realFanSpeed; // текущая скорость вентилятора
|
||||
uint8_t inverter_power; // мощность инвертора
|
||||
bool defrost; // режим разморозки внешнего блока (накопление тепла + прогрев испарителя)
|
||||
ac_powLim_state power_lim_state; // статус ограничения мощности инвертора
|
||||
uint8_t power_lim_value; // значение ограничения мощности инвертора
|
||||
float temp_ambient; // внутренняя температура
|
||||
int8_t temp_outdoor; // внешняя температура
|
||||
int8_t temp_inbound; // температура входящая
|
||||
int8_t temp_outbound; // температура исходящая
|
||||
int8_t temp_compressor; // температура компрессора
|
||||
ac_realFan realFanSpeed; // текущая скорость вентилятора
|
||||
uint8_t inverter_power; // мощность инвертора
|
||||
bool defrost; // режим разморозки внешнего блока (накопление тепла + прогрев испарителя)
|
||||
ac_powLim_state power_lim_state; // статус ограничения мощности инвертора
|
||||
uint8_t power_lim_value; // значение ограничения мощности инвертора
|
||||
};
|
||||
|
||||
typedef ac_command_t ac_state_t; // текущее состояние параметров кондея можно хранить в таком же формате, как и комманды
|
||||
@@ -847,12 +858,19 @@ namespace esphome
|
||||
// как "в простое" (IDLE)
|
||||
bool _is_inverter = false;
|
||||
|
||||
// поддерживаемые кондиционером опции
|
||||
#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0)
|
||||
ClimateModeMask _supported_modes{};
|
||||
ClimateSwingModeMask _supported_swing_modes{};
|
||||
ClimatePresetMask _supported_presets{};
|
||||
std::vector<const char *> _supported_custom_fan_modes{};
|
||||
std::vector<const char *> _supported_custom_presets{};
|
||||
#else
|
||||
std::set<ClimateMode> _supported_modes{};
|
||||
std::set<ClimateSwingMode> _supported_swing_modes{};
|
||||
std::set<ClimatePreset> _supported_presets{};
|
||||
std::set<std::string> _supported_custom_presets{};
|
||||
std::set<std::string> _supported_custom_fan_modes{};
|
||||
#endif
|
||||
|
||||
// The capabilities of the climate device
|
||||
// Шаблон параметров отображения виджета
|
||||
@@ -1520,15 +1538,15 @@ namespace esphome
|
||||
stateByte = small_info_body->display_and_mildew & AC_MILDEW_MASK;
|
||||
stateChangedFlag = stateChangedFlag || (_current_ac_state.mildew != (ac_mildew)stateByte);
|
||||
_current_ac_state.mildew = (ac_mildew)stateByte;
|
||||
|
||||
|
||||
stateByte = AC_POWLIMSTAT_ON * small_info_body->inverter_power_limitation_enable;
|
||||
stateChangedFlag = stateChangedFlag || (_current_ac_state.power_lim_state != (ac_powLim_state)stateByte);
|
||||
_current_ac_state.power_lim_state = (ac_powLim_state)stateByte;
|
||||
|
||||
_current_ac_state.power_lim_state = (ac_powLim_state)stateByte;
|
||||
|
||||
stateByte = small_info_body->inverter_power_limitation_value;
|
||||
stateChangedFlag = stateChangedFlag || (_current_ac_state.power_lim_value != stateByte);
|
||||
_current_ac_state.power_lim_value = stateByte;
|
||||
|
||||
|
||||
// уведомляем об изменении статуса сплита
|
||||
if (stateChangedFlag)
|
||||
stateChanged();
|
||||
@@ -1710,7 +1728,7 @@ namespace esphome
|
||||
|
||||
// заполняем время получения пакета
|
||||
memset(textBuf, 0, 11);
|
||||
sprintf(textBuf, "%010u", packet->msec);
|
||||
sprintf(textBuf, "%010" PRIu32, packet->msec);
|
||||
st = st + textBuf + ": ";
|
||||
|
||||
// формируем преамбулы
|
||||
@@ -2386,11 +2404,16 @@ namespace esphome
|
||||
|
||||
// первоначальная инициализация
|
||||
this->preset = climate::CLIMATE_PRESET_NONE;
|
||||
#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0)
|
||||
this->clear_custom_preset_();
|
||||
this->clear_custom_fan_mode_();
|
||||
#else
|
||||
this->custom_preset = (std::string) "";
|
||||
this->custom_fan_mode = (std::string) "";
|
||||
#endif
|
||||
this->mode = climate::CLIMATE_MODE_OFF;
|
||||
this->action = climate::CLIMATE_ACTION_IDLE;
|
||||
this->fan_mode = climate::CLIMATE_FAN_LOW;
|
||||
this->custom_fan_mode = (std::string) "";
|
||||
};
|
||||
|
||||
float get_setup_priority() const override { return esphome::setup_priority::DATA; }
|
||||
@@ -2411,6 +2434,22 @@ namespace esphome
|
||||
bool get_hw_initialized() { return _hw_initialized; };
|
||||
bool get_has_connection() { return _has_connection; };
|
||||
|
||||
// --- Helper functions for consistent louver interpretation ---
|
||||
// Some AUX-based models use 0x20 for "horizontal off", while others (e.g., ROVEX, Royal Clima) use 0xE0.
|
||||
// These helpers normalize those differences so swing detection stays consistent.
|
||||
// Keeping both encodings here replaces the old workaround that caused HA to jump back to OFF
|
||||
// when horizontal was swinging and vertical was fixed.
|
||||
|
||||
static inline bool is_h_off(uint8_t h) {
|
||||
return (h == AC_LOUVERH_OFF_AUX) || (h == AC_LOUVERH_OFF_ALTERNATIVE);
|
||||
}
|
||||
static inline bool is_h_swing(uint8_t h) {
|
||||
return (h == AC_LOUVERH_SWING_LEFTRIGHT);
|
||||
}
|
||||
static inline bool is_v_swing(uint8_t v) {
|
||||
return (v == AC_LOUVERV_SWING_UPDOWN);
|
||||
}
|
||||
|
||||
// возвращает, есть ли елементы в последовательности команд
|
||||
bool hasSequence()
|
||||
{
|
||||
@@ -2614,15 +2653,24 @@ namespace esphome
|
||||
switch (_current_ac_state.fanTurbo)
|
||||
{
|
||||
case AC_FANTURBO_ON:
|
||||
// if ((_current_ac_state.mode == AC_MODE_HEAT) || (_current_ac_state.mode == AC_MODE_COOL)) {
|
||||
#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0)
|
||||
this->set_custom_fan_mode_(Constants::TURBO.c_str());
|
||||
#else
|
||||
this->custom_fan_mode = Constants::TURBO;
|
||||
//}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case AC_FANTURBO_OFF:
|
||||
default:
|
||||
#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0)
|
||||
if (this->has_custom_fan_mode()) {
|
||||
if (strcmp(this->get_custom_fan_mode(), Constants::TURBO.c_str()) == 0)
|
||||
this->clear_custom_fan_mode_();
|
||||
}
|
||||
#else
|
||||
if (this->custom_fan_mode == Constants::TURBO)
|
||||
this->custom_fan_mode = (std::string) "";
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2634,15 +2682,24 @@ namespace esphome
|
||||
switch (_current_ac_state.fanMute)
|
||||
{
|
||||
case AC_FANMUTE_ON:
|
||||
// if (_current_ac_state.mode == AC_MODE_FAN) {
|
||||
#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0)
|
||||
this->set_custom_fan_mode_(Constants::MUTE.c_str());
|
||||
#else
|
||||
this->custom_fan_mode = Constants::MUTE;
|
||||
//}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case AC_FANMUTE_OFF:
|
||||
default:
|
||||
#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0)
|
||||
if (this->has_custom_fan_mode()) {
|
||||
if (strcmp(this->get_custom_fan_mode(), Constants::MUTE.c_str()) == 0)
|
||||
this->clear_custom_fan_mode_();
|
||||
}
|
||||
#else
|
||||
if (this->custom_fan_mode == Constants::MUTE)
|
||||
this->custom_fan_mode = (std::string) "";
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2654,14 +2711,25 @@ namespace esphome
|
||||
if (_current_ac_state.health == AC_HEALTH_ON &&
|
||||
_current_ac_state.power == AC_POWER_ON)
|
||||
{
|
||||
#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0)
|
||||
this->set_custom_preset_(Constants::HEALTH.c_str());
|
||||
#else
|
||||
this->custom_preset = Constants::HEALTH;
|
||||
#endif
|
||||
}
|
||||
// AC_HEALTH_OFF
|
||||
// только в том случае, если до этого пресет был установлен
|
||||
#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0)
|
||||
else if (this->has_custom_preset() && strcmp(this->get_custom_preset(), Constants::HEALTH.c_str()) == 0)
|
||||
{
|
||||
this->clear_custom_preset_();
|
||||
}
|
||||
#else
|
||||
else if (this->custom_preset == Constants::HEALTH)
|
||||
{
|
||||
// AC_HEALTH_OFF
|
||||
// только в том случае, если до этого пресет был установлен
|
||||
this->custom_preset = (std::string) "";
|
||||
}
|
||||
#endif
|
||||
|
||||
_debugMsg(F("Climate HEALTH preset: %i"), ESPHOME_LOG_LEVEL_VERBOSE, __LINE__, _current_ac_state.health);
|
||||
|
||||
@@ -2689,14 +2757,25 @@ namespace esphome
|
||||
if (_current_ac_state.clean == AC_CLEAN_ON &&
|
||||
_current_ac_state.power == AC_POWER_OFF)
|
||||
{
|
||||
#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0)
|
||||
this->set_custom_preset_(Constants::CLEAN.c_str());
|
||||
#else
|
||||
this->custom_preset = Constants::CLEAN;
|
||||
#endif
|
||||
}
|
||||
// AC_CLEAN_OFF
|
||||
// только в том случае, если до этого пресет был установлен
|
||||
#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0)
|
||||
else if (this->has_custom_preset() && strcmp(this->get_custom_preset(), Constants::CLEAN.c_str()) == 0)
|
||||
{
|
||||
this->clear_custom_preset_();
|
||||
}
|
||||
#else
|
||||
else if (this->custom_preset == Constants::CLEAN)
|
||||
{
|
||||
// AC_CLEAN_OFF
|
||||
// только в том случае, если до этого пресет был установлен
|
||||
this->custom_preset = (std::string) "";
|
||||
}
|
||||
#endif
|
||||
|
||||
_debugMsg(F("Climate CLEAN preset: %i"), ESPHOME_LOG_LEVEL_VERBOSE, __LINE__, _current_ac_state.clean);
|
||||
|
||||
@@ -2719,43 +2798,50 @@ namespace esphome
|
||||
switch (_current_ac_state.mildew)
|
||||
{
|
||||
case AC_MILDEW_ON:
|
||||
#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0)
|
||||
this->set_custom_preset_(Constants::ANTIFUNGUS.c_str());
|
||||
#else
|
||||
this->custom_preset = Constants::ANTIFUNGUS;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case AC_MILDEW_OFF:
|
||||
default:
|
||||
#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0)
|
||||
if (this->has_custom_preset() && strcmp(this->get_custom_preset(), Constants::ANTIFUNGUS.c_str()) == 0)
|
||||
{
|
||||
this->clear_custom_preset_();
|
||||
}
|
||||
#else
|
||||
if (this->custom_preset == Constants::ANTIFUNGUS)
|
||||
this->custom_preset = (std::string) "";
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
_debugMsg(F("Climate ANTIFUNGUS preset: %i"), ESPHOME_LOG_LEVEL_VERBOSE, __LINE__, _current_ac_state.mildew);
|
||||
|
||||
/*************************** LOUVERs ***************************/
|
||||
this->swing_mode = climate::CLIMATE_SWING_OFF;
|
||||
if (_current_ac_state.power == AC_POWER_ON)
|
||||
{
|
||||
if (_current_ac_state.louver.louver_h == AC_LOUVERH_SWING_LEFTRIGHT && _current_ac_state.louver.louver_v == AC_LOUVERV_OFF)
|
||||
{
|
||||
this->swing_mode = climate::CLIMATE_SWING_HORIZONTAL;
|
||||
}
|
||||
else if (_current_ac_state.louver.louver_h == AC_LOUVERH_OFF_AUX && _current_ac_state.louver.louver_v == AC_LOUVERV_SWING_UPDOWN)
|
||||
{
|
||||
// TODO: КОСТЫЛЬ!
|
||||
this->swing_mode = climate::CLIMATE_SWING_VERTICAL;
|
||||
}
|
||||
else if (_current_ac_state.louver.louver_h == AC_LOUVERH_OFF_ALTERNATIVE && _current_ac_state.louver.louver_v == AC_LOUVERV_SWING_UPDOWN)
|
||||
{
|
||||
// TODO: КОСТЫЛЬ!
|
||||
// временно сделал так. Сделать нормально - это надо подумать.
|
||||
// На AUX и многих других марках выключенный режим горизонтальных жалюзи равен 0x20, а на ROVEX и Royal Clima 0xE0
|
||||
// Из-за этого происходил сброс на OFF во фронтенде Home Assistant. Пришлось городить это.
|
||||
// Надо как-то изящнее решить эту историю
|
||||
this->swing_mode = climate::CLIMATE_SWING_VERTICAL;
|
||||
}
|
||||
else if (_current_ac_state.louver.louver_h == AC_LOUVERH_SWING_LEFTRIGHT && _current_ac_state.louver.louver_v == AC_LOUVERV_SWING_UPDOWN)
|
||||
{
|
||||
|
||||
if (_current_ac_state.power == AC_POWER_ON) {
|
||||
const uint8_t h = _current_ac_state.louver.louver_h;
|
||||
const uint8_t v = _current_ac_state.louver.louver_v;
|
||||
|
||||
const bool hSwing = is_h_swing(h);
|
||||
const bool hOff = is_h_off(h);
|
||||
const bool vSwing = is_v_swing(v);
|
||||
|
||||
if (hSwing && vSwing) {
|
||||
this->swing_mode = climate::CLIMATE_SWING_BOTH;
|
||||
} else if (hSwing) {
|
||||
// Horizontal swings even if vertical is fixed to a position
|
||||
this->swing_mode = climate::CLIMATE_SWING_HORIZONTAL;
|
||||
} else if (vSwing && hOff) {
|
||||
// Vertical swings while horizontal is not swinging
|
||||
this->swing_mode = climate::CLIMATE_SWING_VERTICAL;
|
||||
} else {
|
||||
this->swing_mode = climate::CLIMATE_SWING_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2816,10 +2902,17 @@ namespace esphome
|
||||
{
|
||||
state_str += "SLEEP";
|
||||
}
|
||||
#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0)
|
||||
else if (this->has_custom_preset())
|
||||
{
|
||||
state_str += this->get_custom_preset();
|
||||
}
|
||||
#else
|
||||
else if (this->custom_preset.has_value() && this->custom_preset.value().length() > 0)
|
||||
{
|
||||
state_str += this->custom_preset.value().c_str();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
state_str += "NONE";
|
||||
@@ -2839,11 +2932,11 @@ namespace esphome
|
||||
{
|
||||
ESP_LOGCONFIG(TAG, "AUX HVAC:");
|
||||
ESP_LOGCONFIG(TAG, " [x] Firmware version: %s", Constants::AC_FIRMWARE_VERSION.c_str());
|
||||
ESP_LOGCONFIG(TAG, " [x] Period: %dms", this->get_period());
|
||||
ESP_LOGCONFIG(TAG, " [x] Period: %" PRIu32 "ms", this->get_period());
|
||||
ESP_LOGCONFIG(TAG, " [x] Show action: %s", TRUEFALSE(this->get_show_action()));
|
||||
ESP_LOGCONFIG(TAG, " [x] Display inverted: %s", TRUEFALSE(this->get_display_inverted()));
|
||||
ESP_LOGCONFIG(TAG, " [x] Optimistic: %s", TRUEFALSE(this->get_optimistic()));
|
||||
ESP_LOGCONFIG(TAG, " [x] Packet timeout: %dms", this->get_packet_timeout());
|
||||
ESP_LOGCONFIG(TAG, " [x] Packet timeout: %" PRIu32 "ms", this->get_packet_timeout());
|
||||
|
||||
#if defined(PRESETS_SAVING)
|
||||
ESP_LOGCONFIG(TAG, " [x] Save settings %s", TRUEFALSE(this->get_store_settings()));
|
||||
@@ -3009,6 +3102,32 @@ namespace esphome
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0)
|
||||
else if (call.has_custom_fan_mode())
|
||||
{
|
||||
const char *customfanmode = call.get_custom_fan_mode();
|
||||
|
||||
if (strcmp(customfanmode, Constants::TURBO.c_str()) == 0)
|
||||
{
|
||||
// TURBO fan mode is suitable in COOL and HEAT modes.
|
||||
// Other modes don't accept TURBO fan mode.
|
||||
hasCommand = true;
|
||||
cmd.fanTurbo = AC_FANTURBO_ON;
|
||||
cmd.fanMute = AC_FANMUTE_OFF;
|
||||
this->set_custom_fan_mode_(customfanmode);
|
||||
}
|
||||
else if (strcmp(customfanmode, Constants::MUTE.c_str()) == 0)
|
||||
{
|
||||
// MUTE fan mode is suitable in FAN mode only for Rovex air conditioner.
|
||||
// In COOL mode AC receives command without any changes.
|
||||
// May be other AUX-based air conditioners do the same.
|
||||
hasCommand = true;
|
||||
cmd.fanMute = AC_FANMUTE_ON;
|
||||
cmd.fanTurbo = AC_FANTURBO_OFF;
|
||||
this->set_custom_fan_mode_(customfanmode);
|
||||
}
|
||||
}
|
||||
#else
|
||||
else if (call.get_custom_fan_mode().has_value())
|
||||
{
|
||||
std::string customfanmode = *call.get_custom_fan_mode();
|
||||
@@ -3050,6 +3169,7 @@ namespace esphome
|
||||
//}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Пользователь выбрал пресет
|
||||
if (call.get_preset().has_value())
|
||||
@@ -3100,6 +3220,80 @@ namespace esphome
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0)
|
||||
else if (call.has_custom_preset())
|
||||
{
|
||||
const char *custom_preset = call.get_custom_preset();
|
||||
|
||||
if (strcmp(custom_preset, Constants::CLEAN.c_str()) == 0)
|
||||
{
|
||||
// режим очистки кондиционера, включается (или должен включаться) при AC_POWER_OFF
|
||||
// TODO: надо отдебажить выключение этого режима
|
||||
if (cmd.power == AC_POWER_OFF or _current_ac_state.power == AC_POWER_OFF)
|
||||
{
|
||||
hasCommand = true;
|
||||
cmd.clean = AC_CLEAN_ON;
|
||||
cmd.mildew = AC_MILDEW_OFF;
|
||||
this->set_custom_preset_(custom_preset);
|
||||
}
|
||||
else
|
||||
{
|
||||
_debugMsg(F("CLEAN preset is suitable in POWER_OFF mode only."), ESPHOME_LOG_LEVEL_WARN, __LINE__);
|
||||
}
|
||||
}
|
||||
else if (strcmp(custom_preset, Constants::HEALTH.c_str()) == 0)
|
||||
{
|
||||
if (cmd.power == AC_POWER_ON ||
|
||||
_current_ac_state.power == AC_POWER_ON)
|
||||
{
|
||||
hasCommand = true;
|
||||
cmd.health = AC_HEALTH_ON;
|
||||
cmd.fanTurbo = AC_FANTURBO_OFF;
|
||||
cmd.fanMute = AC_FANMUTE_OFF;
|
||||
cmd.sleep = AC_SLEEP_OFF;
|
||||
|
||||
if (cmd.mode == AC_MODE_COOL ||
|
||||
cmd.mode == AC_MODE_HEAT ||
|
||||
cmd.mode == AC_MODE_AUTO ||
|
||||
_current_ac_state.mode == AC_MODE_COOL ||
|
||||
_current_ac_state.mode == AC_MODE_HEAT ||
|
||||
_current_ac_state.mode == AC_MODE_AUTO)
|
||||
{
|
||||
cmd.fanSpeed = AC_FANSPEED_AUTO; // зависимость от health
|
||||
}
|
||||
else if (cmd.mode == AC_MODE_FAN ||
|
||||
_current_ac_state.mode == AC_MODE_FAN)
|
||||
{
|
||||
cmd.fanSpeed = AC_FANSPEED_MEDIUM; // зависимость от health
|
||||
}
|
||||
this->set_custom_preset_(custom_preset);
|
||||
}
|
||||
else
|
||||
{
|
||||
_debugMsg(F("HEALTH preset is suitable in POWER_ON mode only."), ESPHOME_LOG_LEVEL_WARN, __LINE__);
|
||||
}
|
||||
}
|
||||
else if (strcmp(custom_preset, Constants::ANTIFUNGUS.c_str()) == 0)
|
||||
{
|
||||
// включение-выключение функции "Антиплесень".
|
||||
// По факту: после выключения сплита он оставляет минут на 5 открытые жалюзи и глушит вентилятор.
|
||||
// Уличный блок при этом гудит и тарахтит. Возможно, прогревается теплообменник для высыхания.
|
||||
// Через некоторое время внешний блок замолкает и сплит закрывает жалюзи.
|
||||
|
||||
// Brokly:
|
||||
// включение-выключение функции "Антиплесень".
|
||||
// у меня пульт отправляет 5 посылок и на включение и на выключение, но реагирует на эту кнопку
|
||||
// только в режиме POWER_OFF
|
||||
|
||||
// TODO: надо уточнить, в каких режимах штатно включается этот режим у кондиционера
|
||||
cmd.mildew = AC_MILDEW_ON;
|
||||
cmd.clean = AC_CLEAN_OFF; // для логики пресетов
|
||||
|
||||
hasCommand = true;
|
||||
this->set_custom_preset_(custom_preset);
|
||||
}
|
||||
}
|
||||
#else
|
||||
else if (call.get_custom_preset().has_value())
|
||||
{
|
||||
std::string custom_preset = *call.get_custom_preset();
|
||||
@@ -3173,6 +3367,7 @@ namespace esphome
|
||||
this->custom_preset = custom_preset;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// User requested swing_mode change
|
||||
if (call.get_swing_mode().has_value())
|
||||
@@ -3186,8 +3381,16 @@ namespace esphome
|
||||
// But the ROVEX IR-remote does not provide this features. Therefore this features haven't been tested.
|
||||
// May be suitable for other models of AUX-based ACs.
|
||||
case climate::CLIMATE_SWING_OFF:
|
||||
// Stop BOTH axes, but don't disturb vertical if it was already fixed (2..6)
|
||||
cmd.louver.louver_h = AC_LOUVERH_OFF_ALTERNATIVE;
|
||||
cmd.louver.louver_v = AC_LOUVERV_OFF;
|
||||
if (_current_ac_state.louver.louver_v == AC_LOUVERV_SWING_UPDOWN) {
|
||||
// If vertical was swinging, stop it.
|
||||
cmd.louver.louver_v = AC_LOUVERV_OFF;
|
||||
} else {
|
||||
// Keep existing fixed position (2..6).
|
||||
cmd.louver.louver_v = _current_ac_state.louver.louver_v;
|
||||
}
|
||||
|
||||
hasCommand = true;
|
||||
this->swing_mode = swingmode;
|
||||
break;
|
||||
@@ -3208,7 +3411,12 @@ namespace esphome
|
||||
|
||||
case climate::CLIMATE_SWING_HORIZONTAL:
|
||||
cmd.louver.louver_h = AC_LOUVERH_SWING_LEFTRIGHT;
|
||||
cmd.louver.louver_v = AC_LOUVERV_OFF;
|
||||
// Stop vertical only if it was swinging; otherwise preserve prior fixed position
|
||||
if (_current_ac_state.louver.louver_v == AC_LOUVERV_SWING_UPDOWN) {
|
||||
cmd.louver.louver_v = AC_LOUVERV_OFF;
|
||||
} else {
|
||||
cmd.louver.louver_v = _current_ac_state.louver.louver_v;
|
||||
}
|
||||
hasCommand = true;
|
||||
this->swing_mode = swingmode;
|
||||
break;
|
||||
@@ -3545,7 +3753,7 @@ namespace esphome
|
||||
}
|
||||
|
||||
// устанавливает ограничение мощности сплита на нужный уровень
|
||||
bool powerLimitationSetSequence(uint8_t power_limit, bool set_on=false)
|
||||
bool powerLimitationSetSequence(uint8_t power_limit, bool set_on = false)
|
||||
{
|
||||
// нет смысла в последовательности, если нет коннекта с кондиционером
|
||||
if (!get_has_connection())
|
||||
@@ -3560,12 +3768,12 @@ namespace esphome
|
||||
return false;
|
||||
}
|
||||
|
||||
if(power_limit != this->_power_limitation_value_normalise(power_limit))
|
||||
if (power_limit != this->_power_limitation_value_normalise(power_limit))
|
||||
{
|
||||
_debugMsg(F("powerLimitationSetSequence: incorrect power limit value."), ESPHOME_LOG_LEVEL_WARN, __LINE__);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// формируем команду
|
||||
ac_command_t cmd;
|
||||
_clearCommand(&cmd); // не забываем очищать, а то будет мусор
|
||||
@@ -3577,12 +3785,14 @@ namespace esphome
|
||||
// добавляем команду в последовательность
|
||||
if (!commandSequence(&cmd))
|
||||
return false;
|
||||
|
||||
|
||||
if (set_on)
|
||||
{
|
||||
_debugMsg(F("powerLimitationSetSequence: loaded (state = %02X, power limit = %02X)"), ESPHOME_LOG_LEVEL_VERBOSE, __LINE__, cmd.power_lim_state, power_limit);
|
||||
} else {
|
||||
_debugMsg(F("powerLimitationSetSequence: loaded (power limit = %02X)"), ESPHOME_LOG_LEVEL_VERBOSE, __LINE__, power_limit);
|
||||
_debugMsg(F("powerLimitationSetSequence: loaded (state = %02X, power limit = %02X)"), ESPHOME_LOG_LEVEL_VERBOSE, __LINE__, cmd.power_lim_state, power_limit);
|
||||
}
|
||||
else
|
||||
{
|
||||
_debugMsg(F("powerLimitationSetSequence: loaded (power limit = %02X)"), ESPHOME_LOG_LEVEL_VERBOSE, __LINE__, power_limit);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -3602,14 +3812,17 @@ namespace esphome
|
||||
_debugMsg(F("powerLimitationOnSequence: unsupported for noninverter AC."), ESPHOME_LOG_LEVEL_WARN, __LINE__);
|
||||
return false; // если кондиционер не инверторный, то выходим
|
||||
}
|
||||
|
||||
|
||||
// формируем команду
|
||||
ac_command_t cmd;
|
||||
_clearCommand(&cmd); // не забываем очищать, а то будет мусор
|
||||
if(enable_limit){
|
||||
cmd.power_lim_state = AC_POWLIMSTAT_ON; // включить ограничение мощности
|
||||
} else {
|
||||
cmd.power_lim_state = AC_POWLIMSTAT_OFF; // отключить ограничение мощности
|
||||
if (enable_limit)
|
||||
{
|
||||
cmd.power_lim_state = AC_POWLIMSTAT_ON; // включить ограничение мощности
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd.power_lim_state = AC_POWLIMSTAT_OFF; // отключить ограничение мощности
|
||||
}
|
||||
// добавляем команду в последовательность
|
||||
if (!commandSequence(&cmd))
|
||||
@@ -3622,19 +3835,19 @@ namespace esphome
|
||||
// включает ограничение мощности сплита
|
||||
bool powerLimitationOnSequence()
|
||||
{
|
||||
return powerLimitationOnOffSequence(true);
|
||||
return powerLimitationOnOffSequence(true);
|
||||
}
|
||||
|
||||
// включает ограничение мощности сплита на нужный уровень
|
||||
bool powerLimitationOnSequence(uint8_t power_limit)
|
||||
{
|
||||
return powerLimitationSetSequence(power_limit, true);
|
||||
return powerLimitationSetSequence(power_limit, true);
|
||||
}
|
||||
|
||||
|
||||
// выключает ограничение мощности сплита
|
||||
bool powerLimitationOffSequence()
|
||||
{
|
||||
return powerLimitationOnOffSequence(false);
|
||||
return powerLimitationOnOffSequence(false);
|
||||
}
|
||||
|
||||
// конвертирует состояние жалюзи из кодов сплита в коды для фронтенда
|
||||
@@ -3771,7 +3984,13 @@ namespace esphome
|
||||
void set_optimistic(bool optimistic) { this->_optimistic = optimistic; }
|
||||
bool get_optimistic() { return this->_optimistic; }
|
||||
|
||||
// возможно функции get и не нужны, но вроде как должны быть
|
||||
#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0)
|
||||
void set_supported_modes(ClimateModeMask modes) { this->_supported_modes = modes; }
|
||||
void set_supported_swing_modes(ClimateSwingModeMask modes) { this->_supported_swing_modes = modes; }
|
||||
void set_supported_presets(ClimatePresetMask presets) { this->_supported_presets = presets; }
|
||||
void set_custom_presets(std::initializer_list<const char *> presets) { this->_supported_custom_presets = presets; }
|
||||
void set_custom_fan_modes(std::initializer_list<const char *> modes) { this->_supported_custom_fan_modes = modes; }
|
||||
#else
|
||||
void set_supported_modes(const std::set<ClimateMode> &modes) { this->_supported_modes = modes; }
|
||||
std::set<ClimateMode> get_supported_modes() { return this->_supported_modes; }
|
||||
|
||||
@@ -3786,6 +4005,7 @@ namespace esphome
|
||||
|
||||
void set_custom_fan_modes(const std::set<std::string> &modes) { this->_supported_custom_fan_modes = modes; }
|
||||
const std::set<std::string> &get_supported_custom_fan_modes() { return this->_supported_custom_fan_modes; }
|
||||
#endif
|
||||
|
||||
#if defined(PRESETS_SAVING)
|
||||
void set_store_settings(bool store_settings) { this->_store_settings = store_settings; }
|
||||
@@ -3803,8 +4023,13 @@ namespace esphome
|
||||
// заполнение шаблона параметров отображения виджета
|
||||
// GK: всё же похоже правильнее это делать тут, а не в initAC()
|
||||
// initAC() в формируемом питоном коде вызывается до вызова aux_ac.set_supported_***() с установленными пользователем в конфиге параметрами
|
||||
#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0)
|
||||
_traits.add_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_TEMPERATURE);
|
||||
_traits.add_feature_flags(climate::CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE);
|
||||
#else
|
||||
_traits.set_supports_current_temperature(true);
|
||||
_traits.set_supports_two_point_target_temperature(false); // if the climate device's target temperature should be split in target_temperature_low and target_temperature_high instead of just the single target_temperature
|
||||
#endif
|
||||
|
||||
_traits.set_supported_modes(this->_supported_modes);
|
||||
_traits.set_supported_swing_modes(this->_supported_swing_modes);
|
||||
@@ -3833,7 +4058,14 @@ namespace esphome
|
||||
//_traits.add_supported_preset(ClimatePreset::CLIMATE_PRESET_SLEEP);
|
||||
|
||||
// if the climate device supports reporting the active current action of the device with the action property.
|
||||
#if ESPHOME_VERSION_CODE >= VERSION_CODE(2025, 11, 0)
|
||||
if (this->_show_action)
|
||||
{
|
||||
_traits.add_feature_flags(climate::CLIMATE_SUPPORTS_ACTION);
|
||||
}
|
||||
#else
|
||||
_traits.set_supports_action(this->_show_action);
|
||||
#endif
|
||||
};
|
||||
|
||||
void loop() override
|
||||
@@ -3889,4 +4121,4 @@ namespace esphome
|
||||
};
|
||||
|
||||
} // namespace aux_ac
|
||||
} // namespace esphome
|
||||
} // namespace esphome
|
||||
|
||||
@@ -26,6 +26,7 @@ from esphome.const import (
|
||||
DEVICE_CLASS_TEMPERATURE,
|
||||
DEVICE_CLASS_POWER_FACTOR,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
__version__
|
||||
)
|
||||
from esphome.components.climate import (
|
||||
ClimateMode,
|
||||
@@ -33,7 +34,7 @@ from esphome.components.climate import (
|
||||
ClimateSwingMode,
|
||||
)
|
||||
|
||||
AUX_AC_FIRMWARE_VERSION = '0.2.15'
|
||||
AUX_AC_FIRMWARE_VERSION = '0.3.1'
|
||||
AC_PACKET_TIMEOUT_MIN = 150
|
||||
AC_PACKET_TIMEOUT_MAX = 600
|
||||
AC_POWER_LIMIT_MIN = 30
|
||||
@@ -127,6 +128,12 @@ AirConPowerLimitationOnAction = aux_ac_ns.class_(
|
||||
)
|
||||
|
||||
|
||||
def use_new_api():
|
||||
esphome_current_version = tuple(map(int, __version__.split('.')))
|
||||
esphome_bc_version = tuple(map(int, "2025.11.0".split('.')))
|
||||
return esphome_current_version >= esphome_bc_version
|
||||
|
||||
|
||||
def validate_packet_timeout(value):
|
||||
minV = AC_PACKET_TIMEOUT_MIN
|
||||
maxV = AC_PACKET_TIMEOUT_MAX
|
||||
@@ -190,7 +197,7 @@ def output_info(config):
|
||||
|
||||
|
||||
CONFIG_SCHEMA = cv.All(
|
||||
climate.CLIMATE_SCHEMA.extend(
|
||||
climate.climate_schema(climate.Climate).extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(AirCon),
|
||||
cv.Optional(CONF_PERIOD, default="7s"): cv.time_period,
|
||||
@@ -426,10 +433,20 @@ async def to_code(config):
|
||||
cg.add(var.set_supported_swing_modes(config[CONF_SUPPORTED_SWING_MODES]))
|
||||
if CONF_SUPPORTED_PRESETS in config:
|
||||
cg.add(var.set_supported_presets(config[CONF_SUPPORTED_PRESETS]))
|
||||
if CONF_CUSTOM_PRESETS in config:
|
||||
cg.add(var.set_custom_presets(config[CONF_CUSTOM_PRESETS]))
|
||||
if CONF_CUSTOM_FAN_MODES in config:
|
||||
cg.add(var.set_custom_fan_modes(config[CONF_CUSTOM_FAN_MODES]))
|
||||
if use_new_api():
|
||||
if CONF_CUSTOM_PRESETS in config:
|
||||
presets = config[CONF_CUSTOM_PRESETS]
|
||||
c_str_presets = [cg.RawExpression(f"aux_ac::Constants::{p}.c_str()") for p in presets]
|
||||
cg.add(var.set_custom_presets(c_str_presets))
|
||||
if CONF_CUSTOM_FAN_MODES in config:
|
||||
fan_modes = config[CONF_CUSTOM_FAN_MODES]
|
||||
c_str_fan_modes = [cg.RawExpression(f"aux_ac::Constants::{p}.c_str()") for p in fan_modes]
|
||||
cg.add(var.set_custom_fan_modes(c_str_fan_modes))
|
||||
else:
|
||||
if CONF_CUSTOM_PRESETS in config:
|
||||
cg.add(var.set_custom_presets(config[CONF_CUSTOM_PRESETS]))
|
||||
if CONF_CUSTOM_FAN_MODES in config:
|
||||
cg.add(var.set_custom_fan_modes(config[CONF_CUSTOM_FAN_MODES]))
|
||||
|
||||
|
||||
DISPLAY_ACTION_SCHEMA = maybe_simple_id(
|
||||
|
||||
@@ -2,29 +2,44 @@
|
||||
`Aux_ac` has been tested and works successfully with the air conditioners from the list below.<br/>
|
||||
Кондиционеры из списка ниже протестированы и точно совместимы с `aux_ac`.
|
||||
|
||||
+ ANDE (models: AND-12/FA+, AND-AMWM-H12(JA) / AND-AM2-H18/4DR3)
|
||||
+ Argo (models: Greenstyle 9000, Greenstyle 12000, Greenstyle 18000)
|
||||
+ AUX (models: ALMD-H48/5DR2 / AL-H48/5DR2(U), AMWM-H07/4R1 multisplit, AMWM-H12/4R3 multisplit, ASM-H12LL, ASM-H24LD, ASW-H07A4/DE-R1DI, ASW-H07A4/FP-R1DI, ASW-H09A4/FP-R1DI, ASW-H12A4/HA-R2DI, ASW-H09A4/LK-700R1, ASW-H09A4/LK-700R1DI, ASW-H12B4/JD-R2DI, ASW-H12A4/FAR1, ASW-H09B4/LK-700R1, ASW-H12C5C4/JOR3DI-B8, ASW-H12U3/JIR1DI-US, AUX-18QC/I / AUX-18QC/O, AWM-09G1V4-X, KFR-26GW/BpHRB+3, KFR-26GW/BpQYA2+2R3, KFR-26GW/BpQYD2+2R3, KFR-26GW/BpR3QYA1+1, KFR-26GW/BpR3QYD1+1, KFR-26GW/BpR3QYQ1+1, KFR-26GW/BpR3QYQ2+2, KFR-35GW/BpQYA1+1R3, KFR-35GW/BpQYA2+2R3, KFR-35GW/BpQYD1+1R3, KFR-35GW/BpQYD2+2R3, KFR-35GW/BpR3QYQ1+1, KFR-35GW/BpR3QYQ2+2 (see [issue #71](https://github.com/GrKoR/esphome_aux_ac_component/issues/71) for detais of `Aegean Sea`[爱琴海] AUX family AC connection)
|
||||
+ Ballu (models: BLC_CF-60HN1, BSUI-09HN8, BSUI-12HN8, BSUI-18HN8, BSW-09HN1, BSW-12HN1)
|
||||
+ Centek (models: CT-65A12, CT-65EDC07, CT-65F09, CT-65F12, CT-65FDC09, CT-65J09, CT-65J12, CT-65Q09, CT-65Q12, CT-65U13, CT-65V24, CT-65Z10, CT-65Z18)
|
||||
+ Arielli (models: ASW-H09B4/FGR3DI-EU)
|
||||
+ AUX (models: ALLD-H18/4R1C / AL-H18/4R1C(U), ALMD-H48/5DR2 / AL-H48/5DR2(U), ALMD-H24/4DR2A / AL-H24/4DR2A(U), AMWM-H07/4R1 multisplit, AMWM-H07/4R2(J) multisplit, AMWM-H12/4R2(J) multisplit, AMWM-H12/4R3 multisplit, ASM-H12LL, ASM-H24LD, ASW-12A3INV/SS, ASW-H07A4/DE-R1DI, ASW-H07A4/FP-R1DI, ASW-H07A4/JD-R1, ASW-H09A4/FP-R1DI, ASW-H09A4/LK-700R1, ASW-H09A4/LK-700R1DI, ASW-H09B4/LK-700R1, ASW-H09B7A4, ASW-H12A4/FAR1, ASW-H12A4/HA-R2DI, ASW-H12A4/JD-R2DI, ASW-H12B4/JD-R2DI, ASW-H12C5C4/JER3DI-B8-2, ASW-H12C5C4/JOR3DI-B8, ASW-H12U3/JIR1DI-US, ASW-H18A4/QH-R1DI / AS-H18A4/QH-R1DI, ASW-H18E3A4, AUX-07JO/I / AUX-M3-21LCLH multisplit, AUX-09CAA/I / ASW-H09A4/CAR3DI-C3, AUX-12JO/I / AUX-M3-21LCLH multisplit, AUX-12F3H, AUX-18QC/I / AUX-18QC/O, AWM-09G1V4-X, HA-18000BTU, KFR-26GW/BpHRB+3, KFR-26GW/BpQYA2+2R3, KFR-26GW/BpQYD2+2R3, KFR-26GW/BpR3QYA1+1, KFR-26GW/BpR3QYD1+1, KFR-26GW/BpR3QYQ1+1, KFR-26GW/BpR3QYQ2+2, KFR-35GW/BpQYA1+1R3, KFR-35GW/BpQYA2+2R3, KFR-35GW/BpQYD1+1R3, KFR-35GW/BpQYD2+2R3, KFR-35GW/BpR3QYQ1+1, KFR-35GW/BpR3QYQ2+2 (see [issue #71](https://github.com/GrKoR/esphome_aux_ac_component/issues/71) for detais of `Aegean Sea`[爱琴海] AUX family AC connection)
|
||||
+ Ballu (models: BLC_CF/in-60HN1 / BLC_O/out-60HN1, Orbis BPAC-08 OR/N6, BSUI/in-09HN8 / BSUI/out-09HN8, BSUI/in-12HN8 / BSUI/out-12HN8, BSUI/in-18HN8 / BSUI/out-18HN8, BSW/in-09HN1 / BSW/out-09HN1, BSW/in-12HN1 / BSW/out-12HN1, BSW/in-18HN1 / BSW/out-18HN1)
|
||||
+ Baymak (models: Elegant Plus 9, Elegant Plus 12)
|
||||
+ Centek (models: CT-65A09, CT-65A12, CT-65EDC07, CT-65F09, CT-65F12, CT-65FDC07, CT-65FDC09, CT-65J09, CT-65J12, CT-65J24, CT-65K07, CT-65Q09, CT-65Q12, CT-65RDC07, CT-65RDC09, CT-65RDC12, CT-65SDC07, CT-65SDC09, CT-65SDC18, CT-65U13, CT-65U18, CT-65V12, CT-65V24, CT-65X12, CT-65Z10, CT-65Z18)
|
||||
+ Costway (models: FP10318US-22WH, FP10524US-22WH)
|
||||
+ Dimstal (model: SMND-QC-12-J-Smart ECO)
|
||||
+ Elgin (models: HWFI09B2IA/ HWFE09B2NA)
|
||||
+ Energolux (models: SAS07L2-A, SAS07L4-A, SAS07M2-AI, SAS09B3-A, SAS09L4-A, SAS09Z4-AI, SAS12BN1-AI, SAS12CH1-AI, SAS12Z3-AI)
|
||||
+ Electrolux (models: EACS/I-07HSK/N3, EACS/I-09HIX-BLACK/N8)
|
||||
+ Elgin (models: HIFI09C2WA / HIFE09C2CA, HJFI12C2WB, HWFI09B2IA / HWFE09B2NA, HWFI30B2IA / HWFE30B2NA)
|
||||
+ Energolux (models: SAS07L2-A, SAS07L4-A, SAS07M2-AI, SAS09B3-A, SAS09L4-A, SAS09Z4-AI, SAS12BN1-AI, SAS09Z4-AI, SAS18Z4-AI)
|
||||
+ Fujico (models: ACF-I07AHRDN1)
|
||||
+ Hyundai (models: H-AR16-07H, H-AR21-07H, H-AR21-09H)
|
||||
+ iClima (models: ICI-09A/IUI-09A)
|
||||
+ Idea (models: ISR-12HR-SA7-DN1 ION)
|
||||
+ IGC (models: RAK-07NH multysplit, RAS-07AX/RAC-07AX, RAS-V09N2X/RAC-V09N2X)
|
||||
+ Ishimatsu (models: AVK-09I)
|
||||
+ IGC (models: RAK-07NH multysplit, RAS-07AX/RAC-07AX, RAS-V09N2X/RAC-V09N2X, RAS-V12NQR/RAC-V12NQR)
|
||||
+ IKON (models: ASW-H12C5C4/HCR3DI-B8)
|
||||
+ Ishimatsu (models: AVK-07I, AVK-09I)
|
||||
+ Loriot (models: LAC-09AS)
|
||||
+ Mirage (models: EWC121E - CWC121E)
|
||||
+ Osaka (models: STVP-12HH3)
|
||||
+ RCool (models: GRA12B0-KSZKLM641)
|
||||
+ Rinnai (models: RINV25RC)
|
||||
+ Roda (models: RS-AL09F, RS-AL24F)
|
||||
+ Rovex (models: RS-07ALS1, RS-09ALS1, RS-12ALS1)
|
||||
+ Royal Clima (models: CO-D 18HNI/CO-E 18HNI, RC-VNR29HN, RCI-SA30HN)
|
||||
+ Royal Clima (models: CO-D 18HNI/CO-E 18HNI, CO-D 24HNI/CO-E 24HNI, RC-VNR29HN, RC-RNC28HN, RCI-SA30HN)
|
||||
+ RVX (models: RS-12ALS)
|
||||
+ Samurai (models: SMA-07HRN1 ION, SMA-09HRN1 ION)
|
||||
+ Subtropic (models: SUB-07HN1, SUB-09HN1, SUB-12HN1)
|
||||
+ Scarlett (models: RRI-09-MPI)
|
||||
+ SEVRA (models: SEV-09JO)
|
||||
+ Subtropic (models: SUB/in-07HN1 / SUB/out-07HN1, SUB/in-09HN1 / SUB/out-09HN1, SUB/in-12HN1 / SUB/out-12HN1)
|
||||
+ Tesla (models: TA35FFML-12410M)
|
||||
+ Tornado (models: ISKA-INV-12 X WIFI EU)
|
||||
+ TOYOTOMI (models: SONZAI THN/THG-A35SZ)
|
||||
+ VOX (models: IVA5-12JR1, IJO09-SC4D)
|
||||
+ Vertex (models: Falcon-18A)
|
||||
+ VORTEX (models: VAI-A 1219F JMRV)
|
||||
+ VOX (models: IJO09-SC4D, IVA5-12JR1)
|
||||
+ Xigma (models: XG-SJ56RHA-IDU)
|
||||
+ Zephir (models: ZEL 12000BTU)
|
||||
+ Бирюса (models: B-07DPR/B-07DPQ, B-09FIR/B-09FIQ)
|
||||
|
||||
@@ -7,7 +7,8 @@ external_components:
|
||||
|
||||
esphome:
|
||||
name: $devicename
|
||||
platform: ESP8266
|
||||
|
||||
esp8266:
|
||||
board: esp12e
|
||||
|
||||
wifi:
|
||||
@@ -36,7 +37,8 @@ api:
|
||||
password: !secret api_pass
|
||||
|
||||
ota:
|
||||
password: !secret ota_pass
|
||||
- platform: esphome
|
||||
password: !secret ota_pass
|
||||
|
||||
web_server:
|
||||
port: 80
|
||||
|
||||
@@ -5,7 +5,8 @@ external_components:
|
||||
|
||||
esphome:
|
||||
name: aux_air_conditioner
|
||||
platform: ESP8266
|
||||
|
||||
esp8266:
|
||||
board: esp12e
|
||||
|
||||
# don't forget to set your's wifi settings!
|
||||
@@ -30,6 +31,7 @@ logger:
|
||||
api:
|
||||
|
||||
ota:
|
||||
- platform: esphome
|
||||
|
||||
# UART0 configuration for AUX air conditioner communication
|
||||
uart:
|
||||
|
||||
10
tests/.gitignore
vendored
10
tests/.gitignore
vendored
@@ -1,10 +0,0 @@
|
||||
# Gitignore settings for ESPHome
|
||||
# This is an example and may include too much for your use-case.
|
||||
# You can modify this file to suit your needs.
|
||||
/.esphome/
|
||||
**/.pioenvs/
|
||||
**/.piolibdeps/
|
||||
**/lib/
|
||||
**/src/
|
||||
**/platformio.ini
|
||||
/secrets.yaml
|
||||
@@ -1,191 +0,0 @@
|
||||
import time
|
||||
import aioesphomeapi
|
||||
import asyncio
|
||||
import re
|
||||
import sys
|
||||
import argparse
|
||||
from aioesphomeapi.api_pb2 import (LOG_LEVEL_NONE,
|
||||
LOG_LEVEL_ERROR,
|
||||
LOG_LEVEL_WARN,
|
||||
LOG_LEVEL_INFO,
|
||||
LOG_LEVEL_DEBUG,
|
||||
LOG_LEVEL_VERBOSE,
|
||||
LOG_LEVEL_VERY_VERBOSE)
|
||||
|
||||
def createParser ():
|
||||
parser = argparse.ArgumentParser(
|
||||
description='''This script is used for collecting logs from ac_aux ESPHome component.
|
||||
For more info, see https://github.com/GrKoR/ac_python_logger''',
|
||||
add_help = False)
|
||||
parent_group = parser.add_argument_group (title='Params')
|
||||
parent_group.add_argument ('--help', '-h', action='help', help='show this help message and exit')
|
||||
parent_group.add_argument ('-i', '--ip', nargs=1, required=True, help='IP address of the esphome device')
|
||||
parent_group.add_argument ('-p', '--pwd', nargs=1, required=True, help='native API password for the esphome device')
|
||||
return parser
|
||||
|
||||
async def main():
|
||||
"""Connect to an ESPHome device and wait for state changes."""
|
||||
api = aioesphomeapi.APIClient(namespace.ip[0], 6053, namespace.pwd[0])
|
||||
|
||||
try:
|
||||
await api.connect(login=True)
|
||||
except aioesphomeapi.InvalidAuthAPIError as e:
|
||||
return print(e)
|
||||
|
||||
print(api.api_version)
|
||||
|
||||
async def display_off():
|
||||
await api.execute_service(
|
||||
service,
|
||||
data={
|
||||
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||||
"data_buf": [0xBB, 0x00, 0x06, 0x80, 0x01, 0x00, 0x0F, 0x00, 0x01, 0x01, 0x97, 0xE0, 0x00, 0x20, 0x00, 0xC0, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x00],
|
||||
}
|
||||
)
|
||||
|
||||
async def display_on():
|
||||
await api.execute_service(
|
||||
service,
|
||||
data={
|
||||
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||||
"data_buf": [0xBB, 0x00, 0x06, 0x80, 0x01, 0x00, 0x0F, 0x00, 0x01, 0x01, 0x97, 0xE0, 0x00, 0x20, 0x00, 0xC0, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00],
|
||||
}
|
||||
)
|
||||
|
||||
async def ac_enable():
|
||||
await api.execute_service(
|
||||
service,
|
||||
data={
|
||||
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||||
"data_buf": [0xBB, 0x00, 0x06, 0x80, 0x00, 0x00, 0x0F, 0x00, 0x01, 0x00, 0x87, 0xE0, 0x2F, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00],
|
||||
}
|
||||
)
|
||||
|
||||
async def ac_disable():
|
||||
await api.execute_service(
|
||||
service,
|
||||
data={
|
||||
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||||
"data_buf": [0xBB, 0x00, 0x06, 0x80, 0x00, 0x00, 0x0F, 0x00, 0x01, 0x00, 0x87, 0xE0, 0x2F, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
|
||||
}
|
||||
)
|
||||
|
||||
async def ac_get11_01():
|
||||
await api.execute_service(
|
||||
service,
|
||||
data={
|
||||
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||||
"data_buf": [0xBB, 0x00, 0x06, 0x80, 0x00, 0x00, 0x02, 0x00, 0x11, 0x01],
|
||||
}
|
||||
)
|
||||
|
||||
async def ac_get11_00():
|
||||
await api.execute_service(
|
||||
service,
|
||||
data={
|
||||
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||||
"data_buf": [0xBB, 0x00, 0x06, 0x80, 0x00, 0x00, 0x02, 0x00, 0x11, 0x00],
|
||||
}
|
||||
)
|
||||
|
||||
async def ac_set_vlouver(lvr):
|
||||
await api.execute_service(
|
||||
service,
|
||||
data={
|
||||
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||||
"data_buf": [0xBB, 0x00, 0x06, 0x80, 0x00, 0x00, 0x0F, 0x00, 0x01, 0x01, lvr, 0xE0, 0x00, 0x20, 0x00, 0xC0, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00],
|
||||
}
|
||||
)
|
||||
|
||||
async def ac_set_hlouver(lvr):
|
||||
await api.execute_service(
|
||||
service,
|
||||
data={
|
||||
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||||
"data_buf": [0xBB, 0x00, 0x06, 0x80, 0x00, 0x00, 0x0F, 0x00, 0x01, 0x01, 0x97, lvr, 0x00, 0x20, 0x00, 0xC0, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00],
|
||||
}
|
||||
)
|
||||
|
||||
# key надо искать в выводе list_entities_services
|
||||
service = aioesphomeapi.UserService(
|
||||
name="send_data",
|
||||
key=311254518,
|
||||
args=[
|
||||
aioesphomeapi.UserServiceArg(name="data_buf", type=aioesphomeapi.UserServiceArgType.INT_ARRAY),
|
||||
],
|
||||
)
|
||||
|
||||
time.sleep(7)
|
||||
await ac_get11_00()
|
||||
time.sleep(7)
|
||||
await ac_get11_01()
|
||||
|
||||
#await ac_set_vlouver( 0b10010000 ) # swing on
|
||||
#await ac_set_vlouver( 0b10010111 ) # swing off
|
||||
#await ac_set_vlouver( 0b10010001 ) # 1
|
||||
#await ac_set_vlouver( 0b10010010 ) # 2
|
||||
#await ac_set_vlouver( 0b10010011 ) # 3
|
||||
#await ac_set_vlouver( 0b10010100 ) # 4
|
||||
#await ac_set_vlouver( 0b10010101 ) # 5
|
||||
#await ac_set_vlouver( 0b10010110 ) # не работает, сбрасывает на swing on
|
||||
#time.sleep(5)
|
||||
|
||||
#await ac_set_hlouver( 0b00000000 ) # swing on
|
||||
#await ac_set_hlouver( 0b11100000 ) # swing off
|
||||
#await ac_set_hlouver( 0b00100000 ) # не работает, сбрасывает в swing off
|
||||
#await ac_set_hlouver( 0b01000000 ) # не работает, сбрасывает в swing off
|
||||
#await ac_set_hlouver( 0b01100000 ) # не работает, сбрасывает в swing off
|
||||
#await ac_set_hlouver( 0b10000000 ) # не работает, сбрасывает в swing off
|
||||
#await ac_set_hlouver( 0b10100000 ) # не работает, сбрасывает в swing off
|
||||
#await ac_set_hlouver( 0b11000000 ) # не работает, сбрасывает в swing off
|
||||
#time.sleep(5)
|
||||
|
||||
async def test_byte(bt):
|
||||
await api.execute_service(
|
||||
service,
|
||||
data={
|
||||
#display on
|
||||
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||||
#"data_buf": [0xBB, 0x00, 0x06, 0x80, 0x00, 0x00, 0x0F, 0x00, 0x01, 0x01, 0x97, 0xE0, 0x00, 0x20, 0x00, 0xC0, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00],
|
||||
#display off
|
||||
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||||
"data_buf": [0xBB, 0x00, 0x06, 0x80, 0x00, 0x00, 0x0F, 0x00, 0x01, 0x01, 0x97, 0xE0, 0x00, 0x20, 0x00, 0xC0, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x00],
|
||||
# swing on
|
||||
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||||
#"data_buf": [0xBB, 0x00, 0x06, 0x80, 0x00, 0x00, 0x0F, 0x00, 0x01, 0x01, 0x90, 0xE0, 0x00, 0x20, 0x00, 0xC0, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00],
|
||||
# swing off
|
||||
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||||
#"data_buf": [0xBB, 0x00, 0x06, 0x80, 0x00, 0x00, 0x0F, 0x00, 0x01, 0x01, 0x97, 0xE0, 0x00, 0x20, 0x00, 0xC0, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00],
|
||||
}
|
||||
)
|
||||
'''
|
||||
не проходит команда, если байт 1 или 7 не 0x00
|
||||
не проходит команда, если байт 3 не 0x80
|
||||
|
||||
проходит и не меняется, если меняю байт 4 или 5
|
||||
'''
|
||||
|
||||
#await test_byte(0b10000110)
|
||||
#await test_byte(0b01000110)
|
||||
#await test_byte(0b00100110)
|
||||
#await test_byte(0b00010110)
|
||||
time.sleep(2)
|
||||
|
||||
|
||||
parser = createParser()
|
||||
namespace = parser.parse_args()
|
||||
print("IP: ", namespace.ip[0])
|
||||
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
try:
|
||||
#asyncio.ensure_future(main())
|
||||
#loop.run_forever()
|
||||
loop.run_until_complete(main())
|
||||
except aioesphomeapi.InvalidAuthAPIError as e:
|
||||
print(e)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
finally:
|
||||
loop.close()
|
||||
pass
|
||||
@@ -1,121 +0,0 @@
|
||||
external_components:
|
||||
- source: github://GrKoR/esphome_aux_ac_component@dev
|
||||
components: [ aux_ac ]
|
||||
refresh: 0s
|
||||
|
||||
substitutions:
|
||||
devicename: test_aux_ac_ext_esp32
|
||||
upper_devicename: Test AUX
|
||||
|
||||
esphome:
|
||||
name: $devicename
|
||||
platform: ESP32
|
||||
board: nodemcu-32s
|
||||
|
||||
wifi:
|
||||
ssid: !secret wifi_ssid
|
||||
password: !secret wifi_pass
|
||||
manual_ip:
|
||||
static_ip: 192.168.0.151 # Для примера
|
||||
gateway: !secret wifi_gateway
|
||||
subnet: !secret wifi_subnet
|
||||
dns1: 8.8.8.8
|
||||
dns2: 1.1.1.1
|
||||
reboot_timeout: 0s
|
||||
ap:
|
||||
ssid: Test AUX Fallback Hotspot
|
||||
password: !secret wifi_ap_pass
|
||||
|
||||
logger:
|
||||
level: DEBUG
|
||||
baud_rate: 0
|
||||
|
||||
api:
|
||||
password: !secret api_pass
|
||||
reboot_timeout: 0s
|
||||
|
||||
ota:
|
||||
password: !secret ota_pass
|
||||
|
||||
uart:
|
||||
id: ac_uart_bus
|
||||
#tx_pin: GPIO1
|
||||
#rx_pin: GPIO3
|
||||
tx_pin: TX
|
||||
rx_pin: RX
|
||||
baud_rate: 4800
|
||||
data_bits: 8
|
||||
parity: EVEN
|
||||
stop_bits: 1
|
||||
|
||||
sensor:
|
||||
- platform: uptime
|
||||
name: Uptime Sensor
|
||||
|
||||
climate:
|
||||
- platform: aux_ac
|
||||
name: $upper_devicename
|
||||
id: aux_id
|
||||
uart_id: ac_uart_bus
|
||||
period: 7s
|
||||
show_action: true
|
||||
display_inverted: true
|
||||
indoor_temperature:
|
||||
name: $upper_devicename Indoor Temperature
|
||||
id: ${devicename}_indoor_temp
|
||||
internal: false
|
||||
display_state:
|
||||
name: $upper_devicename Display State
|
||||
id: ${devicename}_display_state
|
||||
internal: false
|
||||
outdoor_temperature:
|
||||
name: $upper_devicename Outdoor Temperature
|
||||
id: ${devicename}_outdoor_temp
|
||||
internal: false
|
||||
outbound_temperature:
|
||||
name: $upper_devicename Coolant Outbound Temperature
|
||||
id: ${devicename}_outbound_temp
|
||||
internal: false
|
||||
inbound_temperature:
|
||||
name: $upper_devicename Coolant Inbound Temperature
|
||||
id: ${devicename}_inbound_temp
|
||||
internal: false
|
||||
compressor_temperature:
|
||||
name: $upper_devicename Compressor Temperature
|
||||
id: ${devicename}_strange_temp
|
||||
internal: false
|
||||
defrost_state:
|
||||
name: $upper_devicename Defrost State
|
||||
id: ${devicename}_defrost_state
|
||||
internal: false
|
||||
inverter_power:
|
||||
name: $upper_devicename Invertor Power
|
||||
id: ${devicename}_invertor_power
|
||||
internal: false
|
||||
preset_reporter:
|
||||
name: $upper_devicename Preset Reporter
|
||||
id: ${devicename}_preset_reporter
|
||||
internal: false
|
||||
visual:
|
||||
min_temperature: 16
|
||||
max_temperature: 32
|
||||
temperature_step: 0.5
|
||||
supported_modes:
|
||||
- HEAT_COOL
|
||||
- COOL
|
||||
- HEAT
|
||||
- DRY
|
||||
- FAN_ONLY
|
||||
custom_fan_modes:
|
||||
- MUTE
|
||||
- TURBO
|
||||
supported_presets:
|
||||
- SLEEP
|
||||
custom_presets:
|
||||
- CLEAN
|
||||
- HEALTH
|
||||
- ANTIFUNGUS
|
||||
supported_swing_modes:
|
||||
- VERTICAL
|
||||
- HORIZONTAL
|
||||
- BOTH
|
||||
@@ -1,156 +0,0 @@
|
||||
external_components:
|
||||
- source: github://GrKoR/esphome_aux_ac_component@dev
|
||||
components: [ aux_ac ]
|
||||
refresh: 0s
|
||||
|
||||
substitutions:
|
||||
devicename: test_aux_ac_ext_engeneer
|
||||
upper_devicename: Test AUX
|
||||
|
||||
esphome:
|
||||
name: $devicename
|
||||
platform: ESP8266
|
||||
board: esp12e
|
||||
|
||||
wifi:
|
||||
ssid: !secret wifi_ssid
|
||||
password: !secret wifi_pass
|
||||
manual_ip:
|
||||
static_ip: !secret wifi_ip
|
||||
gateway: !secret wifi_gateway
|
||||
subnet: !secret wifi_subnet
|
||||
dns1: 8.8.8.8
|
||||
dns2: 1.1.1.1
|
||||
reboot_timeout: 0s
|
||||
ap:
|
||||
ssid: Test AUX Fallback Hotspot
|
||||
password: !secret wifi_ap_pass
|
||||
|
||||
logger:
|
||||
level: DEBUG
|
||||
baud_rate: 0
|
||||
|
||||
api:
|
||||
password: !secret api_pass
|
||||
reboot_timeout: 0s
|
||||
services:
|
||||
# этот сервис можно вызвать из Home Assistant или Python. Он отправляет полученные байты в кондиционер
|
||||
- service: send_data
|
||||
variables:
|
||||
data_buf: int[]
|
||||
then:
|
||||
# ВАЖНО! Только для инженеров!
|
||||
# Вызывайте метод aux_ac.send_packet только если понимаете, что делаете! Он не проверяет данные, а передаёт
|
||||
# кондиционеру всё как есть. Какой эффект получится от передачи кондиционеру рандомных байт, никто не знает.
|
||||
# Вы действуете на свой страх и риск.
|
||||
- aux_ac.send_packet:
|
||||
id: aux_id
|
||||
data: !lambda |-
|
||||
std::vector<uint8_t> data{};
|
||||
for (int n : data_buf) {
|
||||
data.push_back( (uint8_t) n );
|
||||
}
|
||||
return data;
|
||||
|
||||
ota:
|
||||
password: !secret ota_pass
|
||||
|
||||
web_server:
|
||||
port: 80
|
||||
|
||||
uart:
|
||||
id: ac_uart_bus
|
||||
tx_pin: GPIO1
|
||||
rx_pin: GPIO3
|
||||
baud_rate: 4800
|
||||
data_bits: 8
|
||||
parity: EVEN
|
||||
stop_bits: 1
|
||||
|
||||
sensor:
|
||||
- platform: uptime
|
||||
name: Uptime Sensor
|
||||
|
||||
climate:
|
||||
- platform: aux_ac
|
||||
name: $upper_devicename
|
||||
id: aux_id
|
||||
uart_id: ac_uart_bus
|
||||
period: 7s
|
||||
show_action: true
|
||||
display_inverted: true
|
||||
optimistic: true
|
||||
indoor_temperature:
|
||||
name: $upper_devicename Indoor Temperature
|
||||
id: ${devicename}_indoor_temp
|
||||
internal: false
|
||||
display_state:
|
||||
name: $upper_devicename Display State
|
||||
id: ${devicename}_display_state
|
||||
internal: false
|
||||
outdoor_temperature:
|
||||
name: $upper_devicename Outdoor Temperature
|
||||
id: ${devicename}_outdoor_temp
|
||||
internal: false
|
||||
outbound_temperature:
|
||||
name: $upper_devicename Coolant Outbound Temperature
|
||||
id: ${devicename}_outbound_temp
|
||||
internal: false
|
||||
inbound_temperature:
|
||||
name: $upper_devicename Coolant Inbound Temperature
|
||||
id: ${devicename}_inbound_temp
|
||||
internal: false
|
||||
compressor_temperature:
|
||||
name: $upper_devicename Compressor Temperature
|
||||
id: ${devicename}_strange_temp
|
||||
internal: false
|
||||
defrost_state:
|
||||
name: $upper_devicename Defrost State
|
||||
id: ${devicename}_defrost_state
|
||||
internal: false
|
||||
inverter_power:
|
||||
name: $upper_devicename Invertor Power
|
||||
id: ${devicename}_invertor_power
|
||||
internal: false
|
||||
preset_reporter:
|
||||
name: $upper_devicename Preset Reporter
|
||||
id: ${devicename}_preset_reporter
|
||||
internal: false
|
||||
visual:
|
||||
min_temperature: 16
|
||||
max_temperature: 32
|
||||
temperature_step: 0.5
|
||||
supported_modes:
|
||||
- HEAT_COOL
|
||||
- COOL
|
||||
- HEAT
|
||||
- DRY
|
||||
- FAN_ONLY
|
||||
custom_fan_modes:
|
||||
- MUTE
|
||||
- TURBO
|
||||
supported_presets:
|
||||
- SLEEP
|
||||
custom_presets:
|
||||
- CLEAN
|
||||
- HEALTH
|
||||
- ANTIFUNGUS
|
||||
supported_swing_modes:
|
||||
- VERTICAL
|
||||
- HORIZONTAL
|
||||
- BOTH
|
||||
|
||||
|
||||
switch:
|
||||
- platform: template
|
||||
name: AC Display
|
||||
lambda: |-
|
||||
if (id(${devicename}_display_state).state) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
turn_on_action:
|
||||
- aux_ac.display_on: aux_id
|
||||
turn_off_action:
|
||||
- aux_ac.display_off: aux_id
|
||||
@@ -1,162 +0,0 @@
|
||||
external_components:
|
||||
- source: github://GrKoR/esphome_aux_ac_component@dev
|
||||
components: [ aux_ac ]
|
||||
refresh: 0s
|
||||
|
||||
substitutions:
|
||||
devicename: test_ext_power_limitations
|
||||
upper_devicename: Test AUX
|
||||
|
||||
esphome:
|
||||
name: $devicename
|
||||
platform: ESP8266
|
||||
board: esp12e
|
||||
|
||||
wifi:
|
||||
ssid: !secret wifi_ssid
|
||||
password: !secret wifi_pass
|
||||
manual_ip:
|
||||
static_ip: !secret wifi_ip
|
||||
gateway: !secret wifi_gateway
|
||||
subnet: !secret wifi_subnet
|
||||
dns1: 8.8.8.8
|
||||
dns2: 1.1.1.1
|
||||
reboot_timeout: 0s
|
||||
ap:
|
||||
ssid: Test AUX Fallback Hotspot
|
||||
password: !secret wifi_ap_pass
|
||||
|
||||
logger:
|
||||
level: DEBUG
|
||||
baud_rate: 0
|
||||
|
||||
api:
|
||||
password: !secret api_pass
|
||||
reboot_timeout: 0s
|
||||
|
||||
ota:
|
||||
password: !secret ota_pass
|
||||
|
||||
web_server:
|
||||
port: 80
|
||||
|
||||
uart:
|
||||
id: ac_uart_bus
|
||||
tx_pin: GPIO1
|
||||
rx_pin: GPIO3
|
||||
baud_rate: 4800
|
||||
data_bits: 8
|
||||
parity: EVEN
|
||||
stop_bits: 1
|
||||
|
||||
sensor:
|
||||
- platform: uptime
|
||||
name: Uptime Sensor
|
||||
|
||||
climate:
|
||||
- platform: aux_ac
|
||||
name: $upper_devicename
|
||||
id: aux_id
|
||||
uart_id: ac_uart_bus
|
||||
period: 7s
|
||||
show_action: true
|
||||
display_inverted: true
|
||||
timeout: 150
|
||||
indoor_temperature:
|
||||
name: $upper_devicename Indoor Temperature
|
||||
id: ${devicename}_indoor_temp
|
||||
internal: false
|
||||
display_state:
|
||||
name: $upper_devicename Display State
|
||||
id: ${devicename}_display_state
|
||||
internal: false
|
||||
outdoor_temperature:
|
||||
name: $upper_devicename Outdoor Temperature
|
||||
id: ${devicename}_outdoor_temp
|
||||
internal: false
|
||||
outbound_temperature:
|
||||
name: $upper_devicename Coolant Outbound Temperature
|
||||
id: ${devicename}_outbound_temp
|
||||
internal: false
|
||||
inbound_temperature:
|
||||
name: $upper_devicename Coolant Inbound Temperature
|
||||
id: ${devicename}_inbound_temp
|
||||
internal: false
|
||||
compressor_temperature:
|
||||
name: $upper_devicename Compressor Temperature
|
||||
id: ${devicename}_strange_temp
|
||||
internal: false
|
||||
defrost_state:
|
||||
name: $upper_devicename Defrost State
|
||||
id: ${devicename}_defrost_state
|
||||
internal: false
|
||||
inverter_power:
|
||||
name: $upper_devicename Inverter Power
|
||||
id: ${devicename}_invertor_power
|
||||
internal: false
|
||||
preset_reporter:
|
||||
name: $upper_devicename Preset Reporter
|
||||
id: ${devicename}_preset_reporter
|
||||
internal: false
|
||||
inverter_power_limit_value:
|
||||
name: $upper_devicename Inverter Power Limit Value
|
||||
id: ${devicename}_inverter_power_limit_value
|
||||
internal: false
|
||||
inverter_power_limit_state:
|
||||
name: $upper_devicename Inverter Power Limit State
|
||||
id: ${devicename}_inverter_power_limit_state
|
||||
internal: false
|
||||
visual:
|
||||
min_temperature: 16
|
||||
max_temperature: 32
|
||||
temperature_step: 0.5
|
||||
supported_modes:
|
||||
- HEAT_COOL
|
||||
- COOL
|
||||
- HEAT
|
||||
- DRY
|
||||
- FAN_ONLY
|
||||
custom_fan_modes:
|
||||
- MUTE
|
||||
- TURBO
|
||||
supported_presets:
|
||||
- SLEEP
|
||||
custom_presets:
|
||||
- CLEAN
|
||||
- HEALTH
|
||||
- ANTIFUNGUS
|
||||
supported_swing_modes:
|
||||
- VERTICAL
|
||||
- HORIZONTAL
|
||||
- BOTH
|
||||
|
||||
|
||||
button:
|
||||
- platform: template
|
||||
name: ${upper_devicename} IPower Limit Off
|
||||
icon: "mdi:power-plug-off-outline"
|
||||
on_press:
|
||||
- aux_ac.power_limit_off: aux_id
|
||||
|
||||
- platform: template
|
||||
name: ${upper_devicename} IPower Limit On Half
|
||||
icon: "mdi:fraction-one-half"
|
||||
on_press:
|
||||
- aux_ac.power_limit_on:
|
||||
id: aux_id
|
||||
limit: 50
|
||||
|
||||
number:
|
||||
- platform: template
|
||||
name: ${upper_devicename} IPower Limit Value
|
||||
id: ${devicename}_ipower_limit_value
|
||||
icon: "mdi:battery-unknown"
|
||||
mode: "slider"
|
||||
min_value: 30
|
||||
max_value: 100
|
||||
step: 1
|
||||
set_action:
|
||||
then:
|
||||
- lambda: !lambda |-
|
||||
id(aux_id).powerLimitationOnSequence( x );
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
external_components:
|
||||
- source:
|
||||
type: local
|
||||
path: ../components
|
||||
|
||||
substitutions:
|
||||
devicename: test_local_airflow_dir
|
||||
upper_devicename: Test AUX
|
||||
|
||||
esphome:
|
||||
name: $devicename
|
||||
platform: ESP8266
|
||||
board: esp12e
|
||||
|
||||
wifi:
|
||||
ssid: !secret wifi_ssid
|
||||
password: !secret wifi_pass
|
||||
manual_ip:
|
||||
static_ip: !secret wifi_ip
|
||||
gateway: !secret wifi_gateway
|
||||
subnet: !secret wifi_subnet
|
||||
dns1: 8.8.8.8
|
||||
dns2: 1.1.1.1
|
||||
reboot_timeout: 0s
|
||||
ap:
|
||||
ssid: $upper_devicename Fallback Hotspot
|
||||
password: !secret wifi_ap_pass
|
||||
|
||||
logger:
|
||||
level: DEBUG
|
||||
baud_rate: 0
|
||||
|
||||
api:
|
||||
password: !secret api_pass
|
||||
reboot_timeout: 0s
|
||||
|
||||
ota:
|
||||
password: !secret ota_pass
|
||||
|
||||
web_server:
|
||||
port: 80
|
||||
|
||||
uart:
|
||||
id: ac_uart_bus
|
||||
tx_pin: GPIO1
|
||||
rx_pin: GPIO3
|
||||
baud_rate: 4800
|
||||
data_bits: 8
|
||||
parity: EVEN
|
||||
stop_bits: 1
|
||||
|
||||
|
||||
sensor:
|
||||
- platform: uptime
|
||||
name: Uptime Sensor
|
||||
|
||||
|
||||
climate:
|
||||
- platform: aux_ac
|
||||
name: $upper_devicename
|
||||
id: aux_id
|
||||
uart_id: ac_uart_bus
|
||||
period: 7s
|
||||
show_action: true
|
||||
display_inverted: true
|
||||
|
||||
|
||||
button:
|
||||
- platform: template
|
||||
name: ${upper_devicename} VLouver Stop
|
||||
icon: "mdi:circle-small"
|
||||
on_press:
|
||||
- aux_ac.vlouver_stop: aux_id
|
||||
|
||||
- platform: template
|
||||
name: ${upper_devicename} VLouver Swing
|
||||
icon: "mdi:pan-vertical"
|
||||
on_press:
|
||||
- aux_ac.vlouver_swing: aux_id
|
||||
|
||||
- platform: template
|
||||
name: ${upper_devicename} VLouver Top
|
||||
icon: "mdi:pan-up"
|
||||
on_press:
|
||||
- aux_ac.vlouver_top: aux_id
|
||||
|
||||
- platform: template
|
||||
name: ${upper_devicename} VLouver Middle Above
|
||||
icon: "mdi:pan-top-left"
|
||||
on_press:
|
||||
- aux_ac.vlouver_middle_above: aux_id
|
||||
|
||||
- platform: template
|
||||
name: ${upper_devicename} VLouver Middle
|
||||
icon: "mdi:pan-left"
|
||||
on_press:
|
||||
- aux_ac.vlouver_middle: aux_id
|
||||
|
||||
- platform: template
|
||||
name: ${upper_devicename} VLouver Middle Below
|
||||
icon: "mdi:pan-bottom-left"
|
||||
on_press:
|
||||
- aux_ac.vlouver_middle_below: aux_id
|
||||
|
||||
- platform: template
|
||||
name: ${upper_devicename} VLouver Bottom
|
||||
icon: "mdi:pan-down"
|
||||
on_press:
|
||||
- aux_ac.vlouver_bottom: aux_id
|
||||
|
||||
|
||||
number:
|
||||
- platform: template
|
||||
name: ${upper_devicename} Vertical Louver
|
||||
id: ${devicename}_vlouver
|
||||
icon: "mdi:circle-small"
|
||||
mode: "slider"
|
||||
min_value: 0
|
||||
max_value: 6
|
||||
step: 1
|
||||
set_action:
|
||||
then:
|
||||
- lambda: !lambda |-
|
||||
if (x == 6) x = 7; // делаем так, чтобы выключение отрабатывать корректно
|
||||
id(aux_id).setVLouverSequence( static_cast<esphome::aux_ac::ac_louver_V>(x) );
|
||||
@@ -1,162 +0,0 @@
|
||||
external_components:
|
||||
- source:
|
||||
type: local
|
||||
path: ../components
|
||||
|
||||
substitutions:
|
||||
devicename: test_local_power_limitations
|
||||
upper_devicename: Test AUX
|
||||
|
||||
esphome:
|
||||
name: $devicename
|
||||
platform: ESP8266
|
||||
board: esp12e
|
||||
|
||||
wifi:
|
||||
ssid: !secret wifi_ssid
|
||||
password: !secret wifi_pass
|
||||
manual_ip:
|
||||
static_ip: !secret wifi_ip
|
||||
gateway: !secret wifi_gateway
|
||||
subnet: !secret wifi_subnet
|
||||
dns1: 8.8.8.8
|
||||
dns2: 1.1.1.1
|
||||
reboot_timeout: 0s
|
||||
ap:
|
||||
ssid: Test AUX Fallback Hotspot
|
||||
password: !secret wifi_ap_pass
|
||||
|
||||
logger:
|
||||
level: DEBUG
|
||||
baud_rate: 0
|
||||
|
||||
api:
|
||||
password: !secret api_pass
|
||||
reboot_timeout: 0s
|
||||
|
||||
ota:
|
||||
password: !secret ota_pass
|
||||
|
||||
web_server:
|
||||
port: 80
|
||||
|
||||
uart:
|
||||
id: ac_uart_bus
|
||||
tx_pin: GPIO1
|
||||
rx_pin: GPIO3
|
||||
baud_rate: 4800
|
||||
data_bits: 8
|
||||
parity: EVEN
|
||||
stop_bits: 1
|
||||
|
||||
sensor:
|
||||
- platform: uptime
|
||||
name: Uptime Sensor
|
||||
|
||||
climate:
|
||||
- platform: aux_ac
|
||||
name: $upper_devicename
|
||||
id: aux_id
|
||||
uart_id: ac_uart_bus
|
||||
period: 7s
|
||||
show_action: true
|
||||
display_inverted: true
|
||||
timeout: 150
|
||||
indoor_temperature:
|
||||
name: $upper_devicename Indoor Temperature
|
||||
id: ${devicename}_indoor_temp
|
||||
internal: false
|
||||
display_state:
|
||||
name: $upper_devicename Display State
|
||||
id: ${devicename}_display_state
|
||||
internal: false
|
||||
outdoor_temperature:
|
||||
name: $upper_devicename Outdoor Temperature
|
||||
id: ${devicename}_outdoor_temp
|
||||
internal: false
|
||||
outbound_temperature:
|
||||
name: $upper_devicename Coolant Outbound Temperature
|
||||
id: ${devicename}_outbound_temp
|
||||
internal: false
|
||||
inbound_temperature:
|
||||
name: $upper_devicename Coolant Inbound Temperature
|
||||
id: ${devicename}_inbound_temp
|
||||
internal: false
|
||||
compressor_temperature:
|
||||
name: $upper_devicename Compressor Temperature
|
||||
id: ${devicename}_strange_temp
|
||||
internal: false
|
||||
defrost_state:
|
||||
name: $upper_devicename Defrost State
|
||||
id: ${devicename}_defrost_state
|
||||
internal: false
|
||||
inverter_power:
|
||||
name: $upper_devicename Inverter Power
|
||||
id: ${devicename}_invertor_power
|
||||
internal: false
|
||||
preset_reporter:
|
||||
name: $upper_devicename Preset Reporter
|
||||
id: ${devicename}_preset_reporter
|
||||
internal: false
|
||||
inverter_power_limit_value:
|
||||
name: $upper_devicename Inverter Power Limit Value
|
||||
id: ${devicename}_inverter_power_limit_value
|
||||
internal: false
|
||||
inverter_power_limit_state:
|
||||
name: $upper_devicename Inverter Power Limit State
|
||||
id: ${devicename}_inverter_power_limit_state
|
||||
internal: false
|
||||
visual:
|
||||
min_temperature: 16
|
||||
max_temperature: 32
|
||||
temperature_step: 0.5
|
||||
supported_modes:
|
||||
- HEAT_COOL
|
||||
- COOL
|
||||
- HEAT
|
||||
- DRY
|
||||
- FAN_ONLY
|
||||
custom_fan_modes:
|
||||
- MUTE
|
||||
- TURBO
|
||||
supported_presets:
|
||||
- SLEEP
|
||||
custom_presets:
|
||||
- CLEAN
|
||||
- HEALTH
|
||||
- ANTIFUNGUS
|
||||
supported_swing_modes:
|
||||
- VERTICAL
|
||||
- HORIZONTAL
|
||||
- BOTH
|
||||
|
||||
|
||||
button:
|
||||
- platform: template
|
||||
name: ${upper_devicename} IPower Limit Off
|
||||
icon: "mdi:power-plug-off-outline"
|
||||
on_press:
|
||||
- aux_ac.power_limit_off: aux_id
|
||||
|
||||
- platform: template
|
||||
name: ${upper_devicename} IPower Limit On Half
|
||||
icon: "mdi:fraction-one-half"
|
||||
on_press:
|
||||
- aux_ac.power_limit_on:
|
||||
id: aux_id
|
||||
limit: 50
|
||||
|
||||
number:
|
||||
- platform: template
|
||||
name: ${upper_devicename} IPower Limit Value
|
||||
id: ${devicename}_ipower_limit_value
|
||||
icon: "mdi:battery-unknown"
|
||||
mode: "slider"
|
||||
min_value: 30
|
||||
max_value: 100
|
||||
step: 1
|
||||
set_action:
|
||||
then:
|
||||
- lambda: !lambda |-
|
||||
id(aux_id).powerLimitationOnSequence( x );
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
external_components:
|
||||
- source:
|
||||
type: local
|
||||
path: ../components
|
||||
|
||||
substitutions:
|
||||
devicename: test_local_airflow_dir
|
||||
upper_devicename: Test AUX
|
||||
|
||||
esphome:
|
||||
name: $devicename
|
||||
platform: ESP8266
|
||||
board: esp12e
|
||||
|
||||
wifi:
|
||||
ssid: !secret wifi_ssid
|
||||
password: !secret wifi_pass
|
||||
manual_ip:
|
||||
static_ip: !secret wifi_ip
|
||||
gateway: !secret wifi_gateway
|
||||
subnet: !secret wifi_subnet
|
||||
dns1: 8.8.8.8
|
||||
dns2: 1.1.1.1
|
||||
reboot_timeout: 0s
|
||||
ap:
|
||||
ssid: Test AUX Fallback Hotspot
|
||||
password: !secret wifi_ap_pass
|
||||
|
||||
logger:
|
||||
level: DEBUG
|
||||
baud_rate: 0
|
||||
|
||||
api:
|
||||
password: !secret api_pass
|
||||
reboot_timeout: 0s
|
||||
|
||||
ota:
|
||||
password: !secret ota_pass
|
||||
|
||||
web_server:
|
||||
port: 80
|
||||
|
||||
uart:
|
||||
id: ac_uart_bus
|
||||
tx_pin: GPIO1
|
||||
rx_pin: GPIO3
|
||||
baud_rate: 4800
|
||||
data_bits: 8
|
||||
parity: EVEN
|
||||
stop_bits: 1
|
||||
|
||||
sensor:
|
||||
- platform: uptime
|
||||
name: Uptime Sensor
|
||||
|
||||
climate:
|
||||
- platform: aux_ac
|
||||
name: $upper_devicename
|
||||
id: aux_id
|
||||
uart_id: ac_uart_bus
|
||||
period: 7s
|
||||
show_action: true
|
||||
display_inverted: true
|
||||
optimistic: true
|
||||
indoor_temperature:
|
||||
name: $upper_devicename Indoor Temperature
|
||||
id: ${devicename}_indoor_temp
|
||||
internal: false
|
||||
display_state:
|
||||
name: $upper_devicename Display State
|
||||
id: ${devicename}_display_state
|
||||
internal: false
|
||||
outdoor_temperature:
|
||||
name: $upper_devicename Outdoor Temperature
|
||||
id: ${devicename}_outdoor_temp
|
||||
internal: false
|
||||
outbound_temperature:
|
||||
name: $upper_devicename Coolant Outbound Temperature
|
||||
id: ${devicename}_outbound_temp
|
||||
internal: false
|
||||
inbound_temperature:
|
||||
name: $upper_devicename Coolant Inbound Temperature
|
||||
id: ${devicename}_inbound_temp
|
||||
internal: false
|
||||
compressor_temperature:
|
||||
name: $upper_devicename Compressor Temperature
|
||||
id: ${devicename}_strange_temp
|
||||
internal: false
|
||||
defrost_state:
|
||||
name: $upper_devicename Defrost State
|
||||
id: ${devicename}_defrost_state
|
||||
internal: false
|
||||
inverter_power:
|
||||
name: $upper_devicename Invertor Power
|
||||
id: ${devicename}_invertor_power
|
||||
internal: false
|
||||
preset_reporter:
|
||||
name: $upper_devicename Preset Reporter
|
||||
id: ${devicename}_preset_reporter
|
||||
internal: false
|
||||
visual:
|
||||
min_temperature: 16
|
||||
max_temperature: 32
|
||||
temperature_step: 0.5
|
||||
supported_modes:
|
||||
- HEAT_COOL
|
||||
- COOL
|
||||
- HEAT
|
||||
- DRY
|
||||
- FAN_ONLY
|
||||
custom_fan_modes:
|
||||
- MUTE
|
||||
- TURBO
|
||||
supported_presets:
|
||||
- SLEEP
|
||||
custom_presets:
|
||||
- CLEAN
|
||||
- HEALTH
|
||||
- ANTIFUNGUS
|
||||
supported_swing_modes:
|
||||
- VERTICAL
|
||||
- HORIZONTAL
|
||||
- BOTH
|
||||
@@ -1,48 +0,0 @@
|
||||
external_components:
|
||||
- source:
|
||||
type: local
|
||||
path: ../components
|
||||
#- source: github://GrKoR/esphome_aux_ac_component@dev
|
||||
#components: [ aux_ac ]
|
||||
#refresh: 0s
|
||||
|
||||
substitutions:
|
||||
devicename: test_local_minimal
|
||||
upper_devicename: Test AUX
|
||||
|
||||
esphome:
|
||||
name: $devicename
|
||||
platform: ESP8266
|
||||
board: esp12e
|
||||
|
||||
wifi:
|
||||
ssid: !secret wifi_ssid
|
||||
password: !secret wifi_pass
|
||||
reboot_timeout: 0s
|
||||
ap:
|
||||
ssid: $upper_devicename Fallback Hotspot
|
||||
password: !secret wifi_ap_pass
|
||||
|
||||
logger:
|
||||
level: DEBUG
|
||||
baud_rate: 0
|
||||
|
||||
api:
|
||||
password: !secret api_pass
|
||||
reboot_timeout: 0s
|
||||
|
||||
ota:
|
||||
password: !secret ota_pass
|
||||
|
||||
uart:
|
||||
id: ac_uart_bus
|
||||
tx_pin: GPIO1
|
||||
rx_pin: GPIO3
|
||||
baud_rate: 4800
|
||||
data_bits: 8
|
||||
parity: EVEN
|
||||
stop_bits: 1
|
||||
|
||||
climate:
|
||||
- platform: aux_ac
|
||||
name: $upper_devicename
|
||||
Reference in New Issue
Block a user