This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Open Thread : No packets available, Data buffer allocations failed (Possible Radio driver issue)

Hello,

I will try to explain my whole network setup along with the issues that i face for better understanding. But please help me because the application is just halted because of this issue.

Thread Network Setup: I am having 3 FTD running in my current network. One acing as COAP server while other two are acting as COAP client sending sensor data on light topic. The update interval for each sensor is set to 200ms. So my server will receive data from both client device on light topic at 200ms rate. In my current application code, both my client device is using multicast address to send data to server. The client server examples are based on COAP Client Server demo examples given in SDK.

Real Issue when experimented in Industry/Inhouse testing

In Industry

I installed two Full Thread devices nRF2840 DK in textile factory, one running as COAP client attached to a machine and another running as COAP server acting as leader (connected to RPi to log sensor data over USB). So for around 2 days approx i was able to recieve data (24x7) on RPi but suddenly the i am not getting any data on my leader device connected to RPi. Other device connected to machine is supplied via USB, so power supply isn't the issue. The distance between 2 nodes was just around 17-18 meter max (not exactly LOS).
In the RPi terminal, i ran the following commands:
ot state - > leader
ot scan -> Empty (Shouldn't this give it's own network entry ?)
 

In Office Premisies

So i start my setup with my COAP server FTD device as leader and turning on other 2 COAP Client FTD devices. 2 FTD starts uploading sensor data on /light URI (default given in example) and my server is just printing out data on terminal whatever is received on URI. Everything works fine at the start for say 20~22 hours everything runs smoothly. After that sometimes it happens that my FTD COAP client device stop uploading data on the server, basically getting disconnected from the network even at a close range. Normally it should reconnect to the network but it doesn't What could be the possible reason for the above. I have posted the same issue on google group for open thread they say it could be possible issue of radio driver. Can you please confirm the same. 

I have attached my coap_client.c and coap_clients_util.c file of my application project. Please have a look at it, and notify me if you find any issue with the application code. 

/*
 * Copyright (c) 2020 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
 */

#include <zephyr.h>
#include <dk_buttons_and_leds.h>
#include <logging/log.h>
#include <ram_pwrdn.h>
#include <device.h>

#include "coap_client_utils.h"

#if CONFIG_BT_NUS
#include "ble_utils.h"
#endif
#include <net/openthread.h>
#include <openthread/thread.h>
#if CONFIG_USB
#include <drivers/uart.h>
#include <usb/usb_device.h>
#endif


#if CONFIG_NFC_T4T_NRFXLIB
#include <nfc_t4t_lib.h>
#include <nfc/ndef/text_rec.h>
#include "ndef_file_m.h"
#include <nfc/ndef/msg.h>
#include "nfc_Parser.h"
#endif
#include <devicetree.h>
#include <drivers/gpio.h>
#include "sensor.h"
#include "pmic.h"
#include <stdio.h>

LOG_MODULE_REGISTER(coap_client, CONFIG_COAP_CLIENT_LOG_LEVEL);

#define CONSOLE_LABEL DT_LABEL(DT_CHOSEN(zephyr_console))


volatile bool is_connected;

#define OT_CONNECTION_LED DK_LED3
#define BLE_CONNECTION_LED DK_LED4
#define MTD_SED_LED DK_LED3
#define LIGHT_LED DK_LED1
#define SENSOR_UPDATE_INTERVAL K_MSEC(200)   //K_MSEC(50)    //K_SECONDS(10) 
bool         SHT_Enable      = false;
bool         BME_Enable      = false;
bool         LPS22H1B_Enable = false;
bool         SI1151_Enable   = false;
bool         LSM6DSOX_Enable = false;
//bool         MP34DT05_Enable = false;
unsigned long     m_counter       = 0;

struct device *i2c_dev;
struct device *i2c_dev1;
//float features[210];
static struct k_delayed_work coapcloud_work;


/**
 * @brief   Function for enable MOSFET Trigger for sensor.
 * @return Nothing
 */
void MOSFET_ENABLE()
{
	const struct device *gpio_dev1;

		gpio_dev1 = device_get_binding("GPIO_1");

       if (gpio_dev1 == NULL) {
		return;
	   }

      gpio_pin_configure(gpio_dev1, 8, GPIO_OUTPUT_INACTIVE| 1);
      gpio_pin_set(gpio_dev1, 8,0); //0 --on
}

/**
 * @brief   Function for disable MOSFET Trigger for sensor.
   @return Nothing
 */
void MOSFET_DISABLE()
{
	const struct device *gpio_dev1;

		gpio_dev1 = device_get_binding("GPIO_1");

       if (gpio_dev1 == NULL) {
		return;
	    }

      gpio_pin_configure(gpio_dev1, 8, GPIO_OUTPUT_INACTIVE| 1);
      gpio_pin_set(gpio_dev1, 8,1); //      1--- off
}

#if CONFIG_NFC_T4T_NRFXLIB

static struct k_delayed_work update_flash;

#define NFC_FIELD_LED		DK_LED3
#define NFC_WRITE_LED		DK_LED3
#define NFC_READ_LED		DK_LED3

#define NDEF_MSG_BUF_SIZE	128

static uint8_t ndef_msg_buf[CONFIG_NDEF_FILE_SIZE]; /**< Buffer for NDEF file. */

uint32_t len = sizeof(ndef_msg_buf);

