feat(gateway): add ESP-Touch smartconfig provisioning support and enhance network management

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
Tony
2026-04-30 18:49:38 +08:00
parent 4ce3513dd2
commit ae4669e1b3
10 changed files with 338 additions and 43 deletions
@@ -185,6 +185,14 @@ bool GatewayController::setupMode() const {
return setup_mode_;
}
bool GatewayController::wirelessSetupMode() const {
return wireless_setup_mode_;
}
void GatewayController::setWirelessSetupMode(bool enabled) {
wireless_setup_mode_ = enabled;
}
bool GatewayController::bleEnabled() const {
return ble_enabled_;
}
@@ -200,6 +208,7 @@ bool GatewayController::ipRouterEnabled() const {
GatewayControllerSnapshot GatewayController::snapshot() {
GatewayControllerSnapshot out;
out.setup_mode = setup_mode_;
out.wireless_setup_mode = wireless_setup_mode_;
out.ble_enabled = ble_enabled_;
out.wifi_enabled = wifi_enabled_;
out.ip_router_enabled = ip_router_enabled_;
@@ -302,8 +311,13 @@ void GatewayController::dispatchCommand(const std::vector<uint8_t>& command) {
case 0x04:
if (addr == 0) {
wifi_enabled_ = false;
} else if (addr == 1 || addr == 101) {
wireless_setup_mode_ = false;
} else if (addr == 1) {
wifi_enabled_ = true;
wireless_setup_mode_ = false;
} else if (addr == 100 || addr == 101) {
wifi_enabled_ = true;
wireless_setup_mode_ = true;
}
for (const auto& sink : wifi_state_sinks_) {
sink(addr);
@@ -317,12 +331,9 @@ void GatewayController::dispatchCommand(const std::vector<uint8_t>& command) {
if (setup_mode_ && config_.setup_supported) {
feature |= 0x01;
}
if (config_.ble_supported) {
if (wireless_setup_mode_ && config_.wifi_supported) {
feature |= 0x02;
}
if (config_.wifi_supported) {
feature |= 0x04;
}
if (config_.ip_router_supported && ip_router_enabled_) {
feature |= 0x08;
}
@@ -593,6 +604,9 @@ bool GatewayController::setSceneEnabled(uint8_t gateway_id, uint8_t scene_id, bo
if (scene_data == nullptr) {
return false;
}
if (scene_data->enabled == enabled) {
return true;
}
scene_data->enabled = enabled;
return saveScene(gateway_id, scene_id);
}
@@ -604,21 +618,29 @@ bool GatewayController::setSceneDetail(uint8_t gateway_id, uint8_t scene_id, uin
if (scene_data == nullptr) {
return false;
}
scene_data->brightness = std::min<uint8_t>(brightness, 254);
scene_data->color_mode = std::min<uint8_t>(color_mode, 2);
if (scene_data->color_mode == 0) {
scene_data->data1 = data1;
scene_data->data2 = data2;
scene_data->data3 = 0;
} else if (scene_data->color_mode == 1) {
scene_data->data1 = data1;
scene_data->data2 = data2;
scene_data->data3 = data3;
} else {
scene_data->data1 = 0;
scene_data->data2 = 0;
scene_data->data3 = 0;
const uint8_t next_brightness = std::min<uint8_t>(brightness, 254);
const uint8_t next_color_mode = std::min<uint8_t>(color_mode, 2);
uint8_t next_data1 = 0;
uint8_t next_data2 = 0;
uint8_t next_data3 = 0;
if (next_color_mode == 0) {
next_data1 = data1;
next_data2 = data2;
} else if (next_color_mode == 1) {
next_data1 = data1;
next_data2 = data2;
next_data3 = data3;
}
if (scene_data->brightness == next_brightness && scene_data->color_mode == next_color_mode &&
scene_data->data1 == next_data1 && scene_data->data2 == next_data2 &&
scene_data->data3 == next_data3) {
return true;
}
scene_data->brightness = next_brightness;
scene_data->color_mode = next_color_mode;
scene_data->data1 = next_data1;
scene_data->data2 = next_data2;
scene_data->data3 = next_data3;
return saveScene(gateway_id, scene_id);
}
@@ -627,7 +649,11 @@ bool GatewayController::setSceneName(uint8_t gateway_id, uint8_t scene_id, std::
if (scene_data == nullptr) {
return false;
}
scene_data->name = NormalizeName(name);
const auto normalized = NormalizeName(name);
if (scene_data->name == normalized) {
return true;
}
scene_data->name = normalized;
return saveSceneName(gateway_id, scene_id, scene_data->name);
}
@@ -636,6 +662,13 @@ bool GatewayController::deleteScene(uint8_t gateway_id, uint8_t scene_id) {
if (scene_data == nullptr) {
return false;
}
const bool already_default = !scene_data->enabled && scene_data->brightness == 254 &&
scene_data->color_mode == 2 && scene_data->data1 == 0 &&
scene_data->data2 == 0 && scene_data->data3 == 0 &&
scene_data->name.empty();
if (already_default) {
return true;
}
*scene_data = InternalScene{};
deleteSceneStorage(gateway_id, scene_id);
deleteSceneNameStorage(gateway_id, scene_id);
@@ -688,6 +721,9 @@ bool GatewayController::setGroupEnabled(uint8_t gateway_id, uint8_t group_id, bo
if (group_data == nullptr) {
return false;
}
if (group_data->enabled == enabled) {
return true;
}
group_data->enabled = enabled;
return saveGroup(gateway_id, group_id);
}
@@ -698,8 +734,13 @@ bool GatewayController::setGroupDetail(uint8_t gateway_id, uint8_t group_id, uin
if (group_data == nullptr) {
return false;
}
group_data->target_type = normalizeGroupTargetType(target_type);
group_data->target_value = normalizeGroupTargetValue(group_data->target_type, target_value);
const uint8_t next_target_type = normalizeGroupTargetType(target_type);
const uint8_t next_target_value = normalizeGroupTargetValue(next_target_type, target_value);
if (group_data->target_type == next_target_type && group_data->target_value == next_target_value) {
return true;
}
group_data->target_type = next_target_type;
group_data->target_value = next_target_value;
return saveGroup(gateway_id, group_id);
}
@@ -708,7 +749,11 @@ bool GatewayController::setGroupName(uint8_t gateway_id, uint8_t group_id, std::
if (group_data == nullptr) {
return false;
}
group_data->name = NormalizeName(name);
const auto normalized = NormalizeName(name);
if (group_data->name == normalized) {
return true;
}
group_data->name = normalized;
return saveGroupName(gateway_id, group_id, group_data->name);
}
@@ -717,6 +762,11 @@ bool GatewayController::deleteGroup(uint8_t gateway_id, uint8_t group_id) {
if (group_data == nullptr) {
return false;
}
const bool already_default = !group_data->enabled && group_data->target_type == 2 &&
group_data->target_value == 0 && group_data->name.empty();
if (already_default) {
return true;
}
*group_data = InternalGroup{};
deleteGroupStorage(gateway_id, group_id);
deleteGroupNameStorage(gateway_id, group_id);
@@ -1125,7 +1175,10 @@ bool GatewayController::eraseKey(std::string_view key) {
return false;
}
const esp_err_t err = nvs_erase_key(storage_, std::string(key).c_str());
if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) {
if (err == ESP_ERR_NVS_NOT_FOUND) {
return true;
}
if (err != ESP_OK) {
return false;
}
return nvs_commit(storage_) == ESP_OK;