require websocket and https combine example

Hi,

I am using SDK v2.6.1.

Is there any course available on DevAcademy for WebSockets?

For WebSocket i take reference of v2.6.1/zephyr/samples/net/sockets/websocket_client,

when i try to give wifi credential using wifi connect -s <ssid> -k 1 -p <password> then i have got wifi: command not found so require to give wifi credential?or how we are able to see WebSocket reference code output,

I need an example that merges WebSocket and HTTPS. Could you also provide feedback on how to merge both into a single code?

Parents
  • Hi,

    Is there any course available on DevAcademy for WebSockets?

    No, there is no course for WebSockets on DevAcademy.

    when i try to give wifi credential using wifi connect -s <ssid> -k 1 -p <password> then i have got wifi: command not found so require to give wifi credential?or how we are able to see WebSocket reference code output,

    You could try to test "wifi connect" command using wi-fi shell sample.

    I need an example that merges WebSocket and HTTPS. Could you also provide feedback on how to merge both into a single code?

    Can you provide more information about your application? Which problem are you trying to solve? What is your goal when combining https and websocket?

    Best regards,
    Dejan

  • I used SDK v2.6.1 with the nrf7002dk_nrf5340_cpuapp board.

    I referenced the Wi-Fi shell example and merged its prj.conf file with the websocket_client prj.conf file.

    However, I encountered errors. If you have a working websocket_client example with Wi-Fi shell integration, please provide it.

    [00:00:00.498,443] <inf> net_config: Initializing network
    [00:00:00.506,683] <inf> net_config: Waiting interface 1 (0x20001960) to be up...
    [00:00:00.517,425] <inf> wpa_supp: Successfully initialized wpa_supplicant
    [00:00:10.517,669] <err> wpa_supp: eloop: select: Not enough space
    [00:00:10.537,780] <inf> wpa_supp: nordic_wlan0: CTRL-EVENT-DSCP-POLICY clear_all
    [00:00:10.548,736] <inf> wpa_supp: nordic_wlan0: CTRL-EVENT-DSCP-POLICY clear_all
    [00:00:10.559,265] <inf> wpa_supp: nordic_wlan0: CTRL-EVENT-TERMINATING 
    [00:00:10.569,152] <err> net_sock: invalid access on sock 1 by thread 0x20002628
    [00:00:10.579,833] <inf> wpa_supp: ELOOP: remaining socket: sock=8 eloop_data=0x2000daa0 user_data=0x0 handler=0x3d91d
    [00:00:10.608,703] <inf> wpa_supp: z_wpas_start: exitcode 0
    [00:00:30.517,761] <inf> net_config: IPv4 address: 192.0.2.1
    [00:00:30.541,259] <inf> net_config: Running dhcpv4 client...
    [00:00:30.565,521] <err> net_if: Cannot join all nodes address ff02::1 (-115)
    [00:00:30.595,184] <err> net_if: Cannot join solicit node address ff02::1:ff00:1 (-115)
    [00:00:30.622,863] <err> net_config: Timeout while waiting network interface
    [00:00:30.648,010] <err> net_config: Network initialization failed (-115)
    [00:00:33.627,838] <err> net_websocket_client_sample: Cannot connect to IPv4 remote (-116)
    [00:00:33.755,035] <err> net_tcp: net_pkt alloc failure
    [00:00:36.778,442] <err> net_websocket_client_sample: Cannot connect to IPv6 remote (-116)
    [00:00:36.805,267] <err> net_websocket_client_sample: Cannot connect to 192.0.2.2:9001
    [00:00:36.831,817] <err> net_websocket_client_sample: Cannot connect to [2001:db8::2]:9001
    [00:00:36.858,337] <err> net_websocket_client_sample: No IPv4 or IPv6 connectivity
    uart:~$ 

    below is my prj.conf file

    # Networking config
    CONFIG_NETWORKING=y
    CONFIG_NET_IPV4=y
    CONFIG_NET_IPV6=y
    CONFIG_NET_TCP=y
    CONFIG_NET_SHELL=y
    CONFIG_NET_STATISTICS=y
    
    # Sockets
    CONFIG_NET_SOCKETS=y
    CONFIG_NET_SOCKETS_POSIX_NAMES=y
    CONFIG_NET_SOCKETS_POLL_MAX=4
    
    # Network driver config
    CONFIG_TEST_RANDOM_GENERATOR=y
    
    # Network address config
    CONFIG_NET_CONFIG_AUTO_INIT=y
    CONFIG_NET_CONFIG_SETTINGS=y
    CONFIG_NET_CONFIG_NEED_IPV4=y
    CONFIG_NET_CONFIG_NEED_IPV6=y
    CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1"
    CONFIG_NET_CONFIG_MY_IPV4_GW="192.0.2.2"
    # Address of HTTP IPv4 server
    CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2"
    CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1"
    # Address of HTTP IPv6 server
    CONFIG_NET_CONFIG_PEER_IPV6_ADDR="2001:db8::2"
    
    # HTTP & Websocket
    CONFIG_HTTP_CLIENT=y
    CONFIG_WEBSOCKET_CLIENT=y
    
    # Network debug config
    CONFIG_LOG=y
    CONFIG_LOG_MODE_IMMEDIATE=y
    CONFIG_NET_LOG=y
    #CONFIG_NET_SOCKETS_LOG_LEVEL_DBG=y
    #CONFIG_NET_HTTP_LOG_LEVEL_DBG=y
    #CONFIG_NET_WEBSOCKET_LOG_LEVEL_DBG=y
    #CONFIG_NET_CONTEXT_LOG_LEVEL_DBG=y
    #CONFIG_NET_TCP_LOG_LEVEL_DBG=y
    
    # CONFIG_MAIN_STACK_SIZE=2048
    # CONFIG_HEAP_MEM_POOL_SIZE=1500
    
    CONFIG_WIFI=y
    CONFIG_WIFI_NRF700X=y
    
    # WPA supplicant
    CONFIG_WPA_SUPP=y
    CONFIG_NET_L2_WIFI_SHELL=y
    
    # System settings
    CONFIG_NEWLIB_LIBC=y
    CONFIG_NEWLIB_LIBC_NANO=n
    
    # Networking
    
    CONFIG_NET_UDP=y
    
    CONFIG_NET_DHCPV4=y
    CONFIG_DNS_RESOLVER=y
    
    
    CONFIG_NET_STATISTICS_WIFI=y
    CONFIG_NET_STATISTICS_USER_API=y
    
    CONFIG_NET_PKT_RX_COUNT=8
    CONFIG_NET_PKT_TX_COUNT=8
    
    # Below section is the primary contributor to SRAM and is currently
    # tuned for performance, but this will be revisited in the future.
    CONFIG_NET_BUF_RX_COUNT=16
    CONFIG_NET_BUF_TX_COUNT=16
    CONFIG_NET_BUF_DATA_SIZE=128
    CONFIG_NRF700X_RX_NUM_BUFS=16
    CONFIG_NRF700X_MAX_TX_AGGREGATION=4
    # nRF700x is main consumer: (16 + 8) * 1600 = ~40KB + ~40KB control path (experimental)
    CONFIG_HEAP_MEM_POOL_SIZE=80000
    CONFIG_NET_TC_TX_COUNT=1
    
    CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=4
    CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=5
    CONFIG_NET_MAX_CONTEXTS=5
    CONFIG_NET_CONTEXT_SYNC_RECV=y
    
    CONFIG_INIT_STACKS=y
    
    CONFIG_NET_L2_ETHERNET=y
    
    
    # Memories
    CONFIG_MAIN_STACK_SIZE=4096
    CONFIG_SHELL_STACK_SIZE=4400
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
    CONFIG_NET_TX_STACK_SIZE=4096
    CONFIG_NET_RX_STACK_SIZE=4096
    
    # Debugging
    CONFIG_STACK_SENTINEL=y
    CONFIG_DEBUG_COREDUMP=y
    CONFIG_DEBUG_COREDUMP_BACKEND_LOGGING=y
    CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_MIN=y
    CONFIG_SHELL_CMDS_RESIZE=n
    #CONFIG_DEBUG=y
    CONFIG_WPA_SUPP_LOG_LEVEL_INF=y
    
    # Kernel options
    CONFIG_ENTROPY_GENERATOR=y
    
    # Logging
    
    CONFIG_PRINTK=y
    CONFIG_SHELL=y
    CONFIG_SHELL_GETOPT=y
    CONFIG_DEVICE_SHELL=y
    CONFIG_POSIX_CLOCK=y
    CONFIG_DATE_SHELL=y
    # CONFIG_NET_CONFIG_AUTO_INIT=n
    
    CONFIG_WIFI_MGMT_EXT=y
    CONFIG_WIFI_CREDENTIALS=y
    # STEP 7.1 - Disable the below Kconfig symbol when using secure storage 
    #CONFIG_WIFI_CREDENTIALS_BACKEND_SETTINGS=y
    
    # STEP 7.2 - Enable the secure credentials storage API
    CONFIG_MBEDTLS=y
    CONFIG_MBEDTLS_ENABLE_HEAP=y
    CONFIG_MBEDTLS_HEAP_SIZE=81920
    CONFIG_WIFI_CREDENTIALS_BACKEND_PSA=y
    CONFIG_TFM_PROFILE_TYPE_MEDIUM=y
    CONFIG_PM_PARTITION_SIZE_TFM_SRAM=0x18000
    CONFIG_MBEDTLS_HEAP_SIZE=16384 
    CONFIG_FLASH=y
    CONFIG_FLASH_PAGE_LAYOUT=y
    CONFIG_FLASH_MAP=y
    CONFIG_NVS=y
    CONFIG_SETTINGS=y
    CONFIG_SETTINGS_NVS=y
    
    # printing of scan results puts pressure on queues in new locking
    # design in net_mgmt. So, use a higher timeout for a crowded
    # environment.
    CONFIG_NET_MGMT_EVENT_QUEUE_TIMEOUT=5000
    

    Can you provide more information about your application? Which problem are you trying to solve? What is your goal when combining https and websocket?

    >> I want to transfer and receive data from the server using HTTPS and WebSocket on the nrf7002dk_nrf5340_cpuapp board. I have implemented HTTPS code on this board.

    Below is my HTTPS code, could you guide me on how to integrate WebSocket code with it?

    /*
     * Copyright (c) 2023 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    #include <errno.h>
    #include <stddef.h>
    #include <string.h>
    #include <stdio.h>
    #include <zephyr/kernel.h>
    #include <zephyr/types.h>
    #include <zephyr/logging/log.h>
    
    #include <dk_buttons_and_leds.h>
    
    /* STEP 3 - Include the necessary header files */
    #include <zephyr/net/wifi.h>
    #include <zephyr/net/wifi_mgmt.h>
    #include <zephyr/net/net_mgmt.h>
    #include <net/wifi_mgmt_ext.h>
    
    /* STEP 12.4 - Include the header file for the Wi-FI credentials library */
    #include <net/wifi_credentials.h>
    #include <zephyr/net/socket.h>
    
    #include <zephyr/net/net_if.h>
    #include <zephyr/sys/printk.h>
    
    // #define SERVER_IP_ADDR "192.168.1.10" // Replace with your server's IP
    // #define SERVER_PORT 8080
    
    // LOG_MODULE_REGISTER(Lesson2_Exercise2, LOG_LEVEL_INF);
    
    /* STEP 4 - Define a macro for the relevant network events */
    // #define EVENT_MASK (NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED)
    
    /* STEP 1.2 - Include the header file of the HTTP client library */
    #include <zephyr/net/http/client.h>
    /* STEP 1.4 - Include the header file for the TLS credentials library */
    #include <zephyr/net/tls_credentials.h>
    
    /* STEP 2.3 - Include the certificate */
    static const char ca_certificate[] = {
    #include "certificate.h"
    };
    
    LOG_MODULE_REGISTER(Lesson5_Exercise1);
    
    #define EVENT_MASK (NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED)
    
    /* STEP 5 - Declare the callback structure for Wi-Fi events */
    static struct net_mgmt_event_callback mgmt_cb;
    
    /* STEP 6.1 - Define the boolean connected and the semaphore run_app */
    static bool connected = 0;
    static bool firsttime = 1;
    static K_SEM_DEFINE(run_app, 0, 1);
    
    /* STEP 4.1 - Define a macro for the credential security tag */
    #define HTTP_TLS_SEC_TAG 1
    
    /* STEP 2 - Define the macros for the HTTP server hostname and port */
    #define HTTP_HOSTNAME "api.nexkey.com" //staging.api.nexkey.com
    #define HTTP_PORT     443
    
    /* STEP 3 - Declare the necessary buffers for receiving messages */
    #define RECV_BUF_SIZE  2048
    #define CLIENT_ID_SIZE 36
    
    static char recv_buf[RECV_BUF_SIZE];
    static char client_id_buf[CLIENT_ID_SIZE + 2];
    
    /* STEP 4 - Define the variable for the counter as 0 */
    static int counter = 0;
    
    static int sock;
    static struct sockaddr_storage server;
    
    //static struct net_mgmt_event_callback mgmt_cb;
    //static bool connected;
    //static K_SEM_DEFINE(run_app, 0, 1);
    
    
    
    static int server_resolve(void)
    {
    	int err;
    	struct addrinfo *result;
    	struct addrinfo hints = {.ai_family = AF_INET, .ai_socktype = SOCK_STREAM};
    
    	err = getaddrinfo(HTTP_HOSTNAME, STRINGIFY(HTTP_PORT), &hints, &result);
    	if (err != 0) {
    		LOG_ERR("getaddrinfo failed, err: %d, %s", err, gai_strerror(err));
    		return -EIO;
    	}
    
    	if (result == NULL) {
    		LOG_ERR("Error, address not found");
    		return -ENOENT;
    	}
    
    	struct sockaddr_in *server4 = ((struct sockaddr_in *)&server);
    	server4->sin_addr.s_addr = ((struct sockaddr_in *)result->ai_addr)->sin_addr.s_addr;
    	server4->sin_family = AF_INET;
    	server4->sin_port = ((struct sockaddr_in *)result->ai_addr)->sin_port;
    
    	char ipv4_addr[NET_IPV4_ADDR_LEN];
    	inet_ntop(AF_INET, &server4->sin_addr.s_addr, ipv4_addr, sizeof(ipv4_addr));
    	LOG_INF("IPv4 address of HTTP server found %s", ipv4_addr);
    
    	freeaddrinfo(result);
    
    	return 0;
    }
    
    static int setup_credentials(void)
    {
    	
    	/* STEP 4.2 - Add the credential to the device */
    	int err = tls_credential_add(HTTP_TLS_SEC_TAG, TLS_CREDENTIAL_CA_CERTIFICATE, ca_certificate,
    				 sizeof(ca_certificate));
    	if (err < 0) {
    		LOG_ERR("Failed to add TLS credentials, err: %d", err);
    		return err;
    	}
    
    	return 0;
    }
    
    static int server_connect(void)
    {
    	int err;
    	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TLS_1_2);
    	if (sock < 0) {
    		LOG_ERR("Failed to create socket, err: %d, %s", errno, strerror(errno));
    		return -errno;
    	}
    
    	/* STEP 5.1 - Configure the socket with the security tag for the certificate */
    	sec_tag_t sec_tag_opt[] = {
    		HTTP_TLS_SEC_TAG,
    	};
    	err = setsockopt(sock, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_opt, sizeof(sec_tag_opt));
    	if (err < 0) {
    		LOG_ERR("Failed to set TLS security TAG list, err: %d", errno);
    		(void)close(sock);
    		return -errno;
    	}
    	/* STEP 5.2 - Configure the socket with the hostname of the HTTP server */
    	err = setsockopt(sock, SOL_TLS, TLS_HOSTNAME, HTTP_HOSTNAME, sizeof(HTTP_HOSTNAME));
    	if (err < 0) {
    		LOG_ERR("Failed to set TLS_HOSTNAME option. Err: %d", errno);
    		(void)close(sock);
    		return -errno;
    	}
    
    	err = connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_in));
    	if (err < 0) {
    		LOG_ERR("Connecting to server failed, err: %d, %s", errno, strerror(errno));
    		return -errno;
    	}
    
    	LOG_INF("Connected to server");
    	return 0;
    }
    
    static void response_cb(struct http_response *rsp, enum http_final_call final_data, void *user_data)
    {
    	/* STEP 9 - Define the callback function to print the body */
    	LOG_INF("Response status: %s", rsp->http_status);
    
    	if (rsp->body_frag_len > 0) {
    		char body_buf[rsp->body_frag_len];
    		strncpy(body_buf, rsp->body_frag_start, rsp->body_frag_len);
    		body_buf[rsp->body_frag_len] = '\0';
    		LOG_INF("Received: %s", body_buf);
    	}
    
    	LOG_INF("Closing socket: %d", sock);
    	close(sock);
    }
    
    static void client_id_cb(struct http_response *rsp, enum http_final_call final_data,
    			 void *user_data)
    {
    	/* STEP 6.1 - Log the HTTP response status */
    	LOG_INF("Response status: %s", rsp->http_status);
    
    	/* STEP 6.2 - Retrieve and format the client ID */
    	char client_id_buf_tmp[CLIENT_ID_SIZE + 1];
    	strncpy(client_id_buf_tmp, rsp->body_frag_start, CLIENT_ID_SIZE);
    	client_id_buf_tmp[CLIENT_ID_SIZE] = '\0';
    	client_id_buf[0] = '/';
    	strcat(client_id_buf, client_id_buf_tmp);
    
    	LOG_INF("Successfully acquired client ID: %s", client_id_buf);
    
    	/* STEP 6.3 - Close the socket */
    	LOG_INF("Closing socket: %d", sock);
    	close(sock);
    }
    
    static int client_http_put(void)
    {
    	/* STEP 7 - Define the function to send a PUT request to the HTTP server */
    	int err = 0;
    	int bytes_written;
    	const char *headers[] = {"Connection: close\r\n", NULL};
    
    	struct http_request req;
    	memset(&req, 0, sizeof(req));
    
    	char buffer[12] = {0};
    	bytes_written = snprintf(buffer, 12, "%d", counter);
    	if (bytes_written < 0) {
    		LOG_INF("Unable to write to buffer, err: %d", bytes_written);
    		return bytes_written;
    	}
    
    	req.header_fields = headers;
    	req.method = HTTP_PUT;
    	req.url = client_id_buf;
    	req.host = HTTP_HOSTNAME;
    	req.protocol = "HTTP/1.1";
    	req.payload = buffer;
    	req.payload_len = bytes_written;
    	req.response = response_cb;
    	req.recv_buf = recv_buf;
    	req.recv_buf_len = sizeof(recv_buf);
    
    	LOG_INF("HTTP PUT request: %s", buffer);
    	err = http_client_req(sock, &req, 5000, NULL);
    	if (err < 0) {
    		LOG_ERR("Failed to send HTTP PUT request %s, err: %d", buffer, err);
    	}
    
    	return err;
    }
    
    static int client_http_get(void)
    {
    	/* STEP 8 - Define the function to send a GET request to the HTTP server */
    	int err = 0;
    	const char *headers[] = {"Connection: close\r\n", NULL};
    	
    	struct http_request req;
    	memset(&req, 0, sizeof(req));
    
    	req.header_fields = headers;
    	req.method = HTTP_GET;
    	req.url = client_id_buf;
    	req.host = HTTP_HOSTNAME;
    	req.protocol = "HTTP/1.1";
    	req.response = response_cb;
    	req.recv_buf = recv_buf;
    	req.recv_buf_len = sizeof(recv_buf);
    
    	LOG_INF("HTTP GET request");
    	err = http_client_req(sock, &req, 5000, NULL);
    	if (err < 0) {
    		LOG_ERR("Failed to send HTTP GET request, err: %d", err);
    	}
    
    	return err;
    }
    
    static int client_get_new_id(void)
    {
    	int err = 0;
    
    	/* STEP 5.1 - Define the structure http_request and fill the block of memory */
    	struct http_request req;
    	memset(&req, 0, sizeof(req));
    
    	/* STEP 5.2 - Populate the http_request structure */
    	const char *headers[] = {"Connection: close\r\n", NULL};
    	req.header_fields = headers;
    	req.method = HTTP_POST;
    	req.url = "https://api.nexkey.com";
    	req.host = HTTP_HOSTNAME;
    	req.protocol = "HTTP/1.1";
    	req.response = client_id_cb;
    	req.recv_buf = recv_buf;
    	req.recv_buf_len = sizeof(recv_buf);
    
    	/* STEP 5.3 - Send the request to the HTTP server */
    	LOG_INF("HTTP POST request");
    	err = http_client_req(sock, &req, 5000, NULL);
    	if (err < 0) {
    		LOG_ERR("Failed to send HTTP POST request, err: %d", err);
    	}
    	return err;
    }
    
    /* STEP 6.2 - Define the callback function for network events */
    static void net_mgmt_event_handler(struct net_mgmt_event_callback *cb,
    			  uint32_t mgmt_event, struct net_if *iface)
    {
    	if ((mgmt_event & EVENT_MASK) != mgmt_event) {
    		return;
    	}
    	if (mgmt_event == NET_EVENT_L4_CONNECTED) {
    		LOG_INF("Network connected");
    		connected = true;
    		dk_set_led_on(DK_LED1);
    		//k_sem_give(&run_app);
    		return;
    	}
    	if (mgmt_event == NET_EVENT_L4_DISCONNECTED) {
    		if (connected == false) {
    			LOG_INF("Waiting for network to be connected");
    		} else {
    			dk_set_led_off(DK_LED1);
    			LOG_INF("Network disconnected");
    			connected = false;
    		}
    		//k_sem_reset(&run_app);
    		return;
    	}
    }
    
    /* STEP 7 - Define the function to populate the Wi-Fi credential parameters */
    //static int wifi_args_to_params(struct wifi_connect_req_params *params)
    //{
    
    	/* STEP 7.1 Populate the SSID and password */
    	//params->ssid = CONFIG_WIFI_CREDENTIALS_STATIC_SSID;
    	//params->ssid_length = strlen(params->ssid);
    
    	//params->psk = CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD;
    	//params->psk_length = strlen(params->psk);
    
    	/* STEP 7.2 - Populate the rest of the relevant members */
    	//params->channel = WIFI_CHANNEL_ANY;
    	//params->security = WIFI_SECURITY_TYPE_PSK;
    	//params->mfp = WIFI_MFP_OPTIONAL;
    	//params->timeout = SYS_FOREVER_MS;
    	//params->band = WIFI_FREQ_BAND_UNKNOWN;
    	//#if NCS_VERSION_NUMBER > 0x20600
    	//memset(params->bssid, 0, sizeof(params->bssid));
    	//#endif
    	//return 0;
    //}
    
    static struct wifi_credentials_personal wifi_cred;
    void set_wifi_credentials_struct() 
    {
    
    	char *wifi_ssid = "realme";
    	char *wifi_password = "Chirag@1527";
    
    	wifi_cred.header.type = WIFI_SECURITY_TYPE_PSK;
    	memset(wifi_cred.header.bssid, 0, sizeof(wifi_cred.header.bssid));
    	wifi_cred.header.flags = 0;
    	//wifi_cred.header.channel = WIFI_CHANNEL_ANY;
    	//wifi_cred.header.timeout = 10;
    
    	wifi_cred.header.ssid_len = strlen(wifi_ssid);
    	memcpy(wifi_cred.header.ssid, wifi_ssid, wifi_cred.header.ssid_len);
    	
    	wifi_cred.password_len = strlen(wifi_password);
    	memcpy(wifi_cred.password, wifi_password, wifi_cred.password_len);
    
    	int ret = wifi_credentials_set_personal_struct(&wifi_cred);
    
    	if (ret != 0) {
    		LOG_ERR("Failed to set credentials, err: %d", ret);
    	}
    }
    static void button_handler(uint32_t button_state, uint32_t has_changed)
    {
    	/* STEP 10 - Define the button handler to send requests upon button triggers */
    	if (has_changed & DK_BTN1_MSK && button_state & DK_BTN1_MSK) {
    		if (server_connect() >= 0) {
    			client_http_put();
    			counter++;
    		}
    	} else if (has_changed & DK_BTN2_MSK && button_state & DK_BTN2_MSK) {
    		if (server_connect() >= 0) {
    			client_http_get();
    		}
    	}
    }
    
    int main(void)
    {
    	/* STEP 8.1 - Declare the variable for the network configuration parameters */
    	//struct wifi_connect_req_params cnx_params;
    
    
    
    	/* STEP 8.2 - Get the network interface */
    	struct net_if *iface = net_if_get_first_wifi();
    	if (iface == NULL) {
    		LOG_ERR("Returned network interface is NULL");
    		return -1;
    	}
    
    	if (dk_leds_init() != 0) {
    		LOG_ERR("Failed to initialize the LED library");
    	}
    
    	/* Sleep to allow initialization of Wi-Fi driver */
    	k_sleep(K_SECONDS(1));
    
    	/* STEP 9 - Initialize and add the callback function for network events */
    	net_mgmt_init_event_callback(&mgmt_cb, net_mgmt_event_handler, EVENT_MASK);
    	net_mgmt_add_event_callback(&mgmt_cb);
    
    	/* STEP 10 - Populate cnx_params with the network configuration */
    	//wifi_args_to_params(&cnx_params);
    
        set_wifi_credentials_struct();
    	/* STEP 11 - Call net_mgmt() to request the Wi-Fi connection */
    	LOG_INF("Connecting to Wi-Fi");
    	//printf("try to connect with wifi");
    	//LOG_ERR("buttons library");
    	//int err = net_mgmt(NET_REQUEST_WIFI_CONNECT_STORED, iface, &wifi_cred, sizeof(struct wifi_credentials_personal));
    	//LOG_ERR("buttons library");
    	// if (err) {
    	// 	LOG_ERR("Connecting to Wi-Fi failed, err: %d", err);
    	// 	//return ENOEXEC;
    	// }
    
    	//k_sem_take(&run_app, K_FOREVER);
    
    	if (dk_buttons_init(button_handler) != 0) {
    		LOG_ERR("Failed to initialize the buttons library ");
    	}
    	while(1)
    	{
    		//LOG_ERR("Failed to initialize the buttons library ");
    		k_sleep(K_SECONDS(1));
    		if(!connected)
    		{
    			int err = net_mgmt(NET_REQUEST_WIFI_CONNECT_STORED, iface, &wifi_cred, sizeof(struct wifi_credentials_personal));
    		}
    		if(connected && firsttime == 1)
    		{
    			k_sleep(K_SECONDS(1));
    			if (server_resolve() != 0) {
    				LOG_ERR("Failed to resolve server name");
    				return 0;
    			}
    			
    			if (setup_credentials() != 0) {
    		        LOG_ERR("Setup credentials failed");
    	        }
    
    			if (server_connect() != 0) {
    				LOG_ERR("Failed to initialize client");
    				return 0;
    			}	
    
    			/* STEP 11 - Retrieve the client ID upon connection */
    			if (client_get_new_id() < 0) {
    				LOG_ERR("Failed to get client ID");
    				return 0;
    			}
    			firsttime = 0;
    			LOG_ERR("buttons library");
    		}
    		//return 0;
    	}
    		
    }

    below is my prj.conf file for https

    # Wi-Fi
    CONFIG_WIFI=y
    CONFIG_WIFI_NRF700X=y
    CONFIG_WPA_SUPP=y
    # CONFIG_WPA_SUPP_CRYPTO_PSA=y
    
    # Wi-Fi Credentials
    CONFIG_WIFI_CREDENTIALS=y
    CONFIG_WIFI_CREDENTIALS_STATIC=n
    
    # Networking Management API
    CONFIG_NET_MGMT=y
    CONFIG_NET_MGMT_EVENT=y
    CONFIG_NET_MGMT_EVENT_INFO=y
    CONFIG_NET_MGMT_EVENT_STACK_SIZE=4096
    CONFIG_NET_CONNECTION_MANAGER=y
    CONFIG_WIFI_MGMT_EXT=y
    
    # Support for shell commands
    # CONFIG_SHELL=y
    # CONFIG_WIFI_CREDENTIALS_SHELL=y
    # CONFIG_SHELL_STACK_SIZE=4400
    
    # Logging
    CONFIG_LOG=y
    
    # DK library
    CONFIG_DK_LIBRARY=y
    
    # System settings
    CONFIG_NEWLIB_LIBC=y
    CONFIG_NEWLIB_LIBC_NANO=n
    
    # Networking
    CONFIG_NETWORKING=y
    CONFIG_NET_NATIVE=y
    CONFIG_NET_SOCKETS=y
    CONFIG_NET_SOCKETS_POSIX_NAMES=y
    CONFIG_POSIX_MAX_FDS=16
    
    CONFIG_NET_L2_ETHERNET=y
    CONFIG_NET_IPV4=y
    CONFIG_NET_IPV6=y
    CONFIG_NET_TCP=y
    CONFIG_NET_DHCPV4=y
    CONFIG_DNS_RESOLVER=y
    
    # TLS
    # STEP 1.1 - Enable the TLS library and security relevant configurations
    CONFIG_NET_SOCKETS_SOCKOPT_TLS=y
    CONFIG_TLS_CREDENTIALS=y
    CONFIG_MBEDTLS_RSA_C=y
    CONFIG_MBEDTLS_DHM_C=y 
    
    # STEP 1.2 - Enable support for server name indication (SNI)
    CONFIG_MBEDTLS_SSL_SERVER_NAME_INDICATION=y
    
    # Memory
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096
    CONFIG_MAIN_STACK_SIZE=4096
    CONFIG_HEAP_MEM_POOL_SIZE=153600
    
    CONFIG_NET_TCP_WORKQ_STACK_SIZE=2048
    CONFIG_NET_TX_STACK_SIZE=4096
    CONFIG_NET_RX_STACK_SIZE=4096
    CONFIG_NET_BUF_RX_COUNT=16
    CONFIG_NET_BUF_TX_COUNT=16
    CONFIG_NET_BUF_DATA_SIZE=256
    CONFIG_NET_TC_TX_COUNT=0
    
    # HTTP
    CONFIG_HTTP_CLIENT=y
    # For storing Wi-Fi credentials
    CONFIG_WIFI_CREDENTIALS_BACKEND_SETTINGS=y
    CONFIG_FLASH=y
    CONFIG_FLASH_PAGE_LAYOUT=y
    CONFIG_FLASH_MAP=y
    CONFIG_NVS=y
    CONFIG_SETTINGS=y
    CONFIG_SETTINGS_NVS=y
    
    # CONFIG_NET_L2_WIFI_SHELL=y
    
    # General
    CONFIG_POSIX_CLOCK=y
    
    # Optimize Wi-Fi stack to save some memory
    
    CONFIG_NRF700X_MAX_TX_AGGREGATION=4
    
    # Wi-Fi
    
    CONFIG_WIFI_NRF700X_LOG_LEVEL_ERR=y
    
    # WPA supplicant
    
    CONFIG_WPA_SUPP_LOG_LEVEL_ERR=y
    
    # Zephyr NET Connection Manager connectivity layer
    CONFIG_L2_WIFI_CONNECTIVITY=y
    # CONFIG_L2_WIFI_CONNECTIVITY_AUTO_DOWN=n
    # CONFIG_L2_WIFI_CONNECTIVITY_AUTO_CONNECT=n
    
    # DNS
    
    # CONFIG_NET_SOCKETS_DNS_TIMEOUT=30000
    
    # NET sockets
    
    CONFIG_NET_UDP=y
    # CONFIG_NET_SOCKETS_OFFLOAD=n
    
    # CONFIG_NET_CONTEXT_SNDTIMEO=y
    
    # TLS networking
    CONFIG_NET_SOCKETS_ENABLE_DTLS=n
    CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=2
    
    
    # TLS credentials
    
    # Here is the overlay I used for nrf7002dk_nrf5340_cpuapp
    
    # CONFIG_TLS_CREDENTIALS_BACKEND_VOLATILE=y
    
    # mbedTLS
    CONFIG_NRF_SECURITY=y
    CONFIG_MBEDTLS=y
    CONFIG_MBEDTLS_ENABLE_HEAP=y
    CONFIG_MBEDTLS_HEAP_SIZE=81920
    CONFIG_PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY=y
    CONFIG_PSA_WANT_RSA_KEY_SIZE_2048=y
    
    CONFIG_MBEDTLS_TLS_LIBRARY=y
    
    CONFIG_PM_SINGLE_IMAGE=y

  • Hi,

    Are you able to connect using only Wi-Fi Shell sample and "wifi connect" command?

    Have you consider using MQTT sample?

    Best regards,
    Dejan

  • Are you able to connect using only Wi-Fi Shell sample and "wifi connect" command?

    >>yes when i separately used wifi shell sample with SDK v2.6.1 and give wifi connect -s <ssid> -k 1 -p <password>  then i am able to connect successfully,

    Have you consider using MQTT sample?

    >>No

    I merged the HTTPS and WebSocket code, but I am still unable to connect to the WebSocket.

    Below is the output I received. Please review my code and provide your valuable feedback so I can resolve this issue as soon as possible.

    00:00:09.124,359] <inf> wifi_mgmt_ext: Connection requested
    [00:00:11.698,547] <inf> wifi_mgmt_ext: Connection requested
    [00:00:11.796,875] <inf> Lesson5_Exercise1: Network connected
    [00:00:14.003,723] <inf> Lesson5_Exercise1: IPv4 address of HTTP server found 3.164.182.37
    [00:00:16.464,599] <inf> Lesson5_Exercise1: Connected to server
    [00:00:16.464,630] <inf> Lesson5_Exercise1: HTTP POST request
    [00:00:18.513,549] <inf> Lesson5_Exercise1: Response status: Created
    [00:00:18.513,580] <inf> Lesson5_Exercise1: Successfully acquired client ID: /bed00a39-9547-49b6-81ac-031562f1998f
    [00:00:18.513,610] <inf> Lesson5_Exercise1: Closing socket: 9
    [00:00:20.928,588] <err> Lesson5_Exercise1: Cannot connect to IPv4 remote (-116)
    [00:00:20.929,016] <err> Lesson5_Exercise1: Cannot connect to 192.0.2.2:9001
    [00:00:20.929,107] <err> Lesson5_Exercise1: No IPv4 or IPv6 connectivity

    Below is my code,

    /*
     * Copyright (c) 2023 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    #include <errno.h>
    #include <stddef.h>
    #include <string.h>
    #include <stdio.h>
    #include <zephyr/kernel.h>
    #include <zephyr/types.h>
    #include <zephyr/logging/log.h>
    
    #include <dk_buttons_and_leds.h>
    
    /* STEP 3 - Include the necessary header files */
    #include <zephyr/net/wifi.h>
    #include <zephyr/net/wifi_mgmt.h>
    #include <zephyr/net/net_mgmt.h>
    #include <net/wifi_mgmt_ext.h>
    
    /* STEP 12.4 - Include the header file for the Wi-FI credentials library */
    #include <net/wifi_credentials.h>
    #include <zephyr/net/socket.h>
    
    #include <zephyr/net/net_if.h>
    #include <zephyr/sys/printk.h>
    
    #include <zephyr/net/websocket.h>
    
    // #define SERVER_IP_ADDR "192.168.1.10" // Replace with your server's IP
    // #define SERVER_PORT 8080
    
    // LOG_MODULE_REGISTER(Lesson2_Exercise2, LOG_LEVEL_INF);
    
    /* STEP 4 - Define a macro for the relevant network events */
    // #define EVENT_MASK (NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED)
    
    /* STEP 1.2 - Include the header file of the HTTP client library */
    #include <zephyr/net/http/client.h>
    /* STEP 1.4 - Include the header file for the TLS credentials library */
    #include <zephyr/net/tls_credentials.h>
    
    /* STEP 2.3 - Include the certificate */
    static const char ca_certificate[] = {
    #include "certificate.h"
    };
    
    LOG_MODULE_REGISTER(Lesson5_Exercise1);
    
    #define EVENT_MASK (NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED)
    
    /* STEP 5 - Declare the callback structure for Wi-Fi events */
    static struct net_mgmt_event_callback mgmt_cb;
    
    /* STEP 6.1 - Define the boolean connected and the semaphore run_app */
    static bool connected = 0;
    static bool firsttime = 1;
    static K_SEM_DEFINE(run_app, 0, 1);
    
    /* STEP 4.1 - Define a macro for the credential security tag */
    #define HTTP_TLS_SEC_TAG 1
    
    /* STEP 2 - Define the macros for the HTTP server hostname and port */
    #define HTTP_HOSTNAME  "echo.thingy.rocks" //staging.api.nexkey.com
    #define HTTP_PORT     443
    
    /* STEP 3 - Declare the necessary buffers for receiving messages */
    #define RECV_BUF_SIZE  2048
    #define CLIENT_ID_SIZE 36
    
    static char recv_buf[RECV_BUF_SIZE];
    static char client_id_buf[CLIENT_ID_SIZE + 2];
    
    /* STEP 4 - Define the variable for the counter as 0 */
    static int counter = 0;
    
    static int sock;
    static struct sockaddr_storage server;
    
    //static struct net_mgmt_event_callback mgmt_cb;
    //static bool connected;
    //static K_SEM_DEFINE(run_app, 0, 1);
    
    
    
    static int server_resolve(void)
    {
    	int err;
    	struct addrinfo *result;
    	struct addrinfo hints = {.ai_family = AF_INET, .ai_socktype = SOCK_STREAM};
    
    	err = getaddrinfo(HTTP_HOSTNAME, STRINGIFY(HTTP_PORT), &hints, &result);
    	if (err != 0) {
    		LOG_ERR("getaddrinfo failed, err: %d, %s", err, gai_strerror(err));
    		return -EIO;
    	}
    
    	if (result == NULL) {
    		LOG_ERR("Error, address not found");
    		return -ENOENT;
    	}
    
    	struct sockaddr_in *server4 = ((struct sockaddr_in *)&server);
    	server4->sin_addr.s_addr = ((struct sockaddr_in *)result->ai_addr)->sin_addr.s_addr;
    	server4->sin_family = AF_INET;
    	server4->sin_port = ((struct sockaddr_in *)result->ai_addr)->sin_port;
    
    	char ipv4_addr[NET_IPV4_ADDR_LEN];
    	inet_ntop(AF_INET, &server4->sin_addr.s_addr, ipv4_addr, sizeof(ipv4_addr));
    	LOG_INF("IPv4 address of HTTP server found %s", ipv4_addr);
    
    	freeaddrinfo(result);
    
    	return 0;
    }
    
    static int setup_credentials(void)
    {
    	
    	/* STEP 4.2 - Add the credential to the device */
    	int err = tls_credential_add(HTTP_TLS_SEC_TAG, TLS_CREDENTIAL_CA_CERTIFICATE, ca_certificate,
    				 sizeof(ca_certificate));
    	if (err < 0) {
    		LOG_ERR("Failed to add TLS credentials, err: %d", err);
    		return err;
    	}
    
    	return 0;
    }
    
    static int server_connect(void)
    {
    	int err;
    	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TLS_1_2);
    	if (sock < 0) {
    		LOG_ERR("Failed to create socket, err: %d, %s", errno, strerror(errno));
    		return -errno;
    	}
    
    	/* STEP 5.1 - Configure the socket with the security tag for the certificate */
    	sec_tag_t sec_tag_opt[] = {
    		HTTP_TLS_SEC_TAG,
    	};
    	err = setsockopt(sock, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_opt, sizeof(sec_tag_opt));
    	if (err < 0) {
    		LOG_ERR("Failed to set TLS security TAG list, err: %d", errno);
    		(void)close(sock);
    		return -errno;
    	}
    	/* STEP 5.2 - Configure the socket with the hostname of the HTTP server */
    	err = setsockopt(sock, SOL_TLS, TLS_HOSTNAME, HTTP_HOSTNAME, sizeof(HTTP_HOSTNAME));
    	if (err < 0) {
    		LOG_ERR("Failed to set TLS_HOSTNAME option. Err: %d", errno);
    		(void)close(sock);
    		return -errno;
    	}
    
    	err = connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_in));
    	if (err < 0) {
    		LOG_ERR("Connecting to server failed, err: %d, %s", errno, strerror(errno));
    		return -errno;
    	}
    
    	LOG_INF("Connected to server");
    	return 0;
    }
    
    static void response_cb(struct http_response *rsp, enum http_final_call final_data, void *user_data)
    {
    	/* STEP 9 - Define the callback function to print the body */
    	LOG_INF("Response status: %s", rsp->http_status);
    
    	if (rsp->body_frag_len > 0) {
    		char body_buf[rsp->body_frag_len];
    		strncpy(body_buf, rsp->body_frag_start, rsp->body_frag_len);
    		body_buf[rsp->body_frag_len] = '\0';
    		LOG_INF("Received: %s", body_buf);
    	}
    
    	LOG_INF("Closing socket: %d", sock);
    	close(sock);
    }
    
    static void client_id_cb(struct http_response *rsp, enum http_final_call final_data,
    			 void *user_data)
    {
    	/* STEP 6.1 - Log the HTTP response status */
    	LOG_INF("Response status: %s", rsp->http_status);
    
    	/* STEP 6.2 - Retrieve and format the client ID */
    	char client_id_buf_tmp[CLIENT_ID_SIZE + 1];
    	strncpy(client_id_buf_tmp, rsp->body_frag_start, CLIENT_ID_SIZE);
    	client_id_buf_tmp[CLIENT_ID_SIZE] = '\0';
    	client_id_buf[0] = '/';
    	strcat(client_id_buf, client_id_buf_tmp);
    
    	LOG_INF("Successfully acquired client ID: %s", client_id_buf);
    
    	/* STEP 6.3 - Close the socket */
    	LOG_INF("Closing socket: %d", sock);
    	close(sock);
    }
    
    static int client_http_put(void)
    {
    	/* STEP 7 - Define the function to send a PUT request to the HTTP server */
    	int err = 0;
    	int bytes_written;
    	const char *headers[] = {"Connection: close\r\n", NULL};
    
    	struct http_request req;
    	memset(&req, 0, sizeof(req));
    
    	char buffer[12] = {0};
    	bytes_written = snprintf(buffer, 12, "%d", counter);
    	if (bytes_written < 0) {
    		LOG_INF("Unable to write to buffer, err: %d", bytes_written);
    		return bytes_written;
    	}
    
    	req.header_fields = headers;
    	req.method = HTTP_PUT;
    	req.url = client_id_buf;
    	req.host = HTTP_HOSTNAME;
    	req.protocol = "HTTP/1.1";
    	req.payload = buffer;
    	req.payload_len = bytes_written;
    	req.response = response_cb;
    	req.recv_buf = recv_buf;
    	req.recv_buf_len = sizeof(recv_buf);
    
    	LOG_INF("HTTP PUT request: %s", buffer);
    	err = http_client_req(sock, &req, 5000, NULL);
    	if (err < 0) {
    		LOG_ERR("Failed to send HTTP PUT request %s, err: %d", buffer, err);
    	}
    
    	return err;
    }
    
    static int client_http_get(void)
    {
    	/* STEP 8 - Define the function to send a GET request to the HTTP server */
    	int err = 0;
    	const char *headers[] = {"Connection: close\r\n", NULL};
    	
    	struct http_request req;
    	memset(&req, 0, sizeof(req));
    
    	req.header_fields = headers;
    	req.method = HTTP_GET;
    	req.url = client_id_buf;
    	req.host = HTTP_HOSTNAME;
    	req.protocol = "HTTP/1.1";
    	req.response = response_cb;
    	req.recv_buf = recv_buf;
    	req.recv_buf_len = sizeof(recv_buf);
    
    	LOG_INF("HTTP GET request");
    	err = http_client_req(sock, &req, 5000, NULL);
    	if (err < 0) {
    		LOG_ERR("Failed to send HTTP GET request, err: %d", err);
    	}
    
    	return err;
    }
    
    static int client_get_new_id(void)
    {
    	int err = 0;
    
    	/* STEP 5.1 - Define the structure http_request and fill the block of memory */
    	struct http_request req;
    	memset(&req, 0, sizeof(req));
    
    	/* STEP 5.2 - Populate the http_request structure */
    	const char *headers[] = {"Connection: close\r\n", NULL};
    	req.header_fields = headers;
    	req.method = HTTP_POST;
    	req.url =  "/new";"https://api.nexkey.com";
    	req.host = HTTP_HOSTNAME;
    	req.protocol = "HTTP/1.1";
    	req.response = client_id_cb;
    	req.recv_buf = recv_buf;
    	req.recv_buf_len = sizeof(recv_buf);
    
    	/* STEP 5.3 - Send the request to the HTTP server */
    	LOG_INF("HTTP POST request");
    	err = http_client_req(sock, &req, 5000, NULL);
    	if (err < 0) {
    		LOG_ERR("Failed to send HTTP POST request, err: %d", err);
    	}
    	return err;
    }
    
    /* STEP 6.2 - Define the callback function for network events */
    static void net_mgmt_event_handler(struct net_mgmt_event_callback *cb,
    			  uint32_t mgmt_event, struct net_if *iface)
    {
    	if ((mgmt_event & EVENT_MASK) != mgmt_event) {
    		return;
    	}
    	if (mgmt_event == NET_EVENT_L4_CONNECTED) {
    		LOG_INF("Network connected");
    		connected = true;
    		dk_set_led_on(DK_LED1);
    		//k_sem_give(&run_app);
    		return;
    	}
    	if (mgmt_event == NET_EVENT_L4_DISCONNECTED) {
    		if (connected == false) {
    			LOG_INF("Waiting for network to be connected");
    		} else {
    			dk_set_led_off(DK_LED1);
    			LOG_INF("Network disconnected");
    			connected = false;
    		}
    		//k_sem_reset(&run_app);
    		return;
    	}
    }
    
    /* STEP 7 - Define the function to populate the Wi-Fi credential parameters */
    //static int wifi_args_to_params(struct wifi_connect_req_params *params)
    //{
    
    	/* STEP 7.1 Populate the SSID and password */
    	//params->ssid = CONFIG_WIFI_CREDENTIALS_STATIC_SSID;
    	//params->ssid_length = strlen(params->ssid);
    
    	//params->psk = CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD;
    	//params->psk_length = strlen(params->psk);
    
    	/* STEP 7.2 - Populate the rest of the relevant members */
    	//params->channel = WIFI_CHANNEL_ANY;
    	//params->security = WIFI_SECURITY_TYPE_PSK;
    	//params->mfp = WIFI_MFP_OPTIONAL;
    	//params->timeout = SYS_FOREVER_MS;
    	//params->band = WIFI_FREQ_BAND_UNKNOWN;
    	//#if NCS_VERSION_NUMBER > 0x20600
    	//memset(params->bssid, 0, sizeof(params->bssid));
    	//#endif
    	//return 0;
    //}
    
    static struct wifi_credentials_personal wifi_cred;
    void set_wifi_credentials_struct() 
    {
    
    	char *wifi_ssid = "realme";
    	char *wifi_password = "Chirag@1527";
    
    	wifi_cred.header.type = WIFI_SECURITY_TYPE_PSK;
    	memset(wifi_cred.header.bssid, 0, sizeof(wifi_cred.header.bssid));
    	wifi_cred.header.flags = 0;
    	//wifi_cred.header.channel = WIFI_CHANNEL_ANY;
    	//wifi_cred.header.timeout = 10;
    
    	wifi_cred.header.ssid_len = strlen(wifi_ssid);
    	memcpy(wifi_cred.header.ssid, wifi_ssid, wifi_cred.header.ssid_len);
    	
    	wifi_cred.password_len = strlen(wifi_password);
    	memcpy(wifi_cred.password, wifi_password, wifi_cred.password_len);
    
    	int ret = wifi_credentials_set_personal_struct(&wifi_cred);
    
    	if (ret != 0) {
    		LOG_ERR("Failed to set credentials, err: %d", ret);
    	}
    }
    static void button_handler(uint32_t button_state, uint32_t has_changed)
    {
    	/* STEP 10 - Define the button handler to send requests upon button triggers */
    	if (has_changed & DK_BTN1_MSK && button_state & DK_BTN1_MSK) {
    		if (server_connect() >= 0) {
    			client_http_put();
    			counter++;
    		}
    	} else if (has_changed & DK_BTN2_MSK && button_state & DK_BTN2_MSK) {
    		if (server_connect() >= 0) {
    			client_http_get();
    		}
    	}
    }
    static const char lorem_ipsum[] =
    	"Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
    	"Vestibulum ultricies sapien tellus, ac viverra dolor bibendum "
    	"lacinia. Vestibulum et nisl tristique tellus finibus gravida "
    	"vitae sit amet nunc. Suspendisse maximus justo mi, vitae porta "
    	"risus suscipit vitae. Curabitur ut fringilla velit. Donec ac nisi "
    	"in dui semper lobortis sed nec ante. Sed nec luctus dui. Sed ut "
    	"ante nisi. Mauris congue euismod felis, et maximus ex pellentesque "
    	"nec. Proin nibh nisl, semper at nunc in, mattis pharetra metus. Nam "
    	"turpis risus, pulvinar sit amet varius ac, pellentesque quis purus."
    	" "
    	"Nam consequat purus in lacinia fringilla. Morbi volutpat, tellus "
    	"nec tempus dapibus, ante sem aliquam dui, eu feugiat libero diam "
    	"at leo. Sed suscipit egestas orci in ultrices. Integer in elementum "
    	"ligula, vel sollicitudin velit. Nullam sit amet eleifend libero. "
    	"Proin sit amet consequat tellus, vel vulputate arcu. Curabitur quis "
    	"lobortis lacus. Sed faucibus vestibulum enim vel elementum. Vivamus "
    	"enim nunc, auctor in purus at, aliquet pulvinar eros. Cras dapibus "
    	"nec quam laoreet sagittis. Quisque dictum ante odio, at imperdiet "
    	"est convallis a. Morbi mattis ut orci vitae volutpat."
    	"\n";
    #define SERVER_ADDR4 "192.0.2.2"
    #define SERVER_PORT 9001
    #define MAX_RECV_BUF_LEN (sizeof(lorem_ipsum) - 1)
    #define EXTRA_BUF_SPACE 30
    static uint8_t temp_recv_buf_ipv4[MAX_RECV_BUF_LEN + EXTRA_BUF_SPACE];
    
    static int setup_socket(sa_family_t family, const char *server, int port,
    			int *sock, struct sockaddr *addr, socklen_t addr_len)
    {
    	const char *family_str = family == AF_INET ? "IPv4" : "IPv6";
    	int ret = 0;
    
    	memset(addr, 0, addr_len);
    
    	//if (family == AF_INET) {
    		net_sin(addr)->sin_family = AF_INET;
    		net_sin(addr)->sin_port = htons(port);
    		inet_pton(family, server, &net_sin(addr)->sin_addr);
    	// } else {
    	// 	net_sin6(addr)->sin6_family = AF_INET6;
    	// 	net_sin6(addr)->sin6_port = htons(port);
    	// 	inet_pton(family, server, &net_sin6(addr)->sin6_addr);
    	// }
    
    	// if (IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS)) {
    	// 	sec_tag_t sec_tag_list[] = {
    	// 		CA_CERTIFICATE_TAG,
    	// 	};
    
    	// 	*sock = socket(family, SOCK_STREAM, IPPROTO_TLS_1_2);
    	// 	if (*sock >= 0) {
    	// 		ret = setsockopt(*sock, SOL_TLS, TLS_SEC_TAG_LIST,
    	// 				 sec_tag_list, sizeof(sec_tag_list));
    	// 		if (ret < 0) {
    	// 			LOG_ERR("Failed to set %s secure option (%d)",
    	// 				family_str, -errno);
    	// 			ret = -errno;
    	// 			goto fail;
    	// 		}
    
    	// 		ret = setsockopt(*sock, SOL_TLS, TLS_HOSTNAME,
    	// 				 TLS_PEER_HOSTNAME,
    	// 				 sizeof(TLS_PEER_HOSTNAME));
    	// 		if (ret < 0) {
    	// 			LOG_ERR("Failed to set %s TLS_HOSTNAME "
    	// 				"option (%d)", family_str, -errno);
    	// 			ret = -errno;
    	// 			goto fail;
    	// 		}
    	// 	}
    	// } else {
    		*sock = socket(family, SOCK_STREAM, IPPROTO_TCP);
    	//}
    
    	if (*sock < 0) {
    		LOG_ERR("Failed to create %s HTTP socket (%d)", family_str,
    			-errno);
    	}
    
    	return ret;
    
    fail:
    	if (*sock >= 0) {
    		close(*sock);
    		*sock = -1;
    	}
    
    	return ret;
    }
    static int connect_cb(int sock, struct http_request *req, void *user_data)
    {
    	LOG_INF("Websocket %d for %s connected.", sock, (char *)user_data);
    
    	return 0;
    }
    static int connect_socket(sa_family_t family, const char *server, int port,
    			  int *sock, struct sockaddr *addr, socklen_t addr_len)
    {
    	int ret;
    
    	ret = setup_socket(family, server, port, sock, addr, addr_len);
    	if (ret < 0 || *sock < 0) {
    		return -1;
    	}
    
    	ret = connect(*sock, addr, addr_len);
    	if (ret < 0) {
    		LOG_ERR("Cannot connect to %s remote (%d)",
    			family == AF_INET ? "IPv4" : "IPv6",
    			-errno);
    		ret = -errno;
    	}
    
    	return ret;
    }
    int main(void)
    {
    	/* STEP 8.1 - Declare the variable for the network configuration parameters */
    	//struct wifi_connect_req_params cnx_params;
    
    
    
    	/* STEP 8.2 - Get the network interface */
    	struct net_if *iface = net_if_get_first_wifi();
    	if (iface == NULL) {
    		LOG_ERR("Returned network interface is NULL");
    		return -1;
    	}
    
    	if (dk_leds_init() != 0) {
    		LOG_ERR("Failed to initialize the LED library");
    	}
    
    	/* Sleep to allow initialization of Wi-Fi driver */
    	k_sleep(K_SECONDS(1));
    
    	/* STEP 9 - Initialize and add the callback function for network events */
    	net_mgmt_init_event_callback(&mgmt_cb, net_mgmt_event_handler, EVENT_MASK);
    	net_mgmt_add_event_callback(&mgmt_cb);
    
    	/* STEP 10 - Populate cnx_params with the network configuration */
    	//wifi_args_to_params(&cnx_params);
    
        set_wifi_credentials_struct();
    	/* STEP 11 - Call net_mgmt() to request the Wi-Fi connection */
    	LOG_INF("Connecting to Wi-Fi");
    	//printf("try to connect with wifi");
    	//LOG_ERR("buttons library");
    	//int err = net_mgmt(NET_REQUEST_WIFI_CONNECT_STORED, iface, &wifi_cred, sizeof(struct wifi_credentials_personal));
    	//LOG_ERR("buttons library");
    	// if (err) {
    	// 	LOG_ERR("Connecting to Wi-Fi failed, err: %d", err);
    	// 	//return ENOEXEC;
    	// }
    
    	//k_sem_take(&run_app, K_FOREVER);
    
    	if (dk_buttons_init(button_handler) != 0) {
    		LOG_ERR("Failed to initialize the buttons library ");
    	}
    	while(1)
    	{
    		//LOG_ERR("Failed to initialize the buttons library ");
    		k_sleep(K_SECONDS(1));
    		if(!connected)
    		{
    			int err = net_mgmt(NET_REQUEST_WIFI_CONNECT_STORED, iface, &wifi_cred, sizeof(struct wifi_credentials_personal));
    		}
    		if(connected && firsttime == 1)
    		{
    			k_sleep(K_SECONDS(1));
    			if (server_resolve() != 0) {
    				LOG_ERR("Failed to resolve server name");
    				return 0;
    			}
    			
    			if (setup_credentials() != 0) {
    		        LOG_ERR("Setup credentials failed");
    	        }
    
    			if (server_connect() != 0) {
    				LOG_ERR("Failed to initialize client");
    				return 0;
    			}	
    
    			/* STEP 11 - Retrieve the client ID upon connection */
    			if (client_get_new_id() < 0) {
    				LOG_ERR("Failed to get client ID");
    				return 0;
    			}
    			firsttime = 0;
    			//LOG_ERR("buttons library");
    		
    		const char *extra_headers[] = 
    		{
    			"Origin: http://foobar\r\n",
    			NULL
    	    };
    		int sock4 = -1, sock6 = -1;
    		int websock4 = -1, websock6 = -1;
    		int32_t timeout = 3 * MSEC_PER_SEC;
    		struct sockaddr_in6 addr6;
    		struct sockaddr_in addr4;
    		size_t amount;
    		int ret;
    
    		//if (IS_ENABLED(CONFIG_NET_IPV4)) 
    		{
    					(void)connect_socket(AF_INET, SERVER_ADDR4, SERVER_PORT,
    				     &sock4, (struct sockaddr *)&addr4,
    				     sizeof(addr4));
    		}
    	
    	if (sock4 < 0) {
    		LOG_ERR("Cannot create HTTP connection.");
    		k_sleep(K_FOREVER);
    	}
    
    	//if (sock4 >= 0 && IS_ENABLED(CONFIG_NET_IPV4)) 
    	{
    		struct websocket_request req;
    
    		memset(&req, 0, sizeof(req));
    
    		req.host = SERVER_ADDR4;
    		req.url = "/";
    		req.optional_headers = extra_headers;
    		req.cb = connect_cb;
    		req.tmp_buf = temp_recv_buf_ipv4;
    		req.tmp_buf_len = sizeof(temp_recv_buf_ipv4);
    
    		websock4 = websocket_connect(sock4, &req, timeout, "IPv4");
    		if (websock4 < 0) {
    			LOG_ERR("Cannot connect to %s:%d", SERVER_ADDR4,
    				SERVER_PORT);
    			close(sock4);
    		}
    	}
    	if (websock4 < 0)
    	 {
    		LOG_ERR("No IPv4 or IPv6 connectivity");
    		k_sleep(K_FOREVER);
    	}
    
    	LOG_INF("Websocket IPv4 %d IPv6 %d", websock4, websock6);
    
    
    
    		//return 0;
    	}
      }
    		
    }

    prj.conf file

    # Wi-Fi
    CONFIG_WIFI=y
    CONFIG_WIFI_NRF700X=y
    CONFIG_WPA_SUPP=y
    # CONFIG_WPA_SUPP_CRYPTO_PSA=y
    
    # Wi-Fi Credentials
    CONFIG_WIFI_CREDENTIALS=y
    CONFIG_WIFI_CREDENTIALS_STATIC=n
    
    # Networking Management API
    CONFIG_NET_MGMT=y
    CONFIG_NET_MGMT_EVENT=y
    CONFIG_NET_MGMT_EVENT_INFO=y
    CONFIG_NET_MGMT_EVENT_STACK_SIZE=4096
    CONFIG_NET_CONNECTION_MANAGER=y
    CONFIG_WIFI_MGMT_EXT=y
    
    # Support for shell commands
    # CONFIG_SHELL=y
    # CONFIG_WIFI_CREDENTIALS_SHELL=y
    # CONFIG_SHELL_STACK_SIZE=4400
    
    # Logging
    CONFIG_LOG=y
    
    # DK library
    CONFIG_DK_LIBRARY=y
    
    # System settings
    CONFIG_NEWLIB_LIBC=y
    CONFIG_NEWLIB_LIBC_NANO=n
    
    # Networking
    CONFIG_NETWORKING=y
    CONFIG_NET_NATIVE=y
    CONFIG_NET_SOCKETS=y
    CONFIG_NET_SOCKETS_POSIX_NAMES=y
    CONFIG_POSIX_MAX_FDS=16
    
    CONFIG_NET_L2_ETHERNET=y
    CONFIG_NET_IPV4=y
    CONFIG_NET_IPV6=y
    CONFIG_NET_TCP=y
    CONFIG_NET_DHCPV4=y
    CONFIG_DNS_RESOLVER=y
    
    # TLS
    # STEP 1.1 - Enable the TLS library and security relevant configurations
    CONFIG_NET_SOCKETS_SOCKOPT_TLS=y
    CONFIG_TLS_CREDENTIALS=y
    CONFIG_MBEDTLS_RSA_C=y
    CONFIG_MBEDTLS_DHM_C=y 
    
    # STEP 1.2 - Enable support for server name indication (SNI)
    CONFIG_MBEDTLS_SSL_SERVER_NAME_INDICATION=y
    
    # Memory
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096
    CONFIG_MAIN_STACK_SIZE=4096
    CONFIG_HEAP_MEM_POOL_SIZE=153600
    
    CONFIG_NET_TCP_WORKQ_STACK_SIZE=2048
    CONFIG_NET_TX_STACK_SIZE=4096
    CONFIG_NET_RX_STACK_SIZE=4096
    CONFIG_NET_BUF_RX_COUNT=16
    CONFIG_NET_BUF_TX_COUNT=16
    CONFIG_NET_BUF_DATA_SIZE=256
    CONFIG_NET_TC_TX_COUNT=0
    
    # HTTP
    CONFIG_HTTP_CLIENT=y
    # For storing Wi-Fi credentials
    CONFIG_WIFI_CREDENTIALS_BACKEND_SETTINGS=y
    CONFIG_FLASH=y
    CONFIG_FLASH_PAGE_LAYOUT=y
    CONFIG_FLASH_MAP=y
    CONFIG_NVS=y
    CONFIG_SETTINGS=y
    CONFIG_SETTINGS_NVS=y
    
    # CONFIG_NET_L2_WIFI_SHELL=y
    
    # General
    CONFIG_POSIX_CLOCK=y
    
    # Optimize Wi-Fi stack to save some memory
    
    CONFIG_NRF700X_MAX_TX_AGGREGATION=4
    
    # Wi-Fi
    
    CONFIG_WIFI_NRF700X_LOG_LEVEL_ERR=y
    
    # WPA supplicant
    
    CONFIG_WPA_SUPP_LOG_LEVEL_ERR=y
    
    # Zephyr NET Connection Manager connectivity layer
    CONFIG_L2_WIFI_CONNECTIVITY=y
    # CONFIG_L2_WIFI_CONNECTIVITY_AUTO_DOWN=n
    # CONFIG_L2_WIFI_CONNECTIVITY_AUTO_CONNECT=n
    
    # DNS
    
    # CONFIG_NET_SOCKETS_DNS_TIMEOUT=30000
    
    # NET sockets
    
    CONFIG_NET_UDP=y
    # CONFIG_NET_SOCKETS_OFFLOAD=n
    
    # CONFIG_NET_CONTEXT_SNDTIMEO=y
    
    # TLS networking
    CONFIG_NET_SOCKETS_ENABLE_DTLS=n
    CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=2
    
    
    # TLS credentials
    
    # Here is the overlay I used for nrf7002dk_nrf5340_cpuapp
    
    # CONFIG_TLS_CREDENTIALS_BACKEND_VOLATILE=y
    
    # mbedTLS
    CONFIG_NRF_SECURITY=y
    CONFIG_MBEDTLS=y
    CONFIG_MBEDTLS_ENABLE_HEAP=y
    CONFIG_MBEDTLS_HEAP_SIZE=81920
    CONFIG_PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY=y
    CONFIG_PSA_WANT_RSA_KEY_SIZE_2048=y
    
    CONFIG_MBEDTLS_TLS_LIBRARY=y
    
    CONFIG_PM_SINGLE_IMAGE=y
    
    
    CONFIG_WEBSOCKET_CLIENT=y