enum {
	FLASH_WRITE_FINISHED,
	FLASH_BUF_PREP_STARTED,
	FLASH_BUF_PREP_FINISHED,
	FLASH_WRITE_STARTED,
};

static atomic_t op_flags;
static uint8_t flash_buf[40]; /**< Buffer for flash update. */
static uint8_t flash_buf_len; /**< Length of the flash buffer. */

static void flash_buffer_prepare(size_t data_length)
{
	if (atomic_cas(&op_flags, FLASH_WRITE_FINISHED,
			FLASH_BUF_PREP_STARTED)) {
		flash_buf_len = data_length + NLEN_FIELD_SIZE;
		memcpy(flash_buf, ndef_msg_buf, sizeof(flash_buf));

		atomic_set(&op_flags, FLASH_BUF_PREP_FINISHED);
	} else {
		LOG_INF("Flash update pending. Discarding new data...\n");
	}

}

/**
 * @brief   Function for update  channel and panid  .
   @return Nothing
 */
static void flash_update(struct k_work *item)
{
	if (atomic_cas(&op_flags, FLASH_BUF_PREP_FINISHED,
				FLASH_WRITE_STARTED)) {
			if (ndef_file_update(flash_buf, flash_buf_len) < 0) {
				LOG_INF("Cannot flash NDEF message!\n");
			} else {
		    nfcParser(ndef_msg_buf+2);
			LOG_INF("NDEF message successfully flashed \n");
			}

			atomic_set(&op_flags, FLASH_WRITE_FINISHED);
		}
	 k_delayed_work_submit(&update_flash, K_SECONDS(1));
}
/**
 * @brief Callback function for handling NFC events.
 */
static void nfc_callback(void *context,
			 enum nfc_t4t_event event,
			 const uint8_t *data,
			 size_t data_length,
			 uint32_t flags)
{
	ARG_UNUSED(context);
	ARG_UNUSED(data);
	ARG_UNUSED(flags);

	switch (event) {
	case NFC_T4T_EVENT_FIELD_ON:
		dk_set_led_on(NFC_FIELD_LED);
		break;

	case NFC_T4T_EVENT_FIELD_OFF:
		dk_set_leds(NFC_FIELD_LED);
		break;

	case NFC_T4T_EVENT_NDEF_READ:
		dk_set_led_on(NFC_FIELD_LED);
		break;

	case NFC_T4T_EVENT_NDEF_UPDATED:
		if (data_length > 0) {
			dk_set_led_on(NFC_READ_LED);
			flash_buffer_prepare(data_length);
		}
		break;

	default:
		break;
	}
}
#endif /*CONFIG_NFC_T4T_NRFXLIB*/

#if defined (CONFIG_SENSOR_BME680)
struct bme680_dev gas_sensor;
struct bme680_field_data data;
void user_delay_ms(uint32_t period)
{
   k_msleep(period);
}

void IO_init()
{
  i2c_init();
  gas_sensor.dev_id = BME680_I2C_ADDR_SECONDARY;
  gas_sensor.intf = BME680_I2C_INTF;
  gas_sensor.read = user_i2c_read;
  gas_sensor.write = user_i2c_write;
  gas_sensor.delay_ms = user_delay_ms;
  gas_sensor.amb_temp = 25;
   bme680_init(&gas_sensor);
    /* Set the temperature, pressure and humidity settings */
    gas_sensor.tph_sett.os_hum = BME680_OS_2X;
    gas_sensor.tph_sett.os_pres = BME680_OS_4X;
    gas_sensor.tph_sett.os_temp = BME680_OS_8X;
    gas_sensor.tph_sett.filter = BME680_FILTER_SIZE_3;

    /* Set the remaining gas sensor settings and link the heating profile */
    gas_sensor.gas_sett.run_gas = BME680_ENABLE_GAS_MEAS;
    /* Create a ramp heat waveform in 3 steps */
    gas_sensor.gas_sett.heatr_temp = 320; /* degree Celsius */
    gas_sensor.gas_sett.heatr_dur = 150; /* milliseconds */

    /* Select the power mode */
    /* Must be set before writing the sensor configuration */
    gas_sensor.power_mode = BME680_FORCED_MODE; 
}
#endif /*CONFIG_SENSOR_BME680*/

 
int32_t i2c_init()
{
  i2c_dev = device_get_binding("I2C_1");
    if (!i2c_dev) {
            printk("I2C: Device driver not found.\n");

    }
  i2c_configure(i2c_dev, I2C_SPEED_SET(I2C_SPEED_STANDARD)| I2C_MODE_MASTER);
    return 0;

}

#if defined (CONFIG_SENSOR_BME680)
int8_t user_i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
{
    int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */
    if(i2c_burst_read(i2c_dev,dev_id,reg_addr,reg_data,len) < 0)   
    {
      LOG_INF("error_bme_read\r\n");
      return -1;
    }
    return rslt;
}

int8_t user_i2c_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
{
    int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */
    if(i2c_burst_write(i2c_dev,dev_id,reg_addr,reg_data,len) < 0)   
    {
      LOG_INF("error_bme_read\r\n");
      return -1;
    }
    return rslt;
}
#endif /*CONFIG_SENSOR_BME680*/

