Mbed library for ENC28J60 Ethernet modules. Full support for TCP/IP and UDP Server, Client and HTTP server (webserver). DHCP and DNS is included.

Dependents:   mBuino_ENC28_MQTT Nucleo_Web_ENC28J60 Nucleo_Web_ENC28J60_ADC Serial_over_Ethernet ... more

Library for ENC28J60 Ethernet modules.

/media/uploads/hudakz/enc28j60_module01.jpg

Ported to mbed from Norbert Truchsess's UIPEthernet library for Arduino. Thank you Norbert!

  • Full support for persistent (streaming) TCP/IP and UDP connections Client and Server each, ARP, ICMP, DHCP and DNS.
  • Works with both Mbed OS 2 and Mbed OS 5.

Usage:

  • Import the library into your project.
  • Add #include "UipEthernet.h" to main.cpp
  • Create one instance of the UipEthernet class initialized with the MAC address you'd like to use and SPI pins of the connected Mbed board.

Example programs:

Import programWebSwitch_ENC28J60

HTTP Server serving a simple webpage which enables to remotely turn a digital output on/off. Compile, download, run and type 'IP_address/secret/' (don't forget the last '/') into your web browser and hit ENTER.

Import programHTTPServer_Echo_ENC28J60

A simple HTTP server echoing received requests. Ethernet connection is over an ENC28J60 board. Usage: Type the server's IP address into you web browser and hit <ENTER>.

Import programTcpServer_ENC28J60

Simple TCP/IP Server using the UIPEthernet library for ENC28J60 Ethernet boards.

Import programTcpClient_ENC28J60

Simple TCP/IP Client using the UIPEthernet library for ENC28J60 Ethernet boards.

Import programUdpServer_ENC28J60

Simple UDP Server using the UIPEthernet library for ENC28J60 Ethernet boards.

Import programUdpClient_ENC28J60

Simple UDP Client using the UIPEthernet library for ENC28J60 Ethernet boards.

Import programMQTT_Hello_ENC28J60

MQTT Client example program. Ethernet connection is via an ENC28J60 module.

Revision:
14:7648334eb41b
Parent:
11:647d53d146f1
Child:
15:53715cc81c63
--- a/UdpSocket.cpp	Sat Aug 31 20:34:52 2019 +0000
+++ b/UdpSocket.cpp	Tue Sep 03 09:16:55 2019 +0000
@@ -30,13 +30,47 @@
 #define UIP_ARPHDRSIZE  42
 #define UDPBUF          ((struct uip_udpip_hdr*) &uip_buf[UIP_LLH_LEN])
 
-// Constructor
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
 UdpSocket::UdpSocket() :
-    _uip_udp_conn(NULL)
+    _uip_udp_conn(NULL),
+    _timeout_ms(1000)
 {
     memset(&appdata, 0, sizeof(appdata));
 }
 
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+UdpSocket::UdpSocket(int timeout_ms) :
+    _uip_udp_conn(NULL),
+    _timeout_ms(timeout_ms)
+{
+    memset(&appdata, 0, sizeof(appdata));
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+UdpSocket::UdpSocket(UipEthernet* net, int timeout_ms /*= 1000*/ ) :
+    _uip_udp_conn(NULL),
+    _timeout_ms(timeout_ms)
+{
+    memset(&appdata, 0, sizeof(appdata));
+    if (UipEthernet::ethernet != net)
+        UipEthernet::ethernet = net;
+}
+
 // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
 uint8_t UdpSocket::begin(uint16_t port)
 {
@@ -67,6 +101,17 @@
     }
 }
 
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+void UdpSocket::close()
+{
+    stop();
+}
+
 // Sending UDP packets
 // Start building up a packet to send to the remote host specific in ip and port
 
@@ -222,13 +267,13 @@
 }
 
 // Number of bytes remaining in the current packet
-int UdpSocket::available()
+size_t UdpSocket::available()
 {
     UipEthernet::ethernet->tick();
     return UipEthernet::ethernet->enc28j60Eth.blockSize(appdata.packet_in);
 }
 
-// Read a single byte from the current packet
+// Read a single byte from the current packet. Returns -1 if no byte is available.
 int UdpSocket::read()
 {
     static unsigned char    c;
@@ -242,7 +287,7 @@
 // Read up to len bytes from the current packet and place them into buffer
 
 // Returns the number of bytes read, or 0 if none are available
-int UdpSocket::read(unsigned char* buffer, size_t len)
+size_t UdpSocket::read(unsigned char* buffer, size_t len)
 {
     UipEthernet::ethernet->tick();
     if (appdata.packet_in != NOBLOCK) {
@@ -372,3 +417,116 @@
     UipEthernet::ethernet->network_send();
 }
 #endif
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+nsapi_size_or_error_t UdpSocket::sendto(const char* host, uint16_t port, const void* data, size_t size)
+{
+    DnsClient   dns;
+    IpAddress   address;
+    uint32_t    address_bytes;
+
+    dns.begin(UipEthernet::ethernet->dnsServerIP());
+    if (dns.getHostByName(host, address) == 1) {
+        address_bytes = address;
+        _remote_addr = SocketAddress(&address_bytes, NSAPI_IPv4, port);
+    }
+    else {
+        _remote_addr = SocketAddress(host, port);
+    }
+
+    if (beginPacket(host, port) == 0) {
+        stop();
+        return NSAPI_ERROR_NO_ADDRESS;
+    }
+
+    if (write((uint8_t*)data, size) == 0) {
+        stop();
+        return NSAPI_ERROR_WOULD_BLOCK;
+    };
+
+    if (endPacket() <= 0) {
+        stop();
+        return NSAPI_ERROR_WOULD_BLOCK;
+    }
+
+    return NSAPI_ERROR_OK;
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+nsapi_size_or_error_t UdpSocket::sendto(const SocketAddress& address, const void* data, size_t size)
+{
+    IpAddress   ip_addr(address.get_addr().bytes);
+    uint16_t    port = address.get_port();
+
+    _remote_addr = address;
+
+    if (beginPacket(ip_addr, port) == 0) {
+        stop();
+        return NSAPI_ERROR_NO_ADDRESS;
+    }
+
+    if (write((uint8_t*)data, size) == 0) {
+        stop();
+        return NSAPI_ERROR_WOULD_BLOCK;
+    };
+
+    if (endPacket() <= 0) {
+        stop();
+        return NSAPI_ERROR_WOULD_BLOCK;
+    }
+
+    return NSAPI_ERROR_OK;
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+nsapi_size_or_error_t UdpSocket::recvfrom(SocketAddress* address, void* data, size_t size)
+{
+    *address = _remote_addr;
+
+    Timer   timer;
+    int     success;
+
+    timer.start();
+    do {
+        success = parsePacket();
+    } while (!success && (timer.read_ms() < _timeout_ms));
+
+    if (!success) {
+        stop();
+        return NSAPI_ERROR_WOULD_BLOCK;
+    }
+
+    size_t      n;
+    size_t      recv_count = 0;
+    uint8_t*    pos = (uint8_t*)data;
+
+    do {
+        if (recv_count + available() <= size) {
+            n = read(pos, available());
+            pos += n;
+            recv_count += n;
+        }
+        else {
+            return NSAPI_ERROR_NO_MEMORY;
+        }
+    } while ((available() > 0) && (recv_count < size));
+
+    flush();
+
+    return NSAPI_ERROR_OK;
+}