feat: Enhance EtsDeviceRuntime constructor and multicast handling
- Updated EtsDeviceRuntime constructor to accept an optional tunnel_client_address parameter with a default value of 0. - Modified EspIdfPlatform::setupMultiCast to use IPPROTO_UDP for socket creation and improved multicast interface selection based on the current IP address. - Ensured that the multicast interface is set only if a valid local address is available. - Adjusted the client address assignment in EtsDeviceRuntime to use the provided tunnel_client_address if valid, falling back to the default otherwise. Signed-off-by: Tony <tonylu@tony-cloud.com>
This commit is contained in:
@@ -2198,11 +2198,36 @@ struct GatewayBridgeService::ChannelRuntime {
|
||||
|
||||
cJSON* knx_json = cJSON_CreateObject();
|
||||
if (knx_json != nullptr) {
|
||||
auto* endpoint_runtime = service.knx_endpoint_runtime_;
|
||||
if (endpoint_runtime == nullptr) {
|
||||
endpoint_runtime = const_cast<GatewayBridgeService&>(service).selectKnxEndpointRuntime();
|
||||
}
|
||||
bool programming_mode = false;
|
||||
bool programming_control_available = false;
|
||||
int endpoint_owner_gateway_id = -1;
|
||||
if (endpoint_runtime != nullptr) {
|
||||
LockGuard owner_guard(endpoint_runtime->lock);
|
||||
endpoint_owner_gateway_id = endpoint_runtime->channel.gateway_id;
|
||||
programming_control_available = endpoint_runtime->knx_router != nullptr &&
|
||||
endpoint_runtime->knx_router->started();
|
||||
if (programming_control_available) {
|
||||
programming_mode = endpoint_runtime->knx_router->programmingMode();
|
||||
}
|
||||
}
|
||||
const auto effective_knx = knx_config.has_value() ? knx_config : service_config.default_knx_config;
|
||||
cJSON_AddBoolToObject(knx_json, "enabled", service_config.knx_enabled);
|
||||
cJSON_AddBoolToObject(knx_json, "startupEnabled", service_config.knx_startup_enabled);
|
||||
cJSON_AddBoolToObject(knx_json, "started", knx_started);
|
||||
cJSON_AddBoolToObject(knx_json, "routerReady", knx_router != nullptr && knx_router->started());
|
||||
cJSON_AddBoolToObject(knx_json, "programmingMode", programming_mode);
|
||||
cJSON_AddBoolToObject(knx_json, "programmingControlAvailable",
|
||||
programming_control_available);
|
||||
cJSON_AddBoolToObject(knx_json, "endpointOwner",
|
||||
endpoint_owner_gateway_id == channel.gateway_id);
|
||||
if (endpoint_owner_gateway_id >= 0) {
|
||||
cJSON_AddNumberToObject(knx_json, "endpointOwnerGatewayId",
|
||||
endpoint_owner_gateway_id);
|
||||
}
|
||||
const std::string router_error = knx_router == nullptr ? "" : knx_router->lastError();
|
||||
cJSON_AddStringToObject(knx_json, "lastError",
|
||||
knx_last_error.empty() ? router_error.c_str()
|
||||
@@ -2269,6 +2294,8 @@ struct GatewayBridgeService::ChannelRuntime {
|
||||
cJSON_AddNumberToObject(knx_json, "udpPort", effective_knx->udp_port);
|
||||
cJSON_AddStringToObject(knx_json, "multicastAddress",
|
||||
effective_knx->multicast_address.c_str());
|
||||
cJSON_AddNumberToObject(knx_json, "ipInterfaceIndividualAddress",
|
||||
effective_knx->ip_interface_individual_address);
|
||||
cJSON_AddNumberToObject(knx_json, "individualAddress",
|
||||
effective_knx->individual_address);
|
||||
cJSON* serial_json = cJSON_CreateObject();
|
||||
@@ -3066,6 +3093,25 @@ struct GatewayBridgeService::ChannelRuntime {
|
||||
}
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (config.ip_interface_individual_address == 0 ||
|
||||
config.ip_interface_individual_address == 0xffff) {
|
||||
if (error_message != nullptr) {
|
||||
*error_message = "KNX IP interface individual address must be a configured address";
|
||||
}
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (config.individual_address == 0 || config.individual_address == 0xffff) {
|
||||
if (error_message != nullptr) {
|
||||
*error_message = "KNX-DALI gateway individual address must be a configured address";
|
||||
}
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (config.ip_interface_individual_address == config.individual_address) {
|
||||
if (error_message != nullptr) {
|
||||
*error_message = "KNX IP interface and KNX-DALI gateway addresses must differ";
|
||||
}
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (!config.ip_router_enabled || !GatewayKnxConfigUsesTpUart(config)) {
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -3162,10 +3208,10 @@ struct GatewayBridgeService::ChannelRuntime {
|
||||
GatewayKnxConfig config = service_config.default_knx_config.value();
|
||||
const uint8_t channel_index = channel.channel_index;
|
||||
config.main_group = static_cast<uint8_t>(std::min<int>(31, config.main_group + channel_index));
|
||||
const uint16_t device = config.individual_address & 0x00ff;
|
||||
const uint16_t device = config.ip_interface_individual_address & 0x00ff;
|
||||
if (device > 0 && device + channel_index <= 0x00ff) {
|
||||
config.individual_address = static_cast<uint16_t>((config.individual_address & 0xff00) |
|
||||
(device + channel_index));
|
||||
config.ip_interface_individual_address = static_cast<uint16_t>(
|
||||
(config.ip_interface_individual_address & 0xff00) | (device + channel_index));
|
||||
}
|
||||
return config;
|
||||
}
|
||||
@@ -4415,6 +4461,40 @@ GatewayBridgeHttpResponse GatewayBridgeService::handlePost(
|
||||
}
|
||||
return handleGet("knx", gateway_id.value());
|
||||
}
|
||||
if (action == "knx_programming_mode") {
|
||||
cJSON* body_root = body.empty() ? nullptr : cJSON_ParseWithLength(body.data(), body.size());
|
||||
if (body_root == nullptr) {
|
||||
return ErrorResponse(ESP_ERR_INVALID_ARG, "KNX programming mode JSON is required");
|
||||
}
|
||||
const cJSON* enabled_item = cJSON_GetObjectItemCaseSensitive(body_root, "enabled");
|
||||
if (!cJSON_IsBool(enabled_item)) {
|
||||
cJSON_Delete(body_root);
|
||||
return ErrorResponse(ESP_ERR_INVALID_ARG, "boolean enabled field is required");
|
||||
}
|
||||
const bool enabled = cJSON_IsTrue(enabled_item);
|
||||
cJSON_Delete(body_root);
|
||||
|
||||
ChannelRuntime* owner = selectKnxEndpointRuntime();
|
||||
if (owner == nullptr) {
|
||||
return ErrorResponse(ESP_ERR_NOT_FOUND, "no KNX/IP endpoint owner is configured");
|
||||
}
|
||||
|
||||
esp_err_t err = ESP_ERR_INVALID_STATE;
|
||||
std::string detail = "KNX/IP router is unavailable";
|
||||
{
|
||||
LockGuard guard(owner->lock);
|
||||
if (owner->knx_router != nullptr) {
|
||||
err = owner->knx_router->setProgrammingMode(enabled);
|
||||
detail = owner->knx_router->lastError();
|
||||
}
|
||||
owner->knx_last_error = err == ESP_OK ? std::string() : detail;
|
||||
}
|
||||
if (err != ESP_OK) {
|
||||
return ErrorResponse(err, detail.empty() ? "failed to change KNX programming mode"
|
||||
: detail.c_str());
|
||||
}
|
||||
return handleGet("status", gateway_id.value());
|
||||
}
|
||||
if (action == "knx_security_read_factory_key") {
|
||||
#if defined(CONFIG_GATEWAY_KNX_SECURITY_DEV_ENDPOINTS) && \
|
||||
defined(CONFIG_GATEWAY_KNX_DATA_SECURE_SUPPORTED)
|
||||
|
||||
Reference in New Issue
Block a user