From 417dbe34cd36949b761c73033b349fbb4f57d40f Mon Sep 17 00:00:00 2001 From: Thomas Peterson Date: Wed, 11 Feb 2026 14:21:43 +0100 Subject: [PATCH] netzwerk --- displayprodLinux/Network.share.xml | 324 ++++++++++++++++++++++++++ displayprodLinux/SmartHomeDisplay.xml | 5 + main/CMakeLists.txt | 2 +- main/Hardware/Eth.cpp | 43 ++++ main/Hardware/Eth.hpp | 11 + main/NetworkConfig.cpp | 96 ++++++++ main/NetworkConfig.hpp | 8 + main/Wifi.cpp | 46 +++- main/Wifi.hpp | 6 + main/main.cpp | 5 + 10 files changed, 542 insertions(+), 4 deletions(-) create mode 100644 displayprodLinux/Network.share.xml create mode 100644 main/NetworkConfig.cpp create mode 100644 main/NetworkConfig.hpp diff --git a/displayprodLinux/Network.share.xml b/displayprodLinux/Network.share.xml new file mode 100644 index 0000000..6198b6a --- /dev/null +++ b/displayprodLinux/Network.share.xml @@ -0,0 +1,324 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/displayprodLinux/SmartHomeDisplay.xml b/displayprodLinux/SmartHomeDisplay.xml index 94b9e72..569d3e0 100644 --- a/displayprodLinux/SmartHomeDisplay.xml +++ b/displayprodLinux/SmartHomeDisplay.xml @@ -25,6 +25,11 @@ + + + #include #include "esp_event.h" +#include "esp_netif.h" #include "freertos/FreeRTOS.h" #include "freertos/event_groups.h" +struct StaticIpConfig { + uint8_t ip[4]; + uint8_t subnet[4]; + uint8_t gateway[4]; + uint8_t dns[4]; +}; + class Eth { public: static Eth& instance(); void init(); + void applyStaticIp(const StaticIpConfig& cfg); + std::string getIPAddress(); private: Eth() = default; @@ -25,4 +35,5 @@ private: bool initialized_ = false; EventGroupHandle_t ethEventGroup_ = nullptr; + esp_netif_t* netif_ = nullptr; }; \ No newline at end of file diff --git a/main/NetworkConfig.cpp b/main/NetworkConfig.cpp new file mode 100644 index 0000000..e2d258e --- /dev/null +++ b/main/NetworkConfig.cpp @@ -0,0 +1,96 @@ +#include "NetworkConfig.hpp" +#include "Hardware/Eth.hpp" +#include "Wifi.hpp" +#include "knx_facade.h" +#include "esp_log.h" + +static const char* TAG = "NetworkConfig"; + +// Parameter offsets within the NW module's parameter block. +// These must match the offsets generated by OpenKNXproducer for the NW module. +// The producer assigns a base offset; these are relative offsets within Network.share.xml. +// After running the producer, update NW_PARAM_BASE to the assigned base offset. + +static constexpr uint16_t NW_PARAM_BASE = 0; // Will be set by producer + +// Byte 0: Flags +static constexpr uint16_t NW_FLAGS = NW_PARAM_BASE + 0; +static constexpr uint8_t NW_LAN_ENABLE_MASK = 0x80; // Bit 7 +static constexpr uint8_t NW_LAN_STATIC_MASK = 0x40; // Bit 6 +static constexpr uint8_t NW_WLAN_ENABLE_MASK = 0x20; // Bit 5 +static constexpr uint8_t NW_WLAN_STATIC_MASK = 0x10; // Bit 4 + +// LAN IP config: bytes 1-16 +static constexpr uint16_t NW_LAN_IP = NW_PARAM_BASE + 1; +static constexpr uint16_t NW_LAN_SUBNET = NW_PARAM_BASE + 5; +static constexpr uint16_t NW_LAN_GATEWAY = NW_PARAM_BASE + 9; +static constexpr uint16_t NW_LAN_DNS = NW_PARAM_BASE + 13; + +// WLAN IP config: bytes 17-32 +static constexpr uint16_t NW_WLAN_IP = NW_PARAM_BASE + 17; +static constexpr uint16_t NW_WLAN_SUBNET = NW_PARAM_BASE + 21; +static constexpr uint16_t NW_WLAN_GATEWAY = NW_PARAM_BASE + 25; +static constexpr uint16_t NW_WLAN_DNS = NW_PARAM_BASE + 29; + +extern KnxFacade knx; + +static void readIpOctets(uint16_t offset, uint8_t out[4]) { + for (int i = 0; i < 4; i++) { + out[i] = knx.paramByte(offset + i); + } +} + +void NetworkConfig::applyFromKnx() { + if (!knx.configured()) { + ESP_LOGW(TAG, "KNX not configured, using default network settings"); + return; + } + + uint8_t flags = knx.paramByte(NW_FLAGS); + bool lanEnabled = (flags & NW_LAN_ENABLE_MASK) != 0; + bool lanStatic = (flags & NW_LAN_STATIC_MASK) != 0; + bool wlanEnabled = (flags & NW_WLAN_ENABLE_MASK) != 0; + bool wlanStatic = (flags & NW_WLAN_STATIC_MASK) != 0; + + ESP_LOGI(TAG, "Network config: LAN=%s(%s) WLAN=%s(%s)", + lanEnabled ? "on" : "off", lanStatic ? "static" : "dhcp", + wlanEnabled ? "on" : "off", wlanStatic ? "static" : "dhcp"); + + // Apply LAN static IP if configured + if (lanEnabled && lanStatic) { + StaticIpConfig cfg = {}; + readIpOctets(NW_LAN_IP, cfg.ip); + readIpOctets(NW_LAN_SUBNET, cfg.subnet); + readIpOctets(NW_LAN_GATEWAY, cfg.gateway); + readIpOctets(NW_LAN_DNS, cfg.dns); + + ESP_LOGI(TAG, "LAN static: %d.%d.%d.%d/%d.%d.%d.%d gw %d.%d.%d.%d dns %d.%d.%d.%d", + cfg.ip[0], cfg.ip[1], cfg.ip[2], cfg.ip[3], + cfg.subnet[0], cfg.subnet[1], cfg.subnet[2], cfg.subnet[3], + cfg.gateway[0], cfg.gateway[1], cfg.gateway[2], cfg.gateway[3], + cfg.dns[0], cfg.dns[1], cfg.dns[2], cfg.dns[3]); + + Eth::instance().applyStaticIp(cfg); + } + + // Initialize WLAN if enabled + if (wlanEnabled) { + Wifi::instance().init(); + + if (wlanStatic) { + StaticIpConfig cfg = {}; + readIpOctets(NW_WLAN_IP, cfg.ip); + readIpOctets(NW_WLAN_SUBNET, cfg.subnet); + readIpOctets(NW_WLAN_GATEWAY, cfg.gateway); + readIpOctets(NW_WLAN_DNS, cfg.dns); + + ESP_LOGI(TAG, "WLAN static: %d.%d.%d.%d/%d.%d.%d.%d gw %d.%d.%d.%d dns %d.%d.%d.%d", + cfg.ip[0], cfg.ip[1], cfg.ip[2], cfg.ip[3], + cfg.subnet[0], cfg.subnet[1], cfg.subnet[2], cfg.subnet[3], + cfg.gateway[0], cfg.gateway[1], cfg.gateway[2], cfg.gateway[3], + cfg.dns[0], cfg.dns[1], cfg.dns[2], cfg.dns[3]); + + Wifi::instance().applyStaticIp(cfg); + } + } +} diff --git a/main/NetworkConfig.hpp b/main/NetworkConfig.hpp new file mode 100644 index 0000000..c9c03ac --- /dev/null +++ b/main/NetworkConfig.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include + +class NetworkConfig { +public: + static void applyFromKnx(); +}; diff --git a/main/Wifi.cpp b/main/Wifi.cpp index 0be16e1..7894505 100644 --- a/main/Wifi.cpp +++ b/main/Wifi.cpp @@ -1,9 +1,11 @@ #include "Wifi.hpp" +#include "Hardware/Eth.hpp" #include "sdkconfig.h" #include "esp_log.h" #include "esp_netif.h" #include "nvs_flash.h" #include "nvs.h" +#include "lwip/ip4_addr.h" #include #include @@ -61,9 +63,8 @@ void Wifi::init() { wifiEventGroup_ = xEventGroupCreate(); - ESP_ERROR_CHECK(esp_netif_init()); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - esp_netif_create_default_wifi_sta(); + // esp_netif_init() and esp_event_loop_create_default() are already called by Eth::init() + netif_ = esp_netif_create_default_wifi_sta(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); @@ -323,3 +324,42 @@ bool Wifi::getSavedPassword(const char* ssid, std::string& password) { nvs_close(handle); return false; } + +void Wifi::applyStaticIp(const StaticIpConfig& cfg) { + if (!netif_) { + ESP_LOGW(TAG, "applyStaticIp: no netif"); + return; + } + + esp_netif_dhcpc_stop(netif_); + + esp_netif_ip_info_t ip_info = {}; + IP4_ADDR(&ip_info.ip, cfg.ip[0], cfg.ip[1], cfg.ip[2], cfg.ip[3]); + IP4_ADDR(&ip_info.netmask, cfg.subnet[0], cfg.subnet[1], cfg.subnet[2], cfg.subnet[3]); + IP4_ADDR(&ip_info.gw, cfg.gateway[0], cfg.gateway[1], cfg.gateway[2], cfg.gateway[3]); + + esp_err_t err = esp_netif_set_ip_info(netif_, &ip_info); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to set static IP: %s", esp_err_to_name(err)); + esp_netif_dhcpc_start(netif_); + return; + } + + esp_netif_dns_info_t dns_info = {}; + IP4_ADDR(&dns_info.ip.u_addr.ip4, cfg.dns[0], cfg.dns[1], cfg.dns[2], cfg.dns[3]); + dns_info.ip.type = ESP_IPADDR_TYPE_V4; + esp_netif_set_dns_info(netif_, ESP_NETIF_DNS_MAIN, &dns_info); + + ESP_LOGI(TAG, "WiFi static IP set: %d.%d.%d.%d", cfg.ip[0], cfg.ip[1], cfg.ip[2], cfg.ip[3]); +} + +std::string Wifi::getIPAddress() { + if (!netif_) return ""; + esp_netif_ip_info_t ip_info; + if (esp_netif_get_ip_info(netif_, &ip_info) == ESP_OK) { + char buf[16]; + snprintf(buf, sizeof(buf), IPSTR, IP2STR(&ip_info.ip)); + return buf; + } + return ""; +} diff --git a/main/Wifi.hpp b/main/Wifi.hpp index 10d9590..926050f 100644 --- a/main/Wifi.hpp +++ b/main/Wifi.hpp @@ -5,14 +5,18 @@ #include #include "esp_wifi.h" #include "esp_event.h" +#include "esp_netif.h" #include "freertos/FreeRTOS.h" #include "freertos/event_groups.h" +struct StaticIpConfig; + class Wifi { public: static Wifi& instance(); void init(); + void applyStaticIp(const StaticIpConfig& cfg); void scan(std::function&)> callback); void connect(const char* ssid, const char* password); void disconnect(); @@ -52,4 +56,6 @@ private: static constexpr const char* NVS_NAMESPACE = "wifi_creds"; static constexpr int MAX_SAVED_NETWORKS = 10; + + esp_netif_t* netif_ = nullptr; }; diff --git a/main/main.cpp b/main/main.cpp index 9a00599..28b0a5b 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -13,6 +13,7 @@ #include "KnxWorker.hpp" #include "Wifi.hpp" #include "Hardware/Eth.hpp" +#include "NetworkConfig.hpp" #include "WebServer.hpp" #include "SdCard.hpp" #include "Fonts.hpp" @@ -22,6 +23,10 @@ static void knx_task(void* arg) { KnxWorker* worker = static_cast(arg); worker->init(); + + // Apply network config from KNX parameters after KNX is initialized + NetworkConfig::applyFromKnx(); + while (true) { worker->loop(); vTaskDelay(pdMS_TO_TICKS(10));