108 Commits

Author SHA1 Message Date
GrKoR
577eac89c8 unfinished 2025-11-25 18:59:00 -08:00
GrKoR
fa3bdf21db initial: clean up 2025-08-28 15:55:46 -07:00
GrKoR
c959d7be7e new AC tested: Elgin HWFI30B2IA / HWFE30B2NA 2025-08-04 18:51:33 -07:00
GrKoR
60d6f56fcf upd: version++, CLIMATE_SCHEMA warning fixed 2025-06-30 22:54:30 -07:00
GK
a8eba8882e fix (#152): WARNING Using climate.CLIMATE_SCHEMA is deprecated (PR #174) 2025-06-30 22:51:44 -07:00
GrKoR
96455e5882 fix (#152): WARNING Using climate.CLIMATE_SCHEMA is deprecated 2025-06-30 22:47:39 -07:00
GrKoR
89db23434b fix: exclude local tests from repo 2025-06-30 22:36:59 -07:00
GK
945d2603f1 Merge pull request #173 from GrKoR/esp-idf-support
Esp idf support
2025-06-30 22:05:56 -07:00
GrKoR
6291828cec Merge branch 'master' into esp-idf-support 2025-06-30 22:05:18 -07:00
GrKoR
8dc9f0f478 New ACs tested: Elgin HIFI09C2WA / HIFE09C2CA and Elgin HJFI12C2WB 2025-06-30 20:45:29 -07:00
GK
03e0ee0d9a Merge pull request #172 from GrKoR/GrKoR/issue145
a list of new tested ACs
2025-06-30 19:56:54 -07:00
GrKoR
848fd8f6c1 New AC tested: VORTEX VAI-A 1219F JMRV 2025-06-30 19:55:04 -07:00
GrKoR
e77d49c52a New AC tested: SEVRA SEV-09JO 2025-06-30 19:49:39 -07:00
GrKoR
42fd8d5ba1 New AC tested: Centek CT-65J24 2025-06-30 19:36:39 -07:00
GrKoR
00aa426bfc New AC tested: Centek CT-65FDC07 2025-06-30 19:32:38 -07:00
GrKoR
029d92be96 New AC tested: IGC Freddo S DC Inverter RAS-V12NQR / RAC-V12NQR 2025-06-30 19:29:39 -07:00
GrKoR
d1e64af8a4 New AC tested: Fujico ACF-I07AHRDN1 2025-06-30 19:26:57 -07:00
GrKoR
d238c8b661 New AC tested: AUX ALLD-H18/4R1C / AL-H18/4R1C(U) 2025-06-30 19:24:00 -07:00
GrKoR
140447ceab New AC tested: Royal Clima Renaissance RC-RNC28HN 2025-06-30 19:17:15 -07:00
GrKoR
6920102969 New AC tested: Royal Clima CO-D 24HNI/CO-E 24HNI 2025-06-30 19:13:05 -07:00
GrKoR
f20f89cb93 New AC tested: Scarlett Comfort RRI-09-MPI 2025-06-30 19:06:53 -07:00
GrKoR
6a98c47ada New AC tested: Ballu Orbis BPAC-08 OR/N6 2025-06-30 18:54:19 -07:00
GrKoR
b5e88f7abc New AC tested: Ballu BSW/in-18HN1 / BSW/out-18HN1 2025-06-30 18:49:57 -07:00
GrKoR
a166d18ede New AC tested: Electrolux EACS/I-09HIX-BLACK/N8 2025-06-30 18:43:52 -07:00
GK
7de56fb656 Merge pull request #171 from GrKoR/GrKoR/issue145
New AC: Electrolux EACS/I-07HSK/N3_24Y SKANDI DC INVERTER
2025-06-30 18:34:14 -07:00
GrKoR
cf5c88662d New AC: Electrolux EACS/I-07HSK/N3_24Y SKANDI DC INVERTER
Fixes #145
2025-06-30 18:29:18 -07:00
GrKoR
a7d2a73802 upd: platform keyword was removed according to the esphome ver. 2025.2.0 + minor fixes 2025-02-20 22:20:45 -08:00
GrKoR
078a6b20cf new AC: Ishimatsu: AVK-07I 2025-02-20 21:35:21 -08:00
GrKoR
69eebdb8c8 new AC: AUX ASW-12A3INV/SS 2025-02-20 21:33:03 -08:00
GrKoR
fe00198764 new AC: AUX AUX-09CAA/I / ASW-H09A4/CAR3DI-C3 2025-02-20 21:30:08 -08:00
GrKoR
da5fcd5848 new AC: AUX ALMD-H24/4DR2A / AL-H24/4DR2A(U) 2025-02-20 21:26:42 -08:00
GrKoR
9d4930d290 new AC: AUX ASW-H18E3A4 2025-02-20 21:19:07 -08:00
GrKoR
26ae9c248c new AC: Costway FP10524US-22WH & FP10318US-22WH 2025-02-20 21:13:00 -08:00
GrKoR
e67898997d new AC: Baymak Elegant Plus 9 2025-02-20 21:04:03 -08:00
GrKoR
e158586268 new AC: Ande AND-AMWM-H12(JA) / AND-AM2-H18/4DR3 2025-02-20 20:58:32 -08:00
GrKoR
2d446f88e4 new AC: Arielli ASW-H09B4/FGR3DI-EU 2025-02-20 20:52:12 -08:00
GrKoR
5591b91f7b new AC: AUX AUX-12F3H 2025-02-20 20:48:27 -08:00
GrKoR
551c476549 new AC: Elgin HJFI12C2WB 2025-02-20 20:40:46 -08:00
GrKoR
bdbd1478b7 version++ 2024-10-26 23:25:36 +03:00
GrKoR
9c2daf0615 fix: esp8266 compatibility 2024-10-26 23:25:08 +03:00
GrKoR
3ca873450d fix: String class was changed to std::string as part of esp-idf support 2024-10-26 20:46:01 +03:00
GK
5e1b78df9f Merge pull request #131 from itay-sho/feature/support-esp-idf
feat: support esp-idf
2024-10-26 21:22:06 +04:00
GK
7a252e5955 new AC tested: AUX ASW-H09B7A4 2024-10-26 21:16:30 +04:00
GK
79f23c341d fix: Tornado AC typo 2024-10-26 21:14:25 +04:00
GK
360d274088 Merge pull request #132 from itay-sho/chore/add-tested-acs-to-the-list
docs: adding Tornado ISKA 12 WIFI to the list
2024-10-26 21:12:34 +04:00
Itay Shoshani
973f961e5f docs: adding Tornado ISKA 12 WIFI to the list
adding AUX ASW-H09B7A4 as well, since the tornado is just a sticker to the "real" model.
2024-10-26 17:25:29 +03:00
Itay Shoshani
cf990eb467 fix: using correct int types to reduce compilation warnings / errors
required due to the fact that esp32-c6 compiler raises errors due to that
2024-10-26 09:47:32 +03:00
Itay Shoshani
1c6575a264 feat: support esp-idf 2024-10-26 09:46:26 +03:00
GrKoR
7f68f3fdac new AC tested: Centek CT-65A09 2024-08-03 20:40:44 +03:00
GrKoR
e7bca33f35 new AC tested: Centek CT-65V12 2024-08-03 20:38:27 +03:00
GrKoR
f859e656a4 upd: OTA in examples and tests was changed to match the ESPHome 2024.6.0 2024-07-20 23:01:50 +03:00
GrKoR
5b229da380 new AC tested: AUX ASW-H18A4/QH-R1DI / AS-H18A4/QH-R1DI 2024-07-17 19:32:53 +03:00
GrKoR
656344dda6 new AC tested: ANDE AND-12/FA+ 2024-07-14 17:14:08 +03:00
GrKoR
b10a2f5dab new AC tested: Rinnai RINV25RC 2024-07-13 19:52:31 +03:00
GrKoR
b80f4972f0 new AC tested: AUX AUX-07JO/I / AUX-M3-21LCLH multisplit and AUX-12JO/I / AUX-M3-21LCLHmultisplit 2024-07-13 19:47:57 +03:00
GrKoR
2a38208628 new AC tested: AUX ASW-H12A4/JD-R2DI 2024-07-13 19:33:36 +03:00
GrKoR
07a98e5789 ref: list of tested ACs was reordered 2024-07-13 19:32:47 +03:00
GrKoR
fe323a6f65 new AC tested: AUX AMWM-H07/4R2(J) multisplit and AMWM-H12/4R2(J) multisplit 2024-07-13 18:45:25 +03:00
GrKoR
584ef0d57a new AC tested: AUX ASW-H07A4/JD-R1 2024-07-12 12:54:24 +03:00
GrKoR
d15272f437 new AC tested: Centek CT-65U18 2024-07-02 17:07:37 +03:00
GrKoR
23584bf53a new AC tested: Osaka STVP-12HH3 2024-07-01 10:26:33 +03:00
GrKoR
1b3bcdfa0f new AC tested: RVX RS-12ALS 2024-06-30 12:42:55 +03:00
GrKoR
558922047e delete from AC tested: Energolux SAS12CH1-AI and SAS12Z3-AI 2024-06-30 12:28:59 +03:00
GrKoR
9f362f475b new AC tested: Vertex Falcon-18A 2024-06-30 12:21:53 +03:00
GrKoR
dad7025632 new AC tested: AUX ASW-H12C5C4/JER3DI-B8-2 2024-06-20 01:13:45 +03:00
GrKoR
16824c10cc new AC tested: Baymak Elegant Plus 12 2024-06-20 01:09:04 +03:00
GrKoR
f31cfb3c16 new AC tested: IKON ASW-H12C5C4/HCR3DI-B8 2024-06-20 01:01:08 +03:00
GrKoR
35d0364655 new AC tested: AUX HA-18000BTU 2024-06-20 00:53:44 +03:00
GrKoR
25ab6feb4f new AC tested: Energolux SAS09Z4-AI and SAS18Z4-AI 2024-06-20 00:48:18 +03:00
GrKoR
3f1b31bb52 new AC tested: Centek CT-65X12 2024-06-06 12:53:52 +03:00
GrKoR
06388ebb2c new AC tested: Centek CT-65RDC07, CT-65RDC09, CT-65RDC12, CT-65SDC07, CT-65SDC09, CT-65SDC18 2024-05-24 15:31:23 +03:00
GrKoR
1f11db4ae0 new AC tested: Centek CT-65K07 2024-05-18 20:31:43 +03:00
GrKoR
87f686564e ref: show firmware version at compile time 2024-05-08 02:19:51 +03:00
GrKoR
37c261700b upd: added uptime sensor 2024-05-08 02:09:37 +03:00
GrKoR
789053e4be ref: AP SSID name changed 2024-05-08 02:07:15 +03:00
GrKoR
f8d3714871 new AC tested: Centek CT-65EDC07 2024-05-07 18:45:05 +03:00
GrKoR
e5704ba869 new AC tested: Centek CT-65J09 2024-04-25 18:39:15 +03:00
GrKoR
e3e60e4f4f new AC tested: AUX AMWM-H12/4R3 multisplit 2024-04-21 22:46:53 +03:00
GrKoR
e98c67e75e new AC tested: IGC RAS-V09N2X 2024-04-21 22:29:16 +03:00
GrKoR
3f1e928a09 new AC tested: Centek CT-65FDC09 2024-04-21 21:34:47 +03:00
GrKoR
507fc06813 new AC tested: Mirage EWC121E - CWC121E 2024-04-21 21:23:37 +03:00
GrKoR
a48ec376b1 new AC tested: Royal Clima RC-VNR29HN 2024-04-21 19:26:05 +03:00
GrKoR
c2dfbefbcf new AC tested: Centek CT-65J12 2024-04-21 16:15:00 +03:00
GrKoR
f324cd1a0e upd: hardware description - USB pinout for newer ACs changed 2024-04-21 16:06:01 +03:00
GrKoR
4bd5c4509d new AC: Subtropic SUB-09HN1 tested 2024-04-08 12:15:48 +03:00
GrKoR
8228ee0777 docs: how to use specific version of the component 2024-04-04 17:24:38 +03:00
GrKoR
453f697c48 Doc - Info on 5V pin (RUS) 2024-04-04 17:22:27 +03:00
Najdanovic Ivan
82a17f0247 Descrption for the 5V PIN 2024-04-04 17:22:04 +03:00
Najdanovic Ivan
d14ed9650d new AC tested: Tesla TA35FFML-12410M 2024-04-04 17:21:18 +03:00
GrKoR
e7377604ba new AC tested: AUX ASM-H24LD 2024-04-04 17:20:30 +03:00
GrKoR
2f0f514ea6 new AC tested: AUX ASM-H12LL 2024-04-04 17:19:58 +03:00
GrKoR
394e64e1f8 new AC tested: Ishimatsu AVK-09I 2024-04-04 17:19:32 +03:00
GrKoR
fcbc853835 new AC tested: AUX AWM-09G1V4-X 2024-04-04 17:18:59 +03:00
GrKoR
c8d661377f new AC tested: AUX ASW-H12C5C4/JOR3DI-B8 2024-04-04 17:18:00 +03:00
GrKoR
9c6faeecb8 new AC tested: AUX ASW-H12A4/HA-R2DI 2024-04-04 17:16:10 +03:00
GrKoR
8afa70a999 new: advanced example have slider for power limitation function. 2024-04-04 17:15:38 +03:00
GrKoR
ca9a76124c new AC tested: Ballu BSUI-18HN8 2024-04-04 17:14:46 +03:00
GrKoR
dacd435177 doc update: new USB-connector pinout and voltage 2024-04-04 17:13:54 +03:00
GrKoR
bf8ab77c02 new AC tested: Xigma XG-SJ56RHA-IDU 2024-04-04 17:12:55 +03:00
GrKoR
61cad07acc fix: version++ 2023-11-09 23:14:13 +03:00
GK
3110c482c9 Merge pull request #88 from GrKoR/brokly's_power
fix: inverter power limitation by Brokly
2023-11-10 00:12:07 +04:00
GrKoR
53a886f818 ref: minor fixes of Brokly's changes 2023-11-09 23:07:54 +03:00
GrKoR
2d4162323a Brokly's changes for power limitation 2023-11-01 18:04:16 +03:00
GK
74d555b5e1 Merge pull request #87 from GrKoR/dev
fix: inverter power limitation off
2023-10-30 02:06:42 +04:00
GrKoR
7df8ab3cc2 fix: version++ 2023-10-30 01:05:30 +03:00
GrKoR
90d9a5cfa7 fix: inverter power limitation off 2023-10-28 22:42:04 +03:00
GrKoR
864ad07699 new AC tested: Ballu BSW-09HN1, Ballu BSW-12HN1 2023-10-17 01:18:16 +03:00
GrKoR
e595a4acf9 new AC tested: Roda RS-AL24F 2023-10-15 22:44:04 +03:00
29 changed files with 446 additions and 5948 deletions

5
.gitignore vendored
View File

@@ -3,6 +3,7 @@
# You can modify this file to suit your needs.
**/.vscode/
**/.esphome/
**/esphome/
**/.pioenvs/
**/.piolibdeps/
**/lib/
@@ -12,6 +13,6 @@
**/livingroom_ac/
**/kitchen_ac/
/examples/*/*.h
**/tests/test_*
**/__pycache__
**/private/
**/private/
**/tests

View File

@@ -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.
@@ -46,6 +46,14 @@ external_components:
type: git
url: https://github.com/GrKoR/esphome_aux_ac_component
```
In case you need a specific version of the component, you can use the component declaration from the example below. The example uses version 0.2.14 of the component. You can find a list of available versions [on the GitHub tags page](https://github.com/GrKoR/esphome_aux_ac_component/tags).
```yaml
external_components:
- source:
type: git
url: https://github.com/GrKoR/esphome_aux_ac_component
ref: v.0.2.14
```
2. Configure UART to communicate with air conditioner:
```yaml
uart:

View File

@@ -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. Подключите компонент.
@@ -54,6 +54,14 @@ external_components:
type: git
url: https://github.com/GrKoR/esphome_aux_ac_component
```
Если требуется прошить определенную версию компонента, используйте синтаксис из примера ниже. Здесь прошивается версия 0.2.14. Список версий смотрите [в тегах на гитхаб](https://github.com/GrKoR/esphome_aux_ac_component/tags).
```yaml
external_components:
- source:
type: git
url: https://github.com/GrKoR/esphome_aux_ac_component
ref: v.0.2.14
```
2. Настройте UART для коммуникации с вашим кондиционером:
```yaml
uart:

View File

@@ -1,186 +0,0 @@
#pragma once
#include "aux_ac.h"
#include "esphome/core/automation.h"
#include "esphome/core/component.h"
namespace esphome {
namespace aux_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(); }
protected:
AirCon *ac_;
};
template <typename... Ts>
class AirConDisplayOnAction : public Action<Ts...> {
public:
explicit AirConDisplayOnAction(AirCon *ac) : ac_(ac) {}
void play(Ts... x) override { this->ac_->displayOnSequence(); }
protected:
AirCon *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(); }
protected:
AirCon *ac_;
};
template <typename... Ts>
class AirConVLouverStopAction : public Action<Ts...> {
public:
explicit AirConVLouverStopAction(AirCon *ac) : ac_(ac) {}
void play(Ts... x) override { this->ac_->setVLouverStopSequence(); }
protected:
AirCon *ac_;
};
template <typename... Ts>
class AirConVLouverTopAction : public Action<Ts...> {
public:
explicit AirConVLouverTopAction(AirCon *ac) : ac_(ac) {}
void play(Ts... x) override { this->ac_->setVLouverTopSequence(); }
protected:
AirCon *ac_;
};
template <typename... Ts>
class AirConVLouverMiddleAboveAction : public Action<Ts...> {
public:
explicit AirConVLouverMiddleAboveAction(AirCon *ac) : ac_(ac) {}
void play(Ts... x) override { this->ac_->setVLouverMiddleAboveSequence(); }
protected:
AirCon *ac_;
};
template <typename... Ts>
class AirConVLouverMiddleAction : public Action<Ts...> {
public:
explicit AirConVLouverMiddleAction(AirCon *ac) : ac_(ac) {}
void play(Ts... x) override { this->ac_->setVLouverMiddleSequence(); }
protected:
AirCon *ac_;
};
template <typename... Ts>
class AirConVLouverMiddleBelowAction : public Action<Ts...> {
public:
explicit AirConVLouverMiddleBelowAction(AirCon *ac) : ac_(ac) {}
void play(Ts... x) override { this->ac_->setVLouverMiddleBelowSequence(); }
protected:
AirCon *ac_;
};
template <typename... Ts>
class AirConVLouverBottomAction : public Action<Ts...> {
public:
explicit AirConVLouverBottomAction(AirCon *ac) : ac_(ac) {}
void play(Ts... x) override { this->ac_->setVLouverBottomSequence(); }
protected:
AirCon *ac_;
};
template <typename... Ts>
class AirConVLouverSetAction : public Action<Ts...> {
public:
AirConVLouverSetAction(AirCon *ac) : ac_(ac) {}
TEMPLATABLE_VALUE(uint8_t, value);
void play(Ts... x) {
vlpos_ = this->value_.value(x...);
this->ac_->setVLouverFrontendSequence((ac_vlouver_frontend)vlpos_);
}
protected:
AirCon *ac_;
uint8_t 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;
}
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);
}
}
protected:
AirCon *ac_;
bool static_{false};
std::function<std::vector<uint8_t>(Ts...)> data_func_{};
std::vector<uint8_t> data_static_{};
};
// **************************************** POWER LIMITATION ACTIONS ****************************************
template <typename... Ts>
class AirConPowerLimitationOffAction : public Action<Ts...> {
public:
explicit AirConPowerLimitationOffAction(AirCon *ac) : ac_(ac) {}
void play(Ts... x) override { this->ac_->powerLimitationOffSequence(); }
protected:
AirCon *ac_;
};
template <typename... Ts>
class AirConPowerLimitationOnAction : public Action<Ts...> {
public:
AirConPowerLimitationOnAction(AirCon *ac) : ac_(ac) {}
TEMPLATABLE_VALUE(uint8_t, value);
void play(Ts... x) {
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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,148 @@
#pragma once
#include <stdint.h>
#include <string.h> // for memcpy and memset, move to .cpp later if needed
namespace esphome
{
namespace aux_ac
{
class AuxFrame
{
private:
// CRC of the AUX frame
// https://github.com/GrKoR/AUX_HVAC_Protocol#packet_crc
union frame_crc_t
{
uint16_t crc16;
uint8_t crc[2];
};
// frame header
// https://github.com/GrKoR/AUX_HVAC_Protocol#packet_header
struct frame_header_t
{
uint8_t startByte;
uint8_t _unknown1;
uint8_t frameType;
uint8_t wifi;
uint8_t pingAnswer;
uint8_t _unknown2;
uint8_t bodyLength;
uint8_t _unknown3;
};
uint8_t *_rawData = nullptr;
frame_header_t *_header = nullptr;
uint8_t *_body = nullptr;
frame_crc_t *_crc = nullptr;
bool _isValid = false;
uint8_t const AC_PACKET_START_BYTE = 0xBB;
uint8_t const AC_HEADER_SIZE = 8;
uint8_t const AC_BODY_LENGTH_OFFSET = 6;
uint8_t const AC_BUFFER_SIZE = 35; // TODO: integrate it with aux_uart.h
uint16_t _CRC16(uint8_t *data, uint8_t len)
{
uint32_t crc = 0;
uint8_t _crcBuffer[AC_BUFFER_SIZE];
memset(_crcBuffer, 0, AC_BUFFER_SIZE);
memcpy(_crcBuffer, data, len);
if ((len % 2) == 1)
len++;
uint32_t word = 0;
for (uint8_t i = 0; i < len; i += 2)
{
word = (_crcBuffer[i] << 8) + _crcBuffer[i + 1];
crc += word;
}
crc = (crc >> 16) + (crc & 0xFFFF);
crc = ~crc;
return crc & 0xFFFF;
}
bool _checkCRC()
{
frame_crc_t crc;
crc.crc16 = _CRC16(this->_rawData, AC_HEADER_SIZE + this->_rawData[AC_BODY_LENGTH_OFFSET]);
return ((this->_crc->crc[0] == crc.crc[1]) && (this->_crc->crc[1] == crc.crc[0]));
}
void _checkFrame()
{
this->_isValid = false;
if (this->_rawData == nullptr)
return;
if (this->_header->startByte != AC_PACKET_START_BYTE)
return;
if (!this->_checkCRC())
return;
this->_isValid = true;
}
public:
AuxFrame() = default;
~AuxFrame() {};
void set_data(uint8_t *data)
{
clearData();
if (data == nullptr)
return;
this->_rawData = data;
this->_header = (frame_header_t *)this->_rawData;
this->_crc = (frame_crc_t *)(this->_rawData + AC_HEADER_SIZE + this->_header->bodyLength);
if (this->_header->bodyLength > 0)
this->_body = this->_rawData + AC_HEADER_SIZE;
else
this->_body = nullptr;
this->_checkFrame();
}
void clearData()
{
this->_rawData = nullptr;
this->_header = nullptr;
this->_crc = nullptr;
this->_body = nullptr;
this->_isValid = false;
}
bool isValid() const
{
return this->_isValid;
};
uint8_t frameSize() const
{
if (!this->isValid())
return 0;
return AC_HEADER_SIZE + this->_header->bodyLength + 2;
}
uint8_t bodyLength() const
{
if (!this->isValid())
return 0;
return this->_header->bodyLength;
}
};
} // namespace aux_ac
} // namespace esphome

View File

@@ -0,0 +1,100 @@
#include "aux_logger.h"
namespace esphome
{
namespace aux_ac
{
static const char *const TAG = "AirCon"; // TODO: verify if this tag is appropriate
/** вывод отладочной информации в лог
*
* dbgLevel - уровень сообщения, определен в ESPHome. За счет его использования можно из ESPHome управлять полнотой сведений в логе.
* msg - сообщение, выводимое в лог
* line - строка, на которой произошел вызов (удобно при отладке)
*/
void debugMsg(const /*String &*/ char *msg, uint8_t dbgLevel, unsigned int line, ...)
{
if (dbgLevel < ESPHOME_LOG_LEVEL_NONE)
dbgLevel = ESPHOME_LOG_LEVEL_NONE;
if (dbgLevel > ESPHOME_LOG_LEVEL_VERY_VERBOSE)
dbgLevel = ESPHOME_LOG_LEVEL_VERY_VERBOSE;
if (line == 0)
line = __LINE__; // если строка не передана, берем текущую строку
va_list vl;
va_start(vl, line);
esp_log_vprintf_(dbgLevel, TAG, line, msg, vl);
va_end(vl);
};
/** выводим данные пакета в лог для отладки
*
* dbgLevel - уровень сообщения, определен в ESPHome. За счет его использования можно из ESPHome управлять полнотой сведений в логе.
* packet - указатель на пакет для вывода;
* если указатель на crc равен nullptr или первый байт в буфере не AC_PACKET_START_BYTE, то считаем, что передан битый пакет
* или не пакет вовсе. Для такого выводим только массив байт.
* Для нормального пакета данные выводятся с форматированием.
* line - строка, на которой произошел вызов (удобно при отладке)
**/
void debugPrintPacket(packet_t *packet, uint8_t dbgLevel, unsigned int line)
{
// определяем, полноценный ли пакет нам передан
bool notAPacket = false;
/*
// указатель заголовка всегда установден на начало буфера
notAPacket = notAPacket || (packet->crc == nullptr);
notAPacket = notAPacket || (packet->data[0] != AC_PACKET_START_BYTE);
String st = "";
char textBuf[11];
// заполняем время получения пакета
memset(textBuf, 0, 11);
sprintf(textBuf, "%010" PRIu32, packet->msec);
st = st + textBuf + ": ";
// формируем преамбулы
if (packet == &_inPacket)
{
st += "[<=] "; // преамбула входящего пакета
}
else if (packet == &_outPacket)
{
st += "[=>] "; // преамбула исходящего пакета
}
else
{
st += "[--] "; // преамбула для "непакета"
}
// формируем данные
for (int i = 0; i < packet->bytesLoaded; i++)
{
// для заголовков нормальных пакетов надо отработать скобки (если они есть)
if ((!notAPacket) && (i == 0))
st += HOLMES_HEADER_BRACKET_OPEN;
// для CRC нормальных пакетов надо отработать скобки (если они есть)
if ((!notAPacket) && (i == packet->header->body_length + AC_HEADER_SIZE))
st += HOLMES_CRC_BRACKET_OPEN;
memset(textBuf, 0, 11);
sprintf(textBuf, HOLMES_BYTE_FORMAT, packet->data[i]);
st += textBuf;
// для заголовков нормальных пакетов надо отработать скобки (если они есть)
if ((!notAPacket) && (i == AC_HEADER_SIZE - 1))
st += HOLMES_HEADER_BRACKET_CLOSE;
// для CRC нормальных пакетов надо отработать скобки (если они есть)
if ((!notAPacket) && (i == packet->header->body_length + AC_HEADER_SIZE + 2 - 1))
st += HOLMES_CRC_BRACKET_CLOSE;
st += HOLMES_DELIMITER;
}
_debugMsg(st, dbgLevel, line);
*/
}
} // namespace aux_ac
} // namespace esphome

View File

@@ -0,0 +1,15 @@
#pragma once
#include <stdint.h>
#include "esphome/core/log.h"
namespace esphome
{
namespace aux_ac
{
using packet_t = uint8_t; // TODO: Replace with actual packet_t definition
void debugMsg(const char *msg, uint8_t dbgLevel, unsigned int line = 0, ...);
void debugPrintPacket(packet_t *packet, uint8_t dbgLevel = ESPHOME_LOG_LEVEL_DEBUG, unsigned int line = __LINE__);
} // namespace aux_ac
} // namespace esphome

View File

@@ -0,0 +1,68 @@
#include "aux_uart.h"
namespace esphome
{
namespace aux_ac
{
void AuxUart::send_frame(const std::vector<uint8_t> &frame)
{
this->write_array(frame);
}
bool AuxUart::read_frame(std::vector<uint8_t> &frame)
{
// Check if enough data is available
if (this->available() < 3)
return false;
// Peek at the first 3 bytes to determine the frame length
uint8_t header[3];
if (!this->peek_array(header, 3))
return false;
// Validate start byte
if (header[0] != 0xAA)
{
// Invalid start byte, discard one byte and return false
uint8_t discard;
this->read_byte(&discard);
return false;
}
// Determine frame length from the second byte
size_t frame_length = header[1];
if (frame_length < 3 || frame_length > AC_BUFFER_SIZE)
{
// Invalid length, discard one byte and return false
uint8_t discard;
this->read_byte(&discard);
return false;
}
// Check if the full frame is available
if (this->available() < frame_length)
return false;
// Read the full frame into the internal buffer
if (!this->read_array(this->_data, frame_length))
return false;
// Validate checksum
uint8_t checksum = 0;
for (size_t i = 0; i < frame_length - 1; i++)
{
checksum += this->_data[i];
}
if (checksum != this->_data[frame_length - 1])
{
// Invalid checksum, discard the frame and return false
return false;
}
// Copy the valid frame to the output vector
frame.assign(this->_data, this->_data + frame_length);
return true;
}
} // namespace aux_ac
} // namespace esphome

View File

@@ -0,0 +1,30 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/components/uart/uart.h"
#define AC_BUFFER_SIZE 35
using namespace esphome::uart;
namespace esphome
{
namespace aux_ac
{
class AuxUart : public UARTDevice
{
public:
AuxUart() = delete;
explicit AuxUart(UARTComponent *parent) : UARTDevice(parent) {}
~AuxUart() = default;
void send_frame(const std::vector<uint8_t> &frame);
bool read_frame(std::vector<uint8_t> &frame);
protected:
// Internal buffer for incoming data
uint8_t _data[AC_BUFFER_SIZE];
};
} // namespace aux_ac
} // namespace esphome

View File

@@ -1,338 +1,46 @@
import logging
from esphome.core import CORE, Define
import esphome.config_validation as cv
import esphome.codegen as cg
from esphome.components import climate, uart, sensor, binary_sensor, text_sensor
from esphome import automation
from esphome.automation import maybe_simple_id
from esphome.components import uart, climate
from esphome.const import (
CONF_CUSTOM_FAN_MODES,
CONF_CUSTOM_PRESETS,
CONF_DATA,
CONF_ID,
CONF_INTERNAL,
CONF_OPTIMISTIC,
CONF_PERIOD,
CONF_POSITION,
CONF_SUPPORTED_MODES,
CONF_SUPPORTED_SWING_MODES,
CONF_SUPPORTED_PRESETS,
CONF_TIMEOUT,
CONF_UART_ID,
UNIT_CELSIUS,
UNIT_PERCENT,
ICON_POWER,
ICON_THERMOMETER,
DEVICE_CLASS_TEMPERATURE,
DEVICE_CLASS_POWER_FACTOR,
STATE_CLASS_MEASUREMENT,
)
from esphome.components.climate import (
ClimateMode,
ClimatePreset,
ClimateSwingMode,
)
AUX_AC_FIRMWARE_VERSION = '0.2.17'
_LOGGER = logging.getLogger(__name__)
CODEOWNERS = ["@GrKoR"]
DEPENDENCIES = ["climate", "uart"]
AUTO_LOAD = ["sensor", "binary_sensor", "text_sensor"]
CONF_SHOW_ACTION = "show_action"
CONF_INDOOR_TEMPERATURE = "indoor_temperature"
CONF_OUTDOOR_TEMPERATURE = "outdoor_temperature"
ICON_OUTDOOR_TEMPERATURE = "mdi:home-thermometer-outline"
CONF_INBOUND_TEMPERATURE = "inbound_temperature"
ICON_INBOUND_TEMPERATURE = "mdi:thermometer-plus"
CONF_OUTBOUND_TEMPERATURE = "outbound_temperature"
ICON_OUTBOUND_TEMPERATURE = "mdi:thermometer-minus"
CONF_COMPRESSOR_TEMPERATURE = "compressor_temperature"
ICON_COMPRESSOR_TEMPERATURE = "mdi:thermometer-lines"
CONF_DISPLAY_STATE = "display_state"
CONF_INVERTER_POWER = "inverter_power"
CONF_INVERTER_POWER_DEPRICATED = "invertor_power"
CONF_DEFROST_STATE = "defrost_state"
ICON_DEFROST = "mdi:snowflake-melt"
CONF_DISPLAY_INVERTED = "display_inverted"
ICON_DISPLAY = "mdi:clock-digital"
CONF_PRESET_REPORTER = "preset_reporter"
ICON_PRESET_REPORTER = "mdi:format-list-group"
CONF_VLOUVER_STATE = "vlouver_state"
ICON_VLOUVER_STATE = "mdi:compare-vertical"
CONF_LIMIT = "limit"
CONF_INVERTER_POWER_LIMIT_VALUE = "inverter_power_limit_value"
ICON_INVERTER_POWER_LIMIT_VALUE = "mdi:meter-electric-outline"
CONF_INVERTER_POWER_LIMIT_STATE = "inverter_power_limit_state"
ICON_INVERTER_POWER_LIMIT_STATE = "mdi:meter-electric-outline"
DEPENDENCIES = ["uart"]
aux_ac_ns = cg.esphome_ns.namespace("aux_ac")
AirCon = aux_ac_ns.class_("AirCon", climate.Climate, cg.Component)
Capabilities = aux_ac_ns.namespace("Constants")
# Display actions
AirConDisplayOffAction = aux_ac_ns.class_("AirConDisplayOffAction", automation.Action)
AirConDisplayOnAction = aux_ac_ns.class_("AirConDisplayOnAction", automation.Action)
# test packet action
AirConSendTestPacketAction = aux_ac_ns.class_(
"AirConSendTestPacketAction", automation.Action
)
# vertical louvers actions
AirConVLouverSwingAction = aux_ac_ns.class_(
"AirConVLouverSwingAction", automation.Action
)
AirConVLouverStopAction = aux_ac_ns.class_("AirConVLouverStopAction", automation.Action)
AirConVLouverTopAction = aux_ac_ns.class_("AirConVLouverTopAction", automation.Action)
AirConVLouverMiddleAboveAction = aux_ac_ns.class_(
"AirConVLouverMiddleAboveAction", automation.Action
)
AirConVLouverMiddleAction = aux_ac_ns.class_(
"AirConVLouverMiddleAction", automation.Action
)
AirConVLouverMiddleBelowAction = aux_ac_ns.class_(
"AirConVLouverMiddleBelowAction", automation.Action
)
AirConVLouverBottomAction = aux_ac_ns.class_(
"AirConVLouverBottomAction", automation.Action
)
AirConVLouverSetAction = aux_ac_ns.class_(
"AirConVLouverSetAction", automation.Action
)
# power limitation actions
AirConPowerLimitationOffAction = aux_ac_ns.class_(
"AirConPowerLimitationOffAction", automation.Action
)
AirConPowerLimitationOnAction = aux_ac_ns.class_(
"AirConPowerLimitationOnAction", automation.Action
)
AC_PACKET_TIMEOUT_MIN = 150
AC_PACKET_TIMEOUT_MAX = 600
def validate_packet_timeout(value):
minV = AC_PACKET_TIMEOUT_MIN
maxV = AC_PACKET_TIMEOUT_MAX
if value in range(minV, maxV+1):
return cv.Schema(cv.uint32_t)(value)
raise cv.Invalid(f"Timeout should be in range: {minV}..{maxV}.")
AC_POWER_LIMIT_MIN = 30
AC_POWER_LIMIT_MAX = 100
def validate_power_limit_range(value):
minV = AC_POWER_LIMIT_MIN
maxV = AC_POWER_LIMIT_MAX
if value in range(minV, maxV+1):
return cv.Schema(cv.uint32_t)(value)
raise cv.Invalid(f"Power limit should be in range: {minV}..{maxV}")
ALLOWED_CLIMATE_MODES = {
"HEAT_COOL": ClimateMode.CLIMATE_MODE_HEAT_COOL,
"COOL": ClimateMode.CLIMATE_MODE_COOL,
"HEAT": ClimateMode.CLIMATE_MODE_HEAT,
"DRY": ClimateMode.CLIMATE_MODE_DRY,
"FAN_ONLY": ClimateMode.CLIMATE_MODE_FAN_ONLY,
}
validate_modes = cv.enum(ALLOWED_CLIMATE_MODES, upper=True)
ALLOWED_CLIMATE_PRESETS = {
"SLEEP": ClimatePreset.CLIMATE_PRESET_SLEEP,
}
validate_presets = cv.enum(ALLOWED_CLIMATE_PRESETS, upper=True)
ALLOWED_CLIMATE_SWING_MODES = {
"BOTH": ClimateSwingMode.CLIMATE_SWING_BOTH,
"VERTICAL": ClimateSwingMode.CLIMATE_SWING_VERTICAL,
"HORIZONTAL": ClimateSwingMode.CLIMATE_SWING_HORIZONTAL,
}
validate_swing_modes = cv.enum(ALLOWED_CLIMATE_SWING_MODES, upper=True)
CUSTOM_FAN_MODES = {
"MUTE": Capabilities.MUTE,
"TURBO": Capabilities.TURBO,
}
validate_custom_fan_modes = cv.enum(CUSTOM_FAN_MODES, upper=True)
CUSTOM_PRESETS = {
"CLEAN": Capabilities.CLEAN,
"HEALTH": Capabilities.HEALTH,
"ANTIFUNGUS": Capabilities.ANTIFUNGUS,
}
validate_custom_presets = cv.enum(CUSTOM_PRESETS, upper=True)
def validate_raw_data(value):
if isinstance(value, list):
return cv.Schema([cv.hex_uint8_t])(value)
raise cv.Invalid("data must be a list of bytes")
AuxUart = aux_ac_ns.class_("AuxUart", uart.UARTDevice)
def output_info(config):
"""_LOGGER.info(config.items())"""
_LOGGER.info("AUX_AC firmware version: %s", AUX_AC_FIRMWARE_VERSION)
return config
CONFIG_SCHEMA = cv.All(
climate.CLIMATE_SCHEMA.extend(
uart.UART_DEVICE_SCHEMA
.extend(
{
cv.GenerateID(): cv.declare_id(AirCon),
cv.Optional(CONF_PERIOD, default="7s"): cv.time_period,
cv.Optional(CONF_SHOW_ACTION, default="true"): cv.boolean,
cv.Optional(CONF_DISPLAY_INVERTED, default="false"): cv.boolean,
cv.Optional(CONF_TIMEOUT, default=AC_PACKET_TIMEOUT_MIN): validate_packet_timeout,
cv.Optional(CONF_OPTIMISTIC, default="true"): cv.boolean,
cv.Optional(CONF_INVERTER_POWER_DEPRICATED): cv.invalid(
"The name of sensor was changed in v.0.2.9 from 'invertor_power' to 'inverter_power'. Update your config please."
),
cv.Optional(CONF_INVERTER_POWER): sensor.sensor_schema(
unit_of_measurement=UNIT_PERCENT,
icon=ICON_POWER,
accuracy_decimals=0,
device_class=DEVICE_CLASS_POWER_FACTOR,
state_class=STATE_CLASS_MEASUREMENT,
).extend(
{
cv.Optional(CONF_INTERNAL, default="true"): cv.boolean,
}
),
cv.Optional(CONF_INDOOR_TEMPERATURE): sensor.sensor_schema(
unit_of_measurement=UNIT_CELSIUS,
icon=ICON_THERMOMETER,
accuracy_decimals=1,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
).extend(
{
cv.Optional(CONF_INTERNAL, default="true"): cv.boolean,
}
),
cv.Optional(CONF_OUTDOOR_TEMPERATURE): sensor.sensor_schema(
unit_of_measurement=UNIT_CELSIUS,
icon=ICON_OUTDOOR_TEMPERATURE,
accuracy_decimals=0,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
).extend(
{
cv.Optional(CONF_INTERNAL, default="true"): cv.boolean,
}
),
cv.Optional(CONF_INBOUND_TEMPERATURE): sensor.sensor_schema(
unit_of_measurement=UNIT_CELSIUS,
icon=ICON_INBOUND_TEMPERATURE,
accuracy_decimals=0,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
).extend(
{
cv.Optional(CONF_INTERNAL, default="true"): cv.boolean,
}
),
cv.Optional(CONF_OUTBOUND_TEMPERATURE): sensor.sensor_schema(
unit_of_measurement=UNIT_CELSIUS,
icon=ICON_OUTBOUND_TEMPERATURE,
accuracy_decimals=0,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
).extend(
{
cv.Optional(CONF_INTERNAL, default="true"): cv.boolean,
}
),
cv.Optional(CONF_COMPRESSOR_TEMPERATURE): sensor.sensor_schema(
unit_of_measurement=UNIT_CELSIUS,
icon=ICON_COMPRESSOR_TEMPERATURE,
accuracy_decimals=0,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
).extend(
{
cv.Optional(CONF_INTERNAL, default="true"): cv.boolean,
}
),
cv.Optional(CONF_VLOUVER_STATE): sensor.sensor_schema(
icon=ICON_VLOUVER_STATE,
accuracy_decimals=0,
).extend(
{
cv.Optional(CONF_INTERNAL, default="true"): cv.boolean,
}
),
cv.Optional(CONF_DISPLAY_STATE): binary_sensor.binary_sensor_schema(
icon=ICON_DISPLAY,
).extend(
{
cv.Optional(CONF_INTERNAL, default="true"): cv.boolean,
}
),
cv.Optional(CONF_DEFROST_STATE): binary_sensor.binary_sensor_schema(
icon=ICON_DEFROST,
).extend(
{
cv.Optional(CONF_INTERNAL, default="true"): cv.boolean,
}
),
cv.Optional(CONF_PRESET_REPORTER): text_sensor.text_sensor_schema(
icon=ICON_PRESET_REPORTER,
).extend(
{
cv.Optional(CONF_INTERNAL, default="true"): cv.boolean,
}
),
cv.Optional(CONF_INVERTER_POWER_LIMIT_VALUE): sensor.sensor_schema(
unit_of_measurement=UNIT_PERCENT,
icon=ICON_INVERTER_POWER_LIMIT_VALUE,
accuracy_decimals=0,
device_class=DEVICE_CLASS_POWER_FACTOR,
state_class=STATE_CLASS_MEASUREMENT,
).extend(
{
cv.Optional(CONF_INTERNAL, default="true"): cv.boolean,
}
),
cv.Optional(CONF_INVERTER_POWER_LIMIT_STATE): binary_sensor.binary_sensor_schema(
icon=ICON_INVERTER_POWER_LIMIT_STATE,
).extend(
{
cv.Optional(CONF_INTERNAL, default="true"): cv.boolean,
}
),
cv.Optional(CONF_SUPPORTED_MODES): cv.ensure_list(validate_modes),
cv.Optional(CONF_SUPPORTED_SWING_MODES): cv.ensure_list(
validate_swing_modes
),
cv.Optional(CONF_SUPPORTED_PRESETS): cv.ensure_list(validate_presets),
cv.Optional(CONF_CUSTOM_PRESETS): cv.ensure_list(validate_custom_presets),
cv.Optional(CONF_CUSTOM_FAN_MODES): cv.ensure_list(
validate_custom_fan_modes
),
cv.GenerateID(): cv.declare_id(AuxUart),
}
)
.extend(uart.UART_DEVICE_SCHEMA)
.extend(cv.COMPONENT_SCHEMA),
),
output_info,
)
async def to_code(config):
CORE.add_define(
Define("AUX_AC_FIRMWARE_VERSION", '"'+AUX_AC_FIRMWARE_VERSION+'"')
)
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await climate.register_climate(var, config)
# await cg.register_component(var, config)
parent = await cg.get_variable(config[CONF_UART_ID])
cg.add(var.initAC(parent))
@@ -386,7 +94,7 @@ async def to_code(config):
conf = config[CONF_PRESET_REPORTER]
sens = await text_sensor.new_text_sensor(conf)
cg.add(var.set_preset_reporter_sensor(sens))
if CONF_INVERTER_POWER_LIMIT_VALUE in config:
conf = config[CONF_INVERTER_POWER_LIMIT_VALUE]
sens = await sensor.new_sensor(conf)
@@ -412,170 +120,3 @@ async def to_code(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(
{
cv.Required(CONF_ID): cv.use_id(AirCon),
}
)
@automation.register_action(
"aux_ac.display_off", AirConDisplayOffAction, DISPLAY_ACTION_SCHEMA
)
async def display_off_to_code(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID])
return cg.new_Pvariable(action_id, template_arg, paren)
@automation.register_action(
"aux_ac.display_on", AirConDisplayOnAction, DISPLAY_ACTION_SCHEMA
)
async def display_on_to_code(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID])
return cg.new_Pvariable(action_id, template_arg, paren)
VLOUVER_ACTION_SCHEMA = maybe_simple_id(
{
cv.Required(CONF_ID): cv.use_id(AirCon),
}
)
@automation.register_action(
"aux_ac.vlouver_stop", AirConVLouverStopAction, VLOUVER_ACTION_SCHEMA
)
async def vlouver_stop_to_code(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID])
return cg.new_Pvariable(action_id, template_arg, paren)
@automation.register_action(
"aux_ac.vlouver_swing", AirConVLouverSwingAction, VLOUVER_ACTION_SCHEMA
)
async def vlouver_swing_to_code(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID])
return cg.new_Pvariable(action_id, template_arg, paren)
@automation.register_action(
"aux_ac.vlouver_top", AirConVLouverTopAction, VLOUVER_ACTION_SCHEMA
)
async def vlouver_top_to_code(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID])
return cg.new_Pvariable(action_id, template_arg, paren)
@automation.register_action(
"aux_ac.vlouver_middle_above", AirConVLouverMiddleAboveAction, VLOUVER_ACTION_SCHEMA
)
async def vlouver_middle_above_to_code(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID])
return cg.new_Pvariable(action_id, template_arg, paren)
@automation.register_action(
"aux_ac.vlouver_middle", AirConVLouverMiddleAction, VLOUVER_ACTION_SCHEMA
)
async def vlouver_middle_to_code(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID])
return cg.new_Pvariable(action_id, template_arg, paren)
@automation.register_action(
"aux_ac.vlouver_middle_below", AirConVLouverMiddleBelowAction, VLOUVER_ACTION_SCHEMA
)
async def vlouver_middle_below_to_code(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID])
return cg.new_Pvariable(action_id, template_arg, paren)
@automation.register_action(
"aux_ac.vlouver_bottom", AirConVLouverBottomAction, VLOUVER_ACTION_SCHEMA
)
async def vlouver_bottom_to_code(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID])
return cg.new_Pvariable(action_id, template_arg, paren)
VLOUVER_SET_ACTION_SCHEMA = cv.Schema(
{
cv.Required(CONF_ID): cv.use_id(AirCon),
cv.Required(CONF_POSITION): cv.templatable(cv.int_range(0, 6)),
}
)
@automation.register_action(
"aux_ac.vlouver_set", AirConVLouverSetAction, VLOUVER_SET_ACTION_SCHEMA
)
async def vlouver_set_to_code(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID])
var = cg.new_Pvariable(action_id, template_arg, paren)
template_ = await cg.templatable(config[CONF_POSITION], args, int)
cg.add(var.set_value(template_))
return var
POWER_LIMITATION_OFF_ACTION_SCHEMA = maybe_simple_id(
{
cv.Required(CONF_ID): cv.use_id(AirCon),
}
)
@automation.register_action(
"aux_ac.power_limit_off", AirConPowerLimitationOffAction, POWER_LIMITATION_OFF_ACTION_SCHEMA
)
async def power_limit_off_to_code(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID])
return cg.new_Pvariable(action_id, template_arg, paren)
POWER_LIMITATION_ON_ACTION_SCHEMA = cv.Schema(
{
cv.Required(CONF_ID): cv.use_id(AirCon),
cv.Optional(CONF_LIMIT, default=AC_POWER_LIMIT_MIN): validate_power_limit_range,
}
)
@automation.register_action(
"aux_ac.power_limit_on", AirConPowerLimitationOnAction, POWER_LIMITATION_ON_ACTION_SCHEMA
)
async def power_limit_on_to_code(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID])
var = cg.new_Pvariable(action_id, template_arg, paren)
template_ = await cg.templatable(config[CONF_LIMIT], args, int)
cg.add(var.set_value(template_))
return var
# *********************************************************************************************************
# ВАЖНО! Только для инженеров!
# Вызывайте метод aux_ac.send_packet только если понимаете, что делаете! Он не проверяет данные, а передаёт
# кондиционеру всё как есть. Какой эффект получится от передачи кондиционеру рандомных байт, никто не знает.
# Вы действуете на свой страх и риск.
# *********************************************************************************************************
SEND_TEST_PACKET_ACTION_SCHEMA = maybe_simple_id(
{
cv.Required(CONF_ID): cv.use_id(AirCon),
cv.Required(CONF_DATA): cv.templatable(validate_raw_data),
}
)
@automation.register_action(
"aux_ac.send_packet", AirConSendTestPacketAction, SEND_TEST_PACKET_ACTION_SCHEMA
)
async def send_packet_to_code(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID])
var = cg.new_Pvariable(action_id, template_arg, paren)
data = config[CONF_DATA]
if isinstance(data, bytes):
data = list(data)
if cg.is_template(data):
templ = await cg.templatable(data, args, cg.std_vector.template(cg.uint8))
cg.add(var.set_data_template(templ))
else:
cg.add(var.set_data_static(data))
return var

