diff --git a/libraries/Ethernet/README.md b/libraries/Ethernet/README.md new file mode 100644 index 000000000..872a66373 --- /dev/null +++ b/libraries/Ethernet/README.md @@ -0,0 +1,11 @@ +# Ethernet Library for Arduino + +Provides Ethernet connectivity for Arduino boards using the Arduino Zephyr core, together with a shield or carrier featuring an Ethernet connector. + +📖 For more information about this library please read the documentation [here](http://www.arduino.cc/en/Reference/Ethernet). + +## License + +Copyright (c) 2025 Arduino SA. All rights reserved. + +This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. \ No newline at end of file diff --git a/libraries/Ethernet/examples/LinkStatus/LinkStatus.ino b/libraries/Ethernet/examples/LinkStatus/LinkStatus.ino new file mode 100644 index 000000000..a38e005d2 --- /dev/null +++ b/libraries/Ethernet/examples/LinkStatus/LinkStatus.ino @@ -0,0 +1,28 @@ +/* + Link Status + This sketch prints the ethernet link status. When the + ethernet cable is connected the link status should go to "ON". +*/ + +#include + +void setup() { + Serial.begin(9600); +} + +void loop() { + auto link = Ethernet.linkStatus(); + Serial.print("Link status: "); + switch (link) { + case Unknown: + Serial.println("Unknown"); + break; + case LinkON: + Serial.println("ON"); + break; + case LinkOFF: + Serial.println("OFF"); + break; + } + delay(1000); +} diff --git a/libraries/Ethernet/examples/TelnetClient/TelnetClient.ino b/libraries/Ethernet/examples/TelnetClient/TelnetClient.ino new file mode 100644 index 000000000..83374495a --- /dev/null +++ b/libraries/Ethernet/examples/TelnetClient/TelnetClient.ino @@ -0,0 +1,94 @@ +/* + Telnet client + + This sketch connects to a telnet server. + You need a telnet server to test this. +*/ + +#include "ZephyrClient.h" +#include "ZephyrEthernet.h" + +// The IP address will be dependent on your local network: +IPAddress ip(192, 168, 1, 177); + +// Example: To get the IP address of telehack.com (an example telnet server), run in a terminal: +// ping telehack.com +// or +// nslookup telehack.com +// Then use the returned IP address in the code. + +// Enter the IP address of the server you're connecting to: +IPAddress server(1, 1, 1, 1); +int port = 23; // Telnet port + +// Initialize the Ethernet client library +// with the IP address and port of the server +// that you want to connect to (port 23 is default for telnet; +// if you're using Processing's ChatServer, use port 10002): +ZephyrClient client; + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only + } + + // Check for Ethernet hardware present + if (Ethernet.hardwareStatus() == EthernetNoHardware) { + Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :("); + while (true) { + delay(1); // do nothing, no point running without Ethernet hardware + } + } + + // in Zephyr system check if Ethernet is ready before proceeding to initialize + while (Ethernet.linkStatus() != LinkON) { + Serial.println("Waiting for link on"); + delay(100); + } + + // start the Ethernet connection: + Ethernet.begin(ip); + + // give the Ethernet shield a second to initialize: + delay(1000); + Serial.println("connecting..."); + + // if you get a connection, report back via serial: + if (client.connect(server, port)) { + Serial.println("connected"); + } else { + // if you didn't get a connection to the server: + Serial.println("connection failed"); + } +} + +void loop() { + // if there are incoming bytes available + // from the server, read them and print them: + if (client.available()) { + char c = client.read(); + Serial.print(c); + } + + // as long as there are bytes in the serial queue, + // read them and send them out the socket if it's open: + while (Serial.available() > 0) { + char inChar = Serial.read(); + if (client.connected()) { + client.print(inChar); + } + } + + // if the server's disconnected, stop the client: + if (!client.connected()) { + Serial.println(); + Serial.println("disconnecting."); + client.stop(); + // do nothing: + while (true) { + delay(1); + } + } +} diff --git a/libraries/Ethernet/examples/UDPSendReceiveString/UDPSendReceiveString.ino b/libraries/Ethernet/examples/UDPSendReceiveString/UDPSendReceiveString.ino new file mode 100644 index 000000000..c675e71a6 --- /dev/null +++ b/libraries/Ethernet/examples/UDPSendReceiveString/UDPSendReceiveString.ino @@ -0,0 +1,125 @@ +/* + UDPSendReceiveString: + This sketch receives UDP message strings, prints them to the serial port + and sends an "acknowledge" string back to the sender + + A Processing sketch is included at the end of file that can be used to send + and received messages for testing with a computer. + */ + +#include +#include + +// The IP address will be dependent on your local network: +IPAddress ip(192, 168, 1, 177); + +unsigned int localPort = 8888; // local port to listen on + +// buffers for receiving and sending data +char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; // buffer to hold incoming packet, +char ReplyBuffer[] = "acknowledged"; // a string to send back + +// An EthernetUDP instance to let us send and receive packets over UDP +ZephyrUDP Udp; + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only + } + + // in Zephyr system check if Ethernet is ready before proceeding to initialize + while (Ethernet.linkStatus() != LinkON) { + Serial.println("Waiting for link on"); + delay(100); + } + + // start the Ethernet + Ethernet.begin(ip); + + // Check for Ethernet hardware present + if (Ethernet.hardwareStatus() == EthernetNoHardware) { + Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :("); + while (true) { + delay(1); // do nothing, no point running without Ethernet hardware + } + } + if (Ethernet.linkStatus() == LinkOFF) { + Serial.println("Ethernet cable is not connected."); + } + + // start UDP + Udp.begin(localPort); +} + +void loop() { + // if there's data available, read a packet + int packetSize = Udp.parsePacket(); + if (packetSize) { + Serial.print("Received packet of size "); + Serial.println(packetSize); + Serial.print("From "); + IPAddress remote = Udp.remoteIP(); + for (int i = 0; i < 4; i++) { + Serial.print(remote[i], DEC); + if (i < 3) { + Serial.print("."); + } + } + Serial.print(", port "); + Serial.println(Udp.remotePort()); + + // read the packet into packetBufffer + Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE); + Serial.println("Contents:"); + Serial.println(packetBuffer); + + // send a reply to the IP address and port that sent us the packet we received + Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); + Udp.write(ReplyBuffer); + Udp.endPacket(); + } + delay(10); +} + + +/* + Processing sketch to run with this example + ===================================================== + + // Processing UDP example to send and receive string data from Arduino + // press any key to send the "Hello Arduino" message + + + import hypermedia.net.*; + + UDP udp; // define the UDP object + + + void setup() { + udp = new UDP( this, 6000 ); // create a new datagram connection on port 6000 + //udp.log( true ); // <-- printout the connection activity + udp.listen( true ); // and wait for incoming message + } + + void draw() + { + } + + void keyPressed() { + String ip = "192.168.1.177"; // the remote IP address + int port = 8888; // the destination port + + udp.send("Hello World", ip, port ); // the message to send + + } + + void receive( byte[] data ) { // <-- default handler + //void receive( byte[] data, String ip, int port ) { // <-- extended handler + + for(int i=0; i < data.length; i++) + print(char(data[i])); + println(); + } + */ diff --git a/libraries/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino b/libraries/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino new file mode 100644 index 000000000..4b93f2f58 --- /dev/null +++ b/libraries/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino @@ -0,0 +1,128 @@ +/* + + Udp NTP Client + + Get the time from a Network Time Protocol (NTP) time server + Demonstrates use of UDP sendPacket and ReceivePacket + For more on NTP time servers and the messages needed to communicate with them, + see http://en.wikipedia.org/wiki/Network_Time_Protocol + + */ + +#include +#include + +unsigned int localPort = 8888; // local port to listen for UDP packets + +const char timeServer[] = "time.nist.gov"; // time.nist.gov NTP server + +const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message + +byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets + +// A UDP instance to let us send and receive packets over UDP +ZephyrUDP Udp; + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only + } + + // in Zephyr system check if Ethernet is ready before proceeding to initialize + while (Ethernet.linkStatus() != LinkON) { + Serial.println("Waiting for link on"); + delay(100); + } + + // start Ethernet and UDP + if (Ethernet.begin() == 0) { + Serial.println("Failed to configure Ethernet using DHCP"); + // Check for Ethernet hardware present + if (Ethernet.hardwareStatus() == EthernetNoHardware) { + Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :("); + } else if (Ethernet.linkStatus() == LinkOFF) { + Serial.println("Ethernet cable is not connected."); + } + // no point in carrying on, so do nothing forevermore: + while (true) { + delay(1); + } + } + Udp.begin(localPort); +} + +void loop() { + // send an NTP packet to a time server + sendNTPpacket(timeServer); + + // wait to see if a reply is available + delay(1000); + if (Udp.parsePacket()) { + // We've received a packet, read the data from it + Udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer + + // the timestamp starts at byte 40 of the received packet and is four bytes, + // or two words, long. First, extract the two words: + + unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); + unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); + // combine the four bytes (two words) into a long integer + // this is NTP time (seconds since Jan 1 1900): + unsigned long secsSince1900 = highWord << 16 | lowWord; + Serial.print("Seconds since Jan 1 1900 = "); + Serial.println(secsSince1900); + + // now convert NTP time into everyday time: + Serial.print("Unix time = "); + // Unix time starts on Jan 1 1970. In seconds, that's 2208988800: + const unsigned long seventyYears = 2208988800UL; + // subtract seventy years: + unsigned long epoch = secsSince1900 - seventyYears; + // print Unix time: + Serial.println(epoch); + + + // print the hour, minute and second: + Serial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT) + Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day) + Serial.print(':'); + if (((epoch % 3600) / 60) < 10) { + // In the first 10 minutes of each hour, we'll want a leading '0' + Serial.print('0'); + } + Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute) + Serial.print(':'); + if ((epoch % 60) < 10) { + // In the first 10 seconds of each minute, we'll want a leading '0' + Serial.print('0'); + } + Serial.println(epoch % 60); // print the second + } + // wait ten seconds before asking for the time again + delay(10000); +} + +// send an NTP request to the time server at the given address +void sendNTPpacket(const char* address) { + // set all bytes in the buffer to 0 + memset(packetBuffer, 0, NTP_PACKET_SIZE); + // Initialize values needed to form NTP request + // (see URL above for details on the packets) + packetBuffer[0] = 0b11100011; // LI, Version, Mode + packetBuffer[1] = 0; // Stratum, or type of clock + packetBuffer[2] = 6; // Polling Interval + packetBuffer[3] = 0xEC; // Peer Clock Precision + // 8 bytes of zero for Root Delay & Root Dispersion + packetBuffer[12] = 49; + packetBuffer[13] = 0x4E; + packetBuffer[14] = 49; + packetBuffer[15] = 52; + + // all NTP fields have been given values, now + // you can send a packet requesting a timestamp: + Udp.beginPacket(address, 123); // NTP requests are to port 123 + Udp.write(packetBuffer, NTP_PACKET_SIZE); + Udp.endPacket(); +} diff --git a/libraries/Ethernet/examples/WebClient/WebClient.ino b/libraries/Ethernet/examples/WebClient/WebClient.ino new file mode 100644 index 000000000..14f47cefc --- /dev/null +++ b/libraries/Ethernet/examples/WebClient/WebClient.ino @@ -0,0 +1,126 @@ +/* + Web client + + This sketch connects to a website (http://www.google.com) + */ + +#include +#include "ZephyrEthernet.h" + +// Enter a MAC address for your controller below. +// Newer Ethernet shields have a MAC address printed on a sticker on the shield +// byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; + +// if you don't want to use DNS (and reduce your sketch size) +// use the numeric IP instead of the name for the server: +//IPAddress server(74,125,232,128); // numeric IP for Google (no DNS) +char server[] = "www.google.com"; // name address for Google (using DNS) + +// Set the static IP address to use if the DHCP fails to assign +IPAddress ip(192, 168, 2, 177); +IPAddress myDns(192, 168, 2, 1); + +// Initialize the Ethernet client library +// with the IP address and port of the server +// that you want to connect to (port 80 is default for HTTP): +ZephyrClient client; + +// Variables to measure the speed +unsigned long beginMicros, endMicros; +unsigned long byteCount = 0; +bool printWebData = true; // set to false for better speed measurement + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only + } + + // in Zephyr system check if Ethernet is ready before proceeding to initialize + while (Ethernet.linkStatus() != LinkON) { + Serial.println("Waiting for link on"); + delay(100); + } + + // start the Ethernet connection: + Serial.println("Initialize Ethernet with DHCP:"); + if (Ethernet.begin() == 0) { + Serial.println("Failed to configure Ethernet using DHCP"); + // Check for Ethernet hardware present + if (Ethernet.hardwareStatus() == EthernetNoHardware) { + Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :("); + while (true) { + delay(1); // do nothing, no point running without Ethernet hardware + } + } + if (Ethernet.linkStatus() == LinkOFF) { + Serial.println("Ethernet cable is not connected."); + } + // try to congifure using IP address instead of DHCP: + Ethernet.begin(ip, myDns); + } else { + Serial.print(" DHCP assigned IP "); + Serial.println(Ethernet.localIP()); + } + + // give the Ethernet shield a second to initialize: + delay(1000); + Serial.print("connecting to "); + Serial.print(server); + Serial.println("..."); + + // if you get a connection, report back via serial: + if (client.connect(server, 80)) { + Serial.print("connected to "); + Serial.println(client.remoteIP()); + // Make a HTTP request: + client.println("GET /search?q=arduino HTTP/1.1"); + client.println("Host: www.google.com"); + client.println("Connection: close"); + client.println(); + } else { + // if you didn't get a connection to the server: + Serial.println("connection failed"); + } + beginMicros = micros(); +} + +void loop() { + // if there are incoming bytes available + // from the server, read them and print them: + int len = client.available(); + if (len > 0) { + byte buffer[80]; + if (len > 80) + len = 80; + client.read(buffer, len); + if (printWebData) { + Serial.write(buffer, len); // show in the serial monitor (slows some boards) + } + byteCount = byteCount + len; + } + + // if the server's disconnected, stop the client: + if (!client.connected()) { + endMicros = micros(); + Serial.println(); + Serial.println("disconnecting."); + client.stop(); + Serial.print("Received "); + Serial.print(byteCount); + Serial.print(" bytes in "); + float seconds = (float)(endMicros - beginMicros) / 1000000.0; + Serial.print(seconds, 4); + float rate = (float)byteCount / seconds / 1000.0; + Serial.print(", rate = "); + Serial.print(rate); + Serial.print(" kbytes/second"); + Serial.println(); + + // do nothing forevermore: + while (true) { + delay(1); + } + } +} diff --git a/libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino b/libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino new file mode 100644 index 000000000..d41b926dd --- /dev/null +++ b/libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino @@ -0,0 +1,112 @@ +/* + Repeating Web client + + This sketch connects to a a web server and makes a request + using the Ethernet interface. + + This example uses DNS, by assigning the Ethernet client with a MAC address, + IP address, and DNS address. + + */ + +#include +#include "ZephyrEthernet.h" + +// assign a MAC address for the Ethernet controller. +// fill in your address here: +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED +}; + +// Set the static IP address to use if the DHCP fails to assign +IPAddress ip(192, 168, 0, 177); +IPAddress myDns(192, 168, 0, 1); + +// initialize the library instance: +ZephyrClient client; + +char server[] = "arduino.tips"; // also change the Host line in httpRequest() +//IPAddress server(64,131,82,241); + +unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds +const unsigned long postingInterval = 10 * 1000; // delay between updates, in milliseconds + +void setup() { + // start serial port: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only + } + + // in Zephyr system check if Ethernet is ready before proceeding to initialize + while (Ethernet.linkStatus() != LinkON) { + Serial.println("Waiting for link on"); + delay(100); + } + + // start the Ethernet connection: + Serial.println("Initialize Ethernet with DHCP:"); + if (Ethernet.begin(mac) == 0) { + Serial.println("Failed to configure Ethernet using DHCP"); + // Check for Ethernet hardware present + if (Ethernet.hardwareStatus() == EthernetNoHardware) { + Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :("); + while (true) { + delay(1); // do nothing, no point running without Ethernet hardware + } + } + if (Ethernet.linkStatus() == LinkOFF) { + Serial.println("Ethernet cable is not connected."); + } + // try to configure using IP address instead of DHCP: + Ethernet.begin(mac, ip, myDns); + Serial.print("My IP address: "); + Serial.println(Ethernet.localIP()); + } else { + Serial.print(" DHCP assigned IP "); + Serial.println(Ethernet.localIP()); + } + // give the Ethernet shield a second to initialize: + delay(1000); +} + +void loop() { + // if there's incoming data from the net connection. + // send it out the serial port. This is for debugging + // purposes only: + if (client.available()) { + char c = client.read(); + Serial.write(c); + } + + // if ten seconds have passed since your last connection, + // then connect again and send data: + if (millis() - lastConnectionTime > postingInterval) { + httpRequest(); + } +} + +// this method makes a HTTP connection to the server: +void httpRequest() { + // close any connection before send a new request. + // This will free the socket on the Ethernet shield + client.stop(); + + // if there's a successful connection: + if (client.connect(server, 80)) { + Serial.println("connecting..."); + // send the HTTP GET request: + client.println("GET /asciilogo.txt HTTP/1.1"); + client.print("Host: "); + client.println(server); + client.println("User-Agent: arduino-ethernet"); + client.println("Connection: close"); + client.println(); + + // note the time that the connection was made: + lastConnectionTime = millis(); + } else { + // if you couldn't make a connection: + Serial.println("connection failed"); + } +} \ No newline at end of file diff --git a/libraries/Ethernet/examples/WebServer/WebServer.ino b/libraries/Ethernet/examples/WebServer/WebServer.ino new file mode 100644 index 000000000..412f72c37 --- /dev/null +++ b/libraries/Ethernet/examples/WebServer/WebServer.ino @@ -0,0 +1,111 @@ +/* + Web Server + + A simple web server that shows the value of the analog input pins. + To view the page, open a web browser and type the server’s IP address in the address bar. + */ + +#include "ZephyrServer.h" +#include "ZephyrClient.h" +#include "ZephyrEthernet.h" + +// Enter a MAC address and IP address for your controller below. +// The IP address will be dependent on your local network: +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED +}; + +IPAddress ip(192, 168, 1, 177); + +// Initialize the Ethernet server library +// with the IP address and port you want to use +// (port 80 is default for HTTP): +ZephyrServer server(80); + +void setup() { + + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only + } + Serial.println("Ethernet WebServer Example"); + + // in Zephyr system check if Ethernet is ready before proceeding to initialize + while (Ethernet.linkStatus() != LinkON) { + Serial.println("Waiting for link on"); + delay(100); + } + + // start the Ethernet connection and the server: + Ethernet.begin(mac, ip); + + // Check for Ethernet hardware present + if (Ethernet.hardwareStatus() == EthernetNoHardware) { + Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :("); + while (true) { + delay(1); // do nothing, no point running without Ethernet hardware + } + } + if (Ethernet.linkStatus() == LinkOFF) { + Serial.println("Ethernet cable is not connected."); + } + + // start the server + server.begin(); + Serial.print("server is at "); + Serial.println(Ethernet.localIP()); +} + + +void loop() { + // listen for incoming clients + ZephyrClient client = server.accept(); + if (client) { + Serial.println("new client"); + // an HTTP request ends with a blank line + bool currentLineIsBlank = true; + while (client.connected()) { + if (client.available()) { + char c = client.read(); + Serial.write(c); + // if you've gotten to the end of the line (received a newline + // character) and the line is blank, the HTTP request has ended, + // so you can send a reply + if (c == '\n' && currentLineIsBlank) { + // send a standard HTTP response header + client.println("HTTP/1.1 200 OK"); + client.println("Content-Type: text/html"); + client.println("Connection: close"); // the connection will be closed after completion of the response + client.println("Refresh: 5"); // refresh the page automatically every 5 sec + client.println(); + client.println(""); + client.println(""); + // output the value of each analog input pin + for (int analogChannel = 0; analogChannel < 6; analogChannel++) { + int sensorReading = analogRead(analogChannel); + client.print("analog input "); + client.print(analogChannel); + client.print(" is "); + client.print(sensorReading); + client.println("
"); + } + client.println(""); + break; + } + if (c == '\n') { + // you're starting a new line + currentLineIsBlank = true; + } else if (c != '\r') { + // you've gotten a character on the current line + currentLineIsBlank = false; + } + } + } + // give the web browser time to receive the data + delay(1); + // close the connection: + client.stop(); + Serial.println("client disconnected"); + } +} \ No newline at end of file diff --git a/libraries/Ethernet/keywords.txt b/libraries/Ethernet/keywords.txt new file mode 100644 index 000000000..3c4ed937a --- /dev/null +++ b/libraries/Ethernet/keywords.txt @@ -0,0 +1,64 @@ +####################################### +# Syntax Coloring Map For Ethernet +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +Ethernet KEYWORD1 Ethernet +EthernetClient KEYWORD1 EthernetClient +EthernetServer KEYWORD1 EthernetServer +IPAddress KEYWORD1 EthernetIPAddress + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +status KEYWORD2 +connect KEYWORD2 +write KEYWORD2 +available KEYWORD2 +availableForWrite KEYWORD2 +read KEYWORD2 +peek KEYWORD2 +flush KEYWORD2 +stop KEYWORD2 +connected KEYWORD2 +accept KEYWORD2 +begin KEYWORD2 +beginMulticast KEYWORD2 +beginPacket KEYWORD2 +endPacket KEYWORD2 +parsePacket KEYWORD2 +remoteIP KEYWORD2 +remotePort KEYWORD2 +getSocketNumber KEYWORD2 +localIP KEYWORD2 +localPort KEYWORD2 +maintain KEYWORD2 +linkStatus KEYWORD2 +hardwareStatus KEYWORD2 +MACAddress KEYWORD2 +subnetMask KEYWORD2 +gatewayIP KEYWORD2 +dnsServerIP KEYWORD2 +setMACAddress KEYWORD2 +setLocalIP KEYWORD2 +setSubnetMask KEYWORD2 +setGatewayIP KEYWORD2 +setDnsServerIP KEYWORD2 +setRetransmissionTimeout KEYWORD2 +setRetransmissionCount KEYWORD2 +setConnectionTimeout KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + +EthernetLinkStatus LITERAL1 +Unknown LITERAL1 +LinkON LITERAL1 +LinkOFF LITERAL1 +EthernetHardwareStatus LITERAL1 +EthernetNoHardware LITERAL1 \ No newline at end of file diff --git a/libraries/Ethernet/library.properties b/libraries/Ethernet/library.properties new file mode 100644 index 000000000..b77a843fc --- /dev/null +++ b/libraries/Ethernet/library.properties @@ -0,0 +1,10 @@ +name=Ethernet +version=0.1.0 +author=Arduino +maintainer=Arduino +sentence=Enables network connection (local and Internet) using Ethernet on Zephyr enabled boards +paragraph=With this library you can connect to Internet via Ethernet. The library provides both Client and server functionalities. The library permits you to connect to a local network also with DHCP and to resolve DNS. +category=Communication +url=http://www.arduino.cc/en/Reference/Ethernet +architectures=zephyr_main,zephyr_contrib +includes=Ethernet.h diff --git a/libraries/Ethernet/src/Ethernet.cpp b/libraries/Ethernet/src/Ethernet.cpp new file mode 100644 index 000000000..bdddefc7c --- /dev/null +++ b/libraries/Ethernet/src/Ethernet.cpp @@ -0,0 +1,92 @@ +#include "Ethernet.h" + +#if DT_HAS_COMPAT_STATUS_OKAY(ethernet_phy) + +int EthernetClass::begin(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) { + (void)timeout; + (void)responseTimeout; + if (hardwareStatus() != EthernetOk) { + return 0; + } + setMACAddress(mac); + return NetworkInterface::begin(); +} + +int EthernetClass::maintain() { + return 0; // DHCP_CHECK_NONE +} + +int EthernetClass::begin(uint8_t *mac, IPAddress ip) { + IPAddress dns = ip; + dns[3] = 1; + + auto ret = begin(mac, ip, dns); + return ret; +} + +int EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns) { + IPAddress gateway = ip; + gateway[3] = 1; + + auto ret = begin(mac, ip, dns, gateway); + return ret; +} + +int EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway) { + IPAddress subnet(255, 255, 255, 0); + auto ret = begin(mac, ip, dns, gateway, subnet); + return ret; +} + +int EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway, + IPAddress subnet, unsigned long timeout, unsigned long responseTimeout) { + (void)timeout; + (void)responseTimeout; + if (hardwareStatus() != EthernetOk) { + return 0; + } + setMACAddress(mac); + config(ip, dns, gateway, subnet); + if (!net_if_is_up(netif)) { + net_if_up(netif); + } + return 1; +} + +EthernetLinkStatus EthernetClass::linkStatus() { + if ((hardwareStatus() == EthernetOk) && net_if_is_up(netif)) { + return LinkON; + } + return LinkOFF; +} + +EthernetHardwareStatus EthernetClass::hardwareStatus() { + const struct device *const dev = DEVICE_DT_GET(DT_COMPAT_GET_ANY_STATUS_OKAY(ethernet_phy)); + if (device_is_ready(dev)) { + for (int i = 1; i < 4; i++) { + auto _if = net_if_get_by_index(i); + if (_if && !net_eth_type_is_wifi(_if)) { + netif = _if; + break; + } + } + return EthernetOk; + } else { + return EthernetNoHardware; + } +} + +void EthernetClass::end() { + disconnect(); +} + +void EthernetClass::setRetransmissionTimeout(uint16_t milliseconds) { + (void)milliseconds; +} + +void EthernetClass::setRetransmissionCount(uint8_t num) { + (void)num; +} + +EthernetClass Ethernet; +#endif diff --git a/libraries/Ethernet/src/Ethernet.h b/libraries/Ethernet/src/Ethernet.h new file mode 100644 index 000000000..617e900b0 --- /dev/null +++ b/libraries/Ethernet/src/Ethernet.h @@ -0,0 +1,63 @@ +#include "SocketHelpers.h" + +#include + +#if DT_HAS_COMPAT_STATUS_OKAY(ethernet_phy) + +enum EthernetLinkStatus { + Unknown, + LinkON, + LinkOFF +}; + +enum EthernetHardwareStatus { + EthernetNoHardware, + EthernetOk +}; + +class EthernetClass : public NetworkInterface { +public: + EthernetClass() { + } + + virtual ~EthernetClass() { + } + + int begin(uint8_t *mac = nullptr, unsigned long timeout = 60000, + unsigned long responseTimeout = 4000); + int maintain(); + EthernetLinkStatus linkStatus(); + EthernetHardwareStatus hardwareStatus(); + + // Manual configuration + int begin(uint8_t *mac, IPAddress ip); + int begin(uint8_t *mac, IPAddress ip, IPAddress dns); + int begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway); + int begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet, + unsigned long timeout = 60000, unsigned long responseTimeout = 4000); + + int begin(IPAddress ip) { + return begin(nullptr, ip); + } + + int begin(IPAddress ip, IPAddress dns) { + return begin(nullptr, ip, dns); + } + + int begin(IPAddress ip, IPAddress dns, IPAddress gateway) { + return begin(nullptr, ip, dns, gateway); + } + + int begin(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) { + return begin(nullptr, ip, dns, gateway, subnet); + } + + void end(void); + + void setRetransmissionTimeout(uint16_t milliseconds); + void setRetransmissionCount(uint8_t num); +}; + +extern EthernetClass Ethernet; + +#endif diff --git a/libraries/Ethernet/src/ZephyrEthernet.h b/libraries/Ethernet/src/ZephyrEthernet.h new file mode 100644 index 000000000..6ada64df6 --- /dev/null +++ b/libraries/Ethernet/src/ZephyrEthernet.h @@ -0,0 +1,3 @@ +#pragma once + +#include "Ethernet.h" diff --git a/libraries/Ethernet/src/Zephyr_Ethernet.h b/libraries/Ethernet/src/Zephyr_Ethernet.h new file mode 100644 index 000000000..61aaa3153 --- /dev/null +++ b/libraries/Ethernet/src/Zephyr_Ethernet.h @@ -0,0 +1 @@ +// placeholder to allow the discovery of this library diff --git a/libraries/SocketWrapper/Ethernet.cpp b/libraries/SocketWrapper/Ethernet.cpp deleted file mode 100644 index 03300d439..000000000 --- a/libraries/SocketWrapper/Ethernet.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "Ethernet.h" - -#if DT_HAS_COMPAT_STATUS_OKAY(ethernet_phy) -EthernetClass Ethernet; -#endif diff --git a/libraries/SocketWrapper/Ethernet.h b/libraries/SocketWrapper/Ethernet.h deleted file mode 100644 index e93107298..000000000 --- a/libraries/SocketWrapper/Ethernet.h +++ /dev/null @@ -1,68 +0,0 @@ -#include "SocketHelpers.h" - -#include - -#if DT_HAS_COMPAT_STATUS_OKAY(ethernet_phy) - -enum EthernetLinkStatus { - Unknown, - LinkON, - LinkOFF -}; - -enum EthernetHardwareStatus { - EthernetNoHardware, - EthernetOk -}; - -class EthernetClass : public NetworkInterface { -public: - EthernetClass() { - } - - virtual ~EthernetClass() { - } - - EthernetLinkStatus linkStatus() { - hardwareStatus(); - if (net_if_is_up(netif)) { - return LinkON; - } else { - return LinkOFF; - } - } - - bool begin(bool blocking = true, uint32_t additional_event_mask = 0) { - hardwareStatus(); - return NetworkInterface::begin(blocking, additional_event_mask); - } - - bool begin(uint8_t *mac_address, int _timeout, int _response_timeout) { - return begin(); - } - - bool begin(uint8_t *mac_address, IPAddress _ip, IPAddress _dns, IPAddress _gateway, - IPAddress _netmask, int _timeout, int _response_timeout) { - return begin(); - } - - EthernetHardwareStatus hardwareStatus() { - const struct device *const dev = DEVICE_DT_GET(DT_COMPAT_GET_ANY_STATUS_OKAY(ethernet_phy)); - if (device_is_ready(dev)) { - for (int i = 1; i < 4; i++) { - auto _if = net_if_get_by_index(i); - if (_if && !net_eth_type_is_wifi(_if)) { - netif = _if; - break; - } - } - return EthernetOk; - } else { - return EthernetNoHardware; - } - } -}; - -extern EthernetClass Ethernet; - -#endif diff --git a/libraries/SocketWrapper/SocketHelpers.cpp b/libraries/SocketWrapper/SocketHelpers.cpp index aa4d59abf..da15b3a30 100644 --- a/libraries/SocketWrapper/SocketHelpers.cpp +++ b/libraries/SocketWrapper/SocketHelpers.cpp @@ -1,4 +1,193 @@ #include "SocketHelpers.h" +#include +LOG_MODULE_DECLARE(sketch, LOG_LEVEL_NONE); + struct net_mgmt_event_callback NetworkInterface::mgmt_cb; struct net_dhcpv4_option_callback NetworkInterface::dhcp_cb; + +void NetworkInterface::event_handler(struct net_mgmt_event_callback *cb, uint64_t mgmt_event, + struct net_if *iface) { + int i = 0; + + if (mgmt_event != NET_EVENT_IPV4_ADDR_ADD) { + return; + } + + for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) { + char buf[NET_IPV4_ADDR_LEN]; + + if (iface->config.ip.ipv4->unicast[i].ipv4.addr_type != NET_ADDR_DHCP) { + continue; + } + + LOG_INF(" Address[%d]: %s", net_if_get_by_iface(iface), + net_addr_ntop(AF_INET, &iface->config.ip.ipv4->unicast[i].ipv4.address.in_addr, buf, + sizeof(buf))); + LOG_INF( + " Subnet[%d]: %s", net_if_get_by_iface(iface), + net_addr_ntop(AF_INET, &iface->config.ip.ipv4->unicast[i].netmask, buf, sizeof(buf))); + LOG_INF(" Router[%d]: %s", net_if_get_by_iface(iface), + net_addr_ntop(AF_INET, &iface->config.ip.ipv4->gw, buf, sizeof(buf))); + LOG_INF("Lease time[%d]: %u seconds", net_if_get_by_iface(iface), + iface->config.dhcpv4.lease_time); + } +} + +void NetworkInterface::option_handler(struct net_dhcpv4_option_callback *cb, size_t length, + enum net_dhcpv4_msg_type msg_type, struct net_if *iface) { + char buf[NET_IPV4_ADDR_LEN]; + + LOG_INF("DHCP Option %d: %s", cb->option, net_addr_ntop(AF_INET, cb->data, buf, sizeof(buf))); +} + +int NetworkInterface::dhcp() { + net_mgmt_init_event_callback(&mgmt_cb, event_handler, + NET_EVENT_IPV4_ADDR_ADD | NET_EVENT_IF_UP | NET_EVENT_IF_DOWN); + net_mgmt_add_event_callback(&mgmt_cb); + + net_dhcpv4_init_option_callback(&dhcp_cb, option_handler, DHCP_OPTION_NTP, ntp_server, + sizeof(ntp_server)); + + net_dhcpv4_add_option_callback(&dhcp_cb); + + net_dhcpv4_start(netif); + + LOG_INF("DHCPv4 started...\n"); + + return 0; +} + +void NetworkInterface::enable_dhcpv4_server(struct net_if *netif, char *_netmask) { + static struct in_addr addr; + static struct in_addr netmaskAddr; + + if (net_addr_pton(AF_INET, String(localIP()).c_str(), &addr)) { + LOG_ERR("Invalid address: %s", String(localIP()).c_str()); + return; + } + + if (net_addr_pton(AF_INET, _netmask, &netmaskAddr)) { + LOG_ERR("Invalid netmask: %s", _netmask); + return; + } + + net_if_ipv4_set_gw(netif, &addr); + + if (net_if_ipv4_addr_add(netif, &addr, NET_ADDR_MANUAL, 0) == NULL) { + LOG_ERR("unable to set IP address for AP interface"); + } + + if (!net_if_ipv4_set_netmask_by_addr(netif, &addr, &netmaskAddr)) { + LOG_ERR("Unable to set netmask for AP interface: %s", _netmask); + } + + addr.s4_addr[3] += 10; /* Starting IPv4 address for DHCPv4 address pool. */ + + if (net_dhcpv4_server_start(netif, &addr) != 0) { + LOG_ERR("DHCP server is not started for desired IP"); + return; + } + + LOG_INF("DHCPv4 server started...\n"); +} + +void NetworkInterface::MACAddress(uint8_t *mac) { + if (netif == NULL || netif->if_dev == NULL || mac == NULL) { + return; + } + memcpy(mac, netif->if_dev->link_addr.addr, netif->if_dev->link_addr.len); +} + +IPAddress NetworkInterface::localIP() { + return IPAddress(netif->config.ip.ipv4->unicast[0].ipv4.address.in_addr.s_addr); +} + +IPAddress NetworkInterface::subnetMask() { + return IPAddress(netif->config.ip.ipv4->unicast[0].netmask.s_addr); +} + +IPAddress NetworkInterface::gatewayIP() { + return IPAddress(netif->config.ip.ipv4->gw.s_addr); +} + +IPAddress NetworkInterface::dnsServerIP() { + return arduino::INADDR_NONE; +} + +void NetworkInterface::setMACAddress(const uint8_t *mac) { + struct ethernet_req_params params = {0}; + + if (mac == nullptr) { + LOG_ERR("MAC address pointer is null"); + return; + } + memcpy(¶ms.mac_address, mac, sizeof(struct net_eth_addr)); + if (!net_eth_is_addr_valid(¶ms.mac_address)) { + LOG_ERR("Invalid MAC address"); + return; + } + + net_if_down(netif); // Ensure the interface is down before changing the MAC address + + int ret = net_mgmt(NET_REQUEST_ETHERNET_SET_MAC_ADDRESS, netif, ¶ms, sizeof(params)); + if (ret != 0) { + LOG_ERR("Failed to set MAC address via net_mgmt, ret=%d", ret); + } else { + LOG_INF("MAC address set successfully via net_mgmt"); + } + + net_if_up(netif); // Bring the interface back up after changing the MAC address +} + +int NetworkInterface::begin(bool blocking, uint32_t additional_event_mask) { + dhcp(); + int ret = net_mgmt_event_wait_on_iface(netif, NET_EVENT_IPV4_ADDR_ADD | additional_event_mask, + NULL, NULL, NULL, blocking ? K_FOREVER : K_SECONDS(1)); + return (ret == 0) ? 1 : 0; +} + +bool NetworkInterface::disconnect() { + return (net_if_down(netif) == 0); +} + +void NetworkInterface::config(const IPAddress ip, const IPAddress dns_server, + const IPAddress gateway, const IPAddress subnet) { + setLocalIP(ip); + setDnsServerIP(dns_server); + setGatewayIP(gateway); + setSubnetMask(subnet); + return; +} + +void NetworkInterface::setLocalIP(const IPAddress ip) { + struct in_addr addr; + addr.s_addr = ip; + + if (!net_if_ipv4_addr_add(netif, &addr, NET_ADDR_MANUAL, 0)) { + LOG_ERR("Failed to set local IP address"); + return; + } + LOG_INF("Local IP address set: %s", ip.toString().c_str()); + return; +} + +void NetworkInterface::setSubnetMask(const IPAddress subnet) { + struct in_addr netmask_addr; + netmask_addr.s_addr = subnet; + net_if_ipv4_set_netmask(netif, &netmask_addr); + LOG_INF("Subnet mask set: %s", subnet.toString().c_str()); + return; +} + +void NetworkInterface::setGatewayIP(const IPAddress gateway) { + struct in_addr gw_addr; + gw_addr.s_addr = gateway; + net_if_ipv4_set_gw(netif, &gw_addr); + LOG_INF("Gateway IP set: %s", gateway.toString().c_str()); + return; +} + +void NetworkInterface::setDnsServerIP(const IPAddress dns_server) { + return; // DNS server dynamic configuration is not supported +} diff --git a/libraries/SocketWrapper/SocketHelpers.h b/libraries/SocketWrapper/SocketHelpers.h index acf510a4c..252108484 100644 --- a/libraries/SocketWrapper/SocketHelpers.h +++ b/libraries/SocketWrapper/SocketHelpers.h @@ -12,16 +12,13 @@ #include #include #include +#include +#include #include #define DHCP_OPTION_NTP (42) -#undef LOG_INF -#define LOG_INF(...) -#undef LOG_ERR -#define LOG_ERR(...) - class NetworkInterface { private: uint8_t ntp_server[4]; @@ -29,133 +26,38 @@ class NetworkInterface { static struct net_dhcpv4_option_callback dhcp_cb; static void event_handler(struct net_mgmt_event_callback *cb, uint64_t mgmt_event, - struct net_if *iface) { - int i = 0; - - if (mgmt_event != NET_EVENT_IPV4_ADDR_ADD) { - return; - } - - for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) { - char buf[NET_IPV4_ADDR_LEN]; - - if (iface->config.ip.ipv4->unicast[i].ipv4.addr_type != NET_ADDR_DHCP) { - continue; - } - - LOG_INF(" Address[%d]: %s", net_if_get_by_iface(iface), - net_addr_ntop(AF_INET, &iface->config.ip.ipv4->unicast[i].ipv4.address.in_addr, - buf, sizeof(buf))); - LOG_INF(" Subnet[%d]: %s", net_if_get_by_iface(iface), - net_addr_ntop(AF_INET, &iface->config.ip.ipv4->unicast[i].netmask, buf, - sizeof(buf))); - LOG_INF(" Router[%d]: %s", net_if_get_by_iface(iface), - net_addr_ntop(AF_INET, &iface->config.ip.ipv4->gw, buf, sizeof(buf))); - LOG_INF("Lease time[%d]: %u seconds", net_if_get_by_iface(iface), - iface->config.dhcpv4.lease_time); - } - } + struct net_if *iface); static void option_handler(struct net_dhcpv4_option_callback *cb, size_t length, - enum net_dhcpv4_msg_type msg_type, struct net_if *iface) { - char buf[NET_IPV4_ADDR_LEN]; - - LOG_INF("DHCP Option %d: %s", cb->option, - net_addr_ntop(AF_INET, cb->data, buf, sizeof(buf))); - } + enum net_dhcpv4_msg_type msg_type, struct net_if *iface); protected: struct net_if *netif = nullptr; - - int dhcp() { - net_mgmt_init_event_callback(&mgmt_cb, event_handler, - NET_EVENT_IPV4_ADDR_ADD | NET_EVENT_IF_UP | NET_EVENT_IF_DOWN); - net_mgmt_add_event_callback(&mgmt_cb); - - net_dhcpv4_init_option_callback(&dhcp_cb, option_handler, DHCP_OPTION_NTP, ntp_server, - sizeof(ntp_server)); - - net_dhcpv4_add_option_callback(&dhcp_cb); - - net_dhcpv4_start(netif); - - return 0; - } - - void enable_dhcpv4_server(struct net_if *netif, char *_netmask = "255.255.255.0") { - static struct in_addr addr; - static struct in_addr netmaskAddr; - - if (net_addr_pton(AF_INET, String(localIP()).c_str(), &addr)) { - LOG_ERR("Invalid address: %s", String(localIP()).c_str()); - return; - } - - if (net_addr_pton(AF_INET, _netmask, &netmaskAddr)) { - LOG_ERR("Invalid netmask: %s", _netmask); - return; - } - - net_if_ipv4_set_gw(netif, &addr); - - if (net_if_ipv4_addr_add(netif, &addr, NET_ADDR_MANUAL, 0) == NULL) { - LOG_ERR("unable to set IP address for AP interface"); - } - - if (!net_if_ipv4_set_netmask_by_addr(netif, &addr, &netmaskAddr)) { - LOG_ERR("Unable to set netmask for AP interface: %s", _netmask); - } - - addr.s4_addr[3] += 10; /* Starting IPv4 address for DHCPv4 address pool. */ - - if (net_dhcpv4_server_start(netif, &addr) != 0) { - LOG_ERR("DHCP server is not started for desired IP"); - return; - } - - LOG_INF("DHCPv4 server started...\n"); - } + int dhcp(); + void enable_dhcpv4_server(struct net_if *netif, char *_netmask = "255.255.255.0"); public: NetworkInterface() { } - ~NetworkInterface() { - } - - IPAddress localIP() { - return IPAddress(netif->config.ip.ipv4->unicast[0].ipv4.address.in_addr.s_addr); + virtual ~NetworkInterface() { } - IPAddress subnetMask() { - return IPAddress(netif->config.ip.ipv4->unicast[0].netmask.s_addr); - } - - IPAddress gatewayIP() { - return IPAddress(netif->config.ip.ipv4->gw.s_addr); - } - - IPAddress dnsServerIP() { - return arduino::INADDR_NONE; - } - - IPAddress dnsIP(int n = 0); + void MACAddress(uint8_t *mac); + IPAddress localIP(); + IPAddress subnetMask(); + IPAddress gatewayIP(); + IPAddress dnsServerIP(); + void config(const IPAddress ip, const IPAddress dns_server, const IPAddress gateway, + const IPAddress subnet); void setMACAddress(const uint8_t *mac); + void setLocalIP(const IPAddress ip); + void setSubnetMask(const IPAddress subnet); + void setGatewayIP(const IPAddress gateway); + void setDnsServerIP(const IPAddress dns_server); - bool begin(bool blocking = true, uint32_t additional_event_mask = 0) { - dhcp(); - int ret = - net_mgmt_event_wait_on_iface(netif, NET_EVENT_IPV4_ADDR_ADD | additional_event_mask, - NULL, NULL, NULL, blocking ? K_FOREVER : K_SECONDS(1)); - return (ret == 0); - } - - bool disconnect() { - return (net_if_down(netif) == 0); - } + int begin(bool blocking = true, uint32_t additional_event_mask = 0); - // TODO: manual functions for setting IP address, subnet mask, gateway, etc. - // net_if_ipv4_set_netmask_by_addr(iface, &addr4, &nm); - // net_if_ipv4_addr_add(iface, &addr4, NET_ADDR_MANUAL, 0); + bool disconnect(); }; diff --git a/libraries/SocketWrapper/SocketWrapper.h b/libraries/SocketWrapper/SocketWrapper.h index 6165d5aca..c9af9ff7b 100644 --- a/libraries/SocketWrapper/SocketWrapper.h +++ b/libraries/SocketWrapper/SocketWrapper.h @@ -267,5 +267,27 @@ class ZephyrSocketWrapper { return ::accept(sock_fd, nullptr, nullptr); } + String remoteIP() { + if (sock_fd == -1) { + return {}; + } + + struct sockaddr_storage addr; + socklen_t addr_len = sizeof(addr); + char ip_str[INET6_ADDRSTRLEN] = {0}; + + if (::getpeername(sock_fd, (struct sockaddr *)&addr, &addr_len) == 0) { + if (addr.ss_family == AF_INET) { + struct sockaddr_in *s = (struct sockaddr_in *)&addr; + ::inet_ntop(AF_INET, &s->sin_addr, ip_str, sizeof(ip_str)); + } else if (addr.ss_family == AF_INET6) { + struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)&addr; + ::inet_ntop(AF_INET6, &s6->sin6_addr, ip_str, sizeof(ip_str)); + } + return String(ip_str); + } + + return {}; + } friend class ZephyrClient; }; diff --git a/libraries/SocketWrapper/ZephyrClient.h b/libraries/SocketWrapper/ZephyrClient.h index 94e135cae..37ee74013 100644 --- a/libraries/SocketWrapper/ZephyrClient.h +++ b/libraries/SocketWrapper/ZephyrClient.h @@ -95,5 +95,9 @@ class ZephyrClient : public arduino::Client, ZephyrSocketWrapper { operator bool() { return sock_fd != -1; } + + String remoteIP() { + return ZephyrSocketWrapper::remoteIP(); + } friend class ZephyrServer; }; diff --git a/libraries/SocketWrapper/ZephyrUDP.h b/libraries/SocketWrapper/ZephyrUDP.h index facf37229..884639bd9 100644 --- a/libraries/SocketWrapper/ZephyrUDP.h +++ b/libraries/SocketWrapper/ZephyrUDP.h @@ -29,6 +29,8 @@ #include #include +#define UDP_TX_PACKET_MAX_SIZE 24 + class ZephyrUDP : public arduino::UDP { private: int _socket; diff --git a/libraries/SocketWrapper/examples/TestClient/TestClient.ino b/libraries/SocketWrapper/examples/TestClient/TestClient.ino deleted file mode 100755 index dc5b98c3d..000000000 --- a/libraries/SocketWrapper/examples/TestClient/TestClient.ino +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include "Ethernet.h" - -ZephyrClient client; -IPAddress addr(93, 184, 215, 14); - -void setup() { - - pinMode(LED_BUILTIN, OUTPUT); - Serial.begin(115200); - - while (Ethernet.linkStatus() != LinkON) { - Serial.println("waiting for link on"); - delay(100); - } - Ethernet.begin(); - Serial.println(Ethernet.localIP()); - - auto res = client.connect("example.com", 80); - res = client.println("GET / HTTP/1.0"); - client.println("Host: example.com"); - client.println("Connection: close"); - client.println(); -} - -// the loop function runs over and over again forever -void loop() { - while (client.available()) { - Serial.write(client.read()); - } -} diff --git a/libraries/SocketWrapper/examples/TestServer/TestServer.ino b/libraries/SocketWrapper/examples/TestServer/TestServer.ino deleted file mode 100644 index b74e6ce31..000000000 --- a/libraries/SocketWrapper/examples/TestServer/TestServer.ino +++ /dev/null @@ -1,72 +0,0 @@ -#include "ZephyrServer.h" -#include "Ethernet.h" - -ZephyrServer server(80); - -void setup() { - Serial.begin(115200); - - while (Ethernet.linkStatus() != LinkON) { - Serial.println("waiting for link on"); - delay(100); - } - Ethernet.begin(); - Serial.println(Ethernet.localIP()); - server.begin(); -} - -void loop() { - - ZephyrClient client = server.available(); - if (client) { - Serial.println("new client"); - // an http request ends with a blank line - bool currentLineIsBlank = true; - while (client.connected()) { - if (client.available()) { - char c = client.read(); - Serial.write(c); - // if you've gotten to the end of the line (received a newline - // character) and the line is blank, the http request has ended, - // so you can send a reply - if (c == '\n' && currentLineIsBlank) { - // send a standard http response header - client.println("HTTP/1.1 200 OK"); - client.println("Content-Type: text/html"); - client.println("Connection: close"); // the connection will be closed after completion of the response - client.println("Refresh: 5"); // refresh the page automatically every 5 sec - client.println(); - client.println(""); - client.println(""); - // output the value of each analog input pin - for (int analogChannel = 0; analogChannel < 6; analogChannel++) { - int sensorReading = random(analogChannel, 100); - client.print("analog input "); - client.print(analogChannel); - client.print(" is "); - client.print(sensorReading); - client.println("
"); - } - client.println(""); - break; - } - - if (c == '\n') { - // you're starting a new line - currentLineIsBlank = true; - - } else if (c != '\r') { - // you've gotten a character on the current line - currentLineIsBlank = false; - } - } - } - // give the web browser time to receive the data - delay(1); - // close the connection: - client.stop(); - Serial.println("client disconnected"); - } else { - delay(100); - } -} \ No newline at end of file diff --git a/loader/llext_exports.c b/loader/llext_exports.c index 6550ea9c1..054d20cd0 100644 --- a/loader/llext_exports.c +++ b/loader/llext_exports.c @@ -66,15 +66,19 @@ EXPORT_SYMBOL(usb_disable); EXPORT_SYMBOL(z_log_msg_runtime_vcreate); +FORCE_EXPORT_SYM(log_dynamic_sketch) + #if defined(CONFIG_NETWORKING) FORCE_EXPORT_SYM(net_if_foreach); FORCE_EXPORT_SYM(net_if_down); +FORCE_EXPORT_SYM(net_if_up); FORCE_EXPORT_SYM(net_if_get_by_iface); #if defined(CONFIG_NET_IPV4) FORCE_EXPORT_SYM(net_if_ipv4_maddr_add); FORCE_EXPORT_SYM(net_if_ipv4_maddr_join); FORCE_EXPORT_SYM(net_if_ipv4_set_gw); FORCE_EXPORT_SYM(net_if_ipv4_addr_add); +FORCE_EXPORT_SYM(net_if_ipv4_set_netmask); FORCE_EXPORT_SYM(net_if_ipv4_set_netmask_by_addr); #endif FORCE_EXPORT_SYM(net_if_lookup_by_dev); @@ -82,6 +86,7 @@ FORCE_EXPORT_SYM(net_if_lookup_by_dev); #if defined(CONFIG_NET_L2_ETHERNET) FORCE_EXPORT_SYM(_net_l2_ETHERNET); +FORCE_EXPORT_SYM(net_mgmt_NET_REQUEST_ETHERNET_SET_MAC_ADDRESS); #endif #if defined(CONFIG_NET_DHCPV4) @@ -169,6 +174,8 @@ FORCE_EXPORT_SYM(inet_pton); FORCE_EXPORT_SYM(sendto); FORCE_EXPORT_SYM(recvfrom); FORCE_EXPORT_SYM(setsockopt); +FORCE_EXPORT_SYM(getpeername); +FORCE_EXPORT_SYM(inet_ntop); #endif #if defined(CONFIG_CDC_ACM_DTE_RATE_CALLBACK_SUPPORT) diff --git a/loader/main.c b/loader/main.c index b879171fe..f96e01307 100644 --- a/loader/main.c +++ b/loader/main.c @@ -6,7 +6,7 @@ #include "zephyr/sys/printk.h" #include -LOG_MODULE_REGISTER(app); +LOG_MODULE_REGISTER(sketch); #include #include diff --git a/variants/frdm_mcxn947_mcxn947_cpu0/frdm_mcxn947_mcxn947_cpu0.conf b/variants/frdm_mcxn947_mcxn947_cpu0/frdm_mcxn947_mcxn947_cpu0.conf index cd131438a..867b155ad 100644 --- a/variants/frdm_mcxn947_mcxn947_cpu0/frdm_mcxn947_mcxn947_cpu0.conf +++ b/variants/frdm_mcxn947_mcxn947_cpu0/frdm_mcxn947_mcxn947_cpu0.conf @@ -56,3 +56,4 @@ CONFIG_NET_MGMT_EVENT_STACK_SIZE=8192 CONFIG_NET_TCP=y CONFIG_NET_SOCKETS=y CONFIG_POSIX_API=y +CONFIG_NET_L2_ETHERNET_MGMT=y \ No newline at end of file