#if defined (CONFIG_SENSOR_LSM6DSOX)
static stmdev_ctx_t dev_ctx;
static int32_t platform_write(void *handle, uint8_t reg, uint8_t *bufp,
                              uint16_t len)
{
    i2c_burst_write(i2c_dev,LSM6DSOX_I2C_ADD_L,reg,bufp,len);
    return 0;
}

static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp,
                             uint16_t len)
{
    i2c_burst_read(i2c_dev,LSM6DSOX_I2C_ADD_L,reg,bufp,len);
    return 0;
}

void LSM6DSOX_init()
{

     i2c_init();
     dev_ctx.write_reg = platform_write;
     dev_ctx.read_reg = platform_read;

     k_msleep(BOOT_TIME);
     lsm6dsox_device_id_get(&dev_ctx, &whoamI);

    

     lsm6dsox_reset_set(&dev_ctx, PROPERTY_ENABLE);
     do {
      lsm6dsox_reset_get(&dev_ctx, &rst);
     }while (rst);
  
     /* Disable I3C interface */
     lsm6dsox_i3c_disable_set(&dev_ctx, LSM6DSOX_I3C_DISABLE);
       /* Enable Block Data Update */
     lsm6dsox_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);
     /* Set Output Data Rate */
     lsm6dsox_xl_data_rate_set(&dev_ctx, LSM6DSOX_XL_ODR_104Hz);
     lsm6dsox_gy_data_rate_set(&dev_ctx, LSM6DSOX_GY_ODR_104Hz);
     /* Set full scale */
     lsm6dsox_xl_full_scale_set(&dev_ctx, LSM6DSOX_16g);
     lsm6dsox_gy_full_scale_set(&dev_ctx, LSM6DSOX_2000dps);
}

void lsm6dsox_data_read()
{
 
  /* Read acceleration field data */
  memset(data_raw_acceleration.u8bit, 0x00, 3 * sizeof(int16_t));
  lsm6dsox_acceleration_raw_get(&dev_ctx, data_raw_acceleration.u8bit);
  acceleration_mg[0] =
    lsm6dsox_from_fs2_to_mg(data_raw_acceleration.i16bit[0]);
  acceleration_mg[1] =
    lsm6dsox_from_fs2_to_mg(data_raw_acceleration.i16bit[1]);
  acceleration_mg[2] =
    lsm6dsox_from_fs2_to_mg(data_raw_acceleration.i16bit[2]);
   printf("%i %i %i\r\n",data_raw_acceleration.i16bit[0],
                                       data_raw_acceleration.i16bit[1],
                                       data_raw_acceleration.i16bit[2]);

		SENSOR_X=data_raw_acceleration.i16bit[0];
        SENSOR_Y=data_raw_acceleration.i16bit[1];
        SENSOR_Z=data_raw_acceleration.i16bit[2];

  /* Read angular rate field data */
  memset(data_raw_angular_rate.u8bit, 0x00, 3 * sizeof(int16_t));
  lsm6dsox_angular_rate_raw_get(&dev_ctx, data_raw_angular_rate.u8bit);
  angular_rate_mdps[0] =
    lsm6dsox_from_fs2000_to_mdps(data_raw_angular_rate.i16bit[0]);
  angular_rate_mdps[1] =
    lsm6dsox_from_fs2000_to_mdps(data_raw_angular_rate.i16bit[1]);
  angular_rate_mdps[2] =
    lsm6dsox_from_fs2000_to_mdps(data_raw_angular_rate.i16bit[2]);
    /*printf("angular rate : %i %i %i \r\n",data_raw_angular_rate.i16bit[0],
                                        data_raw_angular_rate.i16bit[1],
                                        data_raw_angular_rate.i16bit[2]);*/

    printf("\r\n");
}
#endif /*CONFIG_SENSOR_LSM6DSOX*/


#if defined(CONFIG_SENSOR_SI1151)

void getSensorData(void)
{
	// Start next measurement
	Si115xForce(&i2c_dev);
	Si115xHandler(&i2c_dev, &samples);
}

void proximityDemo(void)
{
   // i2c_init();
    static uint8_t proximityOrAls = SI1153_AA00_PROX_ALS;			//Chooses which demo to run
	char * demoName = "Proximity Demo";
	char ch0Str[17];
	int32_t lux;
	int32_t result;
	uint32_t mag;

	//Initialize the demo
		if(proximityOrAls == SI1153_AA00_PROX_ALS){
			Si115xInitProxAls(&i2c_dev, false);
			initialized = SI1153_AA00_PROX_ALS;
		}else if(proximityOrAls == SI1153_AA00_PROX){
			Si115xInitProxAls(&i2c_dev, true);
			initialized = SI1153_AA00_PROX;
		}

	if (proximityOrAls == SI1153_AA00_PROX)
	{
		result = (int32_t) samples.ch0;

		if(result < 0){
			result = 0;
		}


		if (result >= SENSOR_OVERFLOW_VALUE)
		{
			// Overflow occurred
			sprintf(ch0Str, "PROX OVERFLOW");
			mag = 1; // Use 1 because we want to draw a very small square
		}
		else
		{
			//Update display every 10 readings
			if(countsDisplayCounter%10 == 0)
				countsDisplay = (int32_t) result;
			// Display counts
			mag = (uint16_t) result;
			sprintf(ch0Str, "PROX %d COUNTS", (int)countsDisplay);
		}

		//Scale the reading and display a square
		mag /= 5;
		//GRAPHICS_DrawScreenSquare(mag);//, border);
	}
	else if(proximityOrAls == SI1153_AA00_PROX_ALS)// demo Ambient Light Sensing
	{
		// Calculate lux values
      
		lux = (uint32_t)Si1153_getLuxReading(0, &samples);
		demoName = "Ambient Light";
		//GRAPHICS_DrawLightbulb(lux);
		printf("ALS %d LUX\n", (int)lux);
		SENSOR_lux=(int)lux;
	}
}