View File

@@ -2,26 +2,45 @@
`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, ASW-H07A4/DE-R1DI, ASW-H07A4/FP-R1DI, ASW-H09A4/FP-R1DI, ASW-H09A4/LK-700R1, ASW-H09A4/LK-700R1DI, ASW-H12B4/JD-R2DI, ASW-H12A4/FAR1, ASW-H09B4/LK-700R1, ASW-H12U3/JIR1DI-US, AUX-18QC/I / AUX-18QC/O, 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, BSUI-09HN8, BSUI-12HN8)
+ Centek (models: CT-65A12, CT-65F09, CT-65F12, CT-65Q09, CT-65Q12, CT-65U13, CT-65Z10, CT-65Z18, CT-65V24)
+ 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)
+ 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)
+ Roda (models: RS-AL09F)
+ 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, 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-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)

View File

@@ -16,7 +16,7 @@ It use [JST SM](https://www.jst-mfg.com/product/pdf/eng/eSM.pdf) connector for 5
### Pinout ###
1. Yellow: +12V..+14V DC. Measured +14.70V max and +13.70V min. Service manual declares up to +16V.
2. Black: ground.
3. White: +5V DC (max: +5.63V; min: +4.43V) I have no idea what this is for. It goes directly to the air conditioner microcontroller through resistor 1kOhm and it does not affect the operation of the module.
3. White: +5V DC (max: +5.63V; min: +4.43V) Enable signal for the 3V3 buck regulator on the OEM module. It goes directly to the air conditioner microcontroller through resistor 1kOhm. It's non used with the EPS module.
4. Blue: TX of air conditioner. High is +5V.
5. Red: RX of air conditioner. High is +5V.
@@ -26,17 +26,21 @@ You should feed your ESP **from +12V..+14V line only**! It is prohibited to use
## 4-wire connection (pseudo-USB)
For 4-wire connection it is used USB-like connector. It is only physical USB but its pinout is UART with +12V..+14V power line.
**ATTENTION!** It is incompatible with normal USB devices! Ordinary USB device like USB flash drive will be damaged if it will be plugged in air conditioner USB connector.
**ATTENTION!** It is incompatible with normal USB devices! Ordinary USB device like USB flash drive will be damaged if it will be plugged in air conditioner USB connector.
**ATTENTION #2!** Manufacturer was changed power circuit and connector pinout in 2022-2023: power rail has +8.5V DC and TX/RX pins are swapped.
### Pinout ###
<img src="https://github.com/GrKoR/esphome_aux_ac_component/blob/master/images/USB-pinout.png?raw=true" width="400">
1. +12V..+14V DC. Service manual declares up to +16V.
2. RX of air conditioner. High level is +5V.
3. TX of air conditioner. High level is +5V.
1. +12V..+14V DC before 2022-2023, possible +8.5V DC after 2022-2023. Service manual declares up to +16V.
2. RX of the air conditioner for models manufactured before about Jul.2022, TX of the air conditioner for later modifications. High level is +5V.
3. TX of the air conditioner for models manufactured before about Jul.2022, RX of the air conditioner for later modifications. High level is +5V.
4. GND - ground.
Big thanks to [@diabl0](https://github.com/diabl0) for this pinout in [issue #70](https://github.com/GrKoR/esphome_aux_ac_component/issues/70).
Big thanks to [@diabl0](https://github.com/diabl0) for this pinout in [issue #70](https://github.com/GrKoR/esphome_aux_ac_component/issues/70).
If you are not sure, on which USB-pins do you have RX and TX lines, than don't afraid to connect it randomly. Neither air conditioner nor ESP will be damaged in this situation, just `aux_ac` can't receive data from the air conditioner. Swap TX and RX and your device will probably work.
## Power supply

View File

@@ -15,7 +15,7 @@
### Распиновка ###
1. Желтый: +12В..+14В постоянного тока. Осциллограф показал от +13.70В до +14.70В. В сервисном мануале встречалось, что питание возможно до +16В.
2. Черный: земля.
3. Белый: +5В постоянного тока (измерено от +4.43В до +5.63В). Для чего нужна эта линия - не понятно. У меня нет версий. Эксперименты с родным Wi-Fi модулем сплит-системы показали, что эта линия в работе Wi-Fi не участвует. Линия идет напрямую на ножку контроллера в сплите через резистор 1 кОм.
3. Белый: +5В постоянного тока (измерено от +4.43В до +5.63В). По информации от пользователей, это сигнальная линия, включающая по DC-DC конвертор на wifi-модуле по команде с кондиционера. Линия идет напрямую на ножку контроллера в сплите через резистор 1 кОм. Эксперименты с родным Wi-Fi модулем сплит-системы показали, что эта линия в работе Wi-Fi не участвует и имеет всегда высокий уровень. В работе компонента и самодельного wifi-модуля эта линия не используется.
4. Синий: TX кондиционера. Высокий уровень +5В.
5. Red: RX кондиционера. Высокий уровень +5В.
@@ -26,16 +26,20 @@
**ВНИМАНИЕ!** С устройствами c настоящим USB этот интерфейс не совместим! Если вставить в разъём обычную USB-флешку или другое устройство, скорее всего оно просто сгорит.
**ВНИМАНИЕ №2!** В 2022-2023 производитель поменял распиновку и схему питания. Теперь кондиционеры на USB-коннектор выдают +8.5В. А пины RX и TX поменялись местами.
### Распиновка ###
<img src="https://github.com/GrKoR/esphome_aux_ac_component/blob/master/images/USB-pinout.png?raw=true" width="400">
1. +12В..+14В постоянного тока. Осциллограф показал от +13.70В до +14.70В. В сервисном мануале встречалось, что питание возможно до +16В.
2. RX кондиционера. Высокий уровень +5В.
3. TX кондиционера. Высокий уровень +5В.
1. +12В..+14В постоянного тока для кондиционеров до 2023 года, возможно +8.5В для кондиционеров 2022-2023 годов и моложе. В сервисном мануале на кондиционеры до 2022 года встречалось, что питание возможно до +16В.
2. RX кондиционера для моделей, произведенных примерно до 07.2022, TX кондиционера для более поздних модификаций. Высокий уровень +5В.
3. TX кондиционера для моделей, произведенных примерно до 07.2022, RX кондиционера для более поздних модификаций. Высокий уровень +5В.
4. земля.
Большое спасибо [@diabl0](https://github.com/diabl0) за эту распиновку ([issue #70](https://github.com/GrKoR/esphome_aux_ac_component/issues/70)).
Если вы не знаете, на каких именно пинах USB-разъема в вашем случае расположены TX и RX, то не бойтесь подключить наугад. Ни кондиционер, ни ESP не пострадают, если вы перепутаете линии TX и RX. Просто компонент не увидит кондиционер, о чем будут сообщения в логе. В таком случае просто попробуйте поменять TX и RX местами.
## Питание
Для питания ESP8266 можно использовать любой подходящий DC-DC преобразователь. Я использовал такой:

View File

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

View File

@@ -1,217 +0,0 @@
# DON'T COMPILE THIS FILE
# This file contains common settings for all air conditioners of your house
external_components:
- source: github://GrKoR/esphome_aux_ac_component
components: [ aux_ac ]
refresh: 0s
esphome:
name: $devicename
platform: ESP8266
board: esp12e
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_pass
manual_ip:
static_ip: ${wifi_ip}
gateway: !secret wifi_gateway
subnet: !secret wifi_subnet
ap:
ssid: ${upper_devicename} Hotspot
password: !secret wifi_ap_pass
use_address: ${wifi_ota_ip}
captive_portal:
debug:
logger:
level: DEBUG
baud_rate: 0
# set hardware_uart to UART1 and comment out baud_rate above in case of boot crashes
# it is suitable if you need hardware loggin
# hardware_uart: UART1
api:
password: !secret api_pass
ota:
password: !secret ota_pass
web_server:
port: 80
auth:
username: !secret web_server_user
password: !secret web_server_password
# UART0 configuration for AUX air conditioner communication
uart:
id: ac_uart_bus
# ATTENTION! Use GPIO4 (D2) and GPIO5 (D1) as the TX and RX for NodeMCU-like boards!
tx_pin: GPIO1
rx_pin: GPIO3
baud_rate: 4800
data_bits: 8
parity: EVEN
stop_bits: 1
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}_inverter_power
internal: false
preset_reporter:
name: ${upper_devicename} Preset Reporter
id: ${devicename}_preset_reporter
internal: false
vlouver_state:
name: ${upper_devicename} VLouvers State
id: ${devicename}_vlouver_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
sensor:
# just wifi signal strength for debug purpose only
- platform: wifi_signal
name: ${upper_devicename} WiFi Signal
update_interval: 30s
unit_of_measurement: "dBa"
accuracy_decimals: 0
switch:
- platform: template
name: ${upper_devicename} 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
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 Louvers
id: ${devicename}_vlouver
icon: "mdi:circle-small"
mode: "slider"
min_value: 0
max_value: 6
step: 1
update_interval: 2s
lambda: |-
return id(${devicename}_vlouver_state).state;
set_action:
then:
- aux_ac.vlouver_set:
id: aux_id
position: !lambda "return x;"

View File

@@ -1,17 +0,0 @@
# compile this file with ESPHome
# This file contains unique settings for specific air conditioner
#===================================================================================
# KITCHEN AIR CONDITIONER
#===================================================================================
substitutions:
devicename: kitchen_ac
upper_devicename: Kitchen AC
# use different wifi_ip and wifi_ota_ip in case of esp ip-address change
# if ip haven't changed wifi_ip and wifi_ota_ip should be the same
wifi_ip: !secret wifi_ip_kitchen
wifi_ota_ip: !secret wifi_ota_ip_kitchen
<<: !include ac_common.yaml

View File

@@ -1,17 +0,0 @@
# compile this file with ESPHome
# This file contains unique settings for specific air conditioner
#===================================================================================
# LIVINGROOM AIR CONDITIONER
#===================================================================================
substitutions:
devicename: livingroom_ac
upper_devicename: Livingroom AC
# use different wifi_ip and wifi_ota_ip in case of esp ip-address change
# if ip haven't changed wifi_ip and wifi_ota_ip should be the same
wifi_ip: !secret wifi_ip_livingroom
wifi_ota_ip: !secret wifi_ota_ip_livingroom
<<: !include ac_common.yaml

View File

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

View File

@@ -1,47 +0,0 @@
external_components:
- source: github://GrKoR/esphome_aux_ac_component
components: [ aux_ac ]
refresh: 0s
esphome:
name: aux_air_conditioner
platform: ESP8266
board: esp12e
# don't forget to set your's wifi settings!
wifi:
ssid: "WIFI SSID"
password: "seCRETpassWORD"
manual_ip:
static_ip: 192.168.0.2
gateway: 192.168.0.1
subnet: 255.255.255.0
ap:
ssid: AUX Hotspot
password: "seCREThotSPOTpassWORD"
captive_portal:
debug:
logger:
level: DEBUG
baud_rate: 0
api:
ota:
# UART0 configuration for AUX air conditioner communication
uart:
id: ac_uart_bus
# ATTENTION! Use GPIO4 (D2) and GPIO5 (D1) as the TX and RX for NodeMCU-like boards!
tx_pin: GPIO1
rx_pin: GPIO3
baud_rate: 4800
data_bits: 8
parity: EVEN
stop_bits: 1
climate:
- platform: aux_ac
name: "AC Name"

10
tests/.gitignore vendored
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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: 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
baud_rate: 4800
data_bits: 8
parity: EVEN
stop_bits: 1
climate:
- platform: aux_ac
name: $upper_devicename