1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-11-22 23:56:13 +01:00

Merge branch 'devel_fozzie2' of https://github.com/DCC-EX/CommandStation-EX into devel_fozzie2

This commit is contained in:
Harald Barth 2024-09-11 11:25:21 +02:00
commit ec42c09e06
3 changed files with 153 additions and 57 deletions

View File

@ -29,6 +29,13 @@
#include "CommandDistributor.h" #include "CommandDistributor.h"
#include "WiThrottle.h" #include "WiThrottle.h"
#include "DCCTimer.h" #include "DCCTimer.h"
#if __has_include ( "MDNS_Generic.h")
#include "MDNS_Generic.h"
#define DO_MDNS
EthernetUDP udp;
MDNS mdns(udp);
#endif
extern void looptimer(unsigned long timeout, const FSH* message); extern void looptimer(unsigned long timeout, const FSH* message);
@ -42,48 +49,76 @@ RingStream * EthernetInterface::outboundRing = nullptr;
* @brief Setup Ethernet Connection * @brief Setup Ethernet Connection
* *
*/ */
void EthernetInterface::setup()
void EthernetInterface::setup() // STM32 VERSION
{ {
connected=false; DIAG(F("Ethernet begin"
#ifdef DO_MDNS
" with mDNS"
#endif
));
#ifdef STM32_ETHERNET
// Set a HOSTNAME for the DHCP request - a nice to have, but hard it seems on LWIP for STM32
// The default is "lwip", which is **always** set in STM32Ethernet/src/utility/ethernetif.cpp
// for some reason. One can edit it to instead read:
// #if LWIP_NETIF_HOSTNAME
// /* Initialize interface hostname */
// if (netif->hostname == NULL)
// netif->hostname = "lwip";
// #endif /* LWIP_NETIF_HOSTNAME */
// Which seems more useful! We should propose the patch... so the following line actually works!
netif_set_hostname(&gnetif, WIFI_HOSTNAME); // Should probably be passed in the contructor...
#endif
byte mac[6]; byte mac[6];
DCCTimer::getSimulatedMacAddress(mac); DCCTimer::getSimulatedMacAddress(mac);
DIAG(F("Ethernet begin")); #define _MAC_ mac
#ifdef IP_ADDRESS #ifdef IP_ADDRESS
static IPAddress myIP(IP_ADDRESS); static IPAddress myIP(IP_ADDRESS);
Ethernet.begin(mac, myIP); Ethernet.begin(_MAC_,myIP);
#else setup(false);
if (Ethernet.begin(mac) == 0) #else
{ if (Ethernet.begin(_MAC_)==0)
LCD(4,F("IP: No DHCP")); {
return; LCD(4,F("IP: No DHCP"));
} return;
#endif }
auto ip = Ethernet.localIP(); // look what IP was obtained (dynamic or static) #endif
if (!ip) {
LCD(4,F("IP: None"));
return;
}
server = new EthernetServer(IP_PORT); // Ethernet Server listening on default port IP_PORT
server->begin();
#ifdef LCD_DRIVER
const byte lcdData[]={LCD_DRIVER};
const bool wideDisplay=lcdData[1]>=24; // data[1] is cols.
#else
const bool wideDisplay=true;
#endif
if (wideDisplay) {
// OLEDS or just usb diag is ok on one line.
LCD(4,F("IP %d.%d.%d.%d:%d"), ip[0], ip[1], ip[2], ip[3], IP_PORT);
}
else { // LCDs generally too narrow, so take 2 lines
LCD(4,F("IP %d.%d.%d.%d"), ip[0], ip[1], ip[2], ip[3]);
LCD(5,F("Port %d"), IP_PORT);
}
outboundRing=new RingStream(OUTBOUND_RING_SIZE); auto ip = Ethernet.localIP(); // look what IP was obtained (dynamic or static)
connected=true; if (!ip) {
LCD(4,F("IP: None"));
return;
}
server = new EthernetServer(IP_PORT); // Ethernet Server listening on default port IP_PORT
server->begin();
// Arrange display of IP address and port
#ifdef LCD_DRIVER
const byte lcdData[]={LCD_DRIVER};
const bool wideDisplay=lcdData[1]>=24; // data[1] is cols.
#else
const bool wideDisplay=true;
#endif
if (wideDisplay) {
// OLEDS or just usb diag is ok on one line.
LCD(4,F("IP %d.%d.%d.%d:%d"), ip[0], ip[1], ip[2], ip[3], IP_PORT);
}
else { // LCDs generally too narrow, so take 2 lines
LCD(4,F("IP %d.%d.%d.%d"), ip[0], ip[1], ip[2], ip[3]);
LCD(5,F("Port %d"), IP_PORT);
}
outboundRing=new RingStream(OUTBOUND_RING_SIZE);
#ifdef DO_MDNS
mdns.begin(Ethernet.localIP(), WIFI_HOSTNAME); // hostname
mdns.addServiceRecord(WIFI_HOSTNAME "._withrottle", IP_PORT, MDNSServiceTCP);
// Not sure if we need to run it once, but just in case!
mdns.run();
#endif
connected=true;
} }
@ -94,6 +129,7 @@ void EthernetInterface::setup()
void EthernetInterface::loop() void EthernetInterface::loop()
{ {
if (!connected) return; if (!connected) return;
looptimer(5000, F("E.loop"));
static bool warnedAboutLink=false; static bool warnedAboutLink=false;
if (Ethernet.linkStatus() == LinkOFF){ if (Ethernet.linkStatus() == LinkOFF){
@ -102,6 +138,7 @@ void EthernetInterface::loop()
warnedAboutLink=true; warnedAboutLink=true;
return; return;
} }
looptimer(5000, F("E.loop warn"));
// link status must be ok here // link status must be ok here
if (warnedAboutLink) { if (warnedAboutLink) {
@ -109,6 +146,13 @@ void EthernetInterface::loop()
warnedAboutLink=false; warnedAboutLink=false;
} }
#ifdef DO_MDNS
// Always do this because we don't want traffic to intefere with being found!
mdns.run();
looptimer(5000, F("E.mdns"));
#endif
// //
switch (Ethernet.maintain()) { switch (Ethernet.maintain()) {
case 1: case 1:
@ -126,29 +170,47 @@ void EthernetInterface::loop()
//DIAG(F("maintained")); //DIAG(F("maintained"));
break; break;
} }
looptimer(5000, F("E.maintain"));
// get client from the server // get client from the server
auto client = server->accept(); #if defined (STM32_ETHERNET)
// STM32Ethernet doesn't use accept(), just available()
// check for new client auto client = server->available();
if (client) if (client) {
{ // check for new client
if (Diag::ETHERNET) DIAG(F("Ethernet: New client ")); byte socket;
byte socket; bool sockFound = false;
for (socket = 0; socket < MAX_SOCK_NUM; socket++)
{
if (client == clients[socket])
{
sockFound = true;
break;
}
}
if (!sockFound)
{ // new client
for (socket = 0; socket < MAX_SOCK_NUM; socket++) for (socket = 0; socket < MAX_SOCK_NUM; socket++)
{ {
if (!clients[socket]) if (!clients[socket])
{ {
// On accept() the EthernetServer doesn't track the client anymore clients[socket] = client;
// so we store it in our client array sockFound=true;
if (Diag::ETHERNET) DIAG(F("Socket %d"),socket); if (Diag::ETHERNET)
clients[socket] = client; DIAG(F("Ethernet: New client socket %d"), socket);
break; break;
} }
} }
if (socket==MAX_SOCK_NUM) DIAG(F("new Ethernet OVERFLOW")); }
if (!sockFound) DIAG(F("new Ethernet OVERFLOW"));
} }
#else
auto client = server->accept();
if (client) clients[client.getSocketNumber()]=client;
#endif
// check for incoming data from all possible clients // check for incoming data from all possible clients
for (byte socket = 0; socket < MAX_SOCK_NUM; socket++) for (byte socket = 0; socket < MAX_SOCK_NUM; socket++)
{ {

View File

@ -35,6 +35,14 @@
#if defined (ARDUINO_TEENSY41) #if defined (ARDUINO_TEENSY41)
#include <NativeEthernet.h> //TEENSY Ethernet Treiber #include <NativeEthernet.h> //TEENSY Ethernet Treiber
#include <NativeEthernetUdp.h> #include <NativeEthernetUdp.h>
#elif defined (ARDUINO_NUCLEO_F429ZI) || defined (ARDUINO_NUCLEO_F439ZI) || defined (ARDUINO_NUCLEO_F4X9ZI)
#include <LwIP.h>
// #include "STM32lwipopts.h"
#include <STM32Ethernet.h>
#include <lwip/netif.h>
extern "C" struct netif gnetif;
#define STM32_ETHERNET
#define MAX_SOCK_NUM 8
#else #else
#include "Ethernet.h" #include "Ethernet.h"
#endif #endif
@ -45,7 +53,7 @@
* *
*/ */
#define MAX_ETH_BUFFER 512 #define MAX_ETH_BUFFER 128
#define OUTBOUND_RING_SIZE 2048 #define OUTBOUND_RING_SIZE 2048
class EthernetInterface { class EthernetInterface {

View File

@ -104,6 +104,14 @@ lib_deps =
${env.lib_deps} ${env.lib_deps}
arduino-libraries/Ethernet arduino-libraries/Ethernet
SPI SPI
MDNS_Generic
lib_ignore = WiFi101
WiFi101_Generic
WiFiEspAT
WiFiMulti_Generic
WiFiNINA_Generic
monitor_speed = 115200 monitor_speed = 115200
monitor_echo = yes monitor_echo = yes
build_flags = build_flags =
@ -263,6 +271,24 @@ monitor_echo = yes
; Experimental - Ethernet work still in progress ; Experimental - Ethernet work still in progress
; ;
[env:Nucleo-F429ZI]
platform = ststm32
board = nucleo_f429zi
framework = arduino
lib_deps = ${env.lib_deps}
stm32duino/STM32Ethernet @ ^1.3.0
stm32duino/STM32duino LwIP @ ^2.1.2
MDNS_Generic
lib_ignore = WiFi101
WiFi101_Generic
WiFiEspAT
WiFiMulti_Generic
WiFiNINA_Generic
build_flags = -std=c++17 -Os -g2 -Wunused-variable
monitor_speed = 115200
monitor_echo = yes
upload_protocol = stlink
; [env:Nucleo-F429ZI] ; [env:Nucleo-F429ZI]
; platform = ststm32 ; platform = ststm32
; board = nucleo_f429zi ; board = nucleo_f429zi