Network outage detection

I am using MS12SF1 (nrf5340+nrf7002). I integrated wifi and able to connect and disconnect with it but the issue is that if there is situation in which the router is ON (means there will be signal strength) but there is no network or very unstable network in that case it doesn't jump to any specific event.

For eg: I switched ON my device and connected it to the wifi, it got connected and was running than while it was running I removed the lan cable from the router but it didn't do anything 
Only the tasks related to server started generating errors. I have attached the .c and .h files which includes wifi connectivity.

Please let me know if there is any separate event which can be triggered if such kind of issue happens

#include "uh_wifi.h"
#include "uh_gpio.h"
#include "uh_fota.h"

#define EVENT_MASK (NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED)				//indicates that connection at transport layer has been successfully established, completion of tcp connection

#define WIFI_SHELL_MGMT_EVENTS (NET_EVENT_WIFI_CONNECT_RESULT |	NET_EVENT_WIFI_DISCONNECT_RESULT)			// specific to wifi layer,tells the result of wifi connection attempt, any failure like cred err or ap not found comes under this 
				


LOG_MODULE_REGISTER(home_demo_wifi, LOG_LEVEL_INF);

struct net_mgmt_event_callback mgmt_cb;

static struct net_mgmt_event_callback wifi_shell_mgmt_cb;


struct wifi_status *status;

int wifi_strength;

volatile uint8_t incorrect_password_flag = 0;

// struct k_sem run_app;

extern char log_array[400];
extern char tokens[2][100];
extern volatile bool connected_wifi;

extern char nvs_ssid[32],nvs_pw[64];
extern uint8_t wifi_trial_count;

extern k_tid_t wifi_reconnect_thread_id;
extern struct k_thread reconnect_thread;

extern char wifi_cred[200];
extern uint8_t ble_receive_cred_flag;

//Variable for logs

uint8_t wifi_status_code;

K_SEM_DEFINE(run_app, 0, 2);
// Declare a semaphore to signal Wi-Fi reconnection
K_SEM_DEFINE(wifi_reconnect_sem, 0, 1);

K_THREAD_STACK_DEFINE(wifi_reconnect_stack_area, 4096/*data_offloading_thread_STACKSIZE*/);


void switch_wifiCred_thread_init()
{
	wifi_reconnect_thread_id = k_thread_create(&reconnect_thread, wifi_reconnect_stack_area, K_THREAD_STACK_SIZEOF(wifi_reconnect_stack_area), wifi_reconnect_thread,
                              NULL, NULL, NULL, 5, 0, K_FOREVER);
  	k_thread_name_set(wifi_reconnect_thread_id, "ReconnectThread");   
  	k_thread_start(&reconnect_thread);
}


void wifi_mgmt_event_handler(struct net_mgmt_event_callback *cb,
				     uint32_t mgmt_event, struct net_if *iface)
{
	int err;

	if ((mgmt_event & WIFI_SHELL_MGMT_EVENTS) != mgmt_event) {
		return;
	}
	if(mgmt_event == NET_EVENT_WIFI_CONNECT_RESULT)
	{
		// handle_wifi_connect_result(cb);
		err = cmd_wifi_status();

		if(err < 0)
		{
			LOG_ERR("Connection failed %d, check password", err);
		}

		return;

	}

	if(mgmt_event == NET_EVENT_WIFI_DISCONNECT_RESULT)
	{
		return -WIFI_DISCONNECTED;
	}	

}


void net_mgmt_event_handler(struct net_mgmt_event_callback *cb,
			  uint32_t mgmt_event, struct net_if *iface)
{
	int err; 

	if ((mgmt_event & EVENT_MASK) != mgmt_event) {
		return;
	}
	if (mgmt_event == NET_EVENT_L4_CONNECTED) {
		err = cmd_wifi_status();
		if(err == 1)
		{
			white_color_off();
			gpio_pin_set_dt(&led2, 0);						//green led turns on when connected

			wifi_trial_count = 0;
			ble_receive_cred_flag = 0;
			// strcpy(log_array, "Network connected");			// Need to send error code to app instead of Network connected
			connected_wifi = 1;
			strcpy(log_array, "1");			// Need to send error code to app instead of Network connected
			logging_func(log_array);
			memset(log_array, 0, sizeof(log_array));
			LOG_INF("Network connected: %d",err);

			wifi_status_code = WIFI_CONNECTED_STATE;
			k_sem_give(&run_app);
		}	
	}

	if (mgmt_event == NET_EVENT_L4_DISCONNECTED) {		
		gpio_pin_set_dt(&led2, 1);				//green led off and startup led gets on
		white_color_on();

		apply_state(IDLE);

		// strcpy(log_array, "Network disconnected");
		connected_wifi = 0;
		LOG_INF("Network disconnected");
		wifi_status_code = WIFI_DISCONNECTED_STATE;
		strcpy(log_array, "Network disconnected");			// Need to send error code to app instead of Network connected
		logging_func(log_array);
		memset(log_array, 0, sizeof(log_array));
		k_sem_reset(&run_app);			
	}
	
}

