diff --git a/components/ratgdo/number/__init__.py b/components/ratgdo/number/__init__.py index a0f4cbd..38b4bae 100644 --- a/components/ratgdo/number/__init__.py +++ b/components/ratgdo/number/__init__.py @@ -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, } diff --git a/components/ratgdo/number/ratgdo_number.cpp b/components/ratgdo/number/ratgdo_number.cpp index 2139c81..7baf728 100644 --- a/components/ratgdo/number/ratgdo_number.cpp +++ b/components/ratgdo/number/ratgdo_number.cpp @@ -4,26 +4,12 @@ namespace esphome::ratgdo { -using protocol::SetClientID; - -float normalize_client_id(float client_id) -{ - uint32_t int_value = static_cast(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(); 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(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(value) }); - break; default: break; } diff --git a/components/ratgdo/number/ratgdo_number.h b/components/ratgdo/number/ratgdo_number.h index d2457fa..0f50fe9 100644 --- a/components/ratgdo/number/ratgdo_number.h +++ b/components/ratgdo/number/ratgdo_number.h @@ -9,7 +9,6 @@ namespace esphome::ratgdo { enum NumberType { - RATGDO_CLIENT_ID, RATGDO_OPENING_DURATION, RATGDO_CLOSING_DURATION, }; diff --git a/components/ratgdo/protocol.h b/components/ratgdo/protocol.h index 1a773cd..6f42c5c 100644 --- a/components/ratgdo/protocol.h +++ b/components/ratgdo/protocol.h @@ -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), ) diff --git a/components/ratgdo/secplus2.cpp b/components/ratgdo/secplus2.cpp index 0bbc4e0..9081adb 100644 --- a/components/ratgdo/secplus2.cpp +++ b/components/ratgdo/secplus2.cpp @@ -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(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(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 diff --git a/components/ratgdo/secplus2.h b/components/ratgdo/secplus2.h index 754b382..abe6328 100644 --- a/components/ratgdo/secplus2.h +++ b/components/ratgdo/secplus2.h @@ -139,7 +139,9 @@ namespace secplus2 { // Larger structures single_observable 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 on_command_sent_; RatgdoUART uart_; diff --git a/garage-gate.yaml b/garage-gate.yaml index f8f326b..9a3aac5 100644 --- a/garage-gate.yaml +++ b/garage-gate.yaml @@ -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