Phase 1 Ethernet IP address config

Phase 1 Ethernet IP address config (#14385)
- Currently unable to change DNS servers
This commit is contained in:
Theo Arends 2022-01-12 17:32:21 +01:00
parent 2f54cfdf9c
commit 04a4a656d2
3 changed files with 151 additions and 50 deletions

View File

@ -744,10 +744,11 @@ typedef struct {
uint8_t tcp_config; // F5F
uint8_t light_step_pixels; // F60
uint8_t free_f59[59]; // F61 - Decrement if adding new Setting variables just above and below
uint8_t free_f61[39]; // F61 - Decrement if adding new Setting variables just above and below
// Only 32 bit boundary variables below
uint32_t eth_ipv4_address[5]; // F88
uint32_t energy_kWhtotal; // F9C
SBitfield1 sbflag1; // FA0
TeleinfoCfg teleinfo; // FA4
@ -834,11 +835,6 @@ struct XDRVMAILBOX {
char *command;
} XdrvMailbox;
#ifdef USE_SHUTTER
const uint8_t MAX_RULES_FLAG = 11; // Number of bits used in RulesBitfield (tricky I know...)
#else
const uint8_t MAX_RULES_FLAG = 9; // Number of bits used in RulesBitfield (tricky I know...)
#endif // USE_SHUTTER
typedef union { // Restricted by MISRA-C Rule 18.4 but so useful...
uint16_t data; // Allow bit manipulation
struct {
@ -850,11 +846,11 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
uint16_t mqtt_disconnected : 1;
uint16_t wifi_connected : 1;
uint16_t wifi_disconnected : 1;
uint16_t eth_connected : 1;
uint16_t eth_disconnected : 1;
uint16_t http_init : 1;
uint16_t shutter_moved : 1;
uint16_t shutter_moving : 1;
uint16_t spare11 : 1;
uint16_t spare12 : 1;
uint16_t spare13 : 1;
uint16_t spare14 : 1;
uint16_t spare15 : 1;

View File

@ -960,32 +960,65 @@ void RulesEvery50ms(void)
}
}
else if (TasmotaGlobal.rules_flag.data) {
uint16_t mask = 1;
for (uint32_t i = 0; i < MAX_RULES_FLAG; i++) {
if (TasmotaGlobal.rules_flag.data & mask) {
TasmotaGlobal.rules_flag.data ^= mask;
json_event[0] = '\0';
switch (i) {
case 0: strncpy_P(json_event, PSTR("{\"System\":{\"Init\":1}}"), sizeof(json_event)); break;
case 1: strncpy_P(json_event, PSTR("{\"System\":{\"Boot\":1}}"), sizeof(json_event)); break;
case 2: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Initialized\":%d}}"), MinutesPastMidnight()); break;
case 3: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Set\":%d}}"), MinutesPastMidnight()); break;
case 4: strncpy_P(json_event, PSTR("{\"MQTT\":{\"Connected\":1}}"), sizeof(json_event)); break;
case 5: strncpy_P(json_event, PSTR("{\"MQTT\":{\"Disconnected\":1}}"), sizeof(json_event)); break;
case 6: strncpy_P(json_event, PSTR("{\"WIFI\":{\"Connected\":1}}"), sizeof(json_event)); break;
case 7: strncpy_P(json_event, PSTR("{\"WIFI\":{\"Disconnected\":1}}"), sizeof(json_event)); break;
case 8: strncpy_P(json_event, PSTR("{\"HTTP\":{\"Initialized\":1}}"), sizeof(json_event)); break;
json_event[0] = '\0';
if (TasmotaGlobal.rules_flag.system_init) {
TasmotaGlobal.rules_flag.system_init = 0;
strncpy_P(json_event, PSTR("{\"System\":{\"Init\":1}}"), sizeof(json_event));
}
else if (TasmotaGlobal.rules_flag.system_boot) {
TasmotaGlobal.rules_flag.system_boot = 0;
strncpy_P(json_event, PSTR("{\"System\":{\"Boot\":1}}"), sizeof(json_event));
}
else if (TasmotaGlobal.rules_flag.time_init) {
TasmotaGlobal.rules_flag.time_init = 0;
snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Initialized\":%d}}"), MinutesPastMidnight());
}
else if (TasmotaGlobal.rules_flag.time_set) {
TasmotaGlobal.rules_flag.time_set = 0;
snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Set\":%d}}"), MinutesPastMidnight());
}
else if (TasmotaGlobal.rules_flag.mqtt_connected) {
TasmotaGlobal.rules_flag.mqtt_connected = 0;
strncpy_P(json_event, PSTR("{\"MQTT\":{\"Connected\":1}}"), sizeof(json_event));
}
else if (TasmotaGlobal.rules_flag.mqtt_disconnected) {
TasmotaGlobal.rules_flag.mqtt_disconnected = 0;
strncpy_P(json_event, PSTR("{\"MQTT\":{\"Disconnected\":1}}"), sizeof(json_event));
}
else if (TasmotaGlobal.rules_flag.wifi_connected) {
TasmotaGlobal.rules_flag.wifi_connected = 0;
strncpy_P(json_event, PSTR("{\"WIFI\":{\"Connected\":1}}"), sizeof(json_event));
}
else if (TasmotaGlobal.rules_flag.wifi_disconnected) {
TasmotaGlobal.rules_flag.wifi_disconnected = 0;
strncpy_P(json_event, PSTR("{\"WIFI\":{\"Disconnected\":1}}"), sizeof(json_event));
}
#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32 && defined(USE_ETHERNET)
else if (TasmotaGlobal.rules_flag.eth_connected) {
TasmotaGlobal.rules_flag.eth_connected = 0;
strncpy_P(json_event, PSTR("{\"ETH\":{\"Connected\":1}}"), sizeof(json_event));
}
else if (TasmotaGlobal.rules_flag.eth_disconnected) {
TasmotaGlobal.rules_flag.eth_disconnected = 0;
strncpy_P(json_event, PSTR("{\"ETH\":{\"Disconnected\":1}}"), sizeof(json_event));
}
#endif
else if (TasmotaGlobal.rules_flag.http_init) {
TasmotaGlobal.rules_flag.http_init = 0;
strncpy_P(json_event, PSTR("{\"HTTP\":{\"Initialized\":1}}"), sizeof(json_event));
}
#ifdef USE_SHUTTER
case 9: strncpy_P(json_event, PSTR("{\"SHUTTER\":{\"Moved\":1}}"), sizeof(json_event)); break;
case 10: strncpy_P(json_event, PSTR("{\"SHUTTER\":{\"Moving\":1}}"), sizeof(json_event)); break;
else if (TasmotaGlobal.rules_flag.shutter_moved) {
TasmotaGlobal.rules_flag.shutter_moved = 0;
strncpy_P(json_event, PSTR("{\"SHUTTER\":{\"Moved\":1}}"), sizeof(json_event));
}
else if (TasmotaGlobal.rules_flag.shutter_moving) {
TasmotaGlobal.rules_flag.shutter_moving = 0;
strncpy_P(json_event, PSTR("{\"SHUTTER\":{\"Moving\":1}}"), sizeof(json_event));
}
#endif // USE_SHUTTER
}
if (json_event[0]) {
RulesProcessEvent(json_event);
break; // Only service one event within 50mS
}
}
mask <<= 1;
if (json_event[0]) {
RulesProcessEvent(json_event); // Only service one event within 50mS
}
}
}