Reply
  • Are you able to connect using only Wi-Fi Shell sample and "wifi connect" command?

    >>yes when i separately used wifi shell sample with SDK v2.6.1 and give wifi connect -s <ssid> -k 1 -p <password>  then i am able to connect successfully,

    Have you consider using MQTT sample?

    >>No

    I merged the HTTPS and WebSocket code, but I am still unable to connect to the WebSocket.

    Below is the output I received. Please review my code and provide your valuable feedback so I can resolve this issue as soon as possible.

    00:00:09.124,359] <inf> wifi_mgmt_ext: Connection requested
    [00:00:11.698,547] <inf> wifi_mgmt_ext: Connection requested
    [00:00:11.796,875] <inf> Lesson5_Exercise1: Network connected
    [00:00:14.003,723] <inf> Lesson5_Exercise1: IPv4 address of HTTP server found 3.164.182.37
    [00:00:16.464,599] <inf> Lesson5_Exercise1: Connected to server
    [00:00:16.464,630] <inf> Lesson5_Exercise1: HTTP POST request
    [00:00:18.513,549] <inf> Lesson5_Exercise1: Response status: Created
    [00:00:18.513,580] <inf> Lesson5_Exercise1: Successfully acquired client ID: /bed00a39-9547-49b6-81ac-031562f1998f
    [00:00:18.513,610] <inf> Lesson5_Exercise1: Closing socket: 9
    [00:00:20.928,588] <err> Lesson5_Exercise1: Cannot connect to IPv4 remote (-116)
    [00:00:20.929,016] <err> Lesson5_Exercise1: Cannot connect to 192.0.2.2:9001
    [00:00:20.929,107] <err> Lesson5_Exercise1: No IPv4 or IPv6 connectivity

    Below is my code,

    /*
     * Copyright (c) 2023 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    #include <errno.h>
    #include <stddef.h>
    #include <string.h>
    #include <stdio.h>
    #include <zephyr/kernel.h>
    #include <zephyr/types.h>
    #include <zephyr/logging/log.h>
    
    #include <dk_buttons_and_leds.h>
    
    /* STEP 3 - Include the necessary header files */
    #include <zephyr/net/wifi.h>
    #include <zephyr/net/wifi_mgmt.h>
    #include <zephyr/net/net_mgmt.h>
    #include <net/wifi_mgmt_ext.h>
    
    /* STEP 12.4 - Include the header file for the Wi-FI credentials library */
    #include <net/wifi_credentials.h>
    #include <zephyr/net/socket.h>
    
    #include <zephyr/net/net_if.h>
    #include <zephyr/sys/printk.h>
    
    #include <zephyr/net/websocket.h>
    
    // #define SERVER_IP_ADDR "192.168.1.10" // Replace with your server's IP
    // #define SERVER_PORT 8080
    
    // LOG_MODULE_REGISTER(Lesson2_Exercise2, LOG_LEVEL_INF);
    
    /* STEP 4 - Define a macro for the relevant network events */
    // #define EVENT_MASK (NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED)
    
    /* STEP 1.2 - Include the header file of the HTTP client library */
    #include <zephyr/net/http/client.h>
    /* STEP 1.4 - Include the header file for the TLS credentials library */
    #include <zephyr/net/tls_credentials.h>
    
    /* STEP 2.3 - Include the certificate */
    static const char ca_certificate[] = {
    #include "certificate.h"
    };
    
    LOG_MODULE_REGISTER(Lesson5_Exercise1);
    
    #define EVENT_MASK (NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED)
    
    /* STEP 5 - Declare the callback structure for Wi-Fi events */
    static struct net_mgmt_event_callback mgmt_cb;
    
    /* STEP 6.1 - Define the boolean connected and the semaphore run_app */
    static bool connected = 0;
    static bool firsttime = 1;
    static K_SEM_DEFINE(run_app, 0, 1);
    
    /* STEP 4.1 - Define a macro for the credential security tag */
    #define HTTP_TLS_SEC_TAG 1
    
    /* STEP 2 - Define the macros for the HTTP server hostname and port */
    #define HTTP_HOSTNAME  "echo.thingy.rocks" //staging.api.nexkey.com
    #define HTTP_PORT     443
    
    /* STEP 3 - Declare the necessary buffers for receiving messages */
    #define RECV_BUF_SIZE  2048
    #define CLIENT_ID_SIZE 36
    
    static char recv_buf[RECV_BUF_SIZE];
    static char client_id_buf[CLIENT_ID_SIZE + 2];
    
    /* STEP 4 - Define the variable for the counter as 0 */
    static int counter = 0;
    
    static int sock;
    static struct sockaddr_storage server;
    
    //static struct net_mgmt_event_callback mgmt_cb;
    //static bool connected;
    //static K_SEM_DEFINE(run_app, 0, 1);
    
    
    
    static int server_resolve(void)
    {
    	int err;
    	struct addrinfo *result;
    	struct addrinfo hints = {.ai_family = AF_INET, .ai_socktype = SOCK_STREAM};
    
    	err = getaddrinfo(HTTP_HOSTNAME, STRINGIFY(HTTP_PORT), &hints, &result);
    	if (err != 0) {
    		LOG_ERR("getaddrinfo failed, err: %d, %s", err, gai_strerror(err));
    		return -EIO;
    	}
    
    	if (result == NULL) {
    		LOG_ERR("Error, address not found");
    		return -ENOENT;
    	}
    
    	struct sockaddr_in *server4 = ((struct sockaddr_in *)&server);
    	server4->sin_addr.s_addr = ((struct sockaddr_in *)result->ai_addr)->sin_addr.s_addr;
    	server4->sin_family = AF_INET;
    	server4->sin_port = ((struct sockaddr_in *)result->ai_addr)->sin_port;
    
    	char ipv4_addr[NET_IPV4_ADDR_LEN];
    	inet_ntop(AF_INET, &server4->sin_addr.s_addr, ipv4_addr, sizeof(ipv4_addr));
    	LOG_INF("IPv4 address of HTTP server found %s", ipv4_addr);
    
    	freeaddrinfo(result);
    
    	return 0;
    }
    
    static int setup_credentials(void)
    {
    	
    	/* STEP 4.2 - Add the credential to the device */
    	int err = tls_credential_add(HTTP_TLS_SEC_TAG, TLS_CREDENTIAL_CA_CERTIFICATE, ca_certificate,
    				 sizeof(ca_certificate));
    	if (err < 0) {
    		LOG_ERR("Failed to add TLS credentials, err: %d", err);
    		return err;
    	}
    
    	return 0;
    }
    
    static int server_connect(void)
    {
    	int err;
    	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TLS_1_2);
    	if (sock < 0) {
    		LOG_ERR("Failed to create socket, err: %d, %s", errno, strerror(errno));
    		return -errno;
    	}
    
    	/* STEP 5.1 - Configure the socket with the security tag for the certificate */
    	sec_tag_t sec_tag_opt[] = {
    		HTTP_TLS_SEC_TAG,
    	};
    	err = setsockopt(sock, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_opt, sizeof(sec_tag_opt));
    	if (err < 0) {
    		LOG_ERR("Failed to set TLS security TAG list, err: %d", errno);
    		(void)close(sock);
    		return -errno;
    	}
    	/* STEP 5.2 - Configure the socket with the hostname of the HTTP server */
    	err = setsockopt(sock, SOL_TLS, TLS_HOSTNAME, HTTP_HOSTNAME, sizeof(HTTP_HOSTNAME));
    	if (err < 0) {
    		LOG_ERR("Failed to set TLS_HOSTNAME option. Err: %d", errno);
    		(void)close(sock);
    		return -errno;
    	}
    
    	err = connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_in));
    	if (err < 0) {
    		LOG_ERR("Connecting to server failed, err: %d, %s", errno, strerror(errno));
    		return -errno;
    	}
    
    	LOG_INF("Connected to server");
    	return 0;
    }
    
    static void response_cb(struct http_response *rsp, enum http_final_call final_data, void *user_data)
    {
    	/* STEP 9 - Define the callback function to print the body */
    	LOG_INF("Response status: %s", rsp->http_status);
    
    	if (rsp->body_frag_len > 0) {
    		char body_buf[rsp->body_frag_len];
    		strncpy(body_buf, rsp->body_frag_start, rsp->body_frag_len);
    		body_buf[rsp->body_frag_len] = '\0';
    		LOG_INF("Received: %s", body_buf);
    	}
    
    	LOG_INF("Closing socket: %d", sock);
    	close(sock);
    }
    
    static void client_id_cb(struct http_response *rsp, enum http_final_call final_data,
    			 void *user_data)
    {
    	/* STEP 6.1 - Log the HTTP response status */
    	LOG_INF("Response status: %s", rsp->http_status);
    
    	/* STEP 6.2 - Retrieve and format the client ID */
    	char client_id_buf_tmp[CLIENT_ID_SIZE + 1];
    	strncpy(client_id_buf_tmp, rsp->body_frag_start, CLIENT_ID_SIZE);
    	client_id_buf_tmp[CLIENT_ID_SIZE] = '\0';
    	client_id_buf[0] = '/';
    	strcat(client_id_buf, client_id_buf_tmp);
    
    	LOG_INF("Successfully acquired client ID: %s", client_id_buf);
    
    	/* STEP 6.3 - Close the socket */
    	LOG_INF("Closing socket: %d", sock);
    	close(sock);
    }
    
    static int client_http_put(void)
    {
    	/* STEP 7 - Define the function to send a PUT request to the HTTP server */
    	int err = 0;
    	int bytes_written;
    	const char *headers[] = {"Connection: close\r\n", NULL};
    
    	struct http_request req;
    	memset(&req, 0, sizeof(req));
    
    	char buffer[12] = {0};
    	bytes_written = snprintf(buffer, 12, "%d", counter);
    	if (bytes_written < 0) {
    		LOG_INF("Unable to write to buffer, err: %d", bytes_written);
    		return bytes_written;
    	}
    
    	req.header_fields = headers;
    	req.method = HTTP_PUT;
    	req.url = client_id_buf;
    	req.host = HTTP_HOSTNAME;
    	req.protocol = "HTTP/1.1";
    	req.payload = buffer;
    	req.payload_len = bytes_written;
    	req.response = response_cb;
    	req.recv_buf = recv_buf;
    	req.recv_buf_len = sizeof(recv_buf);
    
    	LOG_INF("HTTP PUT request: %s", buffer);
    	err = http_client_req(sock, &req, 5000, NULL);
    	if (err < 0) {
    		LOG_ERR("Failed to send HTTP PUT request %s, err: %d", buffer, err);
    	}
    
    	return err;
    }
    
    static int client_http_get(void)
    {
    	/* STEP 8 - Define the function to send a GET request to the HTTP server */
    	int err = 0;
    	const char *headers[] = {"Connection: close\r\n", NULL};
    	
    	struct http_request req;
    	memset(&req, 0, sizeof(req));
    
    	req.header_fields = headers;
    	req.method = HTTP_GET;
    	req.url = client_id_buf;
    	req.host = HTTP_HOSTNAME;
    	req.protocol = "HTTP/1.1";
    	req.response = response_cb;
    	req.recv_buf = recv_buf;
    	req.recv_buf_len = sizeof(recv_buf);
    
    	LOG_INF("HTTP GET request");
    	err = http_client_req(sock, &req, 5000, NULL);
    	if (err < 0) {
    		LOG_ERR("Failed to send HTTP GET request, err: %d", err);
    	}
    
    	return err;
    }
    
    static int client_get_new_id(void)
    {
    	int err = 0;
    
    	/* STEP 5.1 - Define the structure http_request and fill the block of memory */
    	struct http_request req;
    	memset(&req, 0, sizeof(req));
    
    	/* STEP 5.2 - Populate the http_request structure */
    	const char *headers[] = {"Connection: close\r\n", NULL};
    	req.header_fields = headers;
    	req.method = HTTP_POST;
    	req.url =  "/new";"https://api.nexkey.com";
    	req.host = HTTP_HOSTNAME;
    	req.protocol = "HTTP/1.1";
    	req.response = client_id_cb;
    	req.recv_buf = recv_buf;
    	req.recv_buf_len = sizeof(recv_buf);
    
    	/* STEP 5.3 - Send the request to the HTTP server */
    	LOG_INF("HTTP POST request");
    	err = http_client_req(sock, &req, 5000, NULL);
    	if (err < 0) {
    		LOG_ERR("Failed to send HTTP POST request, err: %d", err);
    	}
    	return err;
    }
    
    /* STEP 6.2 - Define the callback function for network events */
    static void net_mgmt_event_handler(struct net_mgmt_event_callback *cb,
    			  uint32_t mgmt_event, struct net_if *iface)
    {
    	if ((mgmt_event & EVENT_MASK) != mgmt_event) {
    		return;
    	}
    	if (mgmt_event == NET_EVENT_L4_CONNECTED) {
    		LOG_INF("Network connected");
    		connected = true;
    		dk_set_led_on(DK_LED1);
    		//k_sem_give(&run_app);
    		return;
    	}
    	if (mgmt_event == NET_EVENT_L4_DISCONNECTED) {
    		if (connected == false) {
    			LOG_INF("Waiting for network to be connected");
    		} else {
    			dk_set_led_off(DK_LED1);
    			LOG_INF("Network disconnected");
    			connected = false;
    		}
    		//k_sem_reset(&run_app);
    		return;
    	}
    }
    
    /* STEP 7 - Define the function to populate the Wi-Fi credential parameters */
    //static int wifi_args_to_params(struct wifi_connect_req_params *params)
    //{
    
    	/* STEP 7.1 Populate the SSID and password */
    	//params->ssid = CONFIG_WIFI_CREDENTIALS_STATIC_SSID;
    	//params->ssid_length = strlen(params->ssid);
    
    	//params->psk = CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD;
    	//params->psk_length = strlen(params->psk);
    
    	/* STEP 7.2 - Populate the rest of the relevant members */
    	//params->channel = WIFI_CHANNEL_ANY;
    	//params->security = WIFI_SECURITY_TYPE_PSK;
    	//params->mfp = WIFI_MFP_OPTIONAL;
    	//params->timeout = SYS_FOREVER_MS;
    	//params->band = WIFI_FREQ_BAND_UNKNOWN;
    	//#if NCS_VERSION_NUMBER > 0x20600
    	//memset(params->bssid, 0, sizeof(params->bssid));
    	//#endif
    	//return 0;
    //}
    
    static struct wifi_credentials_personal wifi_cred;
    void set_wifi_credentials_struct() 
    {
    
    	char *wifi_ssid = "realme";
    	char *wifi_password = "Chirag@1527";
    
    	wifi_cred.header.type = WIFI_SECURITY_TYPE_PSK;
    	memset(wifi_cred.header.bssid, 0, sizeof(wifi_cred.header.bssid));
    	wifi_cred.header.flags = 0;
    	//wifi_cred.header.channel = WIFI_CHANNEL_ANY;
    	//wifi_cred.header.timeout = 10;
    
    	wifi_cred.header.ssid_len = strlen(wifi_ssid);
    	memcpy(wifi_cred.header.ssid, wifi_ssid, wifi_cred.header.ssid_len);
    	
    	wifi_cred.password_len = strlen(wifi_password);
    	memcpy(wifi_cred.password, wifi_password, wifi_cred.password_len);
    
    	int ret = wifi_credentials_set_personal_struct(&wifi_cred);
    
    	if (ret != 0) {
    		LOG_ERR("Failed to set credentials, err: %d", ret);
    	}
    }
    static void button_handler(uint32_t button_state, uint32_t has_changed)
    {
    	/* STEP 10 - Define the button handler to send requests upon button triggers */
    	if (has_changed & DK_BTN1_MSK && button_state & DK_BTN1_MSK) {
    		if (server_connect() >= 0) {
    			client_http_put();
    			counter++;
    		}
    	} else if (has_changed & DK_BTN2_MSK && button_state & DK_BTN2_MSK) {
    		if (server_connect() >= 0) {
    			client_http_get();
    		}
    	}
    }
    static const char lorem_ipsum[] =
    	"Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
    	"Vestibulum ultricies sapien tellus, ac viverra dolor bibendum "
    	"lacinia. Vestibulum et nisl tristique tellus finibus gravida "
    	"vitae sit amet nunc. Suspendisse maximus justo mi, vitae porta "
    	"risus suscipit vitae. Curabitur ut fringilla velit. Donec ac nisi "
    	"in dui semper lobortis sed nec ante. Sed nec luctus dui. Sed ut "
    	"ante nisi. Mauris congue euismod felis, et maximus ex pellentesque "
    	"nec. Proin nibh nisl, semper at nunc in, mattis pharetra metus. Nam "
    	"turpis risus, pulvinar sit amet varius ac, pellentesque quis purus."
    	" "
    	"Nam consequat purus in lacinia fringilla. Morbi volutpat, tellus "
    	"nec tempus dapibus, ante sem aliquam dui, eu feugiat libero diam "
    	"at leo. Sed suscipit egestas orci in ultrices. Integer in elementum "
    	"ligula, vel sollicitudin velit. Nullam sit amet eleifend libero. "
    	"Proin sit amet consequat tellus, vel vulputate arcu. Curabitur quis "
    	"lobortis lacus. Sed faucibus vestibulum enim vel elementum. Vivamus "
    	"enim nunc, auctor in purus at, aliquet pulvinar eros. Cras dapibus "
    	"nec quam laoreet sagittis. Quisque dictum ante odio, at imperdiet "
    	"est convallis a. Morbi mattis ut orci vitae volutpat."
    	"\n";
    #define SERVER_ADDR4 "192.0.2.2"
    #define SERVER_PORT 9001
    #define MAX_RECV_BUF_LEN (sizeof(lorem_ipsum) - 1)
    #define EXTRA_BUF_SPACE 30
    static uint8_t temp_recv_buf_ipv4[MAX_RECV_BUF_LEN + EXTRA_BUF_SPACE];
    
    static int setup_socket(sa_family_t family, const char *server, int port,
    			int *sock, struct sockaddr *addr, socklen_t addr_len)
    {
    	const char *family_str = family == AF_INET ? "IPv4" : "IPv6";
    	int ret = 0;
    
    	memset(addr, 0, addr_len);
    
    	//if (family == AF_INET) {
    		net_sin(addr)->sin_family = AF_INET;
    		net_sin(addr)->sin_port = htons(port);
    		inet_pton(family, server, &net_sin(addr)->sin_addr);
    	// } else {
    	// 	net_sin6(addr)->sin6_family = AF_INET6;
    	// 	net_sin6(addr)->sin6_port = htons(port);
    	// 	inet_pton(family, server, &net_sin6(addr)->sin6_addr);
    	// }
    
    	// if (IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS)) {
    	// 	sec_tag_t sec_tag_list[] = {
    	// 		CA_CERTIFICATE_TAG,
    	// 	};
    
    	// 	*sock = socket(family, SOCK_STREAM, IPPROTO_TLS_1_2);
    	// 	if (*sock >= 0) {
    	// 		ret = setsockopt(*sock, SOL_TLS, TLS_SEC_TAG_LIST,
    	// 				 sec_tag_list, sizeof(sec_tag_list));
    	// 		if (ret < 0) {
    	// 			LOG_ERR("Failed to set %s secure option (%d)",
    	// 				family_str, -errno);
    	// 			ret = -errno;
    	// 			goto fail;
    	// 		}
    
    	// 		ret = setsockopt(*sock, SOL_TLS, TLS_HOSTNAME,
    	// 				 TLS_PEER_HOSTNAME,
    	// 				 sizeof(TLS_PEER_HOSTNAME));
    	// 		if (ret < 0) {
    	// 			LOG_ERR("Failed to set %s TLS_HOSTNAME "
    	// 				"option (%d)", family_str, -errno);
    	// 			ret = -errno;
    	// 			goto fail;
    	// 		}
    	// 	}
    	// } else {
    		*sock = socket(family, SOCK_STREAM, IPPROTO_TCP);
    	//}
    
    	if (*sock < 0) {
    		LOG_ERR("Failed to create %s HTTP socket (%d)", family_str,
    			-errno);
    	}
    
    	return ret;
    
    fail:
    	if (*sock >= 0) {
    		close(*sock);
    		*sock = -1;
    	}
    
    	return ret;
    }
    static int connect_cb(int sock, struct http_request *req, void *user_data)
    {
    	LOG_INF("Websocket %d for %s connected.", sock, (char *)user_data);
    
    	return 0;
    }
    static int connect_socket(sa_family_t family, const char *server, int port,
    			  int *sock, struct sockaddr *addr, socklen_t addr_len)
    {
    	int ret;
    
    	ret = setup_socket(family, server, port, sock, addr, addr_len);
    	if (ret < 0 || *sock < 0) {
    		return -1;
    	}
    
    	ret = connect(*sock, addr, addr_len);
    	if (ret < 0) {
    		LOG_ERR("Cannot connect to %s remote (%d)",
    			family == AF_INET ? "IPv4" : "IPv6",
    			-errno);
    		ret = -errno;
    	}
    
    	return ret;
    }
    int main(void)
    {
    	/* STEP 8.1 - Declare the variable for the network configuration parameters */
    	//struct wifi_connect_req_params cnx_params;
    
    
    
    	/* STEP 8.2 - Get the network interface */
    	struct net_if *iface = net_if_get_first_wifi();
    	if (iface == NULL) {
    		LOG_ERR("Returned network interface is NULL");
    		return -1;
    	}
    
    	if (dk_leds_init() != 0) {
    		LOG_ERR("Failed to initialize the LED library");
    	}
    
    	/* Sleep to allow initialization of Wi-Fi driver */
    	k_sleep(K_SECONDS(1));
    
    	/* STEP 9 - Initialize and add the callback function for network events */
    	net_mgmt_init_event_callback(&mgmt_cb, net_mgmt_event_handler, EVENT_MASK);
    	net_mgmt_add_event_callback(&mgmt_cb);
    
    	/* STEP 10 - Populate cnx_params with the network configuration */
    	//wifi_args_to_params(&cnx_params);
    
        set_wifi_credentials_struct();
    	/* STEP 11 - Call net_mgmt() to request the Wi-Fi connection */
    	LOG_INF("Connecting to Wi-Fi");
    	//printf("try to connect with wifi");
    	//LOG_ERR("buttons library");
    	//int err = net_mgmt(NET_REQUEST_WIFI_CONNECT_STORED, iface, &wifi_cred, sizeof(struct wifi_credentials_personal));
    	//LOG_ERR("buttons library");
    	// if (err) {
    	// 	LOG_ERR("Connecting to Wi-Fi failed, err: %d", err);
    	// 	//return ENOEXEC;
    	// }
    
    	//k_sem_take(&run_app, K_FOREVER);
    
    	if (dk_buttons_init(button_handler) != 0) {
    		LOG_ERR("Failed to initialize the buttons library ");
    	}
    	while(1)
    	{
    		//LOG_ERR("Failed to initialize the buttons library ");
    		k_sleep(K_SECONDS(1));
    		if(!connected)
    		{
    			int err = net_mgmt(NET_REQUEST_WIFI_CONNECT_STORED, iface, &wifi_cred, sizeof(struct wifi_credentials_personal));
    		}
    		if(connected && firsttime == 1)
    		{
    			k_sleep(K_SECONDS(1));
    			if (server_resolve() != 0) {
    				LOG_ERR("Failed to resolve server name");
    				return 0;
    			}
    			
    			if (setup_credentials() != 0) {
    		        LOG_ERR("Setup credentials failed");
    	        }
    
    			if (server_connect() != 0) {
    				LOG_ERR("Failed to initialize client");
    				return 0;
    			}	
    
    			/* STEP 11 - Retrieve the client ID upon connection */
    			if (client_get_new_id() < 0) {
    				LOG_ERR("Failed to get client ID");
    				return 0;
    			}
    			firsttime = 0;
    			//LOG_ERR("buttons library");
    		
    		const char *extra_headers[] = 
    		{
    			"Origin: http://foobar\r\n",
    			NULL
    	    };
    		int sock4 = -1, sock6 = -1;
    		int websock4 = -1, websock6 = -1;
    		int32_t timeout = 3 * MSEC_PER_SEC;
    		struct sockaddr_in6 addr6;
    		struct sockaddr_in addr4;
    		size_t amount;
    		int ret;
    
    		//if (IS_ENABLED(CONFIG_NET_IPV4)) 
    		{
    					(void)connect_socket(AF_INET, SERVER_ADDR4, SERVER_PORT,
    				     &sock4, (struct sockaddr *)&addr4,
    				     sizeof(addr4));
    		}
    	
    	if (sock4 < 0) {
    		LOG_ERR("Cannot create HTTP connection.");
    		k_sleep(K_FOREVER);
    	}
    
    	//if (sock4 >= 0 && IS_ENABLED(CONFIG_NET_IPV4)) 
    	{
    		struct websocket_request req;
    
    		memset(&req, 0, sizeof(req));
    
    		req.host = SERVER_ADDR4;
    		req.url = "/";
    		req.optional_headers = extra_headers;
    		req.cb = connect_cb;
    		req.tmp_buf = temp_recv_buf_ipv4;
    		req.tmp_buf_len = sizeof(temp_recv_buf_ipv4);
    
    		websock4 = websocket_connect(sock4, &req, timeout, "IPv4");
    		if (websock4 < 0) {
    			LOG_ERR("Cannot connect to %s:%d", SERVER_ADDR4,
    				SERVER_PORT);
    			close(sock4);
    		}
    	}
    	if (websock4 < 0)
    	 {
    		LOG_ERR("No IPv4 or IPv6 connectivity");
    		k_sleep(K_FOREVER);
    	}
    
    	LOG_INF("Websocket IPv4 %d IPv6 %d", websock4, websock6);
    
    
    
    		//return 0;
    	}
      }
    		
    }

    prj.conf file

    # Wi-Fi
    CONFIG_WIFI=y
    CONFIG_WIFI_NRF700X=y
    CONFIG_WPA_SUPP=y
    # CONFIG_WPA_SUPP_CRYPTO_PSA=y
    
    # Wi-Fi Credentials
    CONFIG_WIFI_CREDENTIALS=y
    CONFIG_WIFI_CREDENTIALS_STATIC=n
    
    # Networking Management API
    CONFIG_NET_MGMT=y
    CONFIG_NET_MGMT_EVENT=y
    CONFIG_NET_MGMT_EVENT_INFO=y
    CONFIG_NET_MGMT_EVENT_STACK_SIZE=4096
    CONFIG_NET_CONNECTION_MANAGER=y
    CONFIG_WIFI_MGMT_EXT=y
    
    # Support for shell commands
    # CONFIG_SHELL=y
    # CONFIG_WIFI_CREDENTIALS_SHELL=y
    # CONFIG_SHELL_STACK_SIZE=4400
    
    # Logging
    CONFIG_LOG=y
    
    # DK library
    CONFIG_DK_LIBRARY=y
    
    # System settings
    CONFIG_NEWLIB_LIBC=y
    CONFIG_NEWLIB_LIBC_NANO=n
    
    # Networking
    CONFIG_NETWORKING=y
    CONFIG_NET_NATIVE=y
    CONFIG_NET_SOCKETS=y
    CONFIG_NET_SOCKETS_POSIX_NAMES=y
    CONFIG_POSIX_MAX_FDS=16
    
    CONFIG_NET_L2_ETHERNET=y
    CONFIG_NET_IPV4=y
    CONFIG_NET_IPV6=y
    CONFIG_NET_TCP=y
    CONFIG_NET_DHCPV4=y
    CONFIG_DNS_RESOLVER=y
    
    # TLS
    # STEP 1.1 - Enable the TLS library and security relevant configurations
    CONFIG_NET_SOCKETS_SOCKOPT_TLS=y
    CONFIG_TLS_CREDENTIALS=y
    CONFIG_MBEDTLS_RSA_C=y
    CONFIG_MBEDTLS_DHM_C=y 
    
    # STEP 1.2 - Enable support for server name indication (SNI)
    CONFIG_MBEDTLS_SSL_SERVER_NAME_INDICATION=y
    
    # Memory
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096
    CONFIG_MAIN_STACK_SIZE=4096
    CONFIG_HEAP_MEM_POOL_SIZE=153600
    
    CONFIG_NET_TCP_WORKQ_STACK_SIZE=2048
    CONFIG_NET_TX_STACK_SIZE=4096
    CONFIG_NET_RX_STACK_SIZE=4096
    CONFIG_NET_BUF_RX_COUNT=16
    CONFIG_NET_BUF_TX_COUNT=16
    CONFIG_NET_BUF_DATA_SIZE=256
    CONFIG_NET_TC_TX_COUNT=0
    
    # HTTP
    CONFIG_HTTP_CLIENT=y
    # For storing Wi-Fi credentials
    CONFIG_WIFI_CREDENTIALS_BACKEND_SETTINGS=y
    CONFIG_FLASH=y
    CONFIG_FLASH_PAGE_LAYOUT=y
    CONFIG_FLASH_MAP=y
    CONFIG_NVS=y
    CONFIG_SETTINGS=y
    CONFIG_SETTINGS_NVS=y
    
    # CONFIG_NET_L2_WIFI_SHELL=y
    
    # General
    CONFIG_POSIX_CLOCK=y
    
    # Optimize Wi-Fi stack to save some memory
    
    CONFIG_NRF700X_MAX_TX_AGGREGATION=4
    
    # Wi-Fi
    
    CONFIG_WIFI_NRF700X_LOG_LEVEL_ERR=y
    
    # WPA supplicant
    
    CONFIG_WPA_SUPP_LOG_LEVEL_ERR=y
    
    # Zephyr NET Connection Manager connectivity layer
    CONFIG_L2_WIFI_CONNECTIVITY=y
    # CONFIG_L2_WIFI_CONNECTIVITY_AUTO_DOWN=n
    # CONFIG_L2_WIFI_CONNECTIVITY_AUTO_CONNECT=n
    
    # DNS
    
    # CONFIG_NET_SOCKETS_DNS_TIMEOUT=30000
    
    # NET sockets
    
    CONFIG_NET_UDP=y
    # CONFIG_NET_SOCKETS_OFFLOAD=n
    
    # CONFIG_NET_CONTEXT_SNDTIMEO=y
    
    # TLS networking
    CONFIG_NET_SOCKETS_ENABLE_DTLS=n
    CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=2
    
    
    # TLS credentials
    
    # Here is the overlay I used for nrf7002dk_nrf5340_cpuapp
    
    # CONFIG_TLS_CREDENTIALS_BACKEND_VOLATILE=y
    
    # mbedTLS
    CONFIG_NRF_SECURITY=y
    CONFIG_MBEDTLS=y
    CONFIG_MBEDTLS_ENABLE_HEAP=y
    CONFIG_MBEDTLS_HEAP_SIZE=81920
    CONFIG_PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY=y
    CONFIG_PSA_WANT_RSA_KEY_SIZE_2048=y
    
    CONFIG_MBEDTLS_TLS_LIBRARY=y
    
    CONFIG_PM_SINGLE_IMAGE=y
    
    
    CONFIG_WEBSOCKET_CLIENT=y

