Manage client ID internally only

This commit is contained in:
2026-05-23 10:34:51 +00:00
parent 641883f254
commit fc4d63e99e
7 changed files with 50 additions and 56 deletions
-1
View File
@@ -15,7 +15,6 @@ NumberType = ratgdo_ns.enum("NumberType")
CONF_TYPE = "type"
TYPES = {
"client_id": NumberType.RATGDO_CLIENT_ID,
"opening_duration": NumberType.RATGDO_OPENING_DURATION,
"closing_duration": NumberType.RATGDO_CLOSING_DURATION,
}
+1 -36
View File
@@ -4,26 +4,12 @@
namespace esphome::ratgdo {
using protocol::SetClientID;
float normalize_client_id(float client_id)
{
uint32_t int_value = static_cast<uint32_t>(client_id);
if ((int_value & 0xFFF) != 0x539) {
client_id = ceil((client_id - 0x539) / 0x1000) * 0x1000 + 0x539;
}
return client_id;
}
static const char* const TAG = "ratgdo.number";
void RATGDONumber::dump_config()
{
LOG_NUMBER("", "RATGDO Number", this);
switch (this->number_type_) {
case RATGDO_CLIENT_ID:
ESP_LOGCONFIG(TAG, " Type: Client ID");
break;
case RATGDO_OPENING_DURATION:
ESP_LOGCONFIG(TAG, " Type: Opening Duration");
break;
@@ -40,19 +26,7 @@ void RATGDONumber::setup()
float value;
this->pref_ = this->make_entity_preference<float>();
if (!this->pref_.load(&value)) {
if (this->number_type_ == RATGDO_CLIENT_ID) {
value = ((random_uint32() + 1) % 0x7FF) << 12 | 0x539; // max size limited to be precisely convertible to float
} else {
value = 0;
}
} else {
if (this->number_type_ == RATGDO_CLIENT_ID) {
uint32_t int_value = static_cast<uint32_t>(value);
if ((int_value & 0xFFF) != 0x539) {
value = ((random_uint32() + 1) % 0x7FF) << 12 | 0x539; // max size limited to be precisely convertible to float
this->pref_.save(&value);
}
}
value = 0;
}
this->control(value);
@@ -82,11 +56,6 @@ void RATGDONumber::set_number_type(NumberType number_type_)
this->traits.set_min_value(0.0);
this->traits.set_max_value(180.0);
break;
case RATGDO_CLIENT_ID:
this->traits.set_step(0x1000);
this->traits.set_min_value(0x539);
this->traits.set_max_value(0x7ff539);
break;
default:
break;
}
@@ -110,10 +79,6 @@ void RATGDONumber::control(float value)
case RATGDO_CLOSING_DURATION:
this->parent_->set_closing_duration(value);
break;
case RATGDO_CLIENT_ID:
value = normalize_client_id(value);
this->parent_->call_protocol(SetClientID { static_cast<uint32_t>(value) });
break;
default:
break;
}
-1
View File
@@ -9,7 +9,6 @@
namespace esphome::ratgdo {
enum NumberType {
RATGDO_CLIENT_ID,
RATGDO_OPENING_DURATION,
RATGDO_CLOSING_DURATION,
};
-4
View File
@@ -16,9 +16,6 @@ class RATGDOComponent;
namespace protocol {
struct SetClientID {
uint64_t client_id;
};
struct QueryStatus {
};
struct QueryOpenings {
@@ -26,7 +23,6 @@ namespace protocol {
// a poor man's sum-type, because C++
SUM_TYPE(Args,
(SetClientID, set_client_id),
(QueryStatus, query_status),
(QueryOpenings, query_openings), )
+46 -8
View File
@@ -36,7 +36,39 @@ namespace secplus2 {
this->rx_pin_ = rx_pin;
if (mqtt::global_mqtt_client != nullptr) {
this->mqtt_topic_ = mqtt::global_mqtt_client->get_topic_prefix() + "/rolling_code";
this->mqtt_rolling_code_topic_ = mqtt::global_mqtt_client->get_topic_prefix() + "/gdo/rolling_code";
this->mqtt_client_id_topic_ = mqtt::global_mqtt_client->get_topic_prefix() + "/gdo/client_id";
}
this->client_id_pref_ = global_preferences->make_preference<uint32_t>(3497851610U); // fnv1_hash("ratgdo_client_id")
uint32_t stored_client_id;
if (this->client_id_pref_.load(&stored_client_id)) {
this->client_id_ = stored_client_id;
ESP_LOGI(TAG, "Restored Client ID from flash: 0x%04X", (unsigned)this->client_id_);
if (mqtt::global_mqtt_client != nullptr) {
mqtt::global_mqtt_client->publish(this->mqtt_client_id_topic_, std::to_string(this->client_id_), 0, true);
}
} else if (mqtt::global_mqtt_client != nullptr) {
ESP_LOGI(TAG, "No Client ID in flash, waiting for MQTT: %s", this->mqtt_client_id_topic_.c_str());
mqtt::global_mqtt_client->subscribe(
this->mqtt_client_id_topic_,
[this](const std::string& topic, const std::string& payload) {
if (this->client_id_ == 0x539) {
uint32_t cid = strtoul(payload.c_str(), nullptr, 10);
if (cid != 0) {
ESP_LOGI(TAG, "Received Client ID from MQTT: 0x%04X", (unsigned)cid);
this->set_client_id(cid);
}
}
},
1);
} else {
// Generate a unique ID on first boot.
// We use a range that avoids common reserved IDs.
uint32_t new_id = (random_uint32() & 0xFFFFF) | 0x539;
this->client_id_ = new_id;
this->client_id_pref_.save(&new_id);
ESP_LOGI(TAG, "Generated new unique Client ID: 0x%04X", (unsigned)new_id);
}
this->rolling_code_pref_ = global_preferences->make_preference<uint32_t>(1868352652U); // fnv1_hash("ratgdo_rolling_code")
@@ -44,10 +76,13 @@ namespace secplus2 {
if (this->rolling_code_pref_.load(&rolling_code)) {
this->rolling_code_counter_ = rolling_code;
ESP_LOGI(TAG, "Restored rolling code from flash: %u", rolling_code);
if (mqtt::global_mqtt_client != nullptr) {
mqtt::global_mqtt_client->publish(this->mqtt_rolling_code_topic_, std::to_string(rolling_code), 0, true);
}
} else if (mqtt::global_mqtt_client != nullptr) {
ESP_LOGI(TAG, "No rolling code in flash, waiting for MQTT: %s", this->mqtt_topic_.c_str());
ESP_LOGI(TAG, "No rolling code in flash, waiting for MQTT: %s", this->mqtt_rolling_code_topic_.c_str());
mqtt::global_mqtt_client->subscribe(
this->mqtt_topic_,
this->mqtt_rolling_code_topic_,
[this](const std::string& topic, const std::string& payload) {
if (*this->rolling_code_counter_ == 0) {
uint32_t rc = strtoul(payload.c_str(), nullptr, 10);
@@ -164,8 +199,6 @@ namespace secplus2 {
this->send_command(CommandType::GET_STATUS);
} else if (args.tag == Tag::query_openings) {
this->send_command(CommandType::GET_OPENINGS);
} else if (args.tag == Tag::set_client_id) {
this->set_client_id(args.value.set_client_id.client_id);
}
return { };
}
@@ -362,7 +395,7 @@ namespace secplus2 {
this->rolling_code_counter_ = counter;
this->rolling_code_pref_.save(&counter);
if (mqtt::global_mqtt_client != nullptr) {
mqtt::global_mqtt_client->publish(this->mqtt_topic_, std::to_string(counter), 0, true);
mqtt::global_mqtt_client->publish(this->mqtt_rolling_code_topic_, std::to_string(counter), 0, true);
}
}
@@ -372,13 +405,18 @@ namespace secplus2 {
this->rolling_code_counter_ = counter;
this->rolling_code_pref_.save(&counter);
if (mqtt::global_mqtt_client != nullptr) {
mqtt::global_mqtt_client->publish(this->mqtt_topic_, std::to_string(counter), 0, true);
mqtt::global_mqtt_client->publish(this->mqtt_rolling_code_topic_, std::to_string(counter), 0, true);
}
}
void Secplus2::set_client_id(uint64_t client_id)
{
this->client_id_ = client_id & 0xFFFFFFFF;
uint32_t cid = client_id & 0xFFFFFFFF;
this->client_id_ = cid;
this->client_id_pref_.save(&cid);
if (mqtt::global_mqtt_client != nullptr) {
mqtt::global_mqtt_client->publish(this->mqtt_client_id_topic_, std::to_string(cid), 0, true);
}
}
} // namespace secplus2
+3 -1
View File
@@ -139,7 +139,9 @@ namespace secplus2 {
// Larger structures
single_observable<uint32_t> rolling_code_counter_ { 0 };
ESPPreferenceObject rolling_code_pref_;
std::string mqtt_topic_;
ESPPreferenceObject client_id_pref_;
std::string mqtt_rolling_code_topic_;
std::string mqtt_client_id_topic_;
OnceCallbacks<void()> on_command_sent_;
RatgdoUART uart_;
-5
View File
@@ -105,11 +105,6 @@ number:
entity_category: config
name: "Closing duration"
unit_of_measurement: "s"
- platform: ratgdo
type: client_id
entity_category: config
name: "Client ID"
mode: box
cover:
- platform: ratgdo