View File

@ -83,6 +83,7 @@
#include <ETH.h>
char eth_hostname[sizeof(TasmotaGlobal.hostname)];
uint8_t eth_config_change;
void EthernetEvent(WiFiEvent_t event) {
switch (event) {
@ -97,14 +98,16 @@ void EthernetEvent(WiFiEvent_t event) {
case ARDUINO_EVENT_ETH_GOT_IP:
AddLog(LOG_LEVEL_DEBUG, PSTR("ETH: Mac %s, IPAddress %_I, Hostname %s"),
ETH.macAddress().c_str(), (uint32_t)ETH.localIP(), eth_hostname);
Settings->ipv4_address[1] = (uint32_t)ETH.gatewayIP();
Settings->ipv4_address[2] = (uint32_t)ETH.subnetMask();
Settings->ipv4_address[3] = (uint32_t)ETH.dnsIP();
Settings->ipv4_address[4] = (uint32_t)ETH.dnsIP(1);
Settings->eth_ipv4_address[1] = (uint32_t)ETH.gatewayIP();
Settings->eth_ipv4_address[2] = (uint32_t)ETH.subnetMask();
Settings->eth_ipv4_address[3] = (uint32_t)ETH.dnsIP();
Settings->eth_ipv4_address[4] = (uint32_t)ETH.dnsIP(1);
TasmotaGlobal.rules_flag.eth_connected = 1;
TasmotaGlobal.global_state.eth_down = 0;
break;
case ARDUINO_EVENT_ETH_DISCONNECTED:
AddLog(LOG_LEVEL_INFO, PSTR("ETH: Disconnected"));
TasmotaGlobal.rules_flag.eth_disconnected = 1;
TasmotaGlobal.global_state.eth_down = 1;
break;
case ARDUINO_EVENT_ETH_STOP:
@ -116,6 +119,11 @@ void EthernetEvent(WiFiEvent_t event) {
}
}
void EthernetSetIp(void) {
// IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2
ETH.config(Settings->eth_ipv4_address[0], Settings->eth_ipv4_address[1], Settings->eth_ipv4_address[2], Settings->eth_ipv4_address[3], Settings->eth_ipv4_address[4]); // Set static IP
}
void EthernetInit(void) {
if (!Settings->flag4.network_ethernet) { return; }
if (!PinUsed(GPIO_ETH_PHY_MDC) && !PinUsed(GPIO_ETH_PHY_MDIO)) {
@ -123,6 +131,8 @@ void EthernetInit(void) {
return;
}
eth_config_change = 0;
if (WT32_ETH01 == TasmotaGlobal.module_type) {
Settings->eth_address = 1; // EthAddress
Settings->eth_type = ETH_PHY_LAN8720; // EthType
@ -140,7 +150,12 @@ void EthernetInit(void) {
int eth_mdio = Pin(GPIO_ETH_PHY_MDIO);
if (!ETH.begin(Settings->eth_address, eth_power, eth_mdc, eth_mdio, (eth_phy_type_t)Settings->eth_type, (eth_clock_mode_t)Settings->eth_clk_mode)) {
AddLog(LOG_LEVEL_DEBUG, PSTR("ETH: Bad PHY type or init error"));
return;
};
if (Settings->eth_ipv4_address[0]) {
EthernetSetIp(); // Set static IP
}
}
IPAddress EthernetLocalIP(void) {
@ -155,22 +170,38 @@ String EthernetMacAddress(void) {
return ETH.macAddress();
}
void EthernetConfigChange(void) {
if (eth_config_change) {
eth_config_change--;
if (!eth_config_change) {
EthernetSetIp();
}
}
}
/*********************************************************************************************\
* Commands
\*********************************************************************************************/
#define D_CMND_ETHADDRESS "EthAddress"
#define D_CMND_ETHTYPE "EthType"
#define D_CMND_ETHCLOCKMODE "EthClockMode"
#define D_CMND_ETHADDRESS "Address"
#define D_CMND_ETHTYPE "Type"
#define D_CMND_ETHCLOCKMODE "ClockMode"
#define D_CMND_ETHIPADDRESS D_CMND_IPADDRESS
#define D_CMND_ETHGATEWAY D_JSON_GATEWAY
#define D_CMND_ETHNETMASK D_JSON_SUBNETMASK
#define D_CMND_ETHDNS D_JSON_DNSSERVER
const char kEthernetCommands[] PROGMEM = "|" // No prefix
D_CMND_ETHERNET "|" D_CMND_ETHADDRESS "|" D_CMND_ETHTYPE "|" D_CMND_ETHCLOCKMODE;
const char kEthernetCommands[] PROGMEM = "Eth|" // Prefix
"ernet|" D_CMND_ETHADDRESS "|" D_CMND_ETHTYPE "|" D_CMND_ETHCLOCKMODE "|"
D_CMND_ETHIPADDRESS "|" D_CMND_ETHGATEWAY "|" D_CMND_ETHNETMASK "|" D_CMND_ETHDNS "|Ipconfig" ;
void (* const EthernetCommand[])(void) PROGMEM = {
&CmndEthernet, &CmndEthAddress, &CmndEthType, &CmndEthClockMode };
&CmndEthernet, &CmndEthAddress, &CmndEthType, &CmndEthClockMode,
&CmndEthSetIpConfig, &CmndEthSetIpConfig, &CmndEthSetIpConfig, &CmndEthSetIpConfig, &CmndEthIpConfig };
void CmndEthernet(void)
{
#define ETH_PARAM_OFFSET 4 // Offset of command index in above table of first CmndEthIpConfig
void CmndEthernet(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
Settings->flag4.network_ethernet = XdrvMailbox.payload;
TasmotaGlobal.restart_flag = 2;
@ -178,8 +209,7 @@ void CmndEthernet(void)
ResponseCmndStateText(Settings->flag4.network_ethernet);
}
void CmndEthAddress(void)
{
void CmndEthAddress(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 31)) {
Settings->eth_address = XdrvMailbox.payload;
TasmotaGlobal.restart_flag = 2;
@ -187,8 +217,7 @@ void CmndEthAddress(void)
ResponseCmndNumber(Settings->eth_address);
}
void CmndEthType(void)
{
void CmndEthType(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) {
Settings->eth_type = XdrvMailbox.payload;
TasmotaGlobal.restart_flag = 2;
@ -196,8 +225,7 @@ void CmndEthType(void)
ResponseCmndNumber(Settings->eth_type);
}
void CmndEthClockMode(void)
{
void CmndEthClockMode(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) {
Settings->eth_clk_mode = XdrvMailbox.payload;
TasmotaGlobal.restart_flag = 2;
@ -205,6 +233,47 @@ void CmndEthClockMode(void)
ResponseCmndNumber(Settings->eth_clk_mode);
}
void CmndEthSetIpConfig(void) {
uint32_t param_id = XdrvMailbox.command_code -ETH_PARAM_OFFSET;
char cmnd_idx[2] = { 0 };
if (3 == param_id) { // EthDnsServer
if ((XdrvMailbox.index < 1) || (XdrvMailbox.index > 2)) {
XdrvMailbox.index = 1;
}
cmnd_idx[0] = '0' + XdrvMailbox.index;
param_id += XdrvMailbox.index -1; // EthDnsServer2
}
if (XdrvMailbox.data_len) {
uint32_t ipv4_address;
if (ParseIPv4(&ipv4_address, XdrvMailbox.data)) {
Settings->eth_ipv4_address[param_id] = ipv4_address;
eth_config_change = 2;
}
}
char network_address[22] = { 0 };
if (0 == param_id) {
if (!Settings->eth_ipv4_address[0]) {
ext_snprintf_P(network_address, sizeof(network_address), PSTR(" (%_I)"), (uint32_t)ETH.localIP());
}
}
Response_P(PSTR("{\"%s%s\":\"%_I%s\"}"), XdrvMailbox.command, cmnd_idx, Settings->eth_ipv4_address[param_id], network_address);
}
void CmndEthIpConfig(void) {
char network_address[22] = { 0 };
if (!Settings->eth_ipv4_address[0]) {
ext_snprintf_P(network_address, sizeof(network_address), PSTR(" (%_I)"), (uint32_t)ETH.localIP());
}
Response_P(PSTR("{\"EthIpAddress\":\"%_I%s\""), Settings->eth_ipv4_address[0], network_address);
ResponseAppend_P(PSTR(",\"EthGateway\":\"%_I\""), Settings->eth_ipv4_address[1]);
ResponseAppend_P(PSTR(",\"EthSubNetmask\":\"%_I\""), Settings->eth_ipv4_address[2]);
ResponseAppend_P(PSTR(",\"EthDnsServer1\":\"%_I\""), Settings->eth_ipv4_address[3]);
ResponseAppend_P(PSTR(",\"EthDnsServer2\":\"%_I\"}"), Settings->eth_ipv4_address[4]);
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
@ -213,6 +282,9 @@ bool Xdrv82(uint8_t function) {
bool result = false;
switch (function) {
case FUNC_EVERY_SECOND:
EthernetConfigChange();
break;
case FUNC_COMMAND:
result = DecodeCommand(kEthernetCommands, EthernetCommand);
break;