#endif /*CONFIG_SENSOR_SI1151*/

int32_t i2c_dinit()
{
  return 0;
}


#if (CONFIG_SENSOR_SHT35||CONFIG_SENSOR_LPS22HH1B)

int32_t i2c_write_data(uint16_t adress,uint16_t reg, uint8_t *cmd, uint16_t len)
{
	#if (CONFIG_SENSOR_SHT35)
      i2c_write(i2c_dev,cmd,len,SHT35_I2C_ADDRESS_L);
  	#else
      i2c_burst_write(i2c_dev,ADC_SLAVE_ADDR,reg,cmd,len);
	#endif

   return 0; 
}

int32_t i2c_read_data(uint16_t adress, uint16_t reg, uint8_t *cmd, uint16_t len)
{
	 #if defined(CONFIG_SENSOR_SHT35)
       i2c_read(i2c_dev,cmd,len,SHT35_I2C_ADDRESS_L);
	  #else
       i2c_burst_read(i2c_dev,ADC_SLAVE_ADDR,reg,cmd,len);
     #endif

   return 0;
}

int32_t SHT35_GetTick()
{
  return k_uptime_get();
}

void IO_init()
{
   IO.Init =  i2c_init;  
   IO.DeInit = i2c_dinit;   
   IO.Address = SENSOR_I2C_ADDRESS_L;   
   IO.BusType = SENSOR_I2C_BUS;
   IO.WriteReg =  i2c_write_data; 
   IO.ReadReg =   i2c_read_data;
   #if defined(CONFIG_SENSOR_SHT35)
   IO.GetTick =  SHT35_GetTick ;
   #endif
}
#endif 

/*
*@brief Sensor init function.
*
*/
void  Sensor_init()
{
        
#if (CONFIG_SENSOR_SHT35||CONFIG_SENSOR_LPS22HH1B||CONFIG_SENSOR_BME680)
    IO_init(); 
#endif /*CONFIG_SENSOR_SHT35||CONFIG_SENSOR_LPS22HH1B||CONFIG_SENSOR_BME680*/

#if defined(CONFIG_SENSOR_SHT35)
        LOG_INF("*****Start SHT35_SENSOR Temperature AND HUMIDITY *****");
        SHT_Enable=true;
        SHT35_RegisterBusIO(&Obj, &IO);
#endif /*CONFIG_SENSOR_SHT35*/

#if defined(CONFIG_SENSOR_LPS22HH1B)
   LOG_INF("*****Start LPS22HH1B_SENSOR Temperature AND Pressure*****");
   LPS22H1B_Enable=true;
   LPS22HB_RegisterBusIO(&Obj, &IO);
   LPS22HB_Init(&Obj);
   LPS22HB_TEMP_Enable(&Obj);
   LPS22HB_PRESS_Enable(&Obj);
#endif /* CONFIG_SENSOR_LPS22HH1B */

#if defined(CONFIG_SENSOR_SI1151)
   LOG_INF("*****Start SI1151_SENSOR node  LIGHT AND UV *****");
   SI1151_Enable= true;
   i2c_init();
 
#endif /*CONFIG_SENSOR_SI1151*/

#if defined(CONFIG_SENSOR_BME680)
   LOG_INF("*****Start BME680_SENSOR node  Temperature  HUMIDITY Pressure AND GAS *****");
   BME_Enable=true;
   uint8_t set_required_settings;
    /* Set the required sensor settings needed */
    set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL 
        | BME680_GAS_SENSOR_SEL;
    /* Set the desired sensor configuration */
    bme680_set_sensor_settings(set_required_settings,&gas_sensor);
   /* Set the power mode */
   bme680_set_sensor_mode(&gas_sensor);
   uint16_t meas_period = 2000;
  bme680_get_profile_dur(&meas_period, &gas_sensor);
 
#endif	/*CONFIG_SENSOR_BME680*/

#if defined (CONFIG_SENSOR_LSM6DSOX)
    LOG_INF("*****Start LSM6DSOX  node  ACC x y z *****");
	LSM6DSOX_Enable=true;
    LSM6DSOX_init();
#endif /*CONFIG_SENSOR_LSM6DSOX*/

}
/* 
* @brief read  sensor value interval of SENSOR_UPDATE_INTERVAL
*/

