Initial commit: esphome-xtool-ap2 ESPHome component
Control one or two xTool SafetyPro AP2 air purifiers over BLE and expose them to Home Assistant via an ESP32 (the ap2_hub external component): per-slot fan control with live gear sync, runtime-settable flash-persisted MACs, an on-device scanner, M9033 status polling (filter life, serial, firmware), buzzer control, and BLE bonding. Includes the PC debug tool (tools/ap2_ble.py) and the reverse-engineered protocol spec (SPEC.md). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/text/text.h"
|
||||
#include "ap2_hub.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace ap2_hub {
|
||||
|
||||
/* HA text input for a slot's MAC. Writing a value retargets+persists the slot;
|
||||
* an empty value clears it. Publishes the restored MAC back to HA on boot. */
|
||||
class AP2MacText : public text::Text, public Component {
|
||||
public:
|
||||
void set_hub(AP2Hub *hub) { this->hub_ = hub; }
|
||||
void set_slot(uint8_t slot) { this->slot_ = slot; }
|
||||
|
||||
void loop() override {
|
||||
if (this->published_ || this->hub_ == nullptr || this->hub_->get_slot(this->slot_) == nullptr)
|
||||
return;
|
||||
this->publish_state(this->hub_->slot_mac_str(this->slot_));
|
||||
this->published_ = true;
|
||||
}
|
||||
|
||||
protected:
|
||||
void control(const std::string &value) override {
|
||||
if (this->hub_ != nullptr) {
|
||||
this->hub_->set_slot_mac(this->slot_, value);
|
||||
this->publish_state(this->hub_->slot_mac_str(this->slot_)); // normalized / cleared
|
||||
} else {
|
||||
this->publish_state(value);
|
||||
}
|
||||
}
|
||||
|
||||
AP2Hub *hub_{nullptr};
|
||||
uint8_t slot_{0};
|
||||
bool published_{false};
|
||||
};
|
||||
|
||||
} // namespace ap2_hub
|
||||
} // namespace esphome
|
||||
Reference in New Issue
Block a user