#include "NetworkConfig.hpp" #include "Hardware/Eth.hpp" #include "Wifi.hpp" #include "knx_facade.h" #include "esp_log.h" #include 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; // WLAN credentials: bytes 33-129 static constexpr uint16_t NW_WLAN_WPA = NW_PARAM_BASE + 33; static constexpr uint16_t NW_WLAN_SSID = NW_PARAM_BASE + 34; static constexpr uint16_t NW_WLAN_PASS = NW_PARAM_BASE + 66; static constexpr uint16_t NW_WLAN_SSID_LEN = 32; static constexpr uint16_t NW_WLAN_PASS_LEN = 64; 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); } } static std::string readParamString(uint16_t offset, uint16_t maxLen) { char buf[128] = {}; uint16_t len = (maxLen < sizeof(buf) - 1) ? maxLen : sizeof(buf) - 1; for (uint16_t i = 0; i < len; i++) { buf[i] = (char)knx.paramByte(offset + i); if (buf[i] == '\0') break; } buf[len] = '\0'; return std::string(buf); } static wifi_auth_mode_t wpaVersionToAuthMode(uint8_t wpaVersion) { switch (wpaVersion) { case 1: return WIFI_AUTH_WPA3_PSK; case 2: return WIFI_AUTH_WPA2_WPA3_PSK; default: return WIFI_AUTH_WPA2_PSK; } } 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); } // Read WLAN credentials from KNX parameters std::string ssid = readParamString(NW_WLAN_SSID, NW_WLAN_SSID_LEN); std::string password = readParamString(NW_WLAN_PASS, NW_WLAN_PASS_LEN); uint8_t wpaVersion = knx.paramByte(NW_WLAN_WPA); wifi_auth_mode_t authMode = wpaVersionToAuthMode(wpaVersion); if (!ssid.empty()) { ESP_LOGI(TAG, "WLAN connecting to SSID: %s (WPA=%d)", ssid.c_str(), wpaVersion); Wifi::instance().connect(ssid.c_str(), password.c_str(), authMode); } else { ESP_LOGW(TAG, "WLAN enabled but no SSID configured"); } } }