static void upload(struct k_work *item)
{
	ARG_UNUSED(item);
       
      if(is_connected)
	   {		
		 #if defined(CONFIG_SENSOR_SHT35)
		   SHT35_getTemperature(&Obj,&SENSOR_TEMPRATURE);
           SHT35_getHumidity(&Obj,&SENSOR_HUMIDITY);
		   printf(" tem : %.2f hum : %.2f\r\n",SENSOR_TEMPRATURE,SENSOR_HUMIDITY);
		 #endif
		
		 #if defined(CONFIG_SENSOR_LPS22HH1B)
		   LPS22HB_Get_Temp(&Obj,&SENSOR_TEMPRATURE);
           LPS22HB_PRESS_GetPressure(&Obj,&SENSOR_PRESSURE);
		   printf(" tempratute : %.2f pressure : %.2f\r\n",SENSOR_TEMPRATURE,SENSOR_PRESSURE);

     	 #endif

		 #if defined(CONFIG_SENSOR_SI1151)
		   getSensorData();
		   proximityDemo();
         #endif
       
         #if defined(CONFIG_SENSOR_BME680)
           bme680_get_sensor_data(&data, &gas_sensor);
		   printf("T: %.2f degC, P: %.2f hPa, H %.2f %%rH\r\n ", data.temperature / 100.0f,
             data.pressure / 100.0f, data.humidity / 1000.0f );
		   if(data.status & BME680_GASM_VALID_MSK)
      		{
    			// printf(", G: %d ohms", data.gas_resistance);
				SENSOR_GAS        =  data.gas_resistance;
   			}
			SENSOR_TEMPRATURE =  data.temperature / 100.0f;
			SENSOR_HUMIDITY   =  data.humidity / 1000.0f;
			SENSOR_PRESSURE   =  data.pressure / 100.0f;
		 #endif

	     #if defined (CONFIG_SENSOR_LSM6DSOX)
	   
             lsm6dsox_data_read();
		 #endif
		}
       coap_client_toggle_mesh_lights();
       k_delayed_work_submit(&coapcloud_work, SENSOR_UPDATE_INTERVAL);
	
}


/* 
* @brief init  s_node peripheral
*@return nothing
*/

void S_node_peripheral_init()
{
MOSFET_ENABLE();
Sensor_init();

}

#if CONFIG_BT_NUS

#define COMMAND_REQUEST_UNICAST 'u'
#define COMMAND_REQUEST_MULTICAST 'm'
#define COMMAND_REQUEST_PROVISIONING 'p'



static void on_nus_received(struct bt_conn *conn, const uint8_t *const data,
			    uint16_t len)
{
	if (len != 1) {
		LOG_WRN("Received invalid data length (%hd) from NUS", len);
		return;
	}

	LOG_INF("Received data: %c", data[0]);

	switch (*data) {
	case COMMAND_REQUEST_UNICAST:
		coap_client_toggle_one_light();
		break;

	case COMMAND_REQUEST_MULTICAST:
		coap_client_toggle_mesh_lights();
		break;

	case COMMAND_REQUEST_PROVISIONING:
		coap_client_send_provisioning_request();
		break;

	default:
		LOG_WRN("Received invalid data from NUS");
	}
}


static void on_ble_connect(struct k_work *item)
{
	ARG_UNUSED(item);

	dk_set_led_on(BLE_CONNECTION_LED);
}

static void on_ble_disconnect(struct k_work *item)
{
	ARG_UNUSED(item);

	dk_set_led_off(BLE_CONNECTION_LED);
}

#endif /* CONFIG_BT_NUS */

static void on_ot_connect(struct k_work *item)
{
	ARG_UNUSED(item);

	dk_set_led_on(OT_CONNECTION_LED);
}

static void on_ot_disconnect(struct k_work *item)
{
	ARG_UNUSED(item);

	dk_set_led_off(OT_CONNECTION_LED);
}

static void on_mtd_mode_toggle(uint32_t med)
{
#if IS_ENABLED(CONFIG_DEVICE_POWER_MANAGEMENT)
	const struct device *cons = device_get_binding(CONSOLE_LABEL);

	if (med) {
		device_set_power_state(cons, DEVICE_PM_ACTIVE_STATE,
				       NULL, NULL);
	} else {
		device_set_power_state(cons, DEVICE_PM_OFF_STATE,
				       NULL, NULL);
	}
#endif
	dk_set_led(MTD_SED_LED, med);
}

static void on_button_changed(uint32_t button_state, uint32_t has_changed)
{
	uint32_t buttons = button_state & has_changed;

	if (buttons & DK_BTN4_MSK) {
		coap_client_toggle_one_light();
	}

	if (buttons & DK_BTN2_MSK) {
		coap_client_toggle_mesh_lights();
	}

	if (buttons & DK_BTN3_MSK) {
		coap_client_toggle_minimal_sleepy_end_device();
	}

	if (buttons & DK_BTN1_MSK) {
		//printf("button press 4\r\n");
		coap_client_send_provisioning_request();

	}
}


