---
title: "COAP messages on W5500 built for Nucleo-L476RG"
url: "https://maker.wiznet.io/Aimee0/projects/coap-messages-on-w5500-built-for-nucleo-l476rg/"
markdown_url: "https://maker.wiznet.io/Aimee0/projects/coap-messages-on-w5500-built-for-nucleo-l476rg/md"
type: "UCC: User Created Content"
author: "Aimee"
author_url: "https://maker.wiznet.io/Aimee0/"
original_author: "Aimee"
original_url: "https://os.mbed.com/users/sgnezdov/code/coap-example//file/b56863927244/"
published: "2024-01-02"
language: "en"
hardware: ["WIZnet W5500"]
likes: 0
views: 371
comments: 0
source: "WIZnet Makers (https://maker.wiznet.io/)"
---

# COAP messages on W5500 built for Nucleo-L476RG

> This project is a project to send and receive COAP messages using W5500 over Nucleo-L476RG.

Original author: Aimee (source: https://os.mbed.com/users/sgnezdov/code/coap-example//file/b56863927244/)

## Components

- **WIZnet W5500** x 1 ([docs](https://docs.wiznet.io/Product/Chip/Ethernet/W5500))

WIZnet parts: W5500 ([Datasheet](https://docs.wiznet.io/Product/Chip/Ethernet/W5500/datasheet?utm_source=maker&utm_medium=project&utm_campaign=w5500), [product hub](https://maker.wiznet.io/products/w5500/))

## Documents and links

- [coap-example](https://os.mbed.com/users/sgnezdov/code/coap-example//file/b56863927244/) (code)

## Article

This project is to send and receive COAP messages using W5500 over Nucleo-L476RG.

**What is COAP**

COAP is a lightweight protocol designed primarily to support efficient communication between IoT devices and devices with limited resources, such as various sensors.

**COAP vs MQTT**

|  | COAP | MQTT |
| --- | --- | --- |
| Purpose | It is primarily designed for communication between constrained devices. | It is primarily designed for communication between many devices. |
| Protocol format | Designed based on the RESTful architecture, it has a request and response form similar to HTTP. | It is a message-driven protocol that exchanges messages between brokers and clients. |
| Communication | It uses a request-response model, in which the client sends the request and the server responds. | It is based on the Publish-Subscribe model, where devices can subscribe to specific topics to receive messages or publish messages to specific topics. |
| Reliability and Connection Management | Primarily uses UDP, offering optional extensions for reliability. It is an unconnected protocol because it is UDP based. | Primarily uses TCP, providing reliable connections and message delivery. |

**Project Description**

OS : mbed-OS

mbed-coap library : <https://github.com/ARMmbed/mbed-os/tree/master/connectivity/libraries/mbed-coap>

W5500 interface : <https://os.mbed.com/users/sgnezdov/code/W5500Interface/#41393623ead4>

#main.cpp

```plaintext
......

int main() {
    printf("Easy connect...\n");
    NetworkInterface *network = easy_connect(true);
    if (!network) {
        printf("Cannot connect to the network, see serial output");
        return 1;
    }

    printf("Connected to the network. Opening a socket...\n");

    // Open a socket on the network interface
    socket.open(network);

    // Initialize the CoAP protocol handle, pointing to local implementations on malloc/free/tx/rx functions
    coapHandle = sn_coap_protocol_init(&coap_malloc, &coap_free, &coap_tx_cb, &coap_rx_cb);

    // UDPSocket::recvfrom is blocking, so run it in a separate RTOS thread
    recvfromThread.start(&recvfromMain);

    // Path to the resource we want to retrieve
    const char* coap_uri_path = "/test";

    // See ns_coap_header.h
    sn_coap_hdr_s *coap_res_ptr = (sn_coap_hdr_s*)calloc(sizeof(sn_coap_hdr_s), 1);
    coap_res_ptr->uri_path_ptr = (uint8_t*)coap_uri_path;       // Path
    coap_res_ptr->uri_path_len = strlen(coap_uri_path);
    coap_res_ptr->msg_code = COAP_MSG_CODE_REQUEST_GET;         // CoAP method
    coap_res_ptr->content_format = COAP_CT_TEXT_PLAIN;          // CoAP content type
    coap_res_ptr->payload_len = 0;                              // Body length
    coap_res_ptr->payload_ptr = 0;                              // Body pointer
    coap_res_ptr->options_list_ptr = 0;                         // Optional: options list
    // Message ID is used to track request->response patterns, because we're using UDP (so everything is unconfirmed).
    // See the receive code to verify that we get the same message ID back
    coap_res_ptr->msg_id = 7;

    // Calculate the CoAP message size, allocate the memory and build the message
    uint16_t message_len = sn_coap_builder_calc_needed_packet_data_size(coap_res_ptr);
    printf("Calculated message length: %d bytes\n", message_len);

    uint8_t* message_ptr = (uint8_t*)malloc(message_len);
    sn_coap_builder(message_ptr, coap_res_ptr);

    // Uncomment to see the raw buffer that will be sent...
    // printf("Message is: ");
    // for (size_t ix = 0; ix < message_len; ix++) {
    //     printf("%02x ", message_ptr[ix]);
    // }
    // printf("\n");

    int scount = socket.sendto("i-ce.itron.cloud", 5683, message_ptr, message_len);
    printf("Sent %d bytes to coap://i-ce.itron.cloud:5683\n", scount);

    free(coap_res_ptr);
    free(message_ptr);

    Thread::wait(osWaitForever);
}
```

1. Network initialization

2. open socket

3. COAP protocol init

4. COAP message recv thread start

5. COAP message builder run

6. send COAP message to i-ce.itron.cloud server's 5685 port

#easy_connect.h

```plaintext
......
#define ETHERNET        1
#define WIFI_ESP8266    0
#define MESH_LOWPAN_ND  0
#define MESH_THREAD     0
#define WIFI_ODIN       0
#define WIFI_REALTEK    0

......

NetworkInterface* easy_connect(bool log_messages = false) {
    NetworkInterface* network_interface = 0;
    int connect_success = -1;
    /// This should be removed once mbedOS supports proper dual-stack
#if defined (MESH) || (MBED_CONF_LWIP_IPV6_ENABLED==true)
    printf("[EasyConnect] IPv6 mode\n");
#else
    printf("[EasyConnect] IPv4 mode\n");
#endif

 #if MBED_CONF_APP_NETWORK_INTERFACE == WIFI_ESP8266
		...
#elif MBED_CONF_APP_NETWORK_INTERFACE == WIFI_ODIN
		...
#elif MBED_CONF_APP_NETWORK_INTERFACE == WIFI_REALTEK
		...
#elif MBED_CONF_APP_NETWORK_INTERFACE == ETHERNET

    if (log_messages) {
        printf("[EasyConnect] Ethernet...\n");
    }

    spi.format(32, 0);
    spi.frequency(100000);

    printf("Wait for SPI...\r\n");
    wait(1);
    
    printf("Network Setting DHCP\r\n");
	uint8_t mac_addr[6] = {0x00, 0x08, 0xdc, 0x45, 0x56, 0x67};
	
    printf("Init with MAC address\n");
    eth.init(mac_addr);
    
    int timeout_ms = 15*1000;
    int err = dhcp.setup(&eth, mac_addr, timeout_ms);
    if (err == (-1)) {
        printf("Timeout.\n");
        return NULL;
    }
    printf("DHCP completed\n");
    printf("Connected, IP: %d.%d.%d.%d\r\n", dhcp.yiaddr[0], dhcp.yiaddr[1], dhcp.yiaddr[2], dhcp.yiaddr[3]);
    char ip[24], gateway[24], netmask[24], dnsaddr[24];
    sprintf(ip,      "%d.%d.%d.%d", dhcp.yiaddr[0],  dhcp.yiaddr[1],  dhcp.yiaddr[2],  dhcp.yiaddr[3]);
    sprintf(gateway, "%d.%d.%d.%d", dhcp.gateway[0], dhcp.gateway[1], dhcp.gateway[2], dhcp.gateway[3]);
    sprintf(netmask, "%d.%d.%d.%d", dhcp.netmask[0], dhcp.netmask[1], dhcp.netmask[2], dhcp.netmask[3]);
    sprintf(dnsaddr, "%d.%d.%d.%d", dhcp.dnsaddr[0], dhcp.dnsaddr[1], dhcp.dnsaddr[2], dhcp.dnsaddr[3]);
    eth.init(ip, netmask, gateway);

    dns.setup(&eth);
    dns.set_server(dnsaddr);
    bool isOK = dns.lookup("coap.me");
    if (isOK) {
        printf("is ok\n");
        uint32_t hIP = dns.get_ip();
        printf("coap.me IP: %u\n", hIP);
    } else {
        printf("coap.me IP is not ok\n");
    }

    
    const SocketAddress dns_sa = SocketAddress((const void *)&dhcp.dnsaddr[0], NSAPI_IPv4, 53);
    nsapi_error_t nsErr = nsapi_dns_add_server(dns_sa);
    if (nsErr) {
    	printf("[EasyConnect] error adding DNS entry: %d\n", nsErr);
    }
    printf("[EasyConnect] DNS IP: %s\n", dns_sa.get_ip_address());
    
    SocketAddress coap_sa;
    nsErr = nsapi_dns_query(&eth, "coap.me", &coap_sa, NSAPI_IPv4);
    if (nsErr) {
    	printf("[EasyConnect] error resolving coap.me: %d\n", nsErr);
    }

    if (log_messages) {
        printf("[EasyConnect] Using Ethernet\n");
    }
    network_interface = &eth;
    connect_success = eth.connect();
#endif

#ifdef MESH
		...
#endif
    if(connect_success == 0) {
        if (log_messages) {
            printf("[EasyConnect] Connected to Network successfully\n");
            print_MAC(network_interface, log_messages);
        }
    } else {
        if (log_messages) {
            print_MAC(network_interface, log_messages);
            printf("[EasyConnect] Connection to Network Failed %d!\n", connect_success);
        }
        return NULL;
    }
    const char *ip_addr  = network_interface->get_ip_address();
    if (ip_addr == NULL) {
        if (log_messages) {
            printf("[EasyConnect] ERROR - No IP address\n");
        }
        return NULL;
    }
    if (log_messages) {
        printf("[EasyConnect] IP address %s\n", ip_addr);
    }
    return network_interface;
}
```

Setting up SPI interface and network connectivity to use W5500.

---

Source: https://maker.wiznet.io/Aimee0/projects/coap-messages-on-w5500-built-for-nucleo-l476rg/
