REDAC HybridController
Firmware for LUCIDAC/REDAC Teensy
Loading...
Searching...
No Matches
ethernet.cpp
Go to the documentation of this file.
1// Copyright (c) 2024 anabrid GmbH
2// Contact: https://www.anabrid.com/licensing/
3//
4// SPDX-License-Identifier: MIT OR GPL-2.0-or-later
5
6#ifdef ARDUINO
7
8#include <ArduinoJson.h>
9
10#include "net/ethernet.h"
11#include "net/settings.h"
12#include "utils/logging.h"
13
15#include "web/server.h"
16
17using namespace utils;
18
20#ifdef ANABRID_SKIP_ETHERNET
21 enable_ethernet = false;
22 LOG_ALWAYS("Skipping Ethernet due to build flag ANABRID_ETHERNET");
23#else
24 enable_ethernet = true;
25#endif
26
27// This build flag basically solves a "deadlock" if a no DHCP server is
28// available but the teensy is configured for dhcp.
29#ifdef ANABRID_SKIP_DHCP
30 enable_dhcp = false;
31 LOG_ALWAYS("Skipping DHCP due to build flag ANABRID_SKIP_DHCP");
32#else
33 enable_dhcp = true;
34#endif
35
36 mac.reset();
37
38 // Note that the default hostname by QNEthernet is just "teensy-lwip".
39 // Instead, here we choose something unique to the device.
40 char mac_str[50];
41 sprintf(mac_str, "lucidac-%02X-%02X-%02X", mac[3], mac[4], mac[5]);
42 hostname = mac_str;
43
44 static_ipaddr = IPAddress(192, 168, 1, 100);
45 static_netmask = IPAddress(255, 255, 255, 0);
46 static_gw = IPAddress(192, 168, 1, 1);
47 static_dns = IPAddress(8, 8, 8, 8);
48
49 enable_jsonl = true;
50 enable_webserver = false;
51 enable_websockets = false;
52 enable_mdns = true;
53
54 jsonl_port = 5732;
55 webserver_port = 80;
56
57 connection_timeout_ms = 72 * 1000 * 1000;
58 max_connections = 20;
59}
60
61FLASHMEM void net::StartupConfig::fromJson(JsonObjectConst src, nvmconfig::Context c) {
62 JSON_GET(src, enable_ethernet);
63 JSON_GET(src, enable_dhcp);
64 JSON_GET(src, enable_jsonl);
65 JSON_GET(src, enable_webserver);
66 JSON_GET(src, enable_websockets);
67 JSON_GET(src, enable_mdns);
68 JSON_GET(src, jsonl_port);
69 JSON_GET(src, webserver_port);
70 JSON_GET(src, mac);
71 JSON_GET_AS(src, hostname, const char *);
72 JSON_GET_AS(src, static_ipaddr, IPAddress);
73 JSON_GET_AS(src, static_netmask, IPAddress);
74 JSON_GET_AS(src, static_gw, IPAddress);
75 JSON_GET_AS(src, static_dns, IPAddress);
76
77 // Maximum hostname length is an industry standard (POSIX is 255 chars limits.h)
78 // and also and dictated by EEPROM size.
79 if (hostname.length() > 250)
80 hostname = hostname.substr(0, 250);
81}
82
83FLASHMEM void net::StartupConfig::toJson(JsonObject target, nvmconfig::Context c) const {
84 JSON_SET(target, enable_ethernet);
85 JSON_SET(target, enable_dhcp);
86 JSON_SET(target, enable_jsonl);
87 JSON_SET(target, enable_webserver);
88 JSON_SET(target, enable_websockets);
89 JSON_SET(target, enable_mdns);
90 JSON_SET(target, jsonl_port);
91 JSON_SET(target, webserver_port);
92 JSON_SET(target, mac);
93 JSON_SET(target, hostname);
94 JSON_SET(target, static_ipaddr);
95 JSON_SET(target, static_netmask);
96 JSON_SET(target, static_gw);
97 JSON_SET(target, static_dns);
98}
99
101 if (!enable_ethernet) {
102 LOG_ALWAYS("Ethernet disabled by user setting");
103 }
104
105 // if(!net::Ethernet.linkState()) {
106 // TODO: This is only a workaround in the moment and requires later
107 // setup with the onLinkState callback
108 // LOG_ALWAYS("Ethernet: No link detected. Skipping Ethernet setup.");
109 // return;
110 //}
111
112 if (valid(mac))
113 net::Ethernet.setMACAddress(mac.mac); // else keep system default
114
115 LOG2("MAC: ", toString(mac).c_str())
116
117 // TODO: Should indicate the state of the IP aquisition on the
118 // LEDs of the LUCIDAC front.
119
120 if (enable_dhcp) {
121 LOG2("DHCP with Hostname: ", hostname.c_str());
122 net::Ethernet.setHostname(hostname.c_str());
123 if (!net::Ethernet.begin()) {
124 LOG_ERROR("Error starting ethernet DHCP client.");
125 return 1;
126 }
127 LOG(ANABRID_DEBUG_INIT, "Waiting for IP address on ethernet...");
128 if (!net::Ethernet.waitForLocalIP(10 * 1000 /* ms*/)) {
129 LOG_ERROR("Error getting IP address.");
130 return 2;
131 }
132 } else {
133 if (!valid(static_ipaddr) || !valid(static_netmask) || !valid(static_gw)) {
134 LOG_ERROR("Illegal ipaddr/netmask/gw. Recovering with defaults.");
135 auto defaults = StartupConfig();
136 static_ipaddr = defaults.static_ipaddr;
137 static_netmask = defaults.static_netmask;
138 static_gw = defaults.static_gw;
139 }
140 if (!net::Ethernet.begin(static_ipaddr, static_netmask, static_gw)) {
141 LOG_ERROR("Error starting ethernet with static IP address.");
142 return 3;
143 }
144 if (!valid(static_dns)) {
145 LOG_ERROR("Illegal dns server. Recovering with defaults.")
146 auto defaults = StartupConfig();
147 static_dns = defaults.static_dns;
148 }
149 net::Ethernet.setDnsServerIP(static_dns);
150 }
151
152 LOG4("JSONL Listening on ", net::Ethernet.localIP(), ":", jsonl_port);
153 return 0;
154}
155
157 MDNS.begin(hostname.c_str());
158 if (enable_jsonl)
159 MDNS.addService("_lucijsonl", "_tcp", jsonl_port);
160 if (enable_webserver)
161 MDNS.addService("_http", "_tcp", webserver_port);
162}
163
164/*void net::StartupConfig::begin() {
165 net::register_settings();
166 begin_ip();
167}*/
168
169FLASHMEM void net::status(JsonObject &msg_out) {
170 msg_out["interfaceStatus"] = net::Ethernet.interfaceStatus();
171
172 // TODO: Move to net_get
173 msg_out["otp_mac"] = std::string(MacAddress::otp()); // one time programmable system/permanent mac
174
175 auto ip = msg_out.createNestedObject("ip");
176 ip["local"] = net::Ethernet.localIP();
177 ip["broadcast"] = net::Ethernet.broadcastIP();
178 ip["gateway"] = net::Ethernet.gatewayIP();
179
180 auto dhcp = msg_out.createNestedObject("dhcp");
181 dhcp["active"] = net::Ethernet.isDHCPActive(); // probably move to net_get
182 dhcp["enabled"] = net::Ethernet.isDHCPEnabled();
183
184 auto link = msg_out.createNestedObject("link");
185 link["state"] = net::Ethernet.linkState();
186 link["speed"] = net::Ethernet.linkSpeed(); // in Mpbs
187 link["isCrossover"] = net::Ethernet.linkIsCrossover();
188 link["isFullDuplex"] = net::Ethernet.linkIsFullDuplex();
189
190 // msg_out["tcp_port"] = net::ethernet::Ethernet.server_port;
193 // auto settings = msg_out.createNestedObject("settings");
194 // eth.write_to_json(settings);
195}
196
197#endif // ARDUINO
Persistent user-defined ethernet settings which is mostly relevant only during startup as the informa...
Definition ethernet.h:40
bool enable_ethernet
Turn on/off networking completely.
Definition ethernet.h:50
int begin_ip()
Calls net::Ethernet.begin, sets IP address.
Definition ethernet.cpp:100
void toJson(JsonObject target, nvmconfig::Context c=nvmconfig::Context::Flash) const override
Definition ethernet.cpp:83
void fromJson(JsonObjectConst src, nvmconfig::Context c=nvmconfig::Context::Flash) override
Definition ethernet.cpp:61
IPAddress static_netmask
netmask; used only when use_dhcp=false
Definition ethernet.h:64
int jsonl_port
TCP port for jsonl server.
Definition ethernet.h:57
void begin_mdns()
Calls net::MDNS.begin.
Definition ethernet.cpp:156
IPAddress static_dns
DNS server address; used only when use_dhcp=false.
Definition ethernet.h:66
bool enable_mdns
Enable mDNS/zeroconf multicast service discovery.
Definition ethernet.h:55
bool enable_dhcp
DHCP client vs static IP configuration.
Definition ethernet.h:51
bool enable_webserver
Enable embedded webserver for REST access.
Definition ethernet.h:53
bool enable_websockets
Enable websocket server ontop of webserver.
Definition ethernet.h:54
int webserver_port
TCP port for webserver.
Definition ethernet.h:58
IPAddress static_ipaddr
own ip address, used only when use_dhcp=false
Definition ethernet.h:63
MacAddress mac
Custom MAC address. Defaults to original permanent system Mac.
Definition ethernet.h:60
uint8_t max_connections
(Runtime-changable) Maximum number of parallel connections accepted
Definition ethernet.h:71
std::string hostname
used only for DHCP client. Maximum 250 characters.
Definition ethernet.h:61
IPAddress static_gw
gateway address; used only when use_dhcp=false
Definition ethernet.h:65
uint32_t connection_timeout_ms
(Runtime-changable) Time after idling connections time out.
Definition ethernet.h:70
bool enable_jsonl
Enable the JSONL TCP/IP server.
Definition ethernet.h:52
uint32_t src
Definition flasher.cpp:63
#define JSON_GET(src, key)
Definition json.h:15
#define JSON_GET_AS(src, key, type)
Definition json.h:18
#define JSON_SET(target, key)
Definition json.h:21
#define LOG_ERROR(message)
Definition logging.h:37
#define LOG(LOG_FLAG, message)
Definition logging.h:36
#define LOG2(a, b)
Definition logging.h:97
#define LOG4(a, b, c, d)
Definition logging.h:110
#define LOG_ALWAYS(message)
Definition logging.h:38
void status(JsonObject &msg_out)
This status contains only "static" QNEthernet information, unrelated to UserDefinedEthernet instances...
Definition ethernet.cpp:169
std::string toString(const MacAddress &mac, char sep='-')
EUI48/MAC Canonical Format AA-BB-CC-DD-EE-FF.
Definition mac.cpp:33
bool valid(const MacAddress &mac)
All zero mac bytes considered invalid (0-0-0-0-0-0)
Definition mac.cpp:61
void reset()
set to system default (stored in teensy HW_OCOTP_MAC1 and ...MAC0)
Definition mac.cpp:16
static MacAddress otp()
Handy access to system default/permanent mac address (one time programmed)
Definition mac.h:37