void main(void)
{
	int ret;
	/*USB enable */
#if defined(CONFIG_USB)
	const struct device *dev;
	uint32_t baudrate = 0U;

	dev = device_get_binding(
		CONFIG_UART_CONSOLE_ON_DEV_NAME);
	if (!dev) {
		LOG_ERR("UART device not found");
		return;
	}

	ret = usb_enable(NULL);
	if (ret != 0) {
		LOG_ERR("Failed to enable USB");
		return;
	}
    uart_line_ctrl_get(dev, UART_LINE_CTRL_BAUD_RATE, &baudrate);
	
	if (strlen(CONFIG_UART_CONSOLE_ON_DEV_NAME) !=
	    strlen("CDC_ACM_0") ||
	    strncmp(CONFIG_UART_CONSOLE_ON_DEV_NAME, "CDC_ACM_0",
		    strlen(CONFIG_UART_CONSOLE_ON_DEV_NAME))) {
		printk("Error: Console device name is not USB ACM\n");

		return;
	}
#endif /*CONFIG_USB*/


    S_node_peripheral_init();
    k_delayed_work_init(&coapcloud_work, upload);
    k_delayed_work_submit(&coapcloud_work, K_NO_WAIT); //UPDATE SENSOR DATA INTERVAL
	
#if CONFIG_NFC_T4T_NRFXLIB   /* NFC Enable*/

k_delayed_work_init(&update_flash, flash_update);
k_delayed_work_submit(&update_flash, K_NO_WAIT); 
	/* Initialize NVS. */
     ndef_file_setup();
	 	/* Set up NFC */
     nfc_t4t_setup(nfc_callback, NULL);
	 	/* Run Read-Write mode for Type 4 Tag platform */
	 nfc_t4t_ndef_rwpayload_set(ndef_msg_buf,sizeof(ndef_msg_buf)) ;
	 	/* Start sensing NFC field */
	 nfc_t4t_emulation_start();
#endif/*CONFIG_NFC_T4T_NRFXLIB*/
 
	if (IS_ENABLED(CONFIG_RAM_POWER_DOWN_LIBRARY)) {
		power_down_unused_ram();
	}

	ret = dk_buttons_init(on_button_changed);
	if (ret) {
		LOG_ERR("Cannot init buttons (error: %d)", ret);
		return;
	}

	ret = dk_leds_init();
	if (ret) {
		LOG_ERR("Cannot init leds, (error: %d)", ret);
		return;
	}

#if CONFIG_BT_NUS
	struct bt_nus_cb nus_clbs = {
		.received = on_nus_received,
		.sent = NULL,
	};

	ret = ble_utils_init(&nus_clbs, on_ble_connect, on_ble_disconnect);
	if (ret) {
		LOG_ERR("Cannot init BLE utilities");
		return;
	}

#endif /* CONFIG_BT_NUS */

	coap_client_utils_init(on_ot_connect, on_ot_disconnect,
			       on_mtd_mode_toggle);
}

/*
 * Copyright (c) 2020 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
 */

#include <zephyr.h>
#include <coap_server_client_interface.h>
#include <net/coap_utils.h>
#include <logging/log.h>
#include <net/openthread.h>
#include <net/socket.h>
#include <openthread/thread.h>
#include <stdio.h>
#include "coap_client_utils.h"

// #include "sensor.h"


LOG_MODULE_REGISTER(coap_client_utils, CONFIG_COAP_CLIENT_UTILS_LOG_LEVEL);

#define RESPONSE_POLL_PERIOD 100

static uint32_t poll_period;


static struct k_work unicast_light_work;
static struct k_work multicast_light_work;
static struct k_work toggle_MTD_SED_work;
static struct k_work provisioning_work;
static struct k_work on_connect_work;
static struct k_work on_disconnect_work;

mtd_mode_toggle_cb_t on_mtd_mode_toggle;

/* Options supported by the server */
static const char *const light_option[] = { LIGHT_URI_PATH, NULL };
static const char *const provisioning_option[] = { PROVISIONING_URI_PATH,
						   NULL };

