From 4f7e8093970f13e8026788a663329c9fdc5c5831 Mon Sep 17 00:00:00 2001 From: Leonardo Cavagnis Date: Thu, 31 Jul 2025 18:30:56 +0200 Subject: [PATCH 01/19] ethernet lib: set mac address, log module fix --- libraries/SocketWrapper/Ethernet.h | 108 ++++++++------- libraries/SocketWrapper/SocketHelpers.cpp | 150 ++++++++++++++++++++ libraries/SocketWrapper/SocketHelpers.h | 160 +++++----------------- loader/llext_exports.c | 4 + loader/main.c | 2 +- 5 files changed, 246 insertions(+), 178 deletions(-) diff --git a/libraries/SocketWrapper/Ethernet.h b/libraries/SocketWrapper/Ethernet.h index e9310729..7f3d455d 100644 --- a/libraries/SocketWrapper/Ethernet.h +++ b/libraries/SocketWrapper/Ethernet.h @@ -5,64 +5,76 @@ #if DT_HAS_COMPAT_STATUS_OKAY(ethernet_phy) enum EthernetLinkStatus { - Unknown, - LinkON, - LinkOFF + Unknown, + LinkON, + LinkOFF }; enum EthernetHardwareStatus { - EthernetNoHardware, - EthernetOk + EthernetNoHardware, + EthernetOk }; -class EthernetClass : public NetworkInterface { +class EthernetClass: public NetworkInterface +{ public: - EthernetClass() { - } + EthernetClass() {} + virtual ~EthernetClass() {} - virtual ~EthernetClass() { - } + int begin(bool blocking = true, uint32_t additional_event_mask = 0) { + hardwareStatus(); + return NetworkInterface::begin(blocking, additional_event_mask); + } - EthernetLinkStatus linkStatus() { - hardwareStatus(); - if (net_if_is_up(netif)) { - return LinkON; - } else { - return LinkOFF; - } - } + int begin(uint8_t *mac, unsigned long timeout = 60000, unsigned long responseTimeout = 4000) { + hardwareStatus(); + if (mac != nullptr) { + NetworkInterface::setMACAddress(mac); + } + return NetworkInterface::begin(true, 0); + } - bool begin(bool blocking = true, uint32_t additional_event_mask = 0) { - hardwareStatus(); - return NetworkInterface::begin(blocking, additional_event_mask); - } + int maintain(); //TODO + + EthernetLinkStatus linkStatus() { + hardwareStatus(); + if (net_if_is_up(netif)) { + return LinkON; + } else { + return LinkOFF; + } + } + + 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 < 3; i++) { + auto _if = net_if_get_by_index(i); + if (!net_eth_type_is_wifi(_if)) { + netif = _if; + break; + } + } + return EthernetOk; + } else { + return EthernetNoHardware; + } + } - 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; - } - } + int begin(uint8_t *mac, IPAddress ip) { + return begin(); //TODO + } + int begin(uint8_t *mac, IPAddress ip, IPAddress dns) { + return begin(); //TODO + } + int begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway) { + return begin(); //TODO + } + int begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) { + return begin(); //TODO + } + void init(uint8_t sspin = 10); //TODO }; - extern EthernetClass Ethernet; -#endif +#endif \ No newline at end of file diff --git a/libraries/SocketWrapper/SocketHelpers.cpp b/libraries/SocketWrapper/SocketHelpers.cpp index aa4d59ab..e61eab3b 100644 --- a/libraries/SocketWrapper/SocketHelpers.cpp +++ b/libraries/SocketWrapper/SocketHelpers.cpp @@ -1,4 +1,154 @@ #include "SocketHelpers.h" +#include +LOG_MODULE_DECLARE(sketch, CONFIG_LOG_DEFAULT_LEVEL); + 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"); +} + +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; +} + +IPAddress NetworkInterface::dnsIP(int n) { + //TODO +} + +void NetworkInterface::setMACAddress(const uint8_t* mac) { + struct net_eth_addr new_mac; + struct ethernet_req_params params = { 0 }; + + memcpy(¶ms.mac_address, &new_mac, sizeof(struct net_eth_addr)); + + 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); +} diff --git a/libraries/SocketWrapper/SocketHelpers.h b/libraries/SocketWrapper/SocketHelpers.h index acf510a4..ebf85067 100644 --- a/libraries/SocketWrapper/SocketHelpers.h +++ b/libraries/SocketWrapper/SocketHelpers.h @@ -12,150 +12,52 @@ #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]; - static struct net_mgmt_event_callback mgmt_cb; - 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); - } - } - - 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))); - } - -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"); - } + private: + uint8_t ntp_server[4]; + static struct net_mgmt_event_callback mgmt_cb; + static struct net_dhcpv4_option_callback dhcp_cb; -public: - NetworkInterface() { - } + static void event_handler(struct net_mgmt_event_callback *cb, + uint64_t mgmt_event, + struct net_if *iface); - ~NetworkInterface() { - } + static void option_handler(struct net_dhcpv4_option_callback *cb, + size_t length, + enum net_dhcpv4_msg_type msg_type, + struct net_if *iface); - IPAddress localIP() { - return IPAddress(netif->config.ip.ipv4->unicast[0].ipv4.address.in_addr.s_addr); - } + protected: + struct net_if *netif = nullptr; + int dhcp(); + void enable_dhcpv4_server(struct net_if *netif, char* _netmask = "255.255.255.0"); - IPAddress subnetMask() { - return IPAddress(netif->config.ip.ipv4->unicast[0].netmask.s_addr); - } + public: + NetworkInterface() {} + ~NetworkInterface() {} - IPAddress gatewayIP() { - return IPAddress(netif->config.ip.ipv4->gw.s_addr); - } + IPAddress localIP(); - IPAddress dnsServerIP() { - return arduino::INADDR_NONE; - } + IPAddress subnetMask(); + IPAddress gatewayIP(); + IPAddress dnsServerIP(); - IPAddress dnsIP(int n = 0); + IPAddress dnsIP(int n = 0); - void setMACAddress(const uint8_t *mac); + void setMACAddress(const uint8_t* mac); - 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); - } + int begin(bool blocking = true, uint32_t additional_event_mask = 0); - bool disconnect() { - return (net_if_down(netif) == 0); - } + bool disconnect(); - // 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); + // 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); }; diff --git a/loader/llext_exports.c b/loader/llext_exports.c index 6550ea9c..cecbc87c 100644 --- a/loader/llext_exports.c +++ b/loader/llext_exports.c @@ -66,9 +66,12 @@ 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); @@ -82,6 +85,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) diff --git a/loader/main.c b/loader/main.c index 6aa2b4c8..33db344f 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 From ac6977a65e4e75868da0b90ca5c61701438dc5a6 Mon Sep 17 00:00:00 2001 From: Leonardo Cavagnis Date: Fri, 1 Aug 2025 16:51:42 +0200 Subject: [PATCH 02/19] Ethernet lib: move Ethernet functions implementation in .cpp --- libraries/SocketWrapper/Ethernet.cpp | 67 +++++++++++++++++++++++ libraries/SocketWrapper/Ethernet.h | 79 +++++++++------------------- 2 files changed, 93 insertions(+), 53 deletions(-) diff --git a/libraries/SocketWrapper/Ethernet.cpp b/libraries/SocketWrapper/Ethernet.cpp index 03300d43..cb67b498 100644 --- a/libraries/SocketWrapper/Ethernet.cpp +++ b/libraries/SocketWrapper/Ethernet.cpp @@ -1,5 +1,72 @@ #include "Ethernet.h" #if DT_HAS_COMPAT_STATUS_OKAY(ethernet_phy) + +int EthernetClass::begin(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) { + setMACAddress(mac); + return NetworkInterface::begin(true, 0); +} + +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) { + // TODO: Config the network interface with the provided IP, DNS, gateway, and subnet + + return begin(mac, timeout, responseTimeout); +} + +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 < 3; i++) { + auto _if = net_if_get_by_index(i); + if (!net_eth_type_is_wifi(_if)) { + netif = _if; + break; + } + } + return EthernetOk; + } else { + return EthernetNoHardware; + } +} + +void EthernetClass::setMACAddress(const uint8_t *mac_address) { + if (mac_address != nullptr) { + NetworkInterface::setMACAddress(mac_address); + } +} + +IPAddress EthernetClass::localIP() { + return NetworkInterface::localIP(); +} + EthernetClass Ethernet; #endif diff --git a/libraries/SocketWrapper/Ethernet.h b/libraries/SocketWrapper/Ethernet.h index 7f3d455d..5a98b49d 100644 --- a/libraries/SocketWrapper/Ethernet.h +++ b/libraries/SocketWrapper/Ethernet.h @@ -21,60 +21,33 @@ class EthernetClass: public NetworkInterface EthernetClass() {} virtual ~EthernetClass() {} - int begin(bool blocking = true, uint32_t additional_event_mask = 0) { - hardwareStatus(); - return NetworkInterface::begin(blocking, additional_event_mask); - } - - int begin(uint8_t *mac, unsigned long timeout = 60000, unsigned long responseTimeout = 4000) { - hardwareStatus(); - if (mac != nullptr) { - NetworkInterface::setMACAddress(mac); - } - return NetworkInterface::begin(true, 0); - } - - int maintain(); //TODO - - EthernetLinkStatus linkStatus() { - hardwareStatus(); - if (net_if_is_up(netif)) { - return LinkON; - } else { - return LinkOFF; - } - } - - 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 < 3; i++) { - auto _if = net_if_get_by_index(i); - if (!net_eth_type_is_wifi(_if)) { - netif = _if; - break; - } - } - return EthernetOk; - } else { - return EthernetNoHardware; - } - } - - int begin(uint8_t *mac, IPAddress ip) { - return begin(); //TODO - } - int begin(uint8_t *mac, IPAddress ip, IPAddress dns) { - return begin(); //TODO - } - int begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway) { - return begin(); //TODO - } - int begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) { - return begin(); //TODO - } - void init(uint8_t sspin = 10); //TODO + int begin(uint8_t *mac, 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); + void init(uint8_t sspin = 10); + + void MACAddress(uint8_t *mac_address); + IPAddress localIP(); + IPAddress subnetMask(); + IPAddress gatewayIP(); + IPAddress dnsServerIP(); + + void setMACAddress(const uint8_t *mac_address); + void setLocalIP(const IPAddress local_ip); + void setSubnetMask(const IPAddress subnet); + void setGatewayIP(const IPAddress gateway); + void setDnsServerIP(const IPAddress dns_server); + void setRetransmissionTimeout(uint16_t milliseconds); + void setRetransmissionCount(uint8_t num); }; + extern EthernetClass Ethernet; #endif \ No newline at end of file From 969adfecdf4adced8b69615fae0c16d38da345b2 Mon Sep 17 00:00:00 2001 From: Leonardo Cavagnis Date: Fri, 1 Aug 2025 17:32:17 +0200 Subject: [PATCH 03/19] Ethernet lib: tentative set manual IP,subnet,gateway --- libraries/SocketWrapper/Ethernet.cpp | 12 ++++++++++-- libraries/SocketWrapper/Ethernet.h | 2 +- libraries/SocketWrapper/SocketHelpers.cpp | 22 ++++++++++++++++++++++ libraries/SocketWrapper/SocketHelpers.h | 1 + 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/libraries/SocketWrapper/Ethernet.cpp b/libraries/SocketWrapper/Ethernet.cpp index cb67b498..877468c0 100644 --- a/libraries/SocketWrapper/Ethernet.cpp +++ b/libraries/SocketWrapper/Ethernet.cpp @@ -30,9 +30,17 @@ int EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress ga } int EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet, unsigned long timeout, unsigned long responseTimeout) { - // TODO: Config the network interface with the provided IP, DNS, gateway, and subnet + setMACAddress(mac); + + if (!NetworkInterface::setLocalIP(ip, subnet, gateway)) { + return 0; + } + + if (!net_if_is_up(netif)) { + net_if_up(netif); + } - return begin(mac, timeout, responseTimeout); + return 1; } EthernetLinkStatus EthernetClass::linkStatus() { diff --git a/libraries/SocketWrapper/Ethernet.h b/libraries/SocketWrapper/Ethernet.h index 5a98b49d..99f81c61 100644 --- a/libraries/SocketWrapper/Ethernet.h +++ b/libraries/SocketWrapper/Ethernet.h @@ -21,7 +21,7 @@ class EthernetClass: public NetworkInterface EthernetClass() {} virtual ~EthernetClass() {} - int begin(uint8_t *mac, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); + int begin(uint8_t *mac = nullptr, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); int maintain(); EthernetLinkStatus linkStatus(); EthernetHardwareStatus hardwareStatus(); diff --git a/libraries/SocketWrapper/SocketHelpers.cpp b/libraries/SocketWrapper/SocketHelpers.cpp index e61eab3b..f877781c 100644 --- a/libraries/SocketWrapper/SocketHelpers.cpp +++ b/libraries/SocketWrapper/SocketHelpers.cpp @@ -152,3 +152,25 @@ int NetworkInterface::begin(bool blocking, uint32_t additional_event_mask) { bool NetworkInterface::disconnect() { return (net_if_down(netif) == 0); } + +bool NetworkInterface::setLocalIP(IPAddress ip, IPAddress subnet, IPAddress gateway) { + struct in_addr ip_addr, subnet_addr, gw_addr; + + ip_addr.s_addr = ip; + subnet_addr.s_addr = subnet; + gw_addr.s_addr = gateway; + + if (!net_if_ipv4_addr_add(netif, &ip_addr, NET_ADDR_MANUAL, 0)) { + LOG_ERR("Failed to set static IP address"); + return false; + } + + if (!net_if_ipv4_set_netmask_by_addr(netif, &ip_addr, &subnet_addr)) { + LOG_ERR("Failed to set subnet mask"); + return false; + } + + net_if_ipv4_set_gw(netif, &gw_addr); + LOG_INF("Static IP configured"); + return true; +} \ No newline at end of file diff --git a/libraries/SocketWrapper/SocketHelpers.h b/libraries/SocketWrapper/SocketHelpers.h index ebf85067..20ce4524 100644 --- a/libraries/SocketWrapper/SocketHelpers.h +++ b/libraries/SocketWrapper/SocketHelpers.h @@ -52,6 +52,7 @@ class NetworkInterface { IPAddress dnsIP(int n = 0); void setMACAddress(const uint8_t* mac); + bool setLocalIP(IPAddress ip, IPAddress subnet, IPAddress gateway); int begin(bool blocking = true, uint32_t additional_event_mask = 0); From 5b253f6588342be1a15bf6b15389904c92df9c8b Mon Sep 17 00:00:00 2001 From: Leonardo Cavagnis Date: Mon, 4 Aug 2025 17:19:37 +0200 Subject: [PATCH 04/19] Ethernet lib: add set IP, Subnet, Gateway functions --- libraries/SocketWrapper/Ethernet.cpp | 34 ++++++++++++++++- libraries/SocketWrapper/Ethernet.h | 2 + libraries/SocketWrapper/SocketHelpers.cpp | 45 ++++++++++++++++++++--- libraries/SocketWrapper/SocketHelpers.h | 12 +++--- 4 files changed, 80 insertions(+), 13 deletions(-) diff --git a/libraries/SocketWrapper/Ethernet.cpp b/libraries/SocketWrapper/Ethernet.cpp index 877468c0..551f9a24 100644 --- a/libraries/SocketWrapper/Ethernet.cpp +++ b/libraries/SocketWrapper/Ethernet.cpp @@ -32,7 +32,7 @@ int EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress ga int EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet, unsigned long timeout, unsigned long responseTimeout) { setMACAddress(mac); - if (!NetworkInterface::setLocalIP(ip, subnet, gateway)) { + if (!NetworkInterface::setLocalIPFull(ip, subnet, gateway)) { return 0; } @@ -72,9 +72,41 @@ void EthernetClass::setMACAddress(const uint8_t *mac_address) { } } +void EthernetClass::MACAddress(uint8_t *mac_address) { + setMACAddress(mac_address); +} + IPAddress EthernetClass::localIP() { return NetworkInterface::localIP(); } +IPAddress EthernetClass::subnetMask() { + return NetworkInterface::subnetMask(); +} + +IPAddress EthernetClass::gatewayIP() { + return NetworkInterface::gatewayIP(); +} + +IPAddress EthernetClass::dnsServerIP() { + return NetworkInterface::dnsServerIP(); +} + +void EthernetClass::setLocalIP(const IPAddress local_ip) { + NetworkInterface::setLocalIP(local_ip); +} + +void EthernetClass::setSubnetMask(const IPAddress subnet) { + NetworkInterface::setSubnetMask(subnet); +} + +void EthernetClass::setGatewayIP(const IPAddress gateway) { + NetworkInterface::setGatewayIP(gateway); +} + +void EthernetClass::setDnsServerIP(const IPAddress dns_server) { + NetworkInterface::setDnsServerIP(dns_server); +} + EthernetClass Ethernet; #endif diff --git a/libraries/SocketWrapper/Ethernet.h b/libraries/SocketWrapper/Ethernet.h index 99f81c61..e5657958 100644 --- a/libraries/SocketWrapper/Ethernet.h +++ b/libraries/SocketWrapper/Ethernet.h @@ -31,6 +31,7 @@ class EthernetClass: public NetworkInterface 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); + void init(uint8_t sspin = 10); void MACAddress(uint8_t *mac_address); @@ -44,6 +45,7 @@ class EthernetClass: public NetworkInterface void setSubnetMask(const IPAddress subnet); void setGatewayIP(const IPAddress gateway); void setDnsServerIP(const IPAddress dns_server); + void setRetransmissionTimeout(uint16_t milliseconds); void setRetransmissionCount(uint8_t num); }; diff --git a/libraries/SocketWrapper/SocketHelpers.cpp b/libraries/SocketWrapper/SocketHelpers.cpp index f877781c..b7026199 100644 --- a/libraries/SocketWrapper/SocketHelpers.cpp +++ b/libraries/SocketWrapper/SocketHelpers.cpp @@ -119,10 +119,6 @@ IPAddress NetworkInterface::dnsServerIP() { return arduino::INADDR_NONE; } -IPAddress NetworkInterface::dnsIP(int n) { - //TODO -} - void NetworkInterface::setMACAddress(const uint8_t* mac) { struct net_eth_addr new_mac; struct ethernet_req_params params = { 0 }; @@ -153,7 +149,7 @@ bool NetworkInterface::disconnect() { return (net_if_down(netif) == 0); } -bool NetworkInterface::setLocalIP(IPAddress ip, IPAddress subnet, IPAddress gateway) { +bool NetworkInterface::setLocalIPFull(IPAddress ip, IPAddress subnet, IPAddress gateway) { struct in_addr ip_addr, subnet_addr, gw_addr; ip_addr.s_addr = ip; @@ -173,4 +169,43 @@ bool NetworkInterface::setLocalIP(IPAddress ip, IPAddress subnet, IPAddress gate net_if_ipv4_set_gw(netif, &gw_addr); LOG_INF("Static IP configured"); return true; +} + +bool NetworkInterface::setLocalIP(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 false; + } + + LOG_INF("Local IP address set: %s", ip.toString().c_str()); + return true; +} + +bool NetworkInterface::setSubnetMask(IPAddress subnet) { + struct in_addr netmask_addr; + netmask_addr.s_addr = subnet; + + if (!net_if_ipv4_set_netmask_by_addr(netif, &netmask_addr, &netmask_addr)) { + LOG_ERR("Failed to set subnet mask"); + return false; + } + + LOG_INF("Subnet mask set: %s", subnet.toString().c_str()); + return true; +} + +bool NetworkInterface::setGatewayIP(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 true; +} + +bool NetworkInterface::setDnsServerIP(IPAddress dns_server) { + return false; // DNS server dynamic configuration is not supported } \ No newline at end of file diff --git a/libraries/SocketWrapper/SocketHelpers.h b/libraries/SocketWrapper/SocketHelpers.h index 20ce4524..b407c077 100644 --- a/libraries/SocketWrapper/SocketHelpers.h +++ b/libraries/SocketWrapper/SocketHelpers.h @@ -49,16 +49,14 @@ class NetworkInterface { IPAddress gatewayIP(); IPAddress dnsServerIP(); - IPAddress dnsIP(int n = 0); - void setMACAddress(const uint8_t* mac); - bool setLocalIP(IPAddress ip, IPAddress subnet, IPAddress gateway); + bool setLocalIPFull(IPAddress ip, IPAddress subnet, IPAddress gateway); + bool setLocalIP(IPAddress ip); + bool setSubnetMask(IPAddress subnet); + bool setGatewayIP(IPAddress gateway); + bool setDnsServerIP(IPAddress dns_server); int begin(bool blocking = true, uint32_t additional_event_mask = 0); bool disconnect(); - - // 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); }; From 89e69a5a8316f25633d590d582e4ef6fdf7b1bd4 Mon Sep 17 00:00:00 2001 From: Leonardo Cavagnis Date: Mon, 4 Aug 2025 17:25:19 +0200 Subject: [PATCH 05/19] Ethernet lib: add disconnect fun --- libraries/SocketWrapper/Ethernet.cpp | 8 ++++++++ libraries/SocketWrapper/Ethernet.h | 15 +++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/libraries/SocketWrapper/Ethernet.cpp b/libraries/SocketWrapper/Ethernet.cpp index 551f9a24..8618b4b1 100644 --- a/libraries/SocketWrapper/Ethernet.cpp +++ b/libraries/SocketWrapper/Ethernet.cpp @@ -66,6 +66,14 @@ EthernetHardwareStatus EthernetClass::hardwareStatus() { } } +int EthernetClass::disconnect() { + return NetworkInterface::disconnect(); +} + +void EthernetClass::end() { + disconnect(); +} + void EthernetClass::setMACAddress(const uint8_t *mac_address) { if (mac_address != nullptr) { NetworkInterface::setMACAddress(mac_address); diff --git a/libraries/SocketWrapper/Ethernet.h b/libraries/SocketWrapper/Ethernet.h index e5657958..da0ffc96 100644 --- a/libraries/SocketWrapper/Ethernet.h +++ b/libraries/SocketWrapper/Ethernet.h @@ -21,20 +21,23 @@ class EthernetClass: public NetworkInterface EthernetClass() {} virtual ~EthernetClass() {} - int begin(uint8_t *mac = nullptr, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); + int begin(uint8_t *mac = nullptr, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); int maintain(); EthernetLinkStatus linkStatus(); EthernetHardwareStatus hardwareStatus(); - // Manual configuration + // 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(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); + void init(uint8_t sspin = 10); - void MACAddress(uint8_t *mac_address); + int disconnect(void); + void end(void); + + void MACAddress(uint8_t *mac_address); IPAddress localIP(); IPAddress subnetMask(); IPAddress gatewayIP(); @@ -45,7 +48,7 @@ class EthernetClass: public NetworkInterface void setSubnetMask(const IPAddress subnet); void setGatewayIP(const IPAddress gateway); void setDnsServerIP(const IPAddress dns_server); - + void setRetransmissionTimeout(uint16_t milliseconds); void setRetransmissionCount(uint8_t num); }; From 778992a3d4ca562310001e09b66a0b0c3eba289f Mon Sep 17 00:00:00 2001 From: Leonardo Cavagnis Date: Tue, 5 Aug 2025 13:27:31 +0200 Subject: [PATCH 06/19] Ethernet lib: extract Ethernet lib from SocketWrapper lib --- libraries/Ethernet/README.md | 11 ++++ .../examples/TestClient/TestClient.ino | 0 .../examples/TestServer/TestServer.ino | 0 libraries/Ethernet/keywords.txt | 64 +++++++++++++++++++ libraries/Ethernet/library.properties | 10 +++ .../src}/Ethernet.cpp | 0 .../src}/Ethernet.h | 0 libraries/Ethernet/src/ZephyrEthernet.h | 3 + libraries/Ethernet/src/Zephyr_Ethernet.h | 1 + 9 files changed, 89 insertions(+) create mode 100644 libraries/Ethernet/README.md rename libraries/{SocketWrapper => Ethernet}/examples/TestClient/TestClient.ino (100%) rename libraries/{SocketWrapper => Ethernet}/examples/TestServer/TestServer.ino (100%) create mode 100644 libraries/Ethernet/keywords.txt create mode 100644 libraries/Ethernet/library.properties rename libraries/{SocketWrapper => Ethernet/src}/Ethernet.cpp (100%) rename libraries/{SocketWrapper => Ethernet/src}/Ethernet.h (100%) create mode 100644 libraries/Ethernet/src/ZephyrEthernet.h create mode 100644 libraries/Ethernet/src/Zephyr_Ethernet.h diff --git a/libraries/Ethernet/README.md b/libraries/Ethernet/README.md new file mode 100644 index 00000000..872a6637 --- /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/SocketWrapper/examples/TestClient/TestClient.ino b/libraries/Ethernet/examples/TestClient/TestClient.ino similarity index 100% rename from libraries/SocketWrapper/examples/TestClient/TestClient.ino rename to libraries/Ethernet/examples/TestClient/TestClient.ino diff --git a/libraries/SocketWrapper/examples/TestServer/TestServer.ino b/libraries/Ethernet/examples/TestServer/TestServer.ino similarity index 100% rename from libraries/SocketWrapper/examples/TestServer/TestServer.ino rename to libraries/Ethernet/examples/TestServer/TestServer.ino diff --git a/libraries/Ethernet/keywords.txt b/libraries/Ethernet/keywords.txt new file mode 100644 index 00000000..3c4ed937 --- /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 00000000..cae314d2 --- /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,zephyr_portenta,zephyr_nicla,zephyr_giga +includes=Ethernet.h diff --git a/libraries/SocketWrapper/Ethernet.cpp b/libraries/Ethernet/src/Ethernet.cpp similarity index 100% rename from libraries/SocketWrapper/Ethernet.cpp rename to libraries/Ethernet/src/Ethernet.cpp diff --git a/libraries/SocketWrapper/Ethernet.h b/libraries/Ethernet/src/Ethernet.h similarity index 100% rename from libraries/SocketWrapper/Ethernet.h rename to libraries/Ethernet/src/Ethernet.h diff --git a/libraries/Ethernet/src/ZephyrEthernet.h b/libraries/Ethernet/src/ZephyrEthernet.h new file mode 100644 index 00000000..f1349895 --- /dev/null +++ b/libraries/Ethernet/src/ZephyrEthernet.h @@ -0,0 +1,3 @@ +#pragma once + +#include "Ethernet.h" \ No newline at end of file diff --git a/libraries/Ethernet/src/Zephyr_Ethernet.h b/libraries/Ethernet/src/Zephyr_Ethernet.h new file mode 100644 index 00000000..6761ba5e --- /dev/null +++ b/libraries/Ethernet/src/Zephyr_Ethernet.h @@ -0,0 +1 @@ +// placeholder to allow the discovery of this library \ No newline at end of file From 6b93247700b1117e3b83a57266caa8289150ac8d Mon Sep 17 00:00:00 2001 From: Leonardo Cavagnis Date: Tue, 5 Aug 2025 17:09:41 +0200 Subject: [PATCH 07/19] Ethernet lib: add default examples --- .../AdvancedChatServer/AdvancedChatServer.ino | 97 ++++ .../BarometricPressureWebServer.ino | 231 +++++++++ .../DhcpAddressPrinter/DhcpAddressPrinter.ino | 87 ++++ .../examples/LinkStatus/LinkStatus.ino | 28 + .../examples/TelnetClient/TelnetClient.ino | 94 ++++ .../examples/TestClient/TestClient.ino | 31 -- .../UDPSendReceiveString.ino | 129 +++++ .../examples/UdpNtpClient/UdpNtpClient.ino | 175 +++++++ .../Ethernet/examples/WebClient/WebClient.ino | 129 +++++ .../WebClientRepeating/WebClientRepeating.ino | 114 ++++ .../WebClientRepeatingManual.ino | 142 +++++ .../WebClientRepeatingSSL.ino | 110 ++++ .../WebServer.ino} | 64 ++- libraries/Ethernet/src/Ethernet.h | 12 + libraries/SocketWrapper/SocketWrapper.h | 486 +++++++++--------- libraries/SocketWrapper/ZephyrClient.h | 143 +++--- libraries/SocketWrapper/ZephyrUDP.h | 2 + loader/llext_exports.c | 2 + 18 files changed, 1723 insertions(+), 353 deletions(-) create mode 100644 libraries/Ethernet/examples/AdvancedChatServer/AdvancedChatServer.ino create mode 100644 libraries/Ethernet/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino create mode 100644 libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino create mode 100644 libraries/Ethernet/examples/LinkStatus/LinkStatus.ino create mode 100644 libraries/Ethernet/examples/TelnetClient/TelnetClient.ino delete mode 100755 libraries/Ethernet/examples/TestClient/TestClient.ino create mode 100644 libraries/Ethernet/examples/UDPSendReceiveString/UDPSendReceiveString.ino create mode 100644 libraries/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino create mode 100644 libraries/Ethernet/examples/WebClient/WebClient.ino create mode 100644 libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino create mode 100644 libraries/Ethernet/examples/WebClientRepeatingManual/WebClientRepeatingManual.ino create mode 100644 libraries/Ethernet/examples/WebClientRepeatingSSL/WebClientRepeatingSSL.ino rename libraries/Ethernet/examples/{TestServer/TestServer.ino => WebServer/WebServer.ino} (57%) diff --git a/libraries/Ethernet/examples/AdvancedChatServer/AdvancedChatServer.ino b/libraries/Ethernet/examples/AdvancedChatServer/AdvancedChatServer.ino new file mode 100644 index 00000000..5e70d16c --- /dev/null +++ b/libraries/Ethernet/examples/AdvancedChatServer/AdvancedChatServer.ino @@ -0,0 +1,97 @@ +/* + Advanced Chat Server + + A more advanced server that distributes any incoming messages + to all connected clients but the client the message comes from. + To use, telnet to your device's IP address and type. + + */ + +#include "ZephyrServer.h" +#include "ZephyrClient.h" +#include "ZephyrEthernet.h" + +// The IP address will be dependent on your local network. +// gateway and subnet are optional: +IPAddress ip(192, 168, 1, 177); +IPAddress myDns(192, 168, 1, 1); +IPAddress gateway(192, 168, 1, 1); +IPAddress subnet(255, 255, 255, 0); + + +// telnet defaults to port 23 +ZephyrServer server(23); + +ZephyrClient clients[8]; + +void setup() { + + // initialize the Ethernet device + Ethernet.begin(ip, myDns, gateway, subnet); + + // 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 + } + } + if (Ethernet.linkStatus() == LinkOFF) { + Serial.println("Ethernet cable is not connected."); + } + + // start listening for clients + server.begin(); + + Serial.print("Chat server address:"); + Serial.println(Ethernet.localIP()); +} + +void loop() { + // check for any new client connecting, and say hello (before any incoming data) + ZephyrClient newClient = server.accept(); + if (newClient) { + for (byte i=0; i < 8; i++) { + if (!clients[i]) { + Serial.print("We have a new client #"); + Serial.println(i); + newClient.print("Hello, client number: "); + newClient.println(i); + // Once we "accept", the client is no longer tracked by EthernetServer + // so we must store it into our list of clients + clients[i] = newClient; + break; + } + } + } + + // check for incoming data from all clients + for (byte i=0; i < 8; i++) { + if (clients[i] && clients[i].available() > 0) { + // read bytes from a client + byte buffer[80]; + int count = clients[i].read(buffer, 80); + // write the bytes to all other connected clients + for (byte j=0; j < 8; j++) { + if (j != i && clients[j].connected()) { + clients[j].write(buffer, count); + } + } + } + } + + // stop any clients which disconnect + for (byte i=0; i < 8; i++) { + if (clients[i] && !clients[i].connected()) { + Serial.print("disconnect client #"); + Serial.println(i); + clients[i].stop(); + } + } +} diff --git a/libraries/Ethernet/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino b/libraries/Ethernet/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino new file mode 100644 index 00000000..c7d78938 --- /dev/null +++ b/libraries/Ethernet/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino @@ -0,0 +1,231 @@ +/* + SCP1000 Barometric Pressure Sensor Display + + Serves the output of a Barometric Pressure Sensor as a web page. + Uses the SPI library. For details on the sensor, see: + http://www.sparkfun.com/commerce/product_info.php?products_id=8161 + + This sketch adapted from Nathan Seidle's SCP1000 example for PIC: + http://www.sparkfun.com/datasheets/Sensors/SCP1000-Testing.zip + + TODO: this hardware is long obsolete. This example program should + be rewritten to use https://www.sparkfun.com/products/9721 + + Circuit: + SCP1000 sensor attached to pins 6,7, and 11 - 13: + DRDY: pin 6 + CSB: pin 7 + MOSI: pin 11 + MISO: pin 12 + SCK: pin 13 + + */ + +#include "ZephyrServer.h" +#include "ZephyrEthernet.h" +// the sensor communicates using SPI, so include the library: +#include + +// assign an IP address for the controller: +IPAddress ip(192, 168, 1, 20); + +// Initialize the Ethernet server library +// with the IP address and port you want to use +// (port 80 is default for HTTP): +ZephyrServer server(80); + +//Sensor's memory register addresses: +const int PRESSURE = 0x1F; //3 most significant bits of pressure +const int PRESSURE_LSB = 0x20; //16 least significant bits of pressure +const int TEMPERATURE = 0x21; //16 bit temperature reading + +// pins used for the connection with the sensor +// the others you need are controlled by the SPI library): +const int dataReadyPin = 6; +const int chipSelectPin = 7; + +float temperature = 0.0; +long pressure = 0; +long lastReadingTime = 0; + +void setup() { + + // start the SPI library: + SPI.begin(); + + // start the Ethernet connection + Ethernet.begin(ip); + + // 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 + } + } + if (Ethernet.linkStatus() == LinkOFF) { + Serial.println("Ethernet cable is not connected."); + } + + // start listening for clients + server.begin(); + + // initalize the data ready and chip select pins: + pinMode(dataReadyPin, INPUT); + pinMode(chipSelectPin, OUTPUT); + + //Configure SCP1000 for low noise configuration: + writeRegister(0x02, 0x2D); + writeRegister(0x01, 0x03); + writeRegister(0x03, 0x02); + + // give the sensor and Ethernet shield time to set up: + delay(1000); + + //Set the sensor to high resolution mode tp start readings: + writeRegister(0x03, 0x0A); + +} + +void loop() { + // check for a reading no more than once a second. + if (millis() - lastReadingTime > 1000) { + // if there's a reading ready, read it: + // don't do anything until the data ready pin is high: + if (digitalRead(dataReadyPin) == HIGH) { + getData(); + // timestamp the last time you got a reading: + lastReadingTime = millis(); + } + } + + // listen for incoming Ethernet connections: + listenForEthernetClients(); +} + + +void getData() { + Serial.println("Getting reading"); + //Read the temperature data + int tempData = readRegister(0x21, 2); + + // convert the temperature to celsius and display it: + temperature = (float)tempData / 20.0; + + //Read the pressure data highest 3 bits: + byte pressureDataHigh = readRegister(0x1F, 1); + pressureDataHigh &= 0b00000111; //you only needs bits 2 to 0 + + //Read the pressure data lower 16 bits: + unsigned int pressureDataLow = readRegister(0x20, 2); + //combine the two parts into one 19-bit number: + pressure = ((pressureDataHigh << 16) | pressureDataLow) / 4; + + Serial.print("Temperature: "); + Serial.print(temperature); + Serial.println(" degrees C"); + Serial.print("Pressure: " + String(pressure)); + Serial.println(" Pa"); +} + +void listenForEthernetClients() { + // listen for incoming clients + ZephyrClient client = server.accept(); + if (client) { + Serial.println("Got a client"); + // an http request ends with a blank line + boolean currentLineIsBlank = true; + while (client.connected()) { + if (client.available()) { + char c = client.read(); + // 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(); + // print the current readings, in HTML format: + client.print("Temperature: "); + client.print(temperature); + client.print(" degrees C"); + client.println("
"); + client.print("Pressure: " + String(pressure)); + client.print(" Pa"); + 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(); + } +} + + +//Send a write command to SCP1000 +void writeRegister(byte registerName, byte registerValue) { + // SCP1000 expects the register name in the upper 6 bits + // of the byte: + registerName <<= 2; + // command (read or write) goes in the lower two bits: + registerName |= 0b00000010; //Write command + + // take the chip select low to select the device: + digitalWrite(chipSelectPin, LOW); + + SPI.transfer(registerName); //Send register location + SPI.transfer(registerValue); //Send value to record into register + + // take the chip select high to de-select: + digitalWrite(chipSelectPin, HIGH); +} + + +//Read register from the SCP1000: +unsigned int readRegister(byte registerName, int numBytes) { + byte inByte = 0; // incoming from the SPI read + unsigned int result = 0; // result to return + + // SCP1000 expects the register name in the upper 6 bits + // of the byte: + registerName <<= 2; + // command (read or write) goes in the lower two bits: + registerName &= 0b11111100; //Read command + + // take the chip select low to select the device: + digitalWrite(chipSelectPin, LOW); + // send the device the register you want to read: + int command = SPI.transfer(registerName); + // send a value of 0 to read the first byte returned: + inByte = SPI.transfer(0x00); + + result = inByte; + // if there's more than one byte returned, + // shift the first byte then get the second byte: + if (numBytes > 1) { + result = inByte << 8; + inByte = SPI.transfer(0x00); + result = result | inByte; + } + // take the chip select high to de-select: + digitalWrite(chipSelectPin, HIGH); + // return the result: + return (result); +} diff --git a/libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino b/libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino new file mode 100644 index 00000000..53741f7e --- /dev/null +++ b/libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino @@ -0,0 +1,87 @@ +/* + DHCP-based IP printer + + This sketch uses the DHCP extensions to the Ethernet library + to get an IP address via DHCP and print the address obtained. + using an Arduino Wiznet Ethernet shield. + + */ + +#include "ZephyrEthernet.h" + +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 + Serial.print("Waiting for link on"); + while (Ethernet.linkStatus() != LinkON) { + Serial.print("."); + delay(100); + } + Serial.println(); + + // start the Ethernet connection: + Serial.println("Initialize Ethernet with DHCP:"); + if (Ethernet.begin() == 0) { + Serial.println("Failed to configure Ethernet using DHCP"); + 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); + } + } + // print your local IP address: + Serial.print("My IP address: "); + Serial.println(Ethernet.localIP()); +} + +void loop() +{ + if (Ethernet.linkStatus() != LinkON) { + Serial.println(Ethernet.linkStatus()); + connectEth(); + } +} + +void connectEth() +{ + // in Zephyr system check if Ethernet is ready before proceeding to initialize + Serial.print("Waiting for link on"); + while (Ethernet.linkStatus() != LinkON) { + Serial.print("."); + delay(100); + } + Serial.println(); + + // 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."); + } + } else { + Serial.print(" DHCP assigned IP "); + Serial.println(Ethernet.localIP()); + } + + Serial.println("You're connected to the network"); + Serial.println(); +} diff --git a/libraries/Ethernet/examples/LinkStatus/LinkStatus.ino b/libraries/Ethernet/examples/LinkStatus/LinkStatus.ino new file mode 100644 index 00000000..a38e005d --- /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 00000000..92aad146 --- /dev/null +++ b/libraries/Ethernet/examples/TelnetClient/TelnetClient.ino @@ -0,0 +1,94 @@ +/* + Telnet client + + This sketch connects to a a telnet server (http://www.google.com) + using an Arduino Wiznet Ethernet shield. You'll need a telnet server + to test this with. + Processing's ChatServer example (part of the network library) works well, + running on port 10002. It can be found as part of the examples + in the Processing application, available at + http://processing.org/ + */ + +#include "ZephyrClient.h" +#include "ZephyrEthernet.h" + +// The IP address will be dependent on your local network: +IPAddress ip(192, 168, 1, 177); + +// Enter the IP address of the server you're connecting to: +IPAddress server(1, 1, 1, 1); + +// 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() { + // 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 + } + } + while (Ethernet.linkStatus() == LinkOFF) { + Serial.println("Ethernet cable is not connected."); + delay(500); + } + + // start the Ethernet connection: + Ethernet.begin(ip); + + // 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 + } + + // 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, 10002)) { + 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/TestClient/TestClient.ino b/libraries/Ethernet/examples/TestClient/TestClient.ino deleted file mode 100755 index dc5b98c3..00000000 --- a/libraries/Ethernet/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/Ethernet/examples/UDPSendReceiveString/UDPSendReceiveString.ino b/libraries/Ethernet/examples/UDPSendReceiveString/UDPSendReceiveString.ino new file mode 100644 index 00000000..c733e15b --- /dev/null +++ b/libraries/Ethernet/examples/UDPSendReceiveString/UDPSendReceiveString.ino @@ -0,0 +1,129 @@ +/* + 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 + Serial.print("Waiting for link on"); + while (Ethernet.linkStatus() != LinkON) { + Serial.print("."); + delay(100); + } + Serial.println(); + + // 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 00000000..a8b9a391 --- /dev/null +++ b/libraries/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino @@ -0,0 +1,175 @@ +/* + + 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 + Serial.print("Waiting for link on"); + while (Ethernet.linkStatus() != LinkON) { + Serial.print("."); + delay(100); + } + Serial.println(); + + // 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() { + if (Ethernet.linkStatus() != LinkON) { + Serial.println(Ethernet.linkStatus()); + connectEth(); + } + sendNTPpacket(timeServer); // send an NTP packet to a time server + + // 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(); +} + +void connectEth() +{ + // in Zephyr system check if Ethernet is ready before proceeding to initialize + Serial.print("Waiting for link on"); + while (Ethernet.linkStatus() != LinkON) { + Serial.print("."); + delay(100); + } + Serial.println(); + + // start the Ethernet connection: + Serial.println("Initialize Ethernet with DHCP:"); + if (Ethernet.begin(nullptr) == 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."); + } + } else { + Serial.print(" DHCP assigned IP "); + Serial.println(Ethernet.localIP()); + } + + Serial.println("You're connected to the network"); + Serial.println(); +} + + + + + + + + diff --git a/libraries/Ethernet/examples/WebClient/WebClient.ino b/libraries/Ethernet/examples/WebClient/WebClient.ino new file mode 100644 index 00000000..f5d85a4d --- /dev/null +++ b/libraries/Ethernet/examples/WebClient/WebClient.ino @@ -0,0 +1,129 @@ +/* + 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 00000000..8b37198f --- /dev/null +++ b/libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino @@ -0,0 +1,114 @@ +/* + Repeating Web client + + This sketch connects to a a web server and makes a request + using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or + the Adafruit Ethernet shield, either one will work, as long as it's got + a Wiznet Ethernet module on board. + + This example uses DNS, by assigning the Ethernet client with a MAC address, + IP address, and DNS address. + + */ + +#include +#include "ZephyrEthernet.h" + +// 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[] = "www.arduino.cc"; // 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 + Serial.print("Waiting for link on"); + while (Ethernet.linkStatus() != LinkON) { + Serial.print("."); + delay(100); + } + Serial.println(); + + // 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); + 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 WiFi 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 /latest.txt HTTP/1.1"); + client.println("Host: www.arduino.cc"); + 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"); + } +} + + + + diff --git a/libraries/Ethernet/examples/WebClientRepeatingManual/WebClientRepeatingManual.ino b/libraries/Ethernet/examples/WebClientRepeatingManual/WebClientRepeatingManual.ino new file mode 100644 index 00000000..ce1d728d --- /dev/null +++ b/libraries/Ethernet/examples/WebClientRepeatingManual/WebClientRepeatingManual.ino @@ -0,0 +1,142 @@ +/* + Repeating Web client + + This sketch connects to a a web server and makes a request + using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or + the Adafruit Ethernet shield, either one will work, as long as it's got + a Wiznet Ethernet module on board. + + This example uses DNS, by assigning the Ethernet client with a MAC address, + IP address, and DNS address. + */ + +#include +#include "ZephyrEthernet.h" + +// The IP address will be dependent on your local network. +// DNS, gateway and subnet are optional: +IPAddress ip(192, 168, 1, 177); +IPAddress myDns(192, 168, 1, 1); +IPAddress gateway(192, 168, 1, 1); +IPAddress subnet(255, 255, 0, 0); + +// initialize the library instance: +ZephyrClient client; + +char server[] = "www.arduino.cc"; // 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 + Serial.print("Waiting for link on"); + while (Ethernet.linkStatus() != LinkON) { + Serial.print("."); + delay(100); + } + Serial.println(); + + delay(2500); + + // start the Ethernet connection: + Serial.println("Initialize Ethernet with Static IP Address:"); + if (Ethernet.begin(ip, myDns, gateway, subnet) == 0) { + Serial.println("Failed to configure Ethernet with Static IP Address"); + // 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: + Serial.print("My IP address: "); + Serial.println(Ethernet.localIP()); + Serial.print("My Gateway IP address: "); + Serial.println(Ethernet.gatewayIP()); + Serial.print("My DNS Server IP address: "); + Serial.println(Ethernet.dnsServerIP()); + // give the Ethernet shield a second to initialize: + delay(2500); +} + +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 WiFi 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 /latest.txt HTTP/1.1"); + client.println("Host: www.arduino.cc"); + 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"); + } +} + +void connectEth() +{ + // start the Ethernet connection: + Serial.println("Initialize Ethernet with DHCP:"); + if (Ethernet.begin(nullptr) == 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."); + } + } else { + Serial.print(" DHCP assigned IP "); + Serial.println(Ethernet.localIP()); + } + + Serial.println("You're connected to the network"); + Serial.println(); +} diff --git a/libraries/Ethernet/examples/WebClientRepeatingSSL/WebClientRepeatingSSL.ino b/libraries/Ethernet/examples/WebClientRepeatingSSL/WebClientRepeatingSSL.ino new file mode 100644 index 00000000..748f63c1 --- /dev/null +++ b/libraries/Ethernet/examples/WebClientRepeatingSSL/WebClientRepeatingSSL.ino @@ -0,0 +1,110 @@ +/* + Repeating TLS/SSL Ethernet Web client. + + Remeber to update the CA certificates using WiFiFirmwareUpdater sketch + before using this sketch. + + */ + +#include +#include "ZephyrEthernet.h" + +// initialize the library instance: +ZephyrSSLClient client; + +char server[] = "www.arduino.cc"; +int port = 443; +// IPAddress server(64,131,82,241); + +// 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); + +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 + Serial.print("Waiting for link on"); + while (Ethernet.linkStatus() != LinkON) { + Serial.print("."); + delay(100); + } + Serial.println(); + + // 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); + 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 WiFi shield + client.stop(); + + // if there's a successful connection: + if (client.connect(server, port)) { + Serial.println("connecting..."); + // send the HTTP GET request: + client.println("GET /latest.txt HTTP/1.1"); + client.print("Host: "); + client.println(server); + client.println("User-Agent: arduino-ethernet"); + client.println("Accept: *"); + 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"); + } +} diff --git a/libraries/Ethernet/examples/TestServer/TestServer.ino b/libraries/Ethernet/examples/WebServer/WebServer.ino similarity index 57% rename from libraries/Ethernet/examples/TestServer/TestServer.ino rename to libraries/Ethernet/examples/WebServer/WebServer.ino index b74e6ce3..6dd3a287 100644 --- a/libraries/Ethernet/examples/TestServer/TestServer.ino +++ b/libraries/Ethernet/examples/WebServer/WebServer.ino @@ -1,27 +1,66 @@ +/* + Web Server + + A simple web server that shows the value of the analog input pins. + using an Arduino Wiznet Ethernet shield. + + */ + #include "ZephyrServer.h" -#include "Ethernet.h" +#include "ZephyrClient.h" +#include "ZephyrEthernet.h" + +// The IP address will be dependent on your local network: +IPAddress ip(192, 168, 2, 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() { - Serial.begin(115200); + // 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"); + Serial.println("Waiting for link on"); delay(100); } - Ethernet.begin(); - Serial.println(Ethernet.localIP()); + + // start the Ethernet connection and the server: + 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 the server server.begin(); + Serial.print("server is at "); + Serial.println(Ethernet.localIP()); } -void loop() { - ZephyrClient client = server.available(); +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; + boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); @@ -40,7 +79,7 @@ void loop() { client.println(""); // output the value of each analog input pin for (int analogChannel = 0; analogChannel < 6; analogChannel++) { - int sensorReading = random(analogChannel, 100); + int sensorReading = analogRead(analogChannel); client.print("analog input "); client.print(analogChannel); client.print(" is "); @@ -50,11 +89,9 @@ void loop() { 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; @@ -66,7 +103,6 @@ void loop() { // close the connection: client.stop(); Serial.println("client disconnected"); - } else { - delay(100); } -} \ No newline at end of file +} + diff --git a/libraries/Ethernet/src/Ethernet.h b/libraries/Ethernet/src/Ethernet.h index da0ffc96..09d29de1 100644 --- a/libraries/Ethernet/src/Ethernet.h +++ b/libraries/Ethernet/src/Ethernet.h @@ -32,6 +32,18 @@ class EthernetClass: public NetworkInterface 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 init(uint8_t sspin = 10); int disconnect(void); diff --git a/libraries/SocketWrapper/SocketWrapper.h b/libraries/SocketWrapper/SocketWrapper.h index 6165d5ac..ce58ec8d 100644 --- a/libraries/SocketWrapper/SocketWrapper.h +++ b/libraries/SocketWrapper/SocketWrapper.h @@ -10,262 +10,282 @@ class ZephyrSocketWrapper { protected: - int sock_fd; - bool is_ssl = false; - int ssl_sock_temp_char = -1; + int sock_fd; + bool is_ssl = false; + int ssl_sock_temp_char = -1; public: - ZephyrSocketWrapper() : sock_fd(-1) { - } + ZephyrSocketWrapper() : sock_fd(-1) {} + ZephyrSocketWrapper(int sock_fd) : sock_fd(sock_fd) {} - ZephyrSocketWrapper(int sock_fd) : sock_fd(sock_fd) { - } + ~ZephyrSocketWrapper() { + if (sock_fd != -1) { + ::close(sock_fd); + } + } - ~ZephyrSocketWrapper() { - if (sock_fd != -1) { - ::close(sock_fd); - } - } + bool connect(const char* host, uint16_t port) { - bool connect(const char *host, uint16_t port) { + // Resolve address + struct addrinfo hints; + struct addrinfo *res; + bool rv = true; - // Resolve address - struct addrinfo hints; - struct addrinfo *res; - bool rv = true; + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; + int resolve_attempts = 100; + int ret; - int resolve_attempts = 100; - int ret; + while (resolve_attempts--) { + ret = getaddrinfo(host, String(port).c_str(), &hints, &res); - while (resolve_attempts--) { - ret = getaddrinfo(host, String(port).c_str(), &hints, &res); + if (ret == 0) { + break; + } else { + k_sleep(K_MSEC(1)); + } + } - if (ret == 0) { - break; - } else { - k_sleep(K_MSEC(1)); - } - } + if (ret != 0) { + rv = false; + goto exit; + } - if (ret != 0) { - rv = false; - goto exit; - } + sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock_fd < 0) { + rv = false; - sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sock_fd < 0) { - rv = false; + goto exit; + } - goto exit; - } + if (::connect(sock_fd, res->ai_addr, res->ai_addrlen) < 0) { + ::close(sock_fd); + sock_fd = -1; + rv = false; + goto exit; + } - if (::connect(sock_fd, res->ai_addr, res->ai_addrlen) < 0) { - ::close(sock_fd); - sock_fd = -1; - rv = false; - goto exit; - } + exit: + if(res != nullptr) { + freeaddrinfo(res); + res = nullptr; + } - exit: - if (res != nullptr) { - freeaddrinfo(res); - res = nullptr; - } + return rv; + } - return rv; - } + bool connect(IPAddress host, uint16_t port) { - bool connect(IPAddress host, uint16_t port) { + const char* _host = host.toString().c_str(); - const char *_host = host.toString().c_str(); + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + inet_pton(AF_INET, _host, &addr.sin_addr); - struct sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - inet_pton(AF_INET, _host, &addr.sin_addr); + sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock_fd < 0) { + return false; + } - sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sock_fd < 0) { - return false; - } + if (::connect(sock_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + ::close(sock_fd); + sock_fd = -1; + return false; + } - if (::connect(sock_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - ::close(sock_fd); - sock_fd = -1; - return false; - } - - return true; - } + return true; + } #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) - bool connectSSL(const char *host, uint16_t port, char *ca_certificate_pem = nullptr) { - - // Resolve address - struct addrinfo hints; - struct addrinfo *res; - - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - - int resolve_attempts = 100; - int ret; - bool rv = true; - - sec_tag_t sec_tag_opt[] = { - CA_CERTIFICATE_TAG, - }; - - uint32_t timeo_optval = 100; - - while (resolve_attempts--) { - ret = getaddrinfo(host, String(port).c_str(), &hints, &res); - - if (ret == 0) { - break; - } else { - k_sleep(K_MSEC(1)); - } - } - - if (ret != 0) { - rv = false; - goto exit; - } - - if (ca_certificate_pem != nullptr) { - ret = tls_credential_add(CA_CERTIFICATE_TAG, TLS_CREDENTIAL_CA_CERTIFICATE, - ca_certificate_pem, strlen(ca_certificate_pem) + 1); - } - - sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TLS_1_2); - if (sock_fd < 0) { - rv = false; - goto exit; - } - - setsockopt(sock_fd, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_opt, sizeof(sec_tag_opt)); - - setsockopt(sock_fd, SOL_TLS, TLS_HOSTNAME, host, strlen(host)); - - setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &timeo_optval, sizeof(timeo_optval)); - - if (::connect(sock_fd, res->ai_addr, res->ai_addrlen) < 0) { - ::close(sock_fd); - sock_fd = -1; - rv = false; - goto exit; - } - is_ssl = true; - - exit: - if (res != nullptr) { - freeaddrinfo(res); - res = nullptr; - } - - return rv; - } + bool connectSSL(const char* host, uint16_t port, char* ca_certificate_pem = nullptr) { + + // Resolve address + struct addrinfo hints; + struct addrinfo *res; + + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + + int resolve_attempts = 100; + int ret; + bool rv = true; + + sec_tag_t sec_tag_opt[] = { + CA_CERTIFICATE_TAG, + }; + + uint32_t timeo_optval = 100; + + while (resolve_attempts--) { + ret = getaddrinfo(host, String(port).c_str(), &hints, &res); + + if (ret == 0) { + break; + } else { + k_sleep(K_MSEC(1)); + } + } + + if (ret != 0) { + rv = false; + goto exit; + } + + if (ca_certificate_pem != nullptr) { + ret = tls_credential_add(CA_CERTIFICATE_TAG, TLS_CREDENTIAL_CA_CERTIFICATE, + ca_certificate_pem, strlen(ca_certificate_pem) + 1); + } + + sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TLS_1_2); + if (sock_fd < 0) { + rv = false; + goto exit; + } + + setsockopt(sock_fd, SOL_TLS, TLS_SEC_TAG_LIST, + sec_tag_opt, sizeof(sec_tag_opt)); + + setsockopt(sock_fd, SOL_TLS, TLS_HOSTNAME, host, strlen(host)); + + setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &timeo_optval, sizeof(timeo_optval)); + + if (::connect(sock_fd, res->ai_addr, res->ai_addrlen) < 0) { + ::close(sock_fd); + sock_fd = -1; + rv = false; + goto exit; + } + is_ssl = true; + + exit: + if(res != nullptr) { + freeaddrinfo(res); + res = nullptr; + } + + return rv; + } #endif - int available() { - int count = 0; - if (is_ssl) { - /* - TODO: HACK: - The correct colution would be to call - ::recv(sock_fd, &ssl_sock_temp_char, 1, MSG_PEEK | MSG_DONTWAIT); - but it doesn't seem to work. Instead, save a temporary variable - and use it in read() - */ - if (ssl_sock_temp_char != -1) { - return 1; - } - count = ::recv(sock_fd, &ssl_sock_temp_char, 1, MSG_DONTWAIT); - } else { - zsock_ioctl(sock_fd, ZFD_IOCTL_FIONREAD, &count); - } - if (count <= 0) { - delay(1); - count = 0; - } - return count; - } - - int recv(uint8_t *buffer, size_t size, int flags = MSG_DONTWAIT) { - if (sock_fd == -1) { - return -1; - } - // TODO: see available() - if (ssl_sock_temp_char != -1) { - int ret = ::recv(sock_fd, &buffer[1], size - 1, flags); - buffer[0] = ssl_sock_temp_char; - ssl_sock_temp_char = -1; - return ret + 1; - } - return ::recv(sock_fd, buffer, size, flags); - } - - int send(const uint8_t *buffer, size_t size) { - if (sock_fd == -1) { - return -1; - } - return ::send(sock_fd, buffer, size, 0); - } - - void close() { - if (sock_fd != -1) { - ::close(sock_fd); - sock_fd = -1; - } - } - - bool bind(uint16_t port) { - struct sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = INADDR_ANY; - - sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sock_fd < 0) { - return false; - } - - zsock_ioctl(sock_fd, ZFD_IOCTL_FIONBIO); - - if (::bind(sock_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - ::close(sock_fd); - sock_fd = -1; - return false; - } - - return true; - } - - bool listen(int backlog = 5) { - if (sock_fd == -1) { - return false; - } - - if (::listen(sock_fd, backlog) < 0) { - ::close(sock_fd); - sock_fd = -1; - return false; - } - - return true; - } - - int accept() { - if (sock_fd == -1) { - return -1; - } - - return ::accept(sock_fd, nullptr, nullptr); - } - - friend class ZephyrClient; + int available() { + int count = 0; + if (is_ssl) { + /* + TODO: HACK: + The correct colution would be to call + ::recv(sock_fd, &ssl_sock_temp_char, 1, MSG_PEEK | MSG_DONTWAIT); + but it doesn't seem to work. Instead, save a temporary variable + and use it in read() + */ + if (ssl_sock_temp_char != -1) { + return 1; + } + count = ::recv(sock_fd, &ssl_sock_temp_char, 1, MSG_DONTWAIT); + } else { + zsock_ioctl(sock_fd, ZFD_IOCTL_FIONREAD, &count); + } + if (count <= 0) { + delay(1); + count = 0; + } + return count; + } + + int recv(uint8_t* buffer, size_t size, int flags = MSG_DONTWAIT) { + if (sock_fd == -1) { + return -1; + } + // TODO: see available() + if (ssl_sock_temp_char != -1) { + int ret = ::recv(sock_fd, &buffer[1], size - 1, flags); + buffer[0] = ssl_sock_temp_char; + ssl_sock_temp_char = -1; + return ret + 1; + } + return ::recv(sock_fd, buffer, size, flags); + } + + int send(const uint8_t* buffer, size_t size) { + if (sock_fd == -1) { + return -1; + } + return ::send(sock_fd, buffer, size, 0); + } + + void close() { + if (sock_fd != -1) { + ::close(sock_fd); + sock_fd = -1; + } + } + + bool bind(uint16_t port) { + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = INADDR_ANY; + + sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock_fd < 0) { + return false; + } + + zsock_ioctl(sock_fd, ZFD_IOCTL_FIONBIO); + + if (::bind(sock_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + ::close(sock_fd); + sock_fd = -1; + return false; + } + + return true; + } + + bool listen(int backlog = 5) { + if (sock_fd == -1) { + return false; + } + + if (::listen(sock_fd, backlog) < 0) { + ::close(sock_fd); + sock_fd = -1; + return false; + } + + return true; + } + + int accept() { + if (sock_fd == -1) { + return -1; + } + + 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 94e135ca..7ba08627 100644 --- a/libraries/SocketWrapper/ZephyrClient.h +++ b/libraries/SocketWrapper/ZephyrClient.h @@ -7,57 +7,53 @@ class ZephyrClient : public arduino::Client, ZephyrSocketWrapper { private: - bool _connected = false; + bool _connected = false; protected: - void setSocket(int sock) { - sock_fd = sock; - _connected = true; - } + void setSocket(int sock) { + sock_fd = sock; + _connected = true; + } public: - int connect(const char *host, uint16_t port) override { - auto ret = ZephyrSocketWrapper::connect((char *)host, port); - if (ret) { - _connected = true; - } - return ret; - } - - int connect(IPAddress ip, uint16_t port) { - auto ret = ZephyrSocketWrapper::connect(ip, port); - if (ret) { - _connected = true; - } - return ret; - } + int connect(const char* host, uint16_t port) override { + auto ret = ZephyrSocketWrapper::connect((char*)host, port); + if (ret) { + _connected = true; + } + return ret; + } + int connect(IPAddress ip, uint16_t port) { + auto ret = ZephyrSocketWrapper::connect(ip, port); + if (ret) { + _connected = true; + } + return ret; + } #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) - int connectSSL(const char *host, uint16_t port, char *cert) { - auto ret = ZephyrSocketWrapper::connectSSL((char *)host, port, cert); - if (ret) { - _connected = true; - } - return ret; - } + int connectSSL(const char* host, uint16_t port, char* cert) { + auto ret = ZephyrSocketWrapper::connectSSL((char*)host, port, cert); + if (ret) { + _connected = true; + } + return ret; + } #endif - uint8_t connected() override { - return _connected; - } - - int available() override { - return ZephyrSocketWrapper::available(); - } - - int read() override { - uint8_t c; - read(&c, 1); - return c; - } - - int read(uint8_t *buffer, size_t size) override { - auto received = recv(buffer, size); + uint8_t connected() override { + return _connected; + } + int available() override { + return ZephyrSocketWrapper::available(); + } + int read() override { + uint8_t c; + read(&c, 1); + return c; + } + int read(uint8_t* buffer, size_t size) override { + auto received = recv(buffer, size); - if (received == 0) { + if (received == 0) { return 0; } else if (received < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { @@ -66,34 +62,31 @@ class ZephyrClient : public arduino::Client, ZephyrSocketWrapper { return 0; } } - return received; - } - - size_t write(uint8_t c) override { - return write(&c, 1); - } - - size_t write(const uint8_t *buffer, size_t size) override { - return send(buffer, size); - } - - void flush() override { - // No-op - } - - int peek() override { - uint8_t c; - recv(&c, 1, MSG_PEEK); - return c; - } - - void stop() override { - ZephyrSocketWrapper::close(); - _connected = false; - } - - operator bool() { - return sock_fd != -1; - } - friend class ZephyrServer; -}; + return received; + } + size_t write(uint8_t c) override { + return write(&c, 1); + } + size_t write(const uint8_t* buffer, size_t size) override { + return send(buffer, size); + } + void flush() override { + // No-op + } + int peek() override { + uint8_t c; + recv(&c, 1, MSG_PEEK); + return c; + } + void stop() override { + ZephyrSocketWrapper::close(); + _connected = false; + } + operator bool() { + return sock_fd != -1; + } + String remoteIP() { + return ZephyrSocketWrapper::remoteIP(); + } + friend class ZephyrServer; +}; \ No newline at end of file diff --git a/libraries/SocketWrapper/ZephyrUDP.h b/libraries/SocketWrapper/ZephyrUDP.h index facf3722..884639bd 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/loader/llext_exports.c b/loader/llext_exports.c index cecbc87c..26b672f3 100644 --- a/loader/llext_exports.c +++ b/loader/llext_exports.c @@ -173,6 +173,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) From 6f34b9282aee346a94feac6ae98440c8b33576da Mon Sep 17 00:00:00 2001 From: Leonardo Cavagnis Date: Wed, 6 Aug 2025 16:27:33 +0200 Subject: [PATCH 08/19] ethernet lib: fix examples --- .../AdvancedChatServer/AdvancedChatServer.ino | 40 ++++++++++++++++--- .../BarometricPressureWebServer.ino | 29 ++++++++++---- .../DhcpAddressPrinter/DhcpAddressPrinter.ino | 3 +- .../examples/TelnetClient/TelnetClient.ino | 22 +++++----- .../examples/UdpNtpClient/UdpNtpClient.ino | 1 - .../Ethernet/examples/WebClient/WebClient.ino | 1 - .../WebClientRepeatingManual.ino | 2 +- .../Ethernet/examples/WebServer/WebServer.ino | 7 ++-- 8 files changed, 72 insertions(+), 33 deletions(-) diff --git a/libraries/Ethernet/examples/AdvancedChatServer/AdvancedChatServer.ino b/libraries/Ethernet/examples/AdvancedChatServer/AdvancedChatServer.ino index 5e70d16c..28781ff6 100644 --- a/libraries/Ethernet/examples/AdvancedChatServer/AdvancedChatServer.ino +++ b/libraries/Ethernet/examples/AdvancedChatServer/AdvancedChatServer.ino @@ -5,6 +5,28 @@ to all connected clients but the client the message comes from. To use, telnet to your device's IP address and type. + Usage: + 1. Upload this sketch to your board. + 2. Make sure your board is connected to the network and note its IP address. + 3. From a computer on the same network, open a terminal and connect via Telnet: + + - On macOS or Linux (using netcat if telnet is not available): + telnet 23 + # or, if telnet is missing: + nc 23 + + - On Windows (Command Prompt): + telnet 23 + # If 'telnet' is not recognized, enable it in "Windows Features". + + 4. Type a message and press Enter. + Your message will be broadcast to all connected clients except you. + + Example: + telnet 192.168.1.177 23 + + Press CTRL + ] then 'quit' to exit Telnet. + */ #include "ZephyrServer.h" @@ -18,23 +40,29 @@ IPAddress myDns(192, 168, 1, 1); IPAddress gateway(192, 168, 1, 1); IPAddress subnet(255, 255, 255, 0); - // telnet defaults to port 23 ZephyrServer server(23); ZephyrClient clients[8]; void setup() { - - // initialize the Ethernet device - Ethernet.begin(ip, myDns, gateway, subnet); - - // Open serial communications and wait for port to open: + // 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 + Serial.print("Waiting for link on"); + while (Ethernet.linkStatus() != LinkON) { + Serial.print("."); + delay(100); + } + Serial.println(); + + // initialize the Ethernet device + Ethernet.begin(ip, myDns, gateway, subnet); + // Check for Ethernet hardware present if (Ethernet.hardwareStatus() == EthernetNoHardware) { Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :("); diff --git a/libraries/Ethernet/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino b/libraries/Ethernet/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino index c7d78938..acbcec36 100644 --- a/libraries/Ethernet/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino +++ b/libraries/Ethernet/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino @@ -8,9 +8,6 @@ This sketch adapted from Nathan Seidle's SCP1000 example for PIC: http://www.sparkfun.com/datasheets/Sensors/SCP1000-Testing.zip - TODO: this hardware is long obsolete. This example program should - be rewritten to use https://www.sparkfun.com/products/9721 - Circuit: SCP1000 sensor attached to pins 6,7, and 11 - 13: DRDY: pin 6 @@ -18,7 +15,15 @@ MOSI: pin 11 MISO: pin 12 SCK: pin 13 - + + How it works: + 1. The board reads temperature and pressure data from the SCP1000 sensor. + 2. It hosts a simple HTTP server on port 80 that serves the current readings as a web page. + 3. You can view the readings from any device on the same network via a browser. + Open a web browser and go to: http://192.168.1.20/ (Replace with your board's IP address if changed) + + Note: The SCP1000 sensor is long obsolete. For modern projects, consider replacing it + with the BMP085/BMP180/BMP280 or similar (e.g. https://www.sparkfun.com/products/9721). */ #include "ZephyrServer.h" @@ -53,15 +58,23 @@ void setup() { // start the SPI library: SPI.begin(); - // start the Ethernet connection - Ethernet.begin(ip); - - // Open serial communications and wait for port to open: + // 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 + Serial.print("Waiting for link on"); + while (Ethernet.linkStatus() != LinkON) { + Serial.print("."); + delay(100); + } + Serial.println(); + + // start the Ethernet connection + 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. :("); diff --git a/libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino b/libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino index 53741f7e..a7e60e99 100644 --- a/libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino +++ b/libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino @@ -11,8 +11,7 @@ void setup() { - - // Open serial communications and wait for port to open: + // start serial port: Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only diff --git a/libraries/Ethernet/examples/TelnetClient/TelnetClient.ino b/libraries/Ethernet/examples/TelnetClient/TelnetClient.ino index 92aad146..97f55814 100644 --- a/libraries/Ethernet/examples/TelnetClient/TelnetClient.ino +++ b/libraries/Ethernet/examples/TelnetClient/TelnetClient.ino @@ -1,14 +1,9 @@ -/* + /* Telnet client - This sketch connects to a a telnet server (http://www.google.com) - using an Arduino Wiznet Ethernet shield. You'll need a telnet server - to test this with. - Processing's ChatServer example (part of the network library) works well, - running on port 10002. It can be found as part of the examples - in the Processing application, available at - http://processing.org/ - */ + This sketch connects to a telnet server. + You need a telnet server to test this. +*/ #include "ZephyrClient.h" #include "ZephyrEthernet.h" @@ -16,8 +11,15 @@ // 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 @@ -52,7 +54,7 @@ void setup() { Serial.println("connecting..."); // if you get a connection, report back via serial: - if (client.connect(server, 10002)) { + if (client.connect(server, port)) { Serial.println("connected"); } else { // if you didn't get a connection to the server: diff --git a/libraries/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino b/libraries/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino index a8b9a391..41e39859 100644 --- a/libraries/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino +++ b/libraries/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino @@ -24,7 +24,6 @@ byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packe ZephyrUDP Udp; void setup() { - // Open serial communications and wait for port to open: Serial.begin(9600); while (!Serial) { diff --git a/libraries/Ethernet/examples/WebClient/WebClient.ino b/libraries/Ethernet/examples/WebClient/WebClient.ino index f5d85a4d..6f92a963 100644 --- a/libraries/Ethernet/examples/WebClient/WebClient.ino +++ b/libraries/Ethernet/examples/WebClient/WebClient.ino @@ -32,7 +32,6 @@ 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) { diff --git a/libraries/Ethernet/examples/WebClientRepeatingManual/WebClientRepeatingManual.ino b/libraries/Ethernet/examples/WebClientRepeatingManual/WebClientRepeatingManual.ino index ce1d728d..de8e9266 100644 --- a/libraries/Ethernet/examples/WebClientRepeatingManual/WebClientRepeatingManual.ino +++ b/libraries/Ethernet/examples/WebClientRepeatingManual/WebClientRepeatingManual.ino @@ -18,7 +18,7 @@ IPAddress ip(192, 168, 1, 177); IPAddress myDns(192, 168, 1, 1); IPAddress gateway(192, 168, 1, 1); -IPAddress subnet(255, 255, 0, 0); +IPAddress subnet(255, 255, 255, 0); // initialize the library instance: ZephyrClient client; diff --git a/libraries/Ethernet/examples/WebServer/WebServer.ino b/libraries/Ethernet/examples/WebServer/WebServer.ino index 6dd3a287..81b7dcb9 100644 --- a/libraries/Ethernet/examples/WebServer/WebServer.ino +++ b/libraries/Ethernet/examples/WebServer/WebServer.ino @@ -1,9 +1,8 @@ /* Web Server - A simple web server that shows the value of the analog input pins. - using an Arduino Wiznet Ethernet shield. - + 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" @@ -11,7 +10,7 @@ #include "ZephyrEthernet.h" // The IP address will be dependent on your local network: -IPAddress ip(192, 168, 2, 177); +IPAddress ip(192, 168, 1, 177); // Initialize the Ethernet server library // with the IP address and port you want to use From 4b298c7dc7c7d82a60efe1deebfc9a609037c544 Mon Sep 17 00:00:00 2001 From: Leonardo Cavagnis Date: Wed, 6 Aug 2025 16:35:54 +0200 Subject: [PATCH 09/19] eth lib: disable log print in SocketWrapper module --- libraries/SocketWrapper/SocketHelpers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/SocketWrapper/SocketHelpers.cpp b/libraries/SocketWrapper/SocketHelpers.cpp index b7026199..1f8e0800 100644 --- a/libraries/SocketWrapper/SocketHelpers.cpp +++ b/libraries/SocketWrapper/SocketHelpers.cpp @@ -1,7 +1,7 @@ #include "SocketHelpers.h" #include -LOG_MODULE_DECLARE(sketch, CONFIG_LOG_DEFAULT_LEVEL); +LOG_MODULE_DECLARE(sketch, LOG_LEVEL_NONE); struct net_mgmt_event_callback NetworkInterface::mgmt_cb; struct net_dhcpv4_option_callback NetworkInterface::dhcp_cb; From a3dfdc4aba583bf00b48071b99fb8c339a899121 Mon Sep 17 00:00:00 2001 From: Leonardo Cavagnis Date: Wed, 6 Aug 2025 16:51:50 +0200 Subject: [PATCH 10/19] eth lib: add new line at end of file --- libraries/Ethernet/src/Ethernet.h | 2 +- libraries/Ethernet/src/ZephyrEthernet.h | 2 +- libraries/Ethernet/src/Zephyr_Ethernet.h | 2 +- libraries/SocketWrapper/SocketHelpers.cpp | 2 +- libraries/SocketWrapper/ZephyrClient.h | 2 +- libraries/SocketWrapper/ZephyrServer.h | 94 ++-- libraries/SocketWrapper/ZephyrUDP.h | 583 +++++++++++----------- 7 files changed, 341 insertions(+), 346 deletions(-) diff --git a/libraries/Ethernet/src/Ethernet.h b/libraries/Ethernet/src/Ethernet.h index 09d29de1..52913e6a 100644 --- a/libraries/Ethernet/src/Ethernet.h +++ b/libraries/Ethernet/src/Ethernet.h @@ -67,4 +67,4 @@ class EthernetClass: public NetworkInterface extern EthernetClass Ethernet; -#endif \ No newline at end of file +#endif diff --git a/libraries/Ethernet/src/ZephyrEthernet.h b/libraries/Ethernet/src/ZephyrEthernet.h index f1349895..6ada64df 100644 --- a/libraries/Ethernet/src/ZephyrEthernet.h +++ b/libraries/Ethernet/src/ZephyrEthernet.h @@ -1,3 +1,3 @@ #pragma once -#include "Ethernet.h" \ No newline at end of file +#include "Ethernet.h" diff --git a/libraries/Ethernet/src/Zephyr_Ethernet.h b/libraries/Ethernet/src/Zephyr_Ethernet.h index 6761ba5e..61aaa315 100644 --- a/libraries/Ethernet/src/Zephyr_Ethernet.h +++ b/libraries/Ethernet/src/Zephyr_Ethernet.h @@ -1 +1 @@ -// placeholder to allow the discovery of this library \ No newline at end of file +// placeholder to allow the discovery of this library diff --git a/libraries/SocketWrapper/SocketHelpers.cpp b/libraries/SocketWrapper/SocketHelpers.cpp index 1f8e0800..8c94efa4 100644 --- a/libraries/SocketWrapper/SocketHelpers.cpp +++ b/libraries/SocketWrapper/SocketHelpers.cpp @@ -208,4 +208,4 @@ bool NetworkInterface::setGatewayIP(IPAddress gateway) { bool NetworkInterface::setDnsServerIP(IPAddress dns_server) { return false; // DNS server dynamic configuration is not supported -} \ No newline at end of file +} diff --git a/libraries/SocketWrapper/ZephyrClient.h b/libraries/SocketWrapper/ZephyrClient.h index 7ba08627..8332665b 100644 --- a/libraries/SocketWrapper/ZephyrClient.h +++ b/libraries/SocketWrapper/ZephyrClient.h @@ -89,4 +89,4 @@ class ZephyrClient : public arduino::Client, ZephyrSocketWrapper { return ZephyrSocketWrapper::remoteIP(); } friend class ZephyrServer; -}; \ No newline at end of file +}; diff --git a/libraries/SocketWrapper/ZephyrServer.h b/libraries/SocketWrapper/ZephyrServer.h index d5385588..7ad0568e 100644 --- a/libraries/SocketWrapper/ZephyrServer.h +++ b/libraries/SocketWrapper/ZephyrServer.h @@ -7,56 +7,50 @@ class ZephyrServer : public arduino::Server, ZephyrSocketWrapper { private: - int _port; + int _port; public: - ZephyrServer() : _port(80) {}; - ZephyrServer(uint16_t port) : _port(port) {}; - - virtual ~ZephyrServer() { - end(); - } - - void end() { - ZephyrSocketWrapper::close(); - } - - void begin(uint16_t port) { - _port = port; - begin(); - } - - void begin() { - ZephyrSocketWrapper::bind(_port); - ZephyrSocketWrapper::listen(5); - } - - uint8_t status() { - return 0; - } - - explicit operator bool() { - return sock_fd != -1; - } - - ZephyrClient accept(uint8_t *status = nullptr) { - ZephyrClient client; - int sock = ZephyrSocketWrapper::accept(); - client.setSocket(sock); - return client; - } - - ZephyrClient available(uint8_t *status = nullptr) __attribute__((deprecated("Use accept()."))) { - return accept(status); - } - - size_t write(uint8_t c) override { - return write(&c, 1); - } - - size_t write(const uint8_t *buffer, size_t size) override { - return send(buffer, size); - } - - friend class ZephyrClient; + ZephyrServer() : _port(80){}; + ZephyrServer(uint16_t port) : _port(port){}; + + virtual ~ZephyrServer() { + end(); + } + void end() { + ZephyrSocketWrapper::close(); + } + void begin(uint16_t port) { + _port = port; + begin(); + } + void begin() { + ZephyrSocketWrapper::bind(_port); + ZephyrSocketWrapper::listen(5); + } + uint8_t status() { + return 0; + } + explicit operator bool() { + return sock_fd != -1; + } + + ZephyrClient accept(uint8_t* status = nullptr) { + ZephyrClient client; + int sock = ZephyrSocketWrapper::accept(); + client.setSocket(sock); + return client; + } + + ZephyrClient available(uint8_t* status = nullptr) __attribute__((deprecated("Use accept()."))) { + return accept(status); + } + + size_t write(uint8_t c) override { + return write(&c, 1); + } + size_t write(const uint8_t* buffer, size_t size) override { + return send(buffer, size); + } + + friend class ZephyrClient; }; diff --git a/libraries/SocketWrapper/ZephyrUDP.h b/libraries/SocketWrapper/ZephyrUDP.h index 884639bd..c12b26f0 100644 --- a/libraries/SocketWrapper/ZephyrUDP.h +++ b/libraries/SocketWrapper/ZephyrUDP.h @@ -33,299 +33,300 @@ class ZephyrUDP : public arduino::UDP { private: - int _socket; + int _socket; public: - ZephyrUDP() : _socket(-1) { - } // Constructor - - ~ZephyrUDP() { - stop(); - } - - // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no - // sockets available to use - virtual uint8_t begin(uint16_t port) { - - struct sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = INADDR_ANY; - - _socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - - zsock_ioctl(_socket, ZFD_IOCTL_FIONBIO); - - if (::bind(_socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - ::close(_socket); - _socket = -1; - return false; - } - - return true; - } - - // initialize, start listening on specified multicast IP address and port. Returns 1 if - // successful, 0 if there are no sockets available to use - virtual uint8_t beginMulticast(IPAddress ip, uint16_t port) { - bool ret = begin(port); - if (ret == false) { - return false; - } - - struct sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = ip; - - net_if_ipv4_maddr_join( - net_if_get_by_index(1), - net_if_ipv4_maddr_add(net_if_get_by_index(1), (struct in_addr *)&addr)); - return true; - } - - // Finish with the UDP socket - virtual void stop() { - if (_socket != -1) { - ::close(_socket); - _socket = -1; - } - } - - // Sending UDP packets - - // Start building up a packet to send to the remote host specific in ip and port - // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port - virtual int beginPacket(IPAddress ip, uint16_t port) { - _send_to_ip = ip; - _send_to_port = port; - - /* Make sure that the transmit data buffer is empty. */ - _tx_data.clear(); - return true; - } - - // Start building up a packet to send to the remote host specific in host and port - // Returns 1 if successful, 0 if there was a problem resolving the hostname or port - virtual int beginPacket(const char *host, uint16_t port) { - // Resolve address - struct addrinfo hints; - struct addrinfo *res; - - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_DGRAM; - - int resolve_attempts = 100; - int ret; - - while (resolve_attempts--) { - ret = getaddrinfo(host, String(port).c_str(), &hints, &res); - - if (ret == 0) { - break; - } else { - k_sleep(K_MSEC(1)); - } - } - - if (ret != 0) { - return false; - } - - return beginPacket(IPAddress(((sockaddr_in *)(res->ai_addr))->sin_addr.s_addr), port); - } - - // Finish off this packet and send it - // Returns 1 if the packet was sent successfully, 0 if there was an error - virtual int endPacket() { - struct sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_port = htons(_send_to_port); - addr.sin_addr.s_addr = _send_to_ip; - return ::sendto(_socket, _tx_data.data(), _tx_data.size(), 0, (sockaddr *)&addr, - sizeof(addr)); - } - - // Write a single byte into the packet - virtual size_t write(uint8_t data) { - _tx_data.push_back(data); - return 1; - } - - // Write size bytes from buffer into the packet - virtual size_t write(uint8_t *buffer, size_t size) { - std::copy(buffer, buffer + size, std::back_inserter(_tx_data)); - return size; - } - - // Write size bytes from buffer into the packet - virtual size_t write(const uint8_t *buffer, size_t size) { - std::copy(buffer, buffer + size, std::back_inserter(_tx_data)); - return size; - } - - using Print::write; - - int parsePacket() { - struct sockaddr_in addr; - socklen_t addrlen = sizeof(addr); - uint8_t tmp_buf[512]; - - int ret = ::recvfrom(_socket, tmp_buf, sizeof(tmp_buf), 0, (sockaddr *)&addr, &addrlen); - if (ret > 0) { - auto pkt = std::make_shared(IPAddress(addr.sin_addr.s_addr), - ntohs(addr.sin_port), tmp_buf, ret); - - _rx_pkt_list.push_back(pkt); - - // drop the oldest packet if the list is full - if (_rx_pkt_list.size() > _rx_pkt_list_size) { - _rx_pkt_list.pop_front(); - } - } - - if (_rx_pkt_list.size()) { - /* Discard UdpRxPacket object previously held by _rx_pkt - * and replace it with the new one. - */ - _rx_pkt = _rx_pkt_list.front(); - _rx_pkt_list.pop_front(); - return _rx_pkt->totalSize(); - } else { - /* Otherwise ensure that _rx_pkt definitely - * does not hold any UdpRxPacket object anymore. - */ - _rx_pkt.reset(); - return 0; - } - } - - int available() { - if (_rx_pkt) { - return _rx_pkt->available(); - } else { - return 0; - } - } - - int read() { - if (_rx_pkt) { - return _rx_pkt->read(); - } else { - return -1; - } - } - - int read(unsigned char *buffer, size_t len) { - if (_rx_pkt) { - return _rx_pkt->read(buffer, len); - } else { - return -1; - } - } - - int read(char *buffer, size_t len) { - if (_rx_pkt) { - return _rx_pkt->read(buffer, len); - } else { - return -1; - } - } - - int peek() { - if (_rx_pkt) { - return _rx_pkt->peek(); - } else { - return -1; - } - } - - void flush() { - /* Delete UdpRxPacket object held by _rx_pkt. */ - if (_rx_pkt) { - _rx_pkt.reset(); - } - } - - virtual IPAddress remoteIP() { - if (_rx_pkt) { - return _rx_pkt->remoteIP(); - } else { - return IPAddress(); - } - } - - virtual uint16_t remotePort() { - if (_rx_pkt) { - return _rx_pkt->remotePort(); - } else { - return 0; - } - } + ZephyrUDP() : _socket(-1) {} // Constructor + ~ZephyrUDP() { + stop(); + } + + // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + virtual uint8_t begin(uint16_t port) { + + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = INADDR_ANY; + + _socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + + zsock_ioctl(_socket, ZFD_IOCTL_FIONBIO); + + if (::bind(_socket, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + ::close(_socket); + _socket = -1; + return false; + } + + return true; + } + + // initialize, start listening on specified multicast IP address and port. Returns 1 if successful, 0 if there are no sockets available to use + virtual uint8_t beginMulticast(IPAddress ip, uint16_t port) { + bool ret = begin(port); + if (ret == false) { + return false; + } + + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = ip; + + net_if_ipv4_maddr_join(net_if_get_by_index(1), net_if_ipv4_maddr_add(net_if_get_by_index(1), (struct in_addr*)&addr)); + return true; + } + + // Finish with the UDP socket + virtual void stop() { + if (_socket != -1) { + ::close(_socket); + _socket = -1; + } + } + + // Sending UDP packets + + // Start building up a packet to send to the remote host specific in ip and port + // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port + virtual int beginPacket(IPAddress ip, uint16_t port) { + _send_to_ip = ip; + _send_to_port = port; + + /* Make sure that the transmit data buffer is empty. */ + _tx_data.clear(); + return true; + } + + // Start building up a packet to send to the remote host specific in host and port + // Returns 1 if successful, 0 if there was a problem resolving the hostname or port + virtual int beginPacket(const char* host, uint16_t port) { + // Resolve address + struct addrinfo hints; + struct addrinfo *res; + + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; + + int resolve_attempts = 100; + int ret; + + while (resolve_attempts--) { + ret = getaddrinfo(host, String(port).c_str(), &hints, &res); + + if (ret == 0) { + break; + } else { + k_sleep(K_MSEC(1)); + } + } + + if (ret != 0) { + return false; + } + + return beginPacket(IPAddress(((sockaddr_in*)(res->ai_addr))->sin_addr.s_addr), port); + } + + // Finish off this packet and send it + // Returns 1 if the packet was sent successfully, 0 if there was an error + virtual int endPacket() { + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(_send_to_port); + addr.sin_addr.s_addr = _send_to_ip; + return ::sendto(_socket, _tx_data.data(), _tx_data.size(), 0, (sockaddr*)&addr, sizeof(addr)); + } + + // Write a single byte into the packet + virtual size_t write(uint8_t data) { + _tx_data.push_back(data); + return 1; + } + + // Write size bytes from buffer into the packet + virtual size_t write(uint8_t* buffer, size_t size) { + std::copy(buffer, buffer + size, std::back_inserter(_tx_data)); + return size; + } + + // Write size bytes from buffer into the packet + virtual size_t write(const uint8_t* buffer, size_t size) { + std::copy(buffer, buffer + size, std::back_inserter(_tx_data)); + return size; + } + + using Print::write; + + int parsePacket() + { + struct sockaddr_in addr; + socklen_t addrlen = sizeof(addr); + uint8_t tmp_buf[512]; + + int ret = ::recvfrom(_socket, tmp_buf, sizeof(tmp_buf), 0, (sockaddr*)&addr, &addrlen); + if (ret > 0) + { + auto pkt = std::make_shared( + IPAddress(addr.sin_addr.s_addr), + ntohs(addr.sin_port), tmp_buf, ret); + + _rx_pkt_list.push_back(pkt); + + // drop the oldest packet if the list is full + if(_rx_pkt_list.size() > _rx_pkt_list_size) { + _rx_pkt_list.pop_front(); + } + } + + if (_rx_pkt_list.size()) + { + /* Discard UdpRxPacket object previously held by _rx_pkt + * and replace it with the new one. + */ + _rx_pkt = _rx_pkt_list.front(); + _rx_pkt_list.pop_front(); + return _rx_pkt->totalSize(); + } + else + { + /* Otherwise ensure that _rx_pkt definitely + * does not hold any UdpRxPacket object anymore. + */ + _rx_pkt.reset(); + return 0; + } + } + + int available() + { + if (_rx_pkt) + return _rx_pkt->available(); + else + return 0; + } + + int read() + { + if (_rx_pkt) + return _rx_pkt->read(); + else + return -1; + } + + int read(unsigned char* buffer, size_t len) + { + if (_rx_pkt) + return _rx_pkt->read(buffer, len); + else + return -1; + } + + int read(char* buffer, size_t len) + { + if (_rx_pkt) + return _rx_pkt->read(buffer, len); + else + return -1; + } + + int peek() + { + if (_rx_pkt) + return _rx_pkt->peek(); + else + return -1; + } + + void flush() + { + /* Delete UdpRxPacket object held by _rx_pkt. */ + if (_rx_pkt) + _rx_pkt.reset(); + } + + virtual IPAddress remoteIP() { + if (_rx_pkt) + return _rx_pkt->remoteIP(); + else + return IPAddress(); + } + + virtual uint16_t remotePort() { + if (_rx_pkt) + return _rx_pkt->remotePort(); + else + return 0; + } private: - /* UDP TRANSMISSION */ - IPAddress _send_to_ip; - uint16_t _send_to_port; - std::vector _tx_data; - int _rx_pkt_list_size = 10; - - /* UDP RECEPTION */ - class UdpRxPacket { - private: - IPAddress const _remote_ip; - uint16_t const _remote_port; - size_t const _rx_data_len; - std::deque _rx_data; - - public: - UdpRxPacket(IPAddress const remote_ip, uint16_t const remote_port, uint8_t const *p_data, - size_t const data_len) - : _remote_ip(remote_ip), _remote_port(remote_port), _rx_data_len(data_len), - _rx_data(p_data, p_data + data_len) { - } - - typedef std::shared_ptr SharedPtr; - - IPAddress remoteIP() const { - return _remote_ip; - } - - uint16_t remotePort() const { - return _remote_port; - } - - size_t totalSize() const { - return _rx_data_len; - } - - int available() { - return _rx_data.size(); - } - - int read() { - uint8_t const data = _rx_data.front(); - _rx_data.pop_front(); - return data; - } - - int read(unsigned char *buffer, size_t len) { - size_t bytes_read = 0; - for (; bytes_read < len && !_rx_data.empty(); bytes_read++) { - buffer[bytes_read] = _rx_data.front(); - _rx_data.pop_front(); - } - return bytes_read; - } - - int read(char *buffer, size_t len) { - return read((unsigned char *)buffer, len); - } - - int peek() { - return _rx_data.front(); - } - }; - - std::list _rx_pkt_list; - UdpRxPacket::SharedPtr _rx_pkt; + + /* UDP TRANSMISSION */ + IPAddress _send_to_ip; + uint16_t _send_to_port; + std::vector _tx_data; + int _rx_pkt_list_size = 10; + /* UDP RECEPTION */ + class UdpRxPacket + { + private: + IPAddress const _remote_ip; + uint16_t const _remote_port; + size_t const _rx_data_len; + std::deque _rx_data; + + public: + UdpRxPacket( + IPAddress const remote_ip, + uint16_t const remote_port, + uint8_t const * p_data, + size_t const data_len) + : _remote_ip(remote_ip) + , _remote_port(remote_port) + , _rx_data_len(data_len) + , _rx_data(p_data, p_data + data_len) + { + } + + typedef std::shared_ptr SharedPtr; + + IPAddress remoteIP() const { return _remote_ip; } + uint16_t remotePort() const { return _remote_port; } + size_t totalSize() const { return _rx_data_len; } + + int available() + { + return _rx_data.size(); + } + + int read() + { + uint8_t const data = _rx_data.front(); + _rx_data.pop_front(); + return data; + } + + int read(unsigned char* buffer, size_t len) + { + size_t bytes_read = 0; + for (; bytes_read < len && !_rx_data.empty(); bytes_read++) + { + buffer[bytes_read] = _rx_data.front(); + _rx_data.pop_front(); + } + return bytes_read; + } + + int read(char* buffer, size_t len) + { + return read((unsigned char*)buffer, len); + } + + int peek() + { + return _rx_data.front(); + } + }; + std::list _rx_pkt_list; + UdpRxPacket::SharedPtr _rx_pkt; }; From 4ed5bd62840f8f9098e7dc65ac57b4e439f964fe Mon Sep 17 00:00:00 2001 From: Leonardo Cavagnis Date: Wed, 3 Sep 2025 15:31:28 +0200 Subject: [PATCH 11/19] ethernet lib: add only zephyr architecture in library properties --- libraries/Ethernet/library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Ethernet/library.properties b/libraries/Ethernet/library.properties index cae314d2..425b3a15 100644 --- a/libraries/Ethernet/library.properties +++ b/libraries/Ethernet/library.properties @@ -6,5 +6,5 @@ sentence=Enables network connection (local and Internet) using Ethernet on Zephy 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,zephyr_portenta,zephyr_nicla,zephyr_giga +architectures=zephyr includes=Ethernet.h From 858010f63bc304864d43da8172a8c5d3bd905f4f Mon Sep 17 00:00:00 2001 From: Leonardo Cavagnis Date: Wed, 3 Sep 2025 15:32:29 +0200 Subject: [PATCH 12/19] ethernet lib: remove no-standard example --- .../WebClientRepeatingManual.ino | 142 ------------------ 1 file changed, 142 deletions(-) delete mode 100644 libraries/Ethernet/examples/WebClientRepeatingManual/WebClientRepeatingManual.ino diff --git a/libraries/Ethernet/examples/WebClientRepeatingManual/WebClientRepeatingManual.ino b/libraries/Ethernet/examples/WebClientRepeatingManual/WebClientRepeatingManual.ino deleted file mode 100644 index de8e9266..00000000 --- a/libraries/Ethernet/examples/WebClientRepeatingManual/WebClientRepeatingManual.ino +++ /dev/null @@ -1,142 +0,0 @@ -/* - Repeating Web client - - This sketch connects to a a web server and makes a request - using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or - the Adafruit Ethernet shield, either one will work, as long as it's got - a Wiznet Ethernet module on board. - - This example uses DNS, by assigning the Ethernet client with a MAC address, - IP address, and DNS address. - */ - -#include -#include "ZephyrEthernet.h" - -// The IP address will be dependent on your local network. -// DNS, gateway and subnet are optional: -IPAddress ip(192, 168, 1, 177); -IPAddress myDns(192, 168, 1, 1); -IPAddress gateway(192, 168, 1, 1); -IPAddress subnet(255, 255, 255, 0); - -// initialize the library instance: -ZephyrClient client; - -char server[] = "www.arduino.cc"; // 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 - Serial.print("Waiting for link on"); - while (Ethernet.linkStatus() != LinkON) { - Serial.print("."); - delay(100); - } - Serial.println(); - - delay(2500); - - // start the Ethernet connection: - Serial.println("Initialize Ethernet with Static IP Address:"); - if (Ethernet.begin(ip, myDns, gateway, subnet) == 0) { - Serial.println("Failed to configure Ethernet with Static IP Address"); - // 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: - Serial.print("My IP address: "); - Serial.println(Ethernet.localIP()); - Serial.print("My Gateway IP address: "); - Serial.println(Ethernet.gatewayIP()); - Serial.print("My DNS Server IP address: "); - Serial.println(Ethernet.dnsServerIP()); - // give the Ethernet shield a second to initialize: - delay(2500); -} - -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 WiFi 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 /latest.txt HTTP/1.1"); - client.println("Host: www.arduino.cc"); - 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"); - } -} - -void connectEth() -{ - // start the Ethernet connection: - Serial.println("Initialize Ethernet with DHCP:"); - if (Ethernet.begin(nullptr) == 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."); - } - } else { - Serial.print(" DHCP assigned IP "); - Serial.println(Ethernet.localIP()); - } - - Serial.println("You're connected to the network"); - Serial.println(); -} From efeef199326494a1d59950482cf26d93169c76cf Mon Sep 17 00:00:00 2001 From: Leonardo Cavagnis Date: Wed, 3 Sep 2025 15:34:06 +0200 Subject: [PATCH 13/19] ethernet lib: remove wiznet stuff --- .../examples/WebClientRepeating/WebClientRepeating.ino | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino b/libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino index 8b37198f..a1c1c738 100644 --- a/libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino +++ b/libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino @@ -2,9 +2,7 @@ Repeating Web client This sketch connects to a a web server and makes a request - using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or - the Adafruit Ethernet shield, either one will work, as long as it's got - a Wiznet Ethernet module on board. + using the Ethernet interface. This example uses DNS, by assigning the Ethernet client with a MAC address, IP address, and DNS address. From d345beba9b403cb6dd22cacad07411eaa4995fb8 Mon Sep 17 00:00:00 2001 From: Leonardo Cavagnis Date: Wed, 3 Sep 2025 17:21:38 +0200 Subject: [PATCH 14/19] socket wrapper: cosmetics clang --- libraries/SocketWrapper/SocketHelpers.cpp | 256 +++++----- libraries/SocketWrapper/SocketHelpers.h | 60 +-- libraries/SocketWrapper/SocketWrapper.h | 508 +++++++++---------- libraries/SocketWrapper/ZephyrClient.h | 147 +++--- libraries/SocketWrapper/ZephyrServer.h | 94 ++-- libraries/SocketWrapper/ZephyrUDP.h | 583 +++++++++++----------- 6 files changed, 827 insertions(+), 821 deletions(-) diff --git a/libraries/SocketWrapper/SocketHelpers.cpp b/libraries/SocketWrapper/SocketHelpers.cpp index 8c94efa4..7ca9a0e7 100644 --- a/libraries/SocketWrapper/SocketHelpers.cpp +++ b/libraries/SocketWrapper/SocketHelpers.cpp @@ -6,206 +6,194 @@ 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; +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; - } + 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]; + 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; - } + 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); - } + 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]; +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))); + 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); +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_init_option_callback(&dhcp_cb, option_handler, DHCP_OPTION_NTP, ntp_server, + sizeof(ntp_server)); - net_dhcpv4_add_option_callback(&dhcp_cb); + net_dhcpv4_add_option_callback(&dhcp_cb); - net_dhcpv4_start(netif); + net_dhcpv4_start(netif); - LOG_INF("DHCPv4 started...\n"); + LOG_INF("DHCPv4 started...\n"); - return 0; + return 0; } -void NetworkInterface::enable_dhcpv4_server(struct net_if *netif, char* _netmask) -{ - static struct in_addr addr; - static struct in_addr netmaskAddr; +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, 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; - } + if (net_addr_pton(AF_INET, _netmask, &netmaskAddr)) { + LOG_ERR("Invalid netmask: %s", _netmask); + return; + } - net_if_ipv4_set_gw(netif, &addr); + 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_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); - } + 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. */ + 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; - } + 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"); + LOG_INF("DHCPv4 server started...\n"); } IPAddress NetworkInterface::localIP() { - return IPAddress(netif->config.ip.ipv4->unicast[0].ipv4.address.in_addr.s_addr); + 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); + return IPAddress(netif->config.ip.ipv4->unicast[0].netmask.s_addr); } + IPAddress NetworkInterface::gatewayIP() { - return IPAddress(netif->config.ip.ipv4->gw.s_addr); + return IPAddress(netif->config.ip.ipv4->gw.s_addr); } + IPAddress NetworkInterface::dnsServerIP() { - return arduino::INADDR_NONE; + return arduino::INADDR_NONE; } -void NetworkInterface::setMACAddress(const uint8_t* mac) { - struct net_eth_addr new_mac; - struct ethernet_req_params params = { 0 }; +void NetworkInterface::setMACAddress(const uint8_t *mac) { + struct net_eth_addr new_mac; + struct ethernet_req_params params = {0}; - memcpy(¶ms.mac_address, &new_mac, sizeof(struct net_eth_addr)); + memcpy(¶ms.mac_address, &new_mac, sizeof(struct net_eth_addr)); - net_if_down(netif); // Ensure the interface is down before changing the MAC address + 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 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; + 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); + return (net_if_down(netif) == 0); } bool NetworkInterface::setLocalIPFull(IPAddress ip, IPAddress subnet, IPAddress gateway) { - struct in_addr ip_addr, subnet_addr, gw_addr; - - ip_addr.s_addr = ip; - subnet_addr.s_addr = subnet; - gw_addr.s_addr = gateway; + struct in_addr ip_addr, subnet_addr, gw_addr; + + ip_addr.s_addr = ip; + subnet_addr.s_addr = subnet; + gw_addr.s_addr = gateway; - if (!net_if_ipv4_addr_add(netif, &ip_addr, NET_ADDR_MANUAL, 0)) { - LOG_ERR("Failed to set static IP address"); - return false; - } + if (!net_if_ipv4_addr_add(netif, &ip_addr, NET_ADDR_MANUAL, 0)) { + LOG_ERR("Failed to set static IP address"); + return false; + } - if (!net_if_ipv4_set_netmask_by_addr(netif, &ip_addr, &subnet_addr)) { - LOG_ERR("Failed to set subnet mask"); - return false; - } + if (!net_if_ipv4_set_netmask_by_addr(netif, &ip_addr, &subnet_addr)) { + LOG_ERR("Failed to set subnet mask"); + return false; + } - net_if_ipv4_set_gw(netif, &gw_addr); - LOG_INF("Static IP configured"); - return true; + net_if_ipv4_set_gw(netif, &gw_addr); + LOG_INF("Static IP configured"); + return true; } bool NetworkInterface::setLocalIP(IPAddress ip) { - struct in_addr addr; - addr.s_addr = 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 false; - } + if (!net_if_ipv4_addr_add(netif, &addr, NET_ADDR_MANUAL, 0)) { + LOG_ERR("Failed to set local IP address"); + return false; + } - LOG_INF("Local IP address set: %s", ip.toString().c_str()); - return true; + LOG_INF("Local IP address set: %s", ip.toString().c_str()); + return true; } bool NetworkInterface::setSubnetMask(IPAddress subnet) { - struct in_addr netmask_addr; - netmask_addr.s_addr = subnet; + struct in_addr netmask_addr; + netmask_addr.s_addr = subnet; - if (!net_if_ipv4_set_netmask_by_addr(netif, &netmask_addr, &netmask_addr)) { - LOG_ERR("Failed to set subnet mask"); - return false; - } + if (!net_if_ipv4_set_netmask_by_addr(netif, &netmask_addr, &netmask_addr)) { + LOG_ERR("Failed to set subnet mask"); + return false; + } - LOG_INF("Subnet mask set: %s", subnet.toString().c_str()); - return true; + LOG_INF("Subnet mask set: %s", subnet.toString().c_str()); + return true; } bool NetworkInterface::setGatewayIP(IPAddress gateway) { - struct in_addr gw_addr; - gw_addr.s_addr = 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 true; + net_if_ipv4_set_gw(netif, &gw_addr); + LOG_INF("Gateway IP set: %s", gateway.toString().c_str()); + return true; } bool NetworkInterface::setDnsServerIP(IPAddress dns_server) { - return false; // DNS server dynamic configuration is not supported + return false; // DNS server dynamic configuration is not supported } diff --git a/libraries/SocketWrapper/SocketHelpers.h b/libraries/SocketWrapper/SocketHelpers.h index b407c077..ecf638d6 100644 --- a/libraries/SocketWrapper/SocketHelpers.h +++ b/libraries/SocketWrapper/SocketHelpers.h @@ -20,43 +20,43 @@ #define DHCP_OPTION_NTP (42) class NetworkInterface { - private: - uint8_t ntp_server[4]; - static struct net_mgmt_event_callback mgmt_cb; - static struct net_dhcpv4_option_callback dhcp_cb; +private: + uint8_t ntp_server[4]; + static struct net_mgmt_event_callback mgmt_cb; + 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); + static void event_handler(struct net_mgmt_event_callback *cb, uint64_t mgmt_event, + 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); + static void option_handler(struct net_dhcpv4_option_callback *cb, size_t length, + enum net_dhcpv4_msg_type msg_type, struct net_if *iface); - protected: - struct net_if *netif = nullptr; - int dhcp(); - void enable_dhcpv4_server(struct net_if *netif, char* _netmask = "255.255.255.0"); +protected: + struct net_if *netif = nullptr; + int dhcp(); + void enable_dhcpv4_server(struct net_if *netif, char *_netmask = "255.255.255.0"); - public: - NetworkInterface() {} - ~NetworkInterface() {} +public: + NetworkInterface() { + } - IPAddress localIP(); + ~NetworkInterface() { + } - IPAddress subnetMask(); - IPAddress gatewayIP(); - IPAddress dnsServerIP(); + IPAddress localIP(); - void setMACAddress(const uint8_t* mac); - bool setLocalIPFull(IPAddress ip, IPAddress subnet, IPAddress gateway); - bool setLocalIP(IPAddress ip); - bool setSubnetMask(IPAddress subnet); - bool setGatewayIP(IPAddress gateway); - bool setDnsServerIP(IPAddress dns_server); + IPAddress subnetMask(); + IPAddress gatewayIP(); + IPAddress dnsServerIP(); - int begin(bool blocking = true, uint32_t additional_event_mask = 0); + void setMACAddress(const uint8_t *mac); + bool setLocalIPFull(IPAddress ip, IPAddress subnet, IPAddress gateway); + bool setLocalIP(IPAddress ip); + bool setSubnetMask(IPAddress subnet); + bool setGatewayIP(IPAddress gateway); + bool setDnsServerIP(IPAddress dns_server); - bool disconnect(); + int begin(bool blocking = true, uint32_t additional_event_mask = 0); + + bool disconnect(); }; diff --git a/libraries/SocketWrapper/SocketWrapper.h b/libraries/SocketWrapper/SocketWrapper.h index ce58ec8d..c9af9ff7 100644 --- a/libraries/SocketWrapper/SocketWrapper.h +++ b/libraries/SocketWrapper/SocketWrapper.h @@ -10,282 +10,284 @@ class ZephyrSocketWrapper { protected: - int sock_fd; - bool is_ssl = false; - int ssl_sock_temp_char = -1; + int sock_fd; + bool is_ssl = false; + int ssl_sock_temp_char = -1; public: - ZephyrSocketWrapper() : sock_fd(-1) {} - ZephyrSocketWrapper(int sock_fd) : sock_fd(sock_fd) {} + ZephyrSocketWrapper() : sock_fd(-1) { + } - ~ZephyrSocketWrapper() { - if (sock_fd != -1) { - ::close(sock_fd); - } - } + ZephyrSocketWrapper(int sock_fd) : sock_fd(sock_fd) { + } - bool connect(const char* host, uint16_t port) { + ~ZephyrSocketWrapper() { + if (sock_fd != -1) { + ::close(sock_fd); + } + } - // Resolve address - struct addrinfo hints; - struct addrinfo *res; - bool rv = true; + bool connect(const char *host, uint16_t port) { - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; + // Resolve address + struct addrinfo hints; + struct addrinfo *res; + bool rv = true; - int resolve_attempts = 100; - int ret; + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; - while (resolve_attempts--) { - ret = getaddrinfo(host, String(port).c_str(), &hints, &res); + int resolve_attempts = 100; + int ret; - if (ret == 0) { - break; - } else { - k_sleep(K_MSEC(1)); - } - } + while (resolve_attempts--) { + ret = getaddrinfo(host, String(port).c_str(), &hints, &res); - if (ret != 0) { - rv = false; - goto exit; - } + if (ret == 0) { + break; + } else { + k_sleep(K_MSEC(1)); + } + } - sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sock_fd < 0) { - rv = false; + if (ret != 0) { + rv = false; + goto exit; + } - goto exit; - } + sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock_fd < 0) { + rv = false; - if (::connect(sock_fd, res->ai_addr, res->ai_addrlen) < 0) { - ::close(sock_fd); - sock_fd = -1; - rv = false; - goto exit; - } + goto exit; + } - exit: - if(res != nullptr) { - freeaddrinfo(res); - res = nullptr; - } + if (::connect(sock_fd, res->ai_addr, res->ai_addrlen) < 0) { + ::close(sock_fd); + sock_fd = -1; + rv = false; + goto exit; + } - return rv; - } + exit: + if (res != nullptr) { + freeaddrinfo(res); + res = nullptr; + } - bool connect(IPAddress host, uint16_t port) { + return rv; + } - const char* _host = host.toString().c_str(); + bool connect(IPAddress host, uint16_t port) { - struct sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - inet_pton(AF_INET, _host, &addr.sin_addr); + const char *_host = host.toString().c_str(); - sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sock_fd < 0) { - return false; - } + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + inet_pton(AF_INET, _host, &addr.sin_addr); - if (::connect(sock_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { - ::close(sock_fd); - sock_fd = -1; - return false; - } + sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock_fd < 0) { + return false; + } - return true; - } + if (::connect(sock_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + ::close(sock_fd); + sock_fd = -1; + return false; + } + + return true; + } #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) - bool connectSSL(const char* host, uint16_t port, char* ca_certificate_pem = nullptr) { - - // Resolve address - struct addrinfo hints; - struct addrinfo *res; - - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - - int resolve_attempts = 100; - int ret; - bool rv = true; - - sec_tag_t sec_tag_opt[] = { - CA_CERTIFICATE_TAG, - }; - - uint32_t timeo_optval = 100; - - while (resolve_attempts--) { - ret = getaddrinfo(host, String(port).c_str(), &hints, &res); - - if (ret == 0) { - break; - } else { - k_sleep(K_MSEC(1)); - } - } - - if (ret != 0) { - rv = false; - goto exit; - } - - if (ca_certificate_pem != nullptr) { - ret = tls_credential_add(CA_CERTIFICATE_TAG, TLS_CREDENTIAL_CA_CERTIFICATE, - ca_certificate_pem, strlen(ca_certificate_pem) + 1); - } - - sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TLS_1_2); - if (sock_fd < 0) { - rv = false; - goto exit; - } - - setsockopt(sock_fd, SOL_TLS, TLS_SEC_TAG_LIST, - sec_tag_opt, sizeof(sec_tag_opt)); - - setsockopt(sock_fd, SOL_TLS, TLS_HOSTNAME, host, strlen(host)); - - setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &timeo_optval, sizeof(timeo_optval)); - - if (::connect(sock_fd, res->ai_addr, res->ai_addrlen) < 0) { - ::close(sock_fd); - sock_fd = -1; - rv = false; - goto exit; - } - is_ssl = true; - - exit: - if(res != nullptr) { - freeaddrinfo(res); - res = nullptr; - } - - return rv; - } + bool connectSSL(const char *host, uint16_t port, char *ca_certificate_pem = nullptr) { + + // Resolve address + struct addrinfo hints; + struct addrinfo *res; + + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + + int resolve_attempts = 100; + int ret; + bool rv = true; + + sec_tag_t sec_tag_opt[] = { + CA_CERTIFICATE_TAG, + }; + + uint32_t timeo_optval = 100; + + while (resolve_attempts--) { + ret = getaddrinfo(host, String(port).c_str(), &hints, &res); + + if (ret == 0) { + break; + } else { + k_sleep(K_MSEC(1)); + } + } + + if (ret != 0) { + rv = false; + goto exit; + } + + if (ca_certificate_pem != nullptr) { + ret = tls_credential_add(CA_CERTIFICATE_TAG, TLS_CREDENTIAL_CA_CERTIFICATE, + ca_certificate_pem, strlen(ca_certificate_pem) + 1); + } + + sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TLS_1_2); + if (sock_fd < 0) { + rv = false; + goto exit; + } + + setsockopt(sock_fd, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_opt, sizeof(sec_tag_opt)); + + setsockopt(sock_fd, SOL_TLS, TLS_HOSTNAME, host, strlen(host)); + + setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &timeo_optval, sizeof(timeo_optval)); + + if (::connect(sock_fd, res->ai_addr, res->ai_addrlen) < 0) { + ::close(sock_fd); + sock_fd = -1; + rv = false; + goto exit; + } + is_ssl = true; + + exit: + if (res != nullptr) { + freeaddrinfo(res); + res = nullptr; + } + + return rv; + } #endif - int available() { - int count = 0; - if (is_ssl) { - /* - TODO: HACK: - The correct colution would be to call - ::recv(sock_fd, &ssl_sock_temp_char, 1, MSG_PEEK | MSG_DONTWAIT); - but it doesn't seem to work. Instead, save a temporary variable - and use it in read() - */ - if (ssl_sock_temp_char != -1) { - return 1; - } - count = ::recv(sock_fd, &ssl_sock_temp_char, 1, MSG_DONTWAIT); - } else { - zsock_ioctl(sock_fd, ZFD_IOCTL_FIONREAD, &count); - } - if (count <= 0) { - delay(1); - count = 0; - } - return count; - } - - int recv(uint8_t* buffer, size_t size, int flags = MSG_DONTWAIT) { - if (sock_fd == -1) { - return -1; - } - // TODO: see available() - if (ssl_sock_temp_char != -1) { - int ret = ::recv(sock_fd, &buffer[1], size - 1, flags); - buffer[0] = ssl_sock_temp_char; - ssl_sock_temp_char = -1; - return ret + 1; - } - return ::recv(sock_fd, buffer, size, flags); - } - - int send(const uint8_t* buffer, size_t size) { - if (sock_fd == -1) { - return -1; - } - return ::send(sock_fd, buffer, size, 0); - } - - void close() { - if (sock_fd != -1) { - ::close(sock_fd); - sock_fd = -1; - } - } - - bool bind(uint16_t port) { - struct sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = INADDR_ANY; - - sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sock_fd < 0) { - return false; - } - - zsock_ioctl(sock_fd, ZFD_IOCTL_FIONBIO); - - if (::bind(sock_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { - ::close(sock_fd); - sock_fd = -1; - return false; - } - - return true; - } - - bool listen(int backlog = 5) { - if (sock_fd == -1) { - return false; - } - - if (::listen(sock_fd, backlog) < 0) { - ::close(sock_fd); - sock_fd = -1; - return false; - } - - return true; - } - - int accept() { - if (sock_fd == -1) { - return -1; - } - - 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; + int available() { + int count = 0; + if (is_ssl) { + /* + TODO: HACK: + The correct colution would be to call + ::recv(sock_fd, &ssl_sock_temp_char, 1, MSG_PEEK | MSG_DONTWAIT); + but it doesn't seem to work. Instead, save a temporary variable + and use it in read() + */ + if (ssl_sock_temp_char != -1) { + return 1; + } + count = ::recv(sock_fd, &ssl_sock_temp_char, 1, MSG_DONTWAIT); + } else { + zsock_ioctl(sock_fd, ZFD_IOCTL_FIONREAD, &count); + } + if (count <= 0) { + delay(1); + count = 0; + } + return count; + } + + int recv(uint8_t *buffer, size_t size, int flags = MSG_DONTWAIT) { + if (sock_fd == -1) { + return -1; + } + // TODO: see available() + if (ssl_sock_temp_char != -1) { + int ret = ::recv(sock_fd, &buffer[1], size - 1, flags); + buffer[0] = ssl_sock_temp_char; + ssl_sock_temp_char = -1; + return ret + 1; + } + return ::recv(sock_fd, buffer, size, flags); + } + + int send(const uint8_t *buffer, size_t size) { + if (sock_fd == -1) { + return -1; + } + return ::send(sock_fd, buffer, size, 0); + } + + void close() { + if (sock_fd != -1) { + ::close(sock_fd); + sock_fd = -1; + } + } + + bool bind(uint16_t port) { + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = INADDR_ANY; + + sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock_fd < 0) { + return false; + } + + zsock_ioctl(sock_fd, ZFD_IOCTL_FIONBIO); + + if (::bind(sock_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + ::close(sock_fd); + sock_fd = -1; + return false; + } + + return true; + } + + bool listen(int backlog = 5) { + if (sock_fd == -1) { + return false; + } + + if (::listen(sock_fd, backlog) < 0) { + ::close(sock_fd); + sock_fd = -1; + return false; + } + + return true; + } + + int accept() { + if (sock_fd == -1) { + return -1; + } + + 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 8332665b..37ee7401 100644 --- a/libraries/SocketWrapper/ZephyrClient.h +++ b/libraries/SocketWrapper/ZephyrClient.h @@ -7,53 +7,57 @@ class ZephyrClient : public arduino::Client, ZephyrSocketWrapper { private: - bool _connected = false; + bool _connected = false; protected: - void setSocket(int sock) { - sock_fd = sock; - _connected = true; - } + void setSocket(int sock) { + sock_fd = sock; + _connected = true; + } public: - int connect(const char* host, uint16_t port) override { - auto ret = ZephyrSocketWrapper::connect((char*)host, port); - if (ret) { - _connected = true; - } - return ret; - } - int connect(IPAddress ip, uint16_t port) { - auto ret = ZephyrSocketWrapper::connect(ip, port); - if (ret) { - _connected = true; - } - return ret; - } + int connect(const char *host, uint16_t port) override { + auto ret = ZephyrSocketWrapper::connect((char *)host, port); + if (ret) { + _connected = true; + } + return ret; + } + + int connect(IPAddress ip, uint16_t port) { + auto ret = ZephyrSocketWrapper::connect(ip, port); + if (ret) { + _connected = true; + } + return ret; + } #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) - int connectSSL(const char* host, uint16_t port, char* cert) { - auto ret = ZephyrSocketWrapper::connectSSL((char*)host, port, cert); - if (ret) { - _connected = true; - } - return ret; - } + int connectSSL(const char *host, uint16_t port, char *cert) { + auto ret = ZephyrSocketWrapper::connectSSL((char *)host, port, cert); + if (ret) { + _connected = true; + } + return ret; + } #endif - uint8_t connected() override { - return _connected; - } - int available() override { - return ZephyrSocketWrapper::available(); - } - int read() override { - uint8_t c; - read(&c, 1); - return c; - } - int read(uint8_t* buffer, size_t size) override { - auto received = recv(buffer, size); - - if (received == 0) { + uint8_t connected() override { + return _connected; + } + + int available() override { + return ZephyrSocketWrapper::available(); + } + + int read() override { + uint8_t c; + read(&c, 1); + return c; + } + + int read(uint8_t *buffer, size_t size) override { + auto received = recv(buffer, size); + + if (received == 0) { return 0; } else if (received < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { @@ -62,31 +66,38 @@ class ZephyrClient : public arduino::Client, ZephyrSocketWrapper { return 0; } } - return received; - } - size_t write(uint8_t c) override { - return write(&c, 1); - } - size_t write(const uint8_t* buffer, size_t size) override { - return send(buffer, size); - } - void flush() override { - // No-op - } - int peek() override { - uint8_t c; - recv(&c, 1, MSG_PEEK); - return c; - } - void stop() override { - ZephyrSocketWrapper::close(); - _connected = false; - } - operator bool() { - return sock_fd != -1; - } - String remoteIP() { - return ZephyrSocketWrapper::remoteIP(); - } - friend class ZephyrServer; + return received; + } + + size_t write(uint8_t c) override { + return write(&c, 1); + } + + size_t write(const uint8_t *buffer, size_t size) override { + return send(buffer, size); + } + + void flush() override { + // No-op + } + + int peek() override { + uint8_t c; + recv(&c, 1, MSG_PEEK); + return c; + } + + void stop() override { + ZephyrSocketWrapper::close(); + _connected = false; + } + + operator bool() { + return sock_fd != -1; + } + + String remoteIP() { + return ZephyrSocketWrapper::remoteIP(); + } + friend class ZephyrServer; }; diff --git a/libraries/SocketWrapper/ZephyrServer.h b/libraries/SocketWrapper/ZephyrServer.h index 7ad0568e..d5385588 100644 --- a/libraries/SocketWrapper/ZephyrServer.h +++ b/libraries/SocketWrapper/ZephyrServer.h @@ -7,50 +7,56 @@ class ZephyrServer : public arduino::Server, ZephyrSocketWrapper { private: - int _port; + int _port; public: - ZephyrServer() : _port(80){}; - ZephyrServer(uint16_t port) : _port(port){}; - - virtual ~ZephyrServer() { - end(); - } - void end() { - ZephyrSocketWrapper::close(); - } - void begin(uint16_t port) { - _port = port; - begin(); - } - void begin() { - ZephyrSocketWrapper::bind(_port); - ZephyrSocketWrapper::listen(5); - } - uint8_t status() { - return 0; - } - explicit operator bool() { - return sock_fd != -1; - } - - ZephyrClient accept(uint8_t* status = nullptr) { - ZephyrClient client; - int sock = ZephyrSocketWrapper::accept(); - client.setSocket(sock); - return client; - } - - ZephyrClient available(uint8_t* status = nullptr) __attribute__((deprecated("Use accept()."))) { - return accept(status); - } - - size_t write(uint8_t c) override { - return write(&c, 1); - } - size_t write(const uint8_t* buffer, size_t size) override { - return send(buffer, size); - } - - friend class ZephyrClient; + ZephyrServer() : _port(80) {}; + ZephyrServer(uint16_t port) : _port(port) {}; + + virtual ~ZephyrServer() { + end(); + } + + void end() { + ZephyrSocketWrapper::close(); + } + + void begin(uint16_t port) { + _port = port; + begin(); + } + + void begin() { + ZephyrSocketWrapper::bind(_port); + ZephyrSocketWrapper::listen(5); + } + + uint8_t status() { + return 0; + } + + explicit operator bool() { + return sock_fd != -1; + } + + ZephyrClient accept(uint8_t *status = nullptr) { + ZephyrClient client; + int sock = ZephyrSocketWrapper::accept(); + client.setSocket(sock); + return client; + } + + ZephyrClient available(uint8_t *status = nullptr) __attribute__((deprecated("Use accept()."))) { + return accept(status); + } + + size_t write(uint8_t c) override { + return write(&c, 1); + } + + size_t write(const uint8_t *buffer, size_t size) override { + return send(buffer, size); + } + + friend class ZephyrClient; }; diff --git a/libraries/SocketWrapper/ZephyrUDP.h b/libraries/SocketWrapper/ZephyrUDP.h index c12b26f0..884639bd 100644 --- a/libraries/SocketWrapper/ZephyrUDP.h +++ b/libraries/SocketWrapper/ZephyrUDP.h @@ -33,300 +33,299 @@ class ZephyrUDP : public arduino::UDP { private: - int _socket; + int _socket; public: - ZephyrUDP() : _socket(-1) {} // Constructor - ~ZephyrUDP() { - stop(); - } - - // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use - virtual uint8_t begin(uint16_t port) { - - struct sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = INADDR_ANY; - - _socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - - zsock_ioctl(_socket, ZFD_IOCTL_FIONBIO); - - if (::bind(_socket, (struct sockaddr*)&addr, sizeof(addr)) < 0) { - ::close(_socket); - _socket = -1; - return false; - } - - return true; - } - - // initialize, start listening on specified multicast IP address and port. Returns 1 if successful, 0 if there are no sockets available to use - virtual uint8_t beginMulticast(IPAddress ip, uint16_t port) { - bool ret = begin(port); - if (ret == false) { - return false; - } - - struct sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = ip; - - net_if_ipv4_maddr_join(net_if_get_by_index(1), net_if_ipv4_maddr_add(net_if_get_by_index(1), (struct in_addr*)&addr)); - return true; - } - - // Finish with the UDP socket - virtual void stop() { - if (_socket != -1) { - ::close(_socket); - _socket = -1; - } - } - - // Sending UDP packets - - // Start building up a packet to send to the remote host specific in ip and port - // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port - virtual int beginPacket(IPAddress ip, uint16_t port) { - _send_to_ip = ip; - _send_to_port = port; - - /* Make sure that the transmit data buffer is empty. */ - _tx_data.clear(); - return true; - } - - // Start building up a packet to send to the remote host specific in host and port - // Returns 1 if successful, 0 if there was a problem resolving the hostname or port - virtual int beginPacket(const char* host, uint16_t port) { - // Resolve address - struct addrinfo hints; - struct addrinfo *res; - - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_DGRAM; - - int resolve_attempts = 100; - int ret; - - while (resolve_attempts--) { - ret = getaddrinfo(host, String(port).c_str(), &hints, &res); - - if (ret == 0) { - break; - } else { - k_sleep(K_MSEC(1)); - } - } - - if (ret != 0) { - return false; - } - - return beginPacket(IPAddress(((sockaddr_in*)(res->ai_addr))->sin_addr.s_addr), port); - } - - // Finish off this packet and send it - // Returns 1 if the packet was sent successfully, 0 if there was an error - virtual int endPacket() { - struct sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_port = htons(_send_to_port); - addr.sin_addr.s_addr = _send_to_ip; - return ::sendto(_socket, _tx_data.data(), _tx_data.size(), 0, (sockaddr*)&addr, sizeof(addr)); - } - - // Write a single byte into the packet - virtual size_t write(uint8_t data) { - _tx_data.push_back(data); - return 1; - } - - // Write size bytes from buffer into the packet - virtual size_t write(uint8_t* buffer, size_t size) { - std::copy(buffer, buffer + size, std::back_inserter(_tx_data)); - return size; - } - - // Write size bytes from buffer into the packet - virtual size_t write(const uint8_t* buffer, size_t size) { - std::copy(buffer, buffer + size, std::back_inserter(_tx_data)); - return size; - } - - using Print::write; - - int parsePacket() - { - struct sockaddr_in addr; - socklen_t addrlen = sizeof(addr); - uint8_t tmp_buf[512]; - - int ret = ::recvfrom(_socket, tmp_buf, sizeof(tmp_buf), 0, (sockaddr*)&addr, &addrlen); - if (ret > 0) - { - auto pkt = std::make_shared( - IPAddress(addr.sin_addr.s_addr), - ntohs(addr.sin_port), tmp_buf, ret); - - _rx_pkt_list.push_back(pkt); - - // drop the oldest packet if the list is full - if(_rx_pkt_list.size() > _rx_pkt_list_size) { - _rx_pkt_list.pop_front(); - } - } - - if (_rx_pkt_list.size()) - { - /* Discard UdpRxPacket object previously held by _rx_pkt - * and replace it with the new one. - */ - _rx_pkt = _rx_pkt_list.front(); - _rx_pkt_list.pop_front(); - return _rx_pkt->totalSize(); - } - else - { - /* Otherwise ensure that _rx_pkt definitely - * does not hold any UdpRxPacket object anymore. - */ - _rx_pkt.reset(); - return 0; - } - } - - int available() - { - if (_rx_pkt) - return _rx_pkt->available(); - else - return 0; - } - - int read() - { - if (_rx_pkt) - return _rx_pkt->read(); - else - return -1; - } - - int read(unsigned char* buffer, size_t len) - { - if (_rx_pkt) - return _rx_pkt->read(buffer, len); - else - return -1; - } - - int read(char* buffer, size_t len) - { - if (_rx_pkt) - return _rx_pkt->read(buffer, len); - else - return -1; - } - - int peek() - { - if (_rx_pkt) - return _rx_pkt->peek(); - else - return -1; - } - - void flush() - { - /* Delete UdpRxPacket object held by _rx_pkt. */ - if (_rx_pkt) - _rx_pkt.reset(); - } - - virtual IPAddress remoteIP() { - if (_rx_pkt) - return _rx_pkt->remoteIP(); - else - return IPAddress(); - } - - virtual uint16_t remotePort() { - if (_rx_pkt) - return _rx_pkt->remotePort(); - else - return 0; - } + ZephyrUDP() : _socket(-1) { + } // Constructor + + ~ZephyrUDP() { + stop(); + } + + // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no + // sockets available to use + virtual uint8_t begin(uint16_t port) { + + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = INADDR_ANY; + + _socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + + zsock_ioctl(_socket, ZFD_IOCTL_FIONBIO); + + if (::bind(_socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + ::close(_socket); + _socket = -1; + return false; + } + + return true; + } + + // initialize, start listening on specified multicast IP address and port. Returns 1 if + // successful, 0 if there are no sockets available to use + virtual uint8_t beginMulticast(IPAddress ip, uint16_t port) { + bool ret = begin(port); + if (ret == false) { + return false; + } + + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = ip; + + net_if_ipv4_maddr_join( + net_if_get_by_index(1), + net_if_ipv4_maddr_add(net_if_get_by_index(1), (struct in_addr *)&addr)); + return true; + } + + // Finish with the UDP socket + virtual void stop() { + if (_socket != -1) { + ::close(_socket); + _socket = -1; + } + } + + // Sending UDP packets + + // Start building up a packet to send to the remote host specific in ip and port + // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port + virtual int beginPacket(IPAddress ip, uint16_t port) { + _send_to_ip = ip; + _send_to_port = port; + + /* Make sure that the transmit data buffer is empty. */ + _tx_data.clear(); + return true; + } + + // Start building up a packet to send to the remote host specific in host and port + // Returns 1 if successful, 0 if there was a problem resolving the hostname or port + virtual int beginPacket(const char *host, uint16_t port) { + // Resolve address + struct addrinfo hints; + struct addrinfo *res; + + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; + + int resolve_attempts = 100; + int ret; + + while (resolve_attempts--) { + ret = getaddrinfo(host, String(port).c_str(), &hints, &res); + + if (ret == 0) { + break; + } else { + k_sleep(K_MSEC(1)); + } + } + + if (ret != 0) { + return false; + } + + return beginPacket(IPAddress(((sockaddr_in *)(res->ai_addr))->sin_addr.s_addr), port); + } + + // Finish off this packet and send it + // Returns 1 if the packet was sent successfully, 0 if there was an error + virtual int endPacket() { + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(_send_to_port); + addr.sin_addr.s_addr = _send_to_ip; + return ::sendto(_socket, _tx_data.data(), _tx_data.size(), 0, (sockaddr *)&addr, + sizeof(addr)); + } + + // Write a single byte into the packet + virtual size_t write(uint8_t data) { + _tx_data.push_back(data); + return 1; + } + + // Write size bytes from buffer into the packet + virtual size_t write(uint8_t *buffer, size_t size) { + std::copy(buffer, buffer + size, std::back_inserter(_tx_data)); + return size; + } + + // Write size bytes from buffer into the packet + virtual size_t write(const uint8_t *buffer, size_t size) { + std::copy(buffer, buffer + size, std::back_inserter(_tx_data)); + return size; + } + + using Print::write; + + int parsePacket() { + struct sockaddr_in addr; + socklen_t addrlen = sizeof(addr); + uint8_t tmp_buf[512]; + + int ret = ::recvfrom(_socket, tmp_buf, sizeof(tmp_buf), 0, (sockaddr *)&addr, &addrlen); + if (ret > 0) { + auto pkt = std::make_shared(IPAddress(addr.sin_addr.s_addr), + ntohs(addr.sin_port), tmp_buf, ret); + + _rx_pkt_list.push_back(pkt); + + // drop the oldest packet if the list is full + if (_rx_pkt_list.size() > _rx_pkt_list_size) { + _rx_pkt_list.pop_front(); + } + } + + if (_rx_pkt_list.size()) { + /* Discard UdpRxPacket object previously held by _rx_pkt + * and replace it with the new one. + */ + _rx_pkt = _rx_pkt_list.front(); + _rx_pkt_list.pop_front(); + return _rx_pkt->totalSize(); + } else { + /* Otherwise ensure that _rx_pkt definitely + * does not hold any UdpRxPacket object anymore. + */ + _rx_pkt.reset(); + return 0; + } + } + + int available() { + if (_rx_pkt) { + return _rx_pkt->available(); + } else { + return 0; + } + } + + int read() { + if (_rx_pkt) { + return _rx_pkt->read(); + } else { + return -1; + } + } + + int read(unsigned char *buffer, size_t len) { + if (_rx_pkt) { + return _rx_pkt->read(buffer, len); + } else { + return -1; + } + } + + int read(char *buffer, size_t len) { + if (_rx_pkt) { + return _rx_pkt->read(buffer, len); + } else { + return -1; + } + } + + int peek() { + if (_rx_pkt) { + return _rx_pkt->peek(); + } else { + return -1; + } + } + + void flush() { + /* Delete UdpRxPacket object held by _rx_pkt. */ + if (_rx_pkt) { + _rx_pkt.reset(); + } + } + + virtual IPAddress remoteIP() { + if (_rx_pkt) { + return _rx_pkt->remoteIP(); + } else { + return IPAddress(); + } + } + + virtual uint16_t remotePort() { + if (_rx_pkt) { + return _rx_pkt->remotePort(); + } else { + return 0; + } + } private: - - /* UDP TRANSMISSION */ - IPAddress _send_to_ip; - uint16_t _send_to_port; - std::vector _tx_data; - int _rx_pkt_list_size = 10; - /* UDP RECEPTION */ - class UdpRxPacket - { - private: - IPAddress const _remote_ip; - uint16_t const _remote_port; - size_t const _rx_data_len; - std::deque _rx_data; - - public: - UdpRxPacket( - IPAddress const remote_ip, - uint16_t const remote_port, - uint8_t const * p_data, - size_t const data_len) - : _remote_ip(remote_ip) - , _remote_port(remote_port) - , _rx_data_len(data_len) - , _rx_data(p_data, p_data + data_len) - { - } - - typedef std::shared_ptr SharedPtr; - - IPAddress remoteIP() const { return _remote_ip; } - uint16_t remotePort() const { return _remote_port; } - size_t totalSize() const { return _rx_data_len; } - - int available() - { - return _rx_data.size(); - } - - int read() - { - uint8_t const data = _rx_data.front(); - _rx_data.pop_front(); - return data; - } - - int read(unsigned char* buffer, size_t len) - { - size_t bytes_read = 0; - for (; bytes_read < len && !_rx_data.empty(); bytes_read++) - { - buffer[bytes_read] = _rx_data.front(); - _rx_data.pop_front(); - } - return bytes_read; - } - - int read(char* buffer, size_t len) - { - return read((unsigned char*)buffer, len); - } - - int peek() - { - return _rx_data.front(); - } - }; - std::list _rx_pkt_list; - UdpRxPacket::SharedPtr _rx_pkt; + /* UDP TRANSMISSION */ + IPAddress _send_to_ip; + uint16_t _send_to_port; + std::vector _tx_data; + int _rx_pkt_list_size = 10; + + /* UDP RECEPTION */ + class UdpRxPacket { + private: + IPAddress const _remote_ip; + uint16_t const _remote_port; + size_t const _rx_data_len; + std::deque _rx_data; + + public: + UdpRxPacket(IPAddress const remote_ip, uint16_t const remote_port, uint8_t const *p_data, + size_t const data_len) + : _remote_ip(remote_ip), _remote_port(remote_port), _rx_data_len(data_len), + _rx_data(p_data, p_data + data_len) { + } + + typedef std::shared_ptr SharedPtr; + + IPAddress remoteIP() const { + return _remote_ip; + } + + uint16_t remotePort() const { + return _remote_port; + } + + size_t totalSize() const { + return _rx_data_len; + } + + int available() { + return _rx_data.size(); + } + + int read() { + uint8_t const data = _rx_data.front(); + _rx_data.pop_front(); + return data; + } + + int read(unsigned char *buffer, size_t len) { + size_t bytes_read = 0; + for (; bytes_read < len && !_rx_data.empty(); bytes_read++) { + buffer[bytes_read] = _rx_data.front(); + _rx_data.pop_front(); + } + return bytes_read; + } + + int read(char *buffer, size_t len) { + return read((unsigned char *)buffer, len); + } + + int peek() { + return _rx_data.front(); + } + }; + + std::list _rx_pkt_list; + UdpRxPacket::SharedPtr _rx_pkt; }; From bf1b498f85c7082c5c1c775c4411b78c2be91d53 Mon Sep 17 00:00:00 2001 From: Leonardo Cavagnis Date: Wed, 3 Sep 2025 17:22:42 +0200 Subject: [PATCH 15/19] ethernet lib: cosmetics clang --- libraries/Ethernet/src/Ethernet.cpp | 109 ++++++++++++++-------------- libraries/Ethernet/src/Ethernet.h | 30 +++++--- 2 files changed, 74 insertions(+), 65 deletions(-) diff --git a/libraries/Ethernet/src/Ethernet.cpp b/libraries/Ethernet/src/Ethernet.cpp index 8618b4b1..a497f009 100644 --- a/libraries/Ethernet/src/Ethernet.cpp +++ b/libraries/Ethernet/src/Ethernet.cpp @@ -3,117 +3,118 @@ #if DT_HAS_COMPAT_STATUS_OKAY(ethernet_phy) int EthernetClass::begin(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) { - setMACAddress(mac); - return NetworkInterface::begin(true, 0); + setMACAddress(mac); + return NetworkInterface::begin(true, 0); } int EthernetClass::begin(uint8_t *mac, IPAddress ip) { - IPAddress dns = ip; - dns[3] = 1; + IPAddress dns = ip; + dns[3] = 1; - auto ret = begin(mac, ip, dns); - return ret; + auto ret = begin(mac, ip, dns); + return ret; } int EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns) { - IPAddress gateway = ip; - gateway[3] = 1; + IPAddress gateway = ip; + gateway[3] = 1; - auto ret = begin(mac, ip, dns, gateway); - return ret; + 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; + 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) { - setMACAddress(mac); +int EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway, + IPAddress subnet, unsigned long timeout, unsigned long responseTimeout) { + setMACAddress(mac); - if (!NetworkInterface::setLocalIPFull(ip, subnet, gateway)) { - return 0; - } + if (!NetworkInterface::setLocalIPFull(ip, subnet, gateway)) { + return 0; + } - if (!net_if_is_up(netif)) { - net_if_up(netif); - } + if (!net_if_is_up(netif)) { + net_if_up(netif); + } - return 1; + return 1; } EthernetLinkStatus EthernetClass::linkStatus() { - if ((hardwareStatus() == EthernetOk) && net_if_is_up(netif)) { - return LinkON; - } - return LinkOFF; + 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 < 3; i++) { - auto _if = net_if_get_by_index(i); - if (!net_eth_type_is_wifi(_if)) { - netif = _if; - break; - } - } - return EthernetOk; - } else { - return EthernetNoHardware; - } -} + 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 < 3; i++) { + auto _if = net_if_get_by_index(i); + if (!net_eth_type_is_wifi(_if)) { + netif = _if; + break; + } + } + return EthernetOk; + } else { + return EthernetNoHardware; + } +} int EthernetClass::disconnect() { - return NetworkInterface::disconnect(); + return NetworkInterface::disconnect(); } void EthernetClass::end() { - disconnect(); + disconnect(); } void EthernetClass::setMACAddress(const uint8_t *mac_address) { - if (mac_address != nullptr) { - NetworkInterface::setMACAddress(mac_address); - } + if (mac_address != nullptr) { + NetworkInterface::setMACAddress(mac_address); + } } void EthernetClass::MACAddress(uint8_t *mac_address) { - setMACAddress(mac_address); + setMACAddress(mac_address); } IPAddress EthernetClass::localIP() { - return NetworkInterface::localIP(); + return NetworkInterface::localIP(); } IPAddress EthernetClass::subnetMask() { - return NetworkInterface::subnetMask(); + return NetworkInterface::subnetMask(); } IPAddress EthernetClass::gatewayIP() { - return NetworkInterface::gatewayIP(); + return NetworkInterface::gatewayIP(); } IPAddress EthernetClass::dnsServerIP() { - return NetworkInterface::dnsServerIP(); + return NetworkInterface::dnsServerIP(); } void EthernetClass::setLocalIP(const IPAddress local_ip) { - NetworkInterface::setLocalIP(local_ip); + NetworkInterface::setLocalIP(local_ip); } void EthernetClass::setSubnetMask(const IPAddress subnet) { - NetworkInterface::setSubnetMask(subnet); + NetworkInterface::setSubnetMask(subnet); } void EthernetClass::setGatewayIP(const IPAddress gateway) { - NetworkInterface::setGatewayIP(gateway); + NetworkInterface::setGatewayIP(gateway); } void EthernetClass::setDnsServerIP(const IPAddress dns_server) { - NetworkInterface::setDnsServerIP(dns_server); + NetworkInterface::setDnsServerIP(dns_server); } EthernetClass Ethernet; diff --git a/libraries/Ethernet/src/Ethernet.h b/libraries/Ethernet/src/Ethernet.h index 52913e6a..e0b16389 100644 --- a/libraries/Ethernet/src/Ethernet.h +++ b/libraries/Ethernet/src/Ethernet.h @@ -5,23 +5,26 @@ #if DT_HAS_COMPAT_STATUS_OKAY(ethernet_phy) enum EthernetLinkStatus { - Unknown, - LinkON, - LinkOFF + Unknown, + LinkON, + LinkOFF }; enum EthernetHardwareStatus { - EthernetNoHardware, - EthernetOk + EthernetNoHardware, + EthernetOk }; -class EthernetClass: public NetworkInterface -{ +class EthernetClass : public NetworkInterface { public: - EthernetClass() {} - virtual ~EthernetClass() {} + EthernetClass() { + } + + virtual ~EthernetClass() { + } - int begin(uint8_t *mac = nullptr, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); + int begin(uint8_t *mac = nullptr, unsigned long timeout = 60000, + unsigned long responseTimeout = 4000); int maintain(); EthernetLinkStatus linkStatus(); EthernetHardwareStatus hardwareStatus(); @@ -30,20 +33,25 @@ class EthernetClass: public NetworkInterface 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(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 init(uint8_t sspin = 10); int disconnect(void); From 779e054e171762e748288fb1025a5340b3ddb63f Mon Sep 17 00:00:00 2001 From: Leonardo Cavagnis Date: Thu, 4 Sep 2025 10:55:05 +0200 Subject: [PATCH 16/19] ethernet lib: restore default WebClientRepeating.ino example --- .../WebClientRepeating/WebClientRepeating.ino | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino b/libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino index a1c1c738..786c993f 100644 --- a/libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino +++ b/libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino @@ -12,6 +12,12 @@ #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); @@ -42,7 +48,7 @@ void setup() { // start the Ethernet connection: Serial.println("Initialize Ethernet with DHCP:"); - if (Ethernet.begin() == 0) { + if (Ethernet.begin(mac) == 0) { Serial.println("Failed to configure Ethernet using DHCP"); // Check for Ethernet hardware present if (Ethernet.hardwareStatus() == EthernetNoHardware) { @@ -54,8 +60,8 @@ void setup() { if (Ethernet.linkStatus() == LinkOFF) { Serial.println("Ethernet cable is not connected."); } - // try to congifure using IP address instead of DHCP: - Ethernet.begin(ip, myDns); + // try to configure using IP address instead of DHCP: + Ethernet.begin(mac, ip, myDns); Serial.print("My IP address: "); Serial.println(Ethernet.localIP()); } else { @@ -86,7 +92,7 @@ void loop() { // 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 WiFi shield + // This will free the socket on the Ethernet shield client.stop(); // if there's a successful connection: @@ -105,8 +111,4 @@ void httpRequest() { // if you couldn't make a connection: Serial.println("connection failed"); } -} - - - - +} \ No newline at end of file From efe02a0f2c3362f1995e5462aaff1ca6d4a161a0 Mon Sep 17 00:00:00 2001 From: Leonardo Cavagnis Date: Thu, 4 Sep 2025 11:07:01 +0200 Subject: [PATCH 17/19] ethernet lib: restore default WebServer.ino example --- .../Ethernet/examples/WebServer/WebServer.ino | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/libraries/Ethernet/examples/WebServer/WebServer.ino b/libraries/Ethernet/examples/WebServer/WebServer.ino index 81b7dcb9..cf81a0a6 100644 --- a/libraries/Ethernet/examples/WebServer/WebServer.ino +++ b/libraries/Ethernet/examples/WebServer/WebServer.ino @@ -9,7 +9,12 @@ #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 @@ -33,7 +38,7 @@ void setup() { } // start the Ethernet connection and the server: - Ethernet.begin(ip); + Ethernet.begin(mac, ip); // Check for Ethernet hardware present if (Ethernet.hardwareStatus() == EthernetNoHardware) { @@ -58,17 +63,17 @@ void loop() { ZephyrClient client = server.accept(); if (client) { Serial.println("new client"); - // an http request ends with a blank line - boolean currentLineIsBlank = true; + // 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, + // 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 + // 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 @@ -103,5 +108,4 @@ void loop() { client.stop(); Serial.println("client disconnected"); } -} - +} \ No newline at end of file From 53511a10c3e90794c77f3ce8dc05151f7de98350 Mon Sep 17 00:00:00 2001 From: Leonardo Cavagnis Date: Thu, 4 Sep 2025 11:17:29 +0200 Subject: [PATCH 18/19] ethernet lib: move examples to arduino.tips --- .../examples/WebClientRepeating/WebClientRepeating.ino | 7 ++++--- .../WebClientRepeatingSSL/WebClientRepeatingSSL.ino | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino b/libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino index 786c993f..07f20b42 100644 --- a/libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino +++ b/libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino @@ -25,7 +25,7 @@ IPAddress myDns(192, 168, 0, 1); // initialize the library instance: ZephyrClient client; -char server[] = "www.arduino.cc"; // also change the Host line in httpRequest() +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 @@ -99,8 +99,9 @@ void httpRequest() { if (client.connect(server, 80)) { Serial.println("connecting..."); // send the HTTP GET request: - client.println("GET /latest.txt HTTP/1.1"); - client.println("Host: www.arduino.cc"); + 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(); diff --git a/libraries/Ethernet/examples/WebClientRepeatingSSL/WebClientRepeatingSSL.ino b/libraries/Ethernet/examples/WebClientRepeatingSSL/WebClientRepeatingSSL.ino index 748f63c1..e6c2c9f5 100644 --- a/libraries/Ethernet/examples/WebClientRepeatingSSL/WebClientRepeatingSSL.ino +++ b/libraries/Ethernet/examples/WebClientRepeatingSSL/WebClientRepeatingSSL.ino @@ -12,7 +12,7 @@ // initialize the library instance: ZephyrSSLClient client; -char server[] = "www.arduino.cc"; +char server[] = "arduino.tips"; int port = 443; // IPAddress server(64,131,82,241); @@ -93,7 +93,7 @@ void httpRequest() if (client.connect(server, port)) { Serial.println("connecting..."); // send the HTTP GET request: - client.println("GET /latest.txt HTTP/1.1"); + client.println("GET /asciilogo.txt HTTP/1.1"); client.print("Host: "); client.println(server); client.println("User-Agent: arduino-ethernet"); From 0646d5aeb2c38c0af85e93c5793e3561536a968b Mon Sep 17 00:00:00 2001 From: Leonardo Cavagnis Date: Thu, 4 Sep 2025 12:23:26 +0200 Subject: [PATCH 19/19] ethernet: fix ethernet in variant MCXN947 --- .../frdm_mcxn947_mcxn947_cpu0/frdm_mcxn947_mcxn947_cpu0.conf | 1 + 1 file changed, 1 insertion(+) 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 cd131438..867b155a 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