Children
  • Hi,

    It seems to me that there are 2 different issues - integration of wi-fi with websocket_client and then integration of this with https_client sample. Is this correct?

    For wi-fi shell and websocket integration, your previous log showed

    <inf> wpa_supp: Successfully initialized wpa_supplicant
    <err> wpa_supp: eloop: select: Not enough space

    This looks like the WPA supplicant has not started yet because of the memory issue "Not enough space". Other issues coming after are printed due to network being down. From your previous project configuration you should remove CONFIG_NET_SOCKETS_POLL_MAX=4 because in the cases where supplicant is enabled default value is 6.

    Best regards,
    Dejan

  • Hi,

    In my previous reply, I shared code where I successfully connected to Wi-Fi and established internet access. I was also able to connect to the HTTP host, but I encountered issues when trying to connect to the WebSocket host.

    also i disable the http portion from the code and try to connect with WebSocket host but i am not able to connect with it.

    Could you please review my code and provide feedback to help me resolve the WebSocket connection issue?

  • Hi,

    Can you send your project so that I can try to reproduce the error?

    Best regards,
    Dejan

  • Hi,

    I have tried to replicate your issue, but I was unsuccessful. I have built your application on Windows 10 using nrf7002dk board and built for nrf7002dk_nrf5340_cpuapp in NCS v2.6.1. I have changed only wifi_ssid and wifi_password to reflect my ssid and password.
    Here is my log

    *** Booting nRF Connect SDK v3.5.99-ncs1-1 ***
    [00:00:02.040,771] <inf> wifi_mgmt_ext: Connection requested
    [00:00:02.041,534] <inf> Lesson5_Exercise1: Connecting to Wi-Fi
    [00:00:04.604,827] <inf> wifi_mgmt_ext: Connection requested
    [00:00:07.173,156] <inf> wifi_mgmt_ext: Connection requested
    [00:00:09.741,699] <inf> wifi_mgmt_ext: Connection requested


    Are there any other changes to the project required for it to be built successfully?

    Best regards,
    Dejan

Related