int wifi_args_to_params(struct wifi_connect_req_params *params)
{
	int err;

	if(tokens[0][0] != '\0' && tokens[1][0] != '\0') {
		LOG_INF("Entered into tokens condition");
		LOG_INF("Tokens[0] value: %s",tokens[0]);
		LOG_INF("Tokens[1] value: %s",tokens[1]);
		params->ssid = tokens[0];
		params->ssid_length = strlen(tokens[0]);
		params->psk = tokens[1];
		params->psk_length = strlen(tokens[1]);	
	  
		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;
    
		memset(tokens[0], '\0', sizeof(tokens[0]));
		memset(tokens[1], '\0', sizeof(tokens[1]));
    }
	else {
		LOG_INF("Entered into nvs condition");
		LOG_INF("nvs ssid value: %s",nvs_ssid);
	 	LOG_INF("nvs_pw value: %s",nvs_pw);
		params->ssid = nvs_ssid;
		params->ssid_length = strlen(params->ssid);
		params->psk = nvs_pw;
		params->psk_length = strlen(params->psk);
		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;
	}
	return 0;
}

int connect_wifi(void)
{
	int err = 0;
	static struct wifi_connect_req_params cnx_params;
	struct net_if *iface = net_if_get_first_wifi();
	if(iface == NULL) {
		LOG_ERR("Returned network interface is NULL");
		return -1;
	}

	net_if_up(iface);

	err = wifi_args_to_params(&cnx_params);
	if (err<0) {
		LOG_ERR("Credentials entered is smaller in length %d",err);
		return err;
	} else {
		LOG_INF("Wi-Fi interface is up");
	}

	err = net_mgmt(NET_REQUEST_WIFI_CONNECT, iface, &cnx_params, sizeof(struct wifi_connect_req_params));
	if (err) {
		LOG_ERR("Connecting to Wi-Fi failed, err: %d", err);
		if(err == -134){
			wifi_status_code = CONNECTING_TO_WIFI_FAILED;
		}
		else{
			wifi_status_code = CONNECTING_TO_WIFI_FAILED_OTHER_ERR;
		}
		
		return err;
	}
	else
	{
		return 0;
	}
	
}

void wifi_callbacks_init(void)
{
    net_mgmt_init_event_callback(&mgmt_cb, net_mgmt_event_handler, EVENT_MASK);
    net_mgmt_add_event_callback(&mgmt_cb);
	net_mgmt_init_event_callback(&wifi_shell_mgmt_cb,
				     wifi_mgmt_event_handler,
				     WIFI_SHELL_MGMT_EVENTS);

	net_mgmt_add_event_callback(&wifi_shell_mgmt_cb);

	
}

int cmd_wifi_status(void)
{
	struct net_if *iface = net_if_get_first_wifi();
	struct wifi_iface_status status = {0};
	// struct wifi_status error_status;

	if (net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, iface, &status,
					sizeof(struct wifi_iface_status)))
	{
			LOG_INF("Status request failed");

			return -ENOEXEC;
	}

	LOG_INF("==================");
	LOG_INF("State: %s", wifi_state_txt(status.state));
	snprintk(log_array, sizeof(log_array), "State: %s", wifi_state_txt(status.state));
	logging_func(log_array);
	memset(log_array, 0, sizeof(log_array));

	wifi_strength = status.rssi;
		
	snprintk(log_array, sizeof(log_array), "RSSI: %d", status.rssi);
	logging_func(log_array);
	memset(log_array, 0, sizeof(log_array));

	if (status.state == WIFI_STATE_COMPLETED) {
		uint8_t mac_string_buf[sizeof("xx:xx:xx:xx:xx:xx")];

		LOG_INF("Interface Mode: %s",
				wifi_mode_txt(status.iface_mode));
		LOG_INF("Link Mode: %s",
				wifi_link_mode_txt(status.link_mode));
		LOG_INF("SSID: %-32s", status.ssid);
		LOG_INF("BSSID: %s",
				net_sprint_ll_addr_buf(
					status.bssid, WIFI_MAC_ADDR_LEN,
					mac_string_buf, sizeof(mac_string_buf)));
		LOG_INF("Band: %s", wifi_band_txt(status.band));
		LOG_INF("Channel: %d", status.channel);
		LOG_INF("Security: %s", wifi_security_txt(status.security));
		LOG_INF("MFP: %s", wifi_mfp_txt(status.mfp));
		LOG_INF("RSSI: %d", status.rssi);

		// wifi_strength = status.rssi;
		
		// snprintk(log_array, sizeof(log_array), "RSSI: %d", status.rssi);
		// logging_func(log_array);
		// memset(log_array, 0, sizeof(log_array));
		
		return WIFI_CONNECTION_SUCCESSFUL;
	}
	else if(status.state >= WIFI_STATE_4WAY_HANDSHAKE && status.state != WIFI_STATE_GROUP_HANDSHAKE) {
		// error_status.conn_status = WIFI_STATUS_CONN_WRONG_PASSWORD;
		strcpy(log_array, "-2");			// Need to send error code to app instead of Network connected
		logging_func(log_array);
		memset(log_array, 0, sizeof(log_array));

		incorrect_password_flag = 1;

		wifi_status_code = INCORRECT_PASSWORD;

		disconnect_wifi();
		// return -WIFI_INCORRECT_PASSWORD;
	}
}