/* Thread multicast mesh local address */
static struct sockaddr_in6 multicast_local_addr = {
	.sin6_family = AF_INET6,
	.sin6_port = htons(COAP_PORT),
	.sin6_addr.s6_addr = { 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
	.sin6_scope_id = 0U
};

/* Variable for storing server address acquiring in provisioning handshake */
static char unique_local_addr_str[INET6_ADDRSTRLEN];
static struct sockaddr_in6 unique_local_addr = {
	.sin6_family = AF_INET6,
	.sin6_port = htons(COAP_PORT),
	.sin6_addr.s6_addr = {0, },
	.sin6_scope_id = 0U
};

static bool is_mtd_in_med_mode(otInstance *instance)
{
	return otThreadGetLinkMode(instance).mRxOnWhenIdle;
}

static void poll_period_response_set(void)
{
	otError error;

	otInstance *instance = openthread_get_default_instance();

	if (is_mtd_in_med_mode(instance)) {
		return;
	}

	if (!poll_period) {
		poll_period = otLinkGetPollPeriod(instance);

		error = otLinkSetPollPeriod(instance, RESPONSE_POLL_PERIOD);
		__ASSERT(error == OT_ERROR_NONE, "Failed to set pool period");

		LOG_INF("Poll Period: %dms set", RESPONSE_POLL_PERIOD);
	}
}

static void poll_period_restore(void)
{
	otError error;
	otInstance *instance = openthread_get_default_instance();

	if (is_mtd_in_med_mode(instance)) {
		return;
	}

	if (poll_period) {
		error = otLinkSetPollPeriod(instance, poll_period);
		__ASSERT_NO_MSG(error == OT_ERROR_NONE);

		LOG_INF("Poll Period: %dms restored", poll_period);
		poll_period = 0;
	}
}

static int on_provisioning_reply(const struct coap_packet *response,
				 struct coap_reply *reply,
				 const struct sockaddr *from)
{
	int ret = 0;
	const uint8_t *payload;
	uint16_t payload_size = 0u;

	ARG_UNUSED(reply);
	ARG_UNUSED(from);

	payload = coap_packet_get_payload(response, &payload_size);

	if (payload == NULL ||
	    payload_size != sizeof(unique_local_addr.sin6_addr)) {
		LOG_ERR("Received data is invalid");
		ret = -EINVAL;
		goto exit;
	}

	memcpy(&unique_local_addr.sin6_addr, payload, payload_size);

	if (!inet_ntop(AF_INET6, payload, unique_local_addr_str,
		       INET6_ADDRSTRLEN)) {
		LOG_ERR("Received data is not IPv6 address: %d", errno);
		ret = -errno;
		goto exit;
	}

	LOG_INF("Received peer address: %s", log_strdup(unique_local_addr_str));

exit:
	if (IS_ENABLED(CONFIG_OPENTHREAD_MTD_SED)) {
		poll_period_restore();
	}

	return ret;
}

static void toggle_one_light(struct k_work *item)
{
	uint8_t payload = (uint8_t)THREAD_COAP_UTILS_LIGHT_CMD_TOGGLE;

	ARG_UNUSED(item);

	if (unique_local_addr.sin6_addr.s6_addr16[0] == 0) {
		LOG_WRN("Peer address not set. Activate 'provisioning' option "
			"on the server side");
		return;
	}

	LOG_INF("Send 'light' request to: %s",
		log_strdup(unique_local_addr_str));
	coap_send_request(COAP_METHOD_PUT,
			  (const struct sockaddr *)&unique_local_addr,
			  light_option, &payload, sizeof(payload), NULL);
}

/*
@brief send sensor data  on all CoAP servers in the network mesh.
 */

static void toggle_mesh_lights(struct k_work *item)
{
	
    static char sensor_buffer[120];
    
	ARG_UNUSED(item);
	/* send sensor data */
	#if defined (CONFIG_SENSOR_SHT35)
      sprintf(sensor_buffer,"%.2f,%.2f",SENSOR_TEMPRATURE,SENSOR_HUMIDITY);
	#endif

	#if defined (CONFIG_SENSOR_LSM6DSOX)
	  sprintf(sensor_buffer,"%i %i %i",SENSOR_X,SENSOR_Y,SENSOR_Z);
	#endif

	#if defined (CONFIG_SENSOR_LPS22HH1B)
	 sprintf(sensor_buffer,"%.2f %.2f",SENSOR_TEMPRATURE,SENSOR_PRESSURE);
    #endif

	#if defined (CONFIG_SENSOR_BME680)
	 sprintf(sensor_buffer,"%.2f %.2f %.2f",SENSOR_TEMPRATURE,SENSOR_PRESSURE,SENSOR_HUMIDITY);
    #endif

	#if defined (CONFIG_SENSOR_SI1151)
	sprintf(sensor_buffer,"ALS:%d",SENSOR_lux);
	#endif		
                   
            coap_send_request(COAP_METHOD_PUT,
			  (const struct sockaddr *)&multicast_local_addr,
			  light_option, &sensor_buffer, sizeof(sensor_buffer), NULL);
               
            memset(sensor_buffer,0x00,sizeof(sensor_buffer));
      	    // printk("data:%s\r\n",sensor_buffer);
	
}
/*
static void toggle_mesh_lights(struct k_work *item)
{
	static uint8_t command = (uint8_t)THREAD_COAP_UTILS_LIGHT_CMD_OFF;

	ARG_UNUSED(item);

	command = ((command == THREAD_COAP_UTILS_LIGHT_CMD_OFF) ?
			   THREAD_COAP_UTILS_LIGHT_CMD_ON :
			   THREAD_COAP_UTILS_LIGHT_CMD_OFF);

	LOG_INF("Send multicast mesh 'light' request");
	coap_send_request(COAP_METHOD_PUT,
			  (const struct sockaddr *)&multicast_local_addr,
			  light_option, &command, sizeof(command), NULL);
}*/

static void send_provisioning_request(struct k_work *item)
{
	ARG_UNUSED(item);

	if (IS_ENABLED(CONFIG_OPENTHREAD_MTD_SED)) {
		/* decrease the polling period for higher responsiveness */
		poll_period_response_set();
	}

	LOG_INF("Send 'provisioning' request");
	coap_send_request(COAP_METHOD_GET,
			  (const struct sockaddr *)&multicast_local_addr,
			  provisioning_option, NULL, 0u, on_provisioning_reply);
}

static void toggle_minimal_sleepy_end_device(struct k_work *item)
{
	otError error;
	otLinkModeConfig mode;
	struct openthread_context *context = openthread_get_default_context();

	__ASSERT_NO_MSG(context != NULL);

	openthread_api_mutex_lock(context);
	mode = otThreadGetLinkMode(context->instance);
	mode.mRxOnWhenIdle = !mode.mRxOnWhenIdle;
	error = otThreadSetLinkMode(context->instance, mode);
	openthread_api_mutex_unlock(context);

	if (error != OT_ERROR_NONE) {
		LOG_ERR("Failed to set MLE link mode configuration");
	} else {
		on_mtd_mode_toggle(mode.mRxOnWhenIdle);
	}
}

static void update_device_state(void)
{
	struct otInstance *instance = openthread_get_default_instance();
	otLinkModeConfig mode = otThreadGetLinkMode(instance);
	on_mtd_mode_toggle(mode.mRxOnWhenIdle);
}

static void on_thread_state_changed(uint32_t flags, void *context)
{
	struct openthread_context *ot_context = context;

	if (flags & OT_CHANGED_THREAD_ROLE) {
		switch (otThreadGetDeviceRole(ot_context->instance)) {
		case OT_DEVICE_ROLE_CHILD:
		case OT_DEVICE_ROLE_ROUTER:
		case OT_DEVICE_ROLE_LEADER:
			k_work_submit(&on_connect_work);
			is_connected = true;
			break;

		case OT_DEVICE_ROLE_DISABLED:
		case OT_DEVICE_ROLE_DETACHED:
		 default:
			k_work_submit(&on_disconnect_work);
			is_connected = false;
			break;
		}
	}
}

static void submit_work_if_connected(struct k_work *work)
{
	if (is_connected) {
		k_work_submit(work);
	} else {
		LOG_INF("Connection is broken");
		// printk("Node DETACHED\r\n");
	}
}
/*
@brief coap_client initlize function 
*/
void coap_client_utils_init(ot_connection_cb_t on_connect,
			    ot_disconnection_cb_t on_disconnect,
			    mtd_mode_toggle_cb_t on_toggle)
{
	on_mtd_mode_toggle = on_toggle;

	coap_init(AF_INET6, NULL);

	k_work_init(&on_connect_work, on_connect);
	k_work_init(&on_disconnect_work, on_disconnect);
	k_work_init(&unicast_light_work, toggle_one_light);
	k_work_init(&multicast_light_work, toggle_mesh_lights);
	k_work_init(&provisioning_work, send_provisioning_request);

	openthread_set_state_changed_cb(on_thread_state_changed);
	openthread_start(openthread_get_default_context());

	if (IS_ENABLED(CONFIG_OPENTHREAD_MTD_SED)) {
		k_work_init(&toggle_MTD_SED_work,
			    toggle_minimal_sleepy_end_device);
		update_device_state();
	}
}

void coap_client_toggle_one_light(void)
{
	submit_work_if_connected(&unicast_light_work);
}

void coap_client_toggle_mesh_lights(void)
{
	submit_work_if_connected(&multicast_light_work);
}

void coap_client_send_provisioning_request(void)
{
	submit_work_if_connected(&provisioning_work);
}

void coap_client_toggle_minimal_sleepy_end_device(void)
{
	if (IS_ENABLED(CONFIG_OPENTHREAD_MTD_SED)) {
		k_work_submit(&toggle_MTD_SED_work);
	}
}

In the above files we have just integrated demo COAP client examples with sensor code. Also the variable static bool is_connected  is moved to coap_client.c and changed to volatile bool is_connected. Rest is same as demo coap client example. Also the demo example just shows single client to server example, while in my case i have multiple client devices which will update(at rate 200ms)  the server with different sensor readings (one client connected one sensor only). And we are using the same light topic given in the example. Should we use multiple URI path for all clients or is it Okay to use single URI path ? If in case i have to use multiple URI, can you just guide me what are the steps to be taken on the COAP server side, COAP client side implementation seems easy.  

DEBUGGING from my Side

So to find where is the bug, is it in my application code or is it in SDK i created a demo example based on COAP client just like above where i am updating data from 2 COAP client devices on single COAP server with multicast addressing used and update interval fixed to 200ms. Also with the same URI path as used in the demo examples. I am just updating dummy strings in this example instead of sensor data.

I left one of my COAP client in debugging mode with Logs enabled at Info level, while other COAP client was battery powered and my COAP server also in debgging mode connected to other PC. So debug was on all night, in morning i saw a  error message in my console which states "No packets available, Data buffer allocations failed." Also my server was receiving data in morning, from this own COAP client device which got this error message. 

Below are the Logs from the Console:

I: nRF5 802154 radio initialized
I: 8 Sectors of 4096 bytes
I: alloc wra: 4, 9c0
I: data wra: 4, 8c0
I: State changed! Flags: 0x101fc310 Current role: 0
*** Booting Zephyr OS build v2.4.99-ncs2  ***
I: Start CoAP-client sample
I: Connection is broken
D: CoAP socket receive thread started
I: OpenThread version: OPENTHREAD/gaad6518ee; Zephyr; Jul 20 2021 18:09:35
I: Network name: ot_zephyr
I: State changed! Flags: 0x0100103d Current role: 1
I: Connection is broken
I: Connection is broken
I: Connection is broken
I: Connection is broken
I: State changed! Flags: 0x100010e5 Current role: 4
I: State changed! Flags: 0x00000200 Current role: 4
E: No pkt available
E: Data buffer (127) allocation failed.
E: No pkt available
E: Data buffer (73) allocation failed.
E: No pkt available
I: Device suspended
I: Device disconnected

So what could be the possible reasons why my COAP devices gets disconnected from the network and isn't able to join back to the network. I need to solve this issue in urgent to deliver to client.     

Google Open Thread topics which suggest that this can be possible radio driver issue:

Google Thread Group Topics for Reference:

https://groups.google.com/g/openthread-users/c/xXGOnl9bOWU

https://groups.google.com/g/openthread-users/c/TIQr6Z2GbKA

https://groups.google.com/g/openthread-users/c/s2JkPxNK4j8/m/UYHr_dPuCAAJ

Parents Reply Children
No Data
Related