int disconnect_wifi(void)
{
	int err;
	struct net_if *iface = net_if_get_first_wifi();
	if(iface == NULL) {
		LOG_ERR("Returned network interface is NULL");
		return -1;
	}

	err = net_mgmt(NET_REQUEST_WIFI_DISCONNECT, iface, NULL, 0);
	if (err) {
		LOG_ERR("Disconnecting from Wi-Fi failed, err: %d", err);
		wifi_status_code = DISCONNECTING_FROM_WIFI_FAILED;
		return err;
	}
	else
	{
		connected_wifi = 0;
		return 0;
	}

	// Bring the interface down
    net_if_down(iface);
}

int wifi_connect_trial(int trial_count)
{
	int wifi_flag = 0;

	while(connected_wifi == 0 && wifi_trial_count <= trial_count && incorrect_password_flag == 0) {
		cmd_wifi_status();
		LOG_INF("Wi-Fi connection in progress");
        if(wifi_trial_count == WIFI_TRIAL_LIMIT) {
			LOG_INF("** No. of trials exceeded **");
			strcpy(log_array, "** No. of trials exceeded **\n");
			logging_func(log_array);
			memset(log_array, 0, sizeof(log_array));

			wifi_status_code = NO_OF_TRIALS_EXCEEDED;
			k_sem_give(&run_app);
			return -WIFI_CONNECT_TIMEOUT;
		}
        wifi_flag = connect_wifi();
        if(!wifi_flag){
            LOG_INF("Successfully got wifi cred");
			strcpy(log_array, "Successfully got the wifi credentials now trying to connect");
			logging_func(log_array);
			memset(log_array, 0, sizeof(log_array));
		}
		else
		{
            LOG_INF("Wifi cred failed!!");
			snprintk(log_array, sizeof(log_array), "Getting Wifi credentials failed: %d",wifi_flag);
			logging_func(log_array);
			memset(log_array, 0, sizeof(log_array));
		}
		wifi_trial_count+=1;
		
        k_sleep(K_SECONDS(10)); // Retry every 10 seconds
	}
	
}

// Wi-Fi Reconnection Thread
void wifi_reconnect_thread(void)
{
    while (1) {
        // Wait until the semaphore is given (from the BLE callback)
        k_sem_take(&wifi_reconnect_sem, K_FOREVER);

		//when wifi is switched within the same location
		if(connected_wifi == 1 && ble_receive_cred_flag == 1) {
			LOG_INF("Same loca, wifi switch case, disconnecting wifi");

			wifi_status_code = WIFI_RECONNECTION;
			 // Handle Wi-Fi reconnection outside the BLE callback
			disconnect_wifi();
			wifi_connect_trial(30);

			LOG_INF("Wi-Fi reconnection attempted");
		}
		//when wifi is switched when location is changed
		else if(connected_wifi == 0 && ble_receive_cred_flag == 1){
			LOG_INF("Location change case, entering into wifi cred");
			wifi_connect_trial(30);
		}

		k_sleep(K_MSEC(500));
    }
}

void reset_wifi_trials(void)
{
	wifi_trial_count = 0;
}

int reconnect_wifi(void)
{
	LOG_INF("Reconnecting Wi-Fi");
	struct net_if *iface;
	static struct wifi_connect_req_params cnx_params;
	int err;

    // Get the default Wi-Fi interface
    iface = net_if_get_first_wifi();
    if (!iface) {
        LOG_INF("No Wi-Fi interface found\n");
        return;
    }

    // Disconnect from Wi-Fi
    err = net_mgmt(NET_REQUEST_WIFI_DISCONNECT, iface, NULL, 0);
    if (err) {
        LOG_INF("Failed to disconnect from Wi-Fi: %d\n", err);
        return err;
    }

    // Bring the interface down
    net_if_down(iface);
    
    // Wait for a bit or perform other tasks, if needed
    k_sleep(K_SECONDS(1));

    // Bring the interface back up
    err = net_if_up(iface);
	LOG_INF("Interface state: %d", err);

	wifi_args_to_params(&cnx_params);

	 k_sleep(K_SECONDS(1));

	err = net_mgmt(NET_REQUEST_WIFI_CONNECT, iface, &cnx_params, sizeof(struct wifi_connect_req_params));
	if (err) {
		LOG_ERR("Connecting to Wi-Fi failed, err: %d", err);
		return err;
	}
	else {
		return 0;
	}
}
uh_wifi.h

Related