void ble_agsensor_create_sensor_read_data_msg(void) {

	hvx_p_config_len = 0;
	(hvx_p_config_len) += uint16_encode(BLE_AGSENSOR_CONFIGURATION_OPCODE_START_MEASUREMENT, &hvx_encoded_buffer[hvx_p_config_len]);

	// Add the sensor count in the sending msg
	uint8_t indice = sentek_measurement_get_Indice_toSend();
	hvx_encoded_buffer[hvx_p_config_len] = indice;
	hvx_p_config_len ++;

	// Add the time-stamp value in the sending msg
	(hvx_p_config_len) += uint32_encode(sentek_get_measurement(indice, SENTEK_RESULT_DATA_TIMESTAMP), &hvx_encoded_buffer[hvx_p_config_len]);

	// Add the temperature value in the sending msg
	uint32_t temp = sentek_get_measurement_float(indice, SENTEK_RESULT_DATA_TEMPERATURE);
//	char* tempfloat = &temp;
	(hvx_p_config_len) += uint32_encode(temp, &hvx_encoded_buffer[hvx_p_config_len]);

	// Add the moisture value in the sending msg
//	(hvx_p_config_len) += uint32_encode(sentek_get_measurement(indice, SENTEK_RESULT_DATA_MOISTURE), &hvx_encoded_buffer[hvx_p_config_len]);
	(hvx_p_config_len) += uint32_encode(sentek_get_measurement_float(indice, SENTEK_RESULT_DATA_MOISTURE), &hvx_encoded_buffer[hvx_p_config_len]);

	// Add the salinity value in the sending msg
//	(hvx_p_config_len) += uint32_encode(sentek_get_measurement(indice, SENTEK_RESULT_DATA_SALINITY), &hvx_encoded_buffer[hvx_p_config_len]);
	(hvx_p_config_len) += uint32_encode(sentek_get_measurement_float(indice, SENTEK_RESULT_DATA_SALINITY), &hvx_encoded_buffer[hvx_p_config_len]);
}
/**@brief Function for encoding a ITU Sensor Service Measurement.
 *
 * @param[in]   p_iss			         ITU Sensor Service structure.
 * @param[in]   measurement        Measurement to be encoded.
 * @param[out]  p_encoded_buffer   Buffer where the encoded data will be written.
 *
 * @return      Size of encoded data.
 */
static uint8_t iss_measurement_encode(iss_t * p_iss, int32_t * measurement,uint8_t * p_encoded_buffer,uint32_t * value)
{
    uint8_t flags = 0;
    uint8_t len   = 1;
	
		//Value always present
		*value = (((p_iss->IEEE_exponent << 24) & 0xFF000000) | (*measurement & 0x00FFFFFF));
		len += uint32_encode(*value, &p_encoded_buffer[len]);
		
		//Remember, to increament the seq nr so we have a continuous flow
		++(p_iss->curr_seq_nr);
	
		// Space + Time value
    if (p_iss->space_time_present)
    {
        flags |= ITS_MEAS_FLAG_SPACE_TIME_BIT;
				p_encoded_buffer[len++]  = p_iss->coord;
        len   += uint16_encode(p_iss->curr_seq_nr, &p_encoded_buffer[len]);
    }
	
    // Unit value
    if (p_iss->unit_present)
    {
        flags |= ITS_MEAS_FLAG_UNIT_BIT;
        len   += uint16_encode(p_iss->unit, &p_encoded_buffer[len]);
		}
		
		// Type value
    if (p_iss->type_make_present)
    {
        flags |= ITS_MEAS_FLAG_TYPE_MAKE_BIT;
        p_encoded_buffer[len++]  = p_iss->type;
				p_encoded_buffer[len++]  = p_iss->make;
		}
		
		// ID field
    if (p_iss->ID_present)
    {
        flags |= ITS_MEAS_FLAG_ID_BIT;
        len   += uint16_encode(p_iss->ID, &p_encoded_buffer[len]);
    }
		
		// Sampling Frequency field
    if (p_iss->samp_freq_present)
    {
        flags |= ITS_MEAS_FLAG_SAMP_FREQ_BIT;
        len   += uint32_encode(p_iss->samp_freq_in_m_sec, &p_encoded_buffer[len]);
    }

    // Flags field
    p_encoded_buffer[0] = flags;

    return len;
}
예제 #3
0
static void response_send(serial_dfu_t          * p_dfu,
                          serial_dfu_response_t * p_response)
{
    uint8_t response_buffer[MAX_RESPONSE_SIZE];
    uint8_t encoded_response[MAX_RESPONSE_SIZE*2 + 1];
    uint32_t encoded_response_length;

    uint16_t index = 0;

    NRF_LOG_DEBUG("Sending Response: [0x%01x, 0x%01x]\r\n", p_response->op_code, p_response->resp_val);

    response_buffer[index++] = SERIAL_DFU_OP_CODE_RESPONSE;

    // Encode the Request Op code
    response_buffer[index++] = p_response->op_code;

    // Encode the Response Value.
    response_buffer[index++] = (uint8_t)p_response->resp_val;

    if (p_response->resp_val == NRF_DFU_RES_CODE_SUCCESS)
    {
        switch (p_response->op_code)
        {
            case SERIAL_DFU_OP_CODE_CALCULATE_CRC:
                index += uint32_encode(p_response->crc_response.offset, &response_buffer[index]);
                index += uint32_encode(p_response->crc_response.crc, &response_buffer[index]);
                break;

            case SERIAL_DFU_OP_CODE_SELECT_OBJECT:
                index += uint32_encode(p_response->select_response.max_size, &response_buffer[index]);
                index += uint32_encode(p_response->select_response.offset, &response_buffer[index]);
                index += uint32_encode(p_response->select_response.crc, &response_buffer[index]);
                break;

            case SERIAL_DFU_OP_CODE_GET_SERIAL_MTU:
                index += uint16_encode(p_response->serial_mtu_response.mtu, &response_buffer[index]);
                break;

            default:
                // no implementation
                break;
        }
    }

    // encode into slip
    (void)slip_encode(encoded_response, response_buffer, index, &encoded_response_length);

    // send
    (void)nrf_drv_uart_tx(&p_dfu->uart_instance, encoded_response, encoded_response_length);
}
예제 #4
0
/**@brief Function for encoding a CSCS Measurement.
 *
 * @param[in]   p_cscs              Cycling Speed and Cadence Service structure.
 * @param[in]   p_csc_measurement   Measurement to be encoded.
 * @param[out]  p_encoded_buffer    Buffer where the encoded data will be written.
 *
 * @return      Size of encoded data.
 */
static uint8_t csc_measurement_encode(ble_cscs_t *       p_cscs,
                                      ble_cscs_meas_t *  p_csc_measurement,
                                      uint8_t *          p_encoded_buffer)
{
    uint8_t flags = 0;
    uint8_t len   = 1;

    // Cumulative Wheel Revolutions and Last Wheel Event Time Fields
    if (p_cscs->feature & BLE_CSCS_FEATURE_WHEEL_REV_BIT)
    {
        if (p_csc_measurement->is_wheel_rev_data_present)
        {
            flags |= CSC_MEAS_FLAG_MASK_WHEEL_REV_DATA_PRESENT;
            len += uint32_encode(p_csc_measurement->cumulative_wheel_revs, &p_encoded_buffer[len]);
            len += uint16_encode(p_csc_measurement->last_wheel_event_time, &p_encoded_buffer[len]);
        }
    }
    
    // Cumulative Crank Revolutions and Last Crank Event Time Fields
    if (p_cscs->feature & BLE_CSCS_FEATURE_CRANK_REV_BIT)
    {
        if (p_csc_measurement->is_crank_rev_data_present)
        {
            flags |= CSC_MEAS_FLAG_MASK_CRANK_REV_DATA_PRESENT;
            len += uint16_encode(p_csc_measurement->cumulative_crank_revs, &p_encoded_buffer[len]);
            len += uint16_encode(p_csc_measurement->last_crank_event_time, &p_encoded_buffer[len]);
        }
    }
    
    // Flags Field
    p_encoded_buffer[0] = flags;
    
    return len;
}
예제 #5
0
uint32_t ble_dfu_pkts_rcpt_notify(ble_dfu_t * p_dfu, uint32_t num_of_firmware_bytes_rcvd)
{
    if (p_dfu == NULL)
    {
        return NRF_ERROR_NULL;
    }

    if ((p_dfu->conn_handle == BLE_CONN_HANDLE_INVALID) || !m_is_dfu_service_initialized)
    {
        return NRF_ERROR_INVALID_STATE;
    }

    ble_gatts_hvx_params_t hvx_params;
    uint16_t               index = 0;

    m_notif_buffer[index++] = OP_CODE_PKT_RCPT_NOTIF;

    index += uint32_encode(num_of_firmware_bytes_rcvd, &m_notif_buffer[index]);

    memset(&hvx_params, 0, sizeof(hvx_params));

    hvx_params.handle = p_dfu->dfu_ctrl_pt_handles.value_handle;
    hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
    hvx_params.offset = 0;
    hvx_params.p_len  = &index;
    hvx_params.p_data = m_notif_buffer;

    return sd_ble_gatts_hvx(p_dfu->conn_handle, &hvx_params);
}
예제 #6
0
uint32_t ble_rpc_cmd_resp_send(uint8_t op_code, uint32_t status)
{
    uint8_t * p_buffer;
    uint32_t  err_code;
    uint32_t  index = 0;

    // Allocate a memory buffer from HCI transport layer for transmitting the Command Response.
    // Loop until a buffer is available.
    do
    {    
        err_code = hci_transport_tx_alloc(&p_buffer);
    }
    while (err_code == NRF_ERROR_NO_MEM);

    if (err_code == NRF_SUCCESS)
    {
        // Encode packet type.
        p_buffer[index++] = BLE_RPC_PKT_RESP;

        // Encode Op Code.
        p_buffer[index++] = op_code;

        // Encode Status.
        index += uint32_encode(status, &(p_buffer[RPC_CMD_RESP_STATUS_POS]));

        return hci_transport_pkt_write(p_buffer, index);
    }

    return err_code;
}
예제 #7
0
void ant_sdm_page_16_encode(uint8_t                     * p_page_buffer,
                            ant_sdm_common_data_t const * p_common_data)
{
    ant_sdm_page16_data_layout_t * p_outcoming_data = (ant_sdm_page16_data_layout_t *)p_page_buffer;

    UNUSED_PARAMETER(uint24_encode(p_common_data->strides, p_outcoming_data->strides));
    UNUSED_PARAMETER(uint32_encode(p_common_data->distance << 4, p_outcoming_data->distance));

    page_16_data_log(p_common_data);
}
/**@brief Function for encoding a ITU Sensor Service Configuration.
 *
 * @param[in]   p_iss			         ITU Sensor Service structure.
 * @param[out]  p_encoded_buffer   Buffer where the encoded data will be written.
 *
 * @return      Size of encoded data.
 */
static uint8_t its_conf_encode(iss_t * p_iss, uint8_t * p_encoded_buffer)
{
		uint8_t pres_flags = 0;
    uint8_t len   = 1;
		
	/*
    // Sequence number field
    if (p_iss->space_time_present)
    {
        pres_flags |= ITS_MEAS_FLAG_SPACE_TIME_BIT;
    }
	
		// Unit value
    if (p_iss->unit_present)
    {
        pres_flags |= ITS_MEAS_FLAG_UNIT_BIT;
		}
		
		// Type value
    if (p_iss->type_make_present)
    {
        pres_flags |= ITS_MEAS_FLAG_TYPE_MAKE_BIT;
		}
		
		// ID field
    if (p_iss->ID_present)
    {
        pres_flags |= ITS_MEAS_FLAG_ID_BIT;
    }
		
		// Sampling Frequency field
    if (p_iss->samp_freq_present)
    {
        pres_flags |= ITS_MEAS_FLAG_SAMP_FREQ_BIT;
    }*/
		
		pres_flags |= ITS_MEAS_FLAG_SPACE_TIME_BIT;
		pres_flags |= ITS_MEAS_FLAG_UNIT_BIT;
		pres_flags |= ITS_MEAS_FLAG_TYPE_MAKE_BIT;
		pres_flags |= ITS_MEAS_FLAG_ID_BIT;
		pres_flags |= ITS_MEAS_FLAG_SAMP_FREQ_BIT;

    // Presentation Flag field
    p_encoded_buffer[0] = pres_flags;		
		p_encoded_buffer[len++]  = p_iss->coord;
		len += uint16_encode(p_iss->curr_seq_nr, &p_encoded_buffer[len]);
		len += uint16_encode(p_iss->unit, &p_encoded_buffer[len]);
		p_encoded_buffer[len++]  = p_iss->type;
		p_encoded_buffer[len++]  = p_iss->make;
		len += uint16_encode(p_iss->ID, &p_encoded_buffer[len]);
		len += uint32_encode(p_iss->samp_freq_in_m_sec, &p_encoded_buffer[len]);

    return len;
}
예제 #9
0
/**@brief Encode a Health Thermometer Measurement.
 *
 * @param[in]   p_hts              Health Thermometer Service structure.
 * @param[in]   p_hts_meas         Measurement to be encoded.
 * @param[out]  p_encoded_buffer   Buffer where the encoded data will be written.
 *
 * @return      Size of encoded data.
 */
static uint8_t hts_measurement_encode(ble_hts_t *      p_hts,
                                      ble_hts_meas_t * p_hts_meas,
                                      uint8_t *        p_encoded_buffer)
{
    uint8_t flags = 0;
    uint8_t len   = 1;
    uint32_t encoded_temp;

    // Flags field
    if (p_hts_meas->temp_in_fahr_units)
    {
        flags |= HTS_MEAS_FLAG_TEMP_UNITS_BIT;
    }
    if (p_hts_meas->time_stamp_present)
    {
        flags |= HTS_MEAS_FLAG_TIME_STAMP_BIT;
    }

    // Temperature Measurement Value field
    if (p_hts_meas->temp_in_fahr_units)
    {
        flags |= HTS_MEAS_FLAG_TEMP_UNITS_BIT;
        
        encoded_temp = ((p_hts_meas->temp_in_fahr.exponent << 24) & 0xFF000000) |
                       ((p_hts_meas->temp_in_fahr.mantissa <<  0) & 0x00FFFFFF);
    }
    else
    {
        encoded_temp = ((p_hts_meas->temp_in_celcius.exponent << 24) & 0xFF000000) |
                       ((p_hts_meas->temp_in_celcius.mantissa <<  0) & 0x00FFFFFF);
    }
    len += uint32_encode(encoded_temp, &p_encoded_buffer[len]);

    // Time Stamp field
    if (p_hts_meas->time_stamp_present)
    {
        flags |= HTS_MEAS_FLAG_TIME_STAMP_BIT;
        len   += ble_date_time_encode(&p_hts_meas->time_stamp, &p_encoded_buffer[len]);
    }
    
    // Temperature Type field
    if (p_hts_meas->temp_type_present)
    {
        flags                   |= HTS_MEAS_FLAG_TEMP_TYPE_BIT;
        p_encoded_buffer[len++]  = p_hts_meas->temp_type;
    }

    // Flags field
    p_encoded_buffer[0] = flags;

    return len;
}
예제 #10
0
static uint32_t response_select_object_cmd_send(ble_dfu_t         * p_dfu,
                                                uint32_t            max_size,
                                                uint32_t            offset,
                                                uint32_t            crc)
{
    uint16_t               index = 0;

    NRF_LOG_INFO("Sending Object Info: [0x60, 0x06, 0x01 max: 0:x%08x 0:x%08x, CRC:0x%08x]\r\n", max_size, offset, crc);
#ifndef NRF51
    if (p_dfu == NULL)
    {
        return NRF_ERROR_NULL;
    }
#endif

    if ((m_conn_handle == BLE_CONN_HANDLE_INVALID) || (m_flags & DFU_BLE_FLAG_SERVICE_INITIALIZED) == 0)
    {
        return NRF_ERROR_INVALID_STATE;
    }

    m_notif_buffer[index++] = BLE_DFU_OP_CODE_RESPONSE;

    // Encode the Request Op code
    m_notif_buffer[index++] = BLE_DFU_OP_CODE_SELECT_OBJECT;

    // Encode the Success Response Value.
    m_notif_buffer[index++] = (uint8_t)NRF_DFU_RES_CODE_SUCCESS;

    // Encode the Max Size Value.
    index += uint32_encode(max_size, &m_notif_buffer[index]);

    // Encode the Offset Value.
    index += uint32_encode(offset, &m_notif_buffer[index]);

    // Encode the Crc Value.
    index += uint32_encode(crc, &m_notif_buffer[index]);

    return send_hvx(m_conn_handle, p_dfu->dfu_ctrl_pt_handles.value_handle, index);
}
예제 #11
0
static void antfs_ota_update_information_file_update(void)
{
    uint32_t u32_temp, err_code;

    m_ota_update_info_file[OTA_INFO_FILE_STRUCTURE_VERSION_OFFSET]    = OTA_INFO_FILE_STRUCTURE_VERSION;                        /* File Structure Version */
    m_ota_update_info_file[OTA_INFO_HARDWARE_VERSION_OFFSET]          = OTA_INFO_HARDWARE_VERSION;                              /* Hardware Version */
    m_ota_update_info_file[OTA_INFO_REGION_PRODUCT_ID_OFFSET]         = OTA_INFO_REGION_PRODUCT_ID;                             /* Region/Product Identifier*/

    u32_temp = DFU_IMAGE_MAX_SIZE_FULL;                                                                                         /* Maximum swap space */
    (void)uint32_encode(u32_temp, &m_ota_update_info_file[OTA_INFO_MAXIMUM_SWAP_SPACE_OFFSET]);

    u32_temp = OTA_INFO_WIRELESS_STACK_VERSION_ID;
    (void)uint32_encode(u32_temp, &m_ota_update_info_file[OTA_INFO_WIRELESS_STACK_VERSION_ID_OFFSET]);                          /* Wireless Protocol Stack Version Identifier*/

    m_ota_update_info_file[OTA_INFO_WIRELESS_STACK_VERSION_LENGTH_OFFSET]   = OTA_INFO_WIRELESS_STACK_VERSION_STRING_BYTES;     /* Wireless Protocol Stack Version String Length*/

    err_code = sd_ant_version_get(&m_ota_update_info_file[OTA_INFO_WIRELESS_STACK_VERSION_STRING_OFFSET]);                      /* Wireless Protocol Stack Version String*/
    APP_ERROR_CHECK(err_code);

    u32_temp = OTA_INFO_BOOTLOADER_VERSION_ID;
    (void)uint32_encode(u32_temp, &m_ota_update_info_file[OTA_INFO_BOOTLOADER_VERSION_ID_OFFSET]);                              /* Bootloader Version Identifier*/

    m_ota_update_info_file[OTA_INFO_BOOTLOADER_VERSION_LENGTH_OFFSET]   = OTA_INFO_BOOTLOADER_VERSION_STRING_BYTES;             /* Bootloader Version String Length*/

    memcpy(&m_ota_update_info_file[OTA_INFO_BOOTLOADER_VERSION_STRING_OFFSET],                                                  /* Bootloader Version String*/
            ac_bootloader_version,
            sizeof(ac_bootloader_version));

    u32_temp = OTA_INFO_APPLICATION_VERSION_ID;
    (void)uint32_encode(u32_temp, &m_ota_update_info_file[OTA_INFO_APPLICATION_VERSION_ID_OFFSET]);                             /* Application Version Identifier*/

    m_ota_update_info_file[OTA_INFO_APPLICATION_VERSION_LENGTH_OFFSET]  = OTA_INFO_APPLICATION_VERSION_STRING_BYTES;            /* Application Version String Length*/

    memcpy(&m_ota_update_info_file[OTA_INFO_APPLICATION_VERSION_STRING_OFFSET],                                                 /* Application Version String*/
            ANT_BOOT_APP_VERSION,
            OTA_INFO_APPLICATION_VERSION_STRING_BYTES);
}
예제 #12
0
void ant_common_page_81_encode(uint8_t                                 * p_page_buffer,
                               volatile ant_common_page81_data_t const * p_page_data)
{
    ant_common_page81_data_layout_t * p_outcoming_data =
        (ant_common_page81_data_layout_t *)p_page_buffer;

    p_outcoming_data->reserved = UINT8_MAX;

    p_outcoming_data->sw_revision_minor = p_page_data->sw_revision_minor;
    p_outcoming_data->sw_revision_major = p_page_data->sw_revision_major;

    UNUSED_PARAMETER(uint32_encode(p_page_data->serial_number, p_outcoming_data->serial_number));

    page81_data_log(p_page_data);
}
예제 #13
0
uint32_t ble_ancs_get_notif_attrs(const ble_ancs_c_t * p_ancs,
                                  const uint32_t       p_uid)
{
    tx_message_t * p_msg;
    uint32_t       index                    = 0;
    uint32_t       number_of_requested_attr = 0;

    p_msg              = &m_tx_buffer[m_tx_insert_index++];
    m_tx_insert_index &= TX_BUFFER_MASK;

    p_msg->req.write_req.gattc_params.handle   = m_service.control_point.handle_value;
    p_msg->req.write_req.gattc_params.p_value  = p_msg->req.write_req.gattc_value;
    p_msg->req.write_req.gattc_params.offset   = 0;
    p_msg->req.write_req.gattc_params.write_op = BLE_GATT_OP_WRITE_REQ;

    //Encode Command ID.
    p_msg->req.write_req.gattc_value[index++] = BLE_ANCS_COMMAND_ID_GET_NOTIF_ATTRIBUTES;
    
    //Encode Notification UID.
    index += uint32_encode(p_uid, &p_msg->req.write_req.gattc_value[index]);

    //Encode Attribute ID.
    for (uint32_t attr = 0; attr < BLE_ANCS_NB_OF_ATTRS; attr++)
    {
        if (m_ancs_attr_list[attr].get == true)
        {
            p_msg->req.write_req.gattc_value[index++] = attr;
            if ((attr == BLE_ANCS_NOTIF_ATTR_ID_TITLE) ||
                (attr == BLE_ANCS_NOTIF_ATTR_ID_SUBTITLE) ||
                (attr == BLE_ANCS_NOTIF_ATTR_ID_MESSAGE))
            {
                //Encode Length field, only applicable for Title, Subtitle and Message
                index += uint16_encode(m_ancs_attr_list[attr].attr_len,
                              &p_msg->req.write_req.gattc_value[index]);
            }
            number_of_requested_attr++;
        }
    }
    p_msg->req.write_req.gattc_params.len = index;
    p_msg->conn_handle                    = p_ancs->conn_handle;
    p_msg->type                           = WRITE_REQ;
    m_expected_number_of_attrs            = number_of_requested_attr;

    tx_buffer_process();

    return NRF_SUCCESS;
}
/**@brief Function for encoding configuration.
 *
 * @param[in]   p_configuration              configuration characteristic structure to be encoded.
 * @param[out]  p_encoded_buffer   Buffer where the encoded data will be written.
 *
 * @return      Size of encoded data.
 */
static uint8_t configuration_encode(ble_agsensor_configuration_t * p_configuration, uint8_t * encoded_buffer)
{

    uint8_t len = 0; 

    (len) += uint16_encode(p_configuration->ble_agsensor_code, &encoded_buffer[len]);
    (len) += uint32_encode(p_configuration->data.ble_agsensor_date_time_Sec, &encoded_buffer[len]);

//    uint8_t test = sizeof(p_configuration->ble_agsensor_data);
//    // Encode additional manufacturer specific data.
//    if (p_configuration->ble_agsensor_data != NULL && sizeof(p_configuration->ble_agsensor_data) > 0)
//    {
//        memcpy(&encoded_buffer[len], p_configuration->ble_agsensor_data, 6);
//        (len) += sizeof(p_configuration->ble_agsensor_data);
//    }
    return len;
}
uint32_t uint32_t_enc(void const * const p_field,
                      uint8_t * const    p_buf,
                      uint32_t           buf_len,
                      uint32_t * const   p_index)
{
    SER_ASSERT_NOT_NULL(p_buf);
    SER_ASSERT_NOT_NULL(p_field);
    SER_ASSERT_NOT_NULL(p_index);

    uint32_t * p_uint32 = (uint32_t *)p_field;

    SER_ASSERT_LENGTH_LEQ(4, buf_len - *p_index);

    *p_index += uint32_encode(*p_uint32, &p_buf[*p_index]);

    return NRF_SUCCESS;
}
uint32_t ser_ble_cmd_rsp_status_code_enc(uint8_t          op_code,
                                         uint32_t         command_status,
                                         uint8_t * const  p_buf,
                                         uint32_t * const p_buf_len)
{
    SER_ASSERT_NOT_NULL(p_buf);
    SER_ASSERT_NOT_NULL(p_buf_len);
    uint32_t index = 0;

    SER_ASSERT_LENGTH_LEQ(SER_CMD_RSP_HEADER_SIZE, *p_buf_len);

    //Encode Op Code.
    p_buf[index++] = op_code;

    //Encode Status.
    index     += uint32_encode(command_status, &(p_buf[index]));
    *p_buf_len = index;

    return NRF_SUCCESS;
}
uint32_t op_status_enc(uint8_t          op_code,
                       uint32_t         return_code,
                       uint8_t * const  p_buff,
                       uint32_t * const p_buff_len,
                       uint32_t * const p_index)
{
    SER_ASSERT_NOT_NULL(p_buff);
    SER_ASSERT_NOT_NULL(p_buff_len);
    SER_ASSERT_NOT_NULL(p_index);
    SER_ASSERT_LENGTH_LEQ(SER_CMD_RSP_HEADER_SIZE, *p_buff_len - *p_index);

    //Encode Op Code.
    p_buff[(*p_index)++] = op_code;
    //Encode Status.
    *p_index += uint32_encode(return_code, &(p_buff[*p_index]));
    //update size of used buffer
    *p_buff_len = *p_index;

    return NRF_SUCCESS;
}
예제 #18
0
uint32_t ble_rpc_cmd_resp_data_send(uint8_t               op_code,
                                    uint8_t               status,
                                    const uint8_t * const p_data,
                                    uint16_t              data_len)
{
    uint8_t * p_buffer;
    uint32_t  err_code;
    uint32_t  index = 0;

    // Allocate a memory buffer from HCI transport layer for transmitting the Command Response.
    // Loop until a buffer is available.
    do
    {    
        err_code = hci_transport_tx_alloc(&p_buffer);
    }
    while (err_code == NRF_ERROR_NO_MEM);

    if (err_code == NRF_SUCCESS)
    {
        // Encode packet type.
        p_buffer[index++] = BLE_RPC_PKT_RESP;

        // Encode Op Code.
        p_buffer[index++] = op_code;

        // Encode Status.
        index += uint32_encode(status, &(p_buffer[index]));

        // Additional data in response packet.
        memcpy(&p_buffer[index], p_data, data_len);

        index += data_len;

        return hci_transport_pkt_write(p_buffer, index);
    }

    return err_code;
}
예제 #19
0
uint32_t ble_dfu_bytes_rcvd_report(ble_dfu_t * p_dfu, uint32_t num_of_firmware_bytes_rcvd)
{
    if (p_dfu == NULL)
    {
        return NRF_ERROR_NULL;
    }

    if ((p_dfu->conn_handle == BLE_CONN_HANDLE_INVALID) || !m_is_dfu_service_initialized)
    {
        return NRF_ERROR_INVALID_STATE;
    }

    ble_gatts_hvx_params_t hvx_params;
    uint16_t               index = 0;

    // Encode the Op Code.
    m_notif_buffer[index++] = OP_CODE_RESPONSE;

    // Encode the Reqest Op Code.
    m_notif_buffer[index++] = OP_CODE_IMAGE_SIZE_REQ;

    // Encode the Response Value.
    m_notif_buffer[index++] = (uint8_t)BLE_DFU_RESP_VAL_SUCCESS;

    index += uint32_encode(num_of_firmware_bytes_rcvd, &m_notif_buffer[index]);

    memset(&hvx_params, 0, sizeof(hvx_params));

    hvx_params.handle = p_dfu->dfu_ctrl_pt_handles.value_handle;
    hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
    hvx_params.offset = 0;
    hvx_params.p_len  = &index;
    hvx_params.p_data = m_notif_buffer;

    return sd_ble_gatts_hvx(p_dfu->conn_handle, &hvx_params);
}
void ble_agsensor_process_request(uint8_t data_len, uint8_t * p_data, uint16_t op_code, bool read_start, bool app_request, bool write)
{

    APPL_LOG("ble_agsensor_process_request opcode %d \r\n", (int)op_code);
    if (isConfigSendWaiting == true && write == false && app_request == false)
    {
        APPL_LOG("ble_agsensor_process_request 1 \r\n");
        return;
    }

//    APPL_LOG("ble_agsensor_process_request 2 \r\n");

	uint8_t sensor_depth;
	uint32_t tempData32 = 0;
	uint16_t tempData16 = 0;

    // Asked for stop sending the Data for specific opcode
    if (app_request == true && read_start == false && opcode_inRead == op_code && write == false){
    	// Set to date time as they count as the ping message
    	opcode_inRead = BLE_AGSENSOR_CONFIGURATION_OPCODE_DATETIME;
        APPL_LOG("ble_agsensor_process_request 2 \r\n");
    	return;
    }

    hvx_p_config_len = 0;
    (hvx_p_config_len) += uint16_encode(op_code, &hvx_encoded_buffer[hvx_p_config_len]);

    switch (op_code)
    {
		case BLE_AGSENSOR_CONFIGURATION_OPCODE_DATETIME:
			if (write && data_len >=4 && p_data != NULL) {
				tempData32 = (((uint32_t)((uint8_t *)p_data)[0]) << 0)  |
			                     (((uint32_t)((uint8_t *)p_data)[1]) << 8)  |
			                     (((uint32_t)((uint8_t *)p_data)[2]) << 16) |
			                     (((uint32_t)((uint8_t *)p_data)[3]) << 24 );

			    setOffsetTime(tempData32);
			    APPL_LOG("Date time offset update  \r\n");
			    return;
			}
			else {
//			    APPL_LOG("Date time msg created  \r\n");
				datetimeReadEnable = read_start;
				tempData32 = getTimeInSec();
//				tempData32 = SwapByte4(tempData32);
			    (hvx_p_config_len) += uint32_encode(tempData32, &hvx_encoded_buffer[hvx_p_config_len]);
			}
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_BATTERY_LEVEL: // read only
			batteryLevelReadEnable = read_start;
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_LONGITUDE_LATITUDE:
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_BONDED_DONGLE_RSSI: // read only
			bondedDongleRssiReadEnable = read_start;
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_BONDED_DONGLE_MAC_ADDRESS: // read only
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_TIME_SYNC_OFFSET:
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_UPDATE_RATE:
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_DATUM:
			break;

			/*Mosture */
		case BLE_AGSENSOR_CONFIGURATION_OPCODE_MOSTURE_AIRWATER:
			if (write && data_len >= 5 && p_data != NULL)
			{
			    APPL_LOG("Moisture sensor AirWater write request\r\n");
				sensor_depth = p_data[0];
				// Write the Air value in the config
				tempData16 = uint16_decode(&p_data[1]);
				cfgWriteConfig(&moisture_air[sensor_depth], &tempData16, sizeof(tempData16));

				// Write the Water value in the config
				tempData16 = uint16_decode(&p_data[3]);
				cfgWriteConfig(&moisture_water[sensor_depth], &tempData16, sizeof(tempData16));

				// Need to create response msg so application get the response to update the UI.
				ble_agsensor_create_temp_msg(op_code, p_data, data_len);
			    return;
			}
			else
			{
				if(read_start)
				{
					msg_sensor_depth = MAX_SENSOR_COUNT;
				    APPL_LOG("moisture sensor air Water read request\r\n");
				    // Job is done so need to return msg will be created on the ACK call back
				    return;
				}
				else
				{
					msg_sensor_depth--;
					if (msg_sensor_depth == 0) {
				    	opcode_inRead = BLE_AGSENSOR_CONFIGURATION_OPCODE_DATETIME;
					}
				}
				// Add the sensor count in the sending msg
				hvx_encoded_buffer[hvx_p_config_len] = msg_sensor_depth;
				hvx_p_config_len ++;

				// Add the Air value in the sending msg
				cfgReadConfig(&moisture_air[msg_sensor_depth], &tempData16, sizeof(tempData16));
				(hvx_p_config_len) += uint16_encode(tempData16, &hvx_encoded_buffer[hvx_p_config_len]);

				// Add the Water value in the sending msg
				cfgReadConfig(&moisture_water[msg_sensor_depth], &tempData16, sizeof(tempData16));
				(hvx_p_config_len) += uint16_encode(tempData16, &hvx_encoded_buffer[hvx_p_config_len]);

				// If app have requested specific data which is not read start then need to create the temp msg
				if(app_request == true) {
					ble_agsensor_create_temp_msg(0, &hvx_encoded_buffer, hvx_p_config_len);
				}
			    APPL_LOG("moisture sensor Air Water data created %d\r\n", msg_sensor_depth);
			}
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_MOSTURE_ABCD:
			if (write && data_len >=17 && p_data != NULL)
			{
			    APPL_LOG("Moisture sensor ABCD write request\r\n");
				sensor_depth = p_data[0];
				// Write the A value in the config
				tempData32 = uint32_decode(&p_data[1]);
				cfgWriteConfig(&moisture_A[sensor_depth], &tempData32, sizeof(tempData32));
				// Write the B value in the config
				tempData32 = uint32_decode(&p_data[5]);
				cfgWriteConfig(&moisture_B[sensor_depth], &tempData32, sizeof(tempData32));
				// Write the B value in the config
				tempData32 = uint32_decode(&p_data[9]);
				cfgWriteConfig(&moisture_C[sensor_depth], &tempData32, sizeof(tempData32));
				// Write the B value in the config
				tempData32 = uint32_decode(&p_data[13]);
				cfgWriteConfig(&moisture_D[sensor_depth], &tempData32, sizeof(tempData32));

				// Need to create response msg so application get the response to update the UI.
				ble_agsensor_create_temp_msg(op_code, p_data, data_len);
			    return;
			}
			else
			{
				if(read_start)
				{
					msg_sensor_depth = MAX_SENSOR_COUNT;
				    APPL_LOG("moisture sensor ABCD read request\r\n");
				    // Job is done so need to return msg will be created on the ACK call back
				    return;
				}
				else
				{
					msg_sensor_depth--;
					if (msg_sensor_depth == 0) {
				    	opcode_inRead = BLE_AGSENSOR_CONFIGURATION_OPCODE_DATETIME;
					}
				}
				// Add the sensor count in the sending msg
				hvx_encoded_buffer[hvx_p_config_len] = msg_sensor_depth;
				hvx_p_config_len ++;

				// Add the A value in the sending msg
				cfgReadConfig(&moisture_A[msg_sensor_depth], &tempData32, sizeof(tempData32));
				(hvx_p_config_len) += uint32_encode(tempData32, &hvx_encoded_buffer[hvx_p_config_len]);

				// Add the B value in the sending msg
				cfgReadConfig(&moisture_B[msg_sensor_depth], &tempData32, sizeof(tempData32));
				(hvx_p_config_len) += uint32_encode(tempData32, &hvx_encoded_buffer[hvx_p_config_len]);

				// Add the C value in the sending msg
				cfgReadConfig(&moisture_C[msg_sensor_depth], &tempData32, sizeof(tempData32));
				(hvx_p_config_len) += uint32_encode(tempData32, &hvx_encoded_buffer[hvx_p_config_len]);

				// Add the D value in the sending msg
				cfgReadConfig(&moisture_D[msg_sensor_depth], &tempData32, sizeof(tempData32));
				(hvx_p_config_len) += uint32_encode(tempData32, &hvx_encoded_buffer[hvx_p_config_len]);

				// If app have requested specific data which is not read start then need to create the temp msg
				if(app_request == true) {
					ble_agsensor_create_temp_msg(0, &hvx_encoded_buffer, hvx_p_config_len);
				}
			    APPL_LOG("moisture sensor ABCD data created %d\r\n", msg_sensor_depth);
			}
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_TEMPERATURE_AB:
			if (write && data_len >=9 && p_data != NULL)
			{
			    APPL_LOG("temperature sensor AB write request\r\n");
				sensor_depth = p_data[0];
				// Write the A value in the config
				tempData32 = uint32_decode(&p_data[1]);
				cfgWriteConfig(&temperature_A[sensor_depth], &tempData32, sizeof(tempData32));
				// Write the B value in the config
				tempData32 = uint32_decode(&p_data[5]);
				cfgWriteConfig(&temperature_B[sensor_depth], &tempData32, sizeof(tempData32));

				// Need to create response msg so application get the response to update the UI.
				ble_agsensor_create_temp_msg(op_code, p_data, data_len);
			    return;
			}
			else
			{
				if(read_start)
				{
					msg_sensor_depth = MAX_SENSOR_COUNT;
				    APPL_LOG("temperature sensor AB read request\r\n");
				    // Job is done so need to return msg will be created on the ACK call back
				    return;
				}
				else
				{
					msg_sensor_depth--;
					if (msg_sensor_depth == 0) {
				    	opcode_inRead = BLE_AGSENSOR_CONFIGURATION_OPCODE_DATETIME;
					}
				}
				// Add the sensor count in the sending msg
				hvx_encoded_buffer[hvx_p_config_len] = msg_sensor_depth;
				hvx_p_config_len ++;

				// Add the A value in the sending msg
				cfgReadConfig(&temperature_A[msg_sensor_depth], &tempData32, sizeof(tempData32));
				(hvx_p_config_len) += uint32_encode(tempData32, &hvx_encoded_buffer[hvx_p_config_len]);

				// Add the B value in the sending msg
				cfgReadConfig(&temperature_B[msg_sensor_depth], &tempData32, sizeof(tempData32));
				(hvx_p_config_len) += uint32_encode(tempData32, &hvx_encoded_buffer[hvx_p_config_len]);

				// If app have requested specific data which is not read start then need to create the temp msg
				if(app_request == true) {
					ble_agsensor_create_temp_msg(0, &hvx_encoded_buffer, hvx_p_config_len);
				}
			    APPL_LOG("temperature sensor AB data created %d\r\n", msg_sensor_depth);
			}
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_SALINITY_AIRWATER:
			if (write && data_len >=5 && p_data != NULL)
			{
			    APPL_LOG("Salinity sensor AirWater write request\r\n");
				sensor_depth = p_data[0];

				// Write the Air value in the config
				tempData16 = uint16_decode(&p_data[1]);
				cfgWriteConfig(&salinity_air[sensor_depth], &tempData16, sizeof(tempData16));

				// Write the Water value in the config
				tempData16 = uint16_decode(&p_data[3]);
				cfgWriteConfig(&salinity_water[sensor_depth], &tempData16, sizeof(tempData16));

				// Need to create response msg so application get the response to update the UI.
				ble_agsensor_create_temp_msg(op_code, p_data, data_len);
			    return;
			}
			else
			{
				if(read_start)
				{
					msg_sensor_depth = MAX_SENSOR_COUNT;
				    APPL_LOG("Salinity sensor AirWater read request\r\n");
				    // Job is done so need to return msg will be created on the ACK call back
				    return;
				}
				else
				{
					msg_sensor_depth--;
					if (msg_sensor_depth == 0) {
				    	opcode_inRead = BLE_AGSENSOR_CONFIGURATION_OPCODE_DATETIME;
					}
				}
				// Add the sensor count in the sending msg
				hvx_encoded_buffer[hvx_p_config_len] = msg_sensor_depth;
				hvx_p_config_len ++;

				// Add the Air value in the sending msg
				cfgReadConfig(&salinity_air[msg_sensor_depth], &tempData16, sizeof(tempData16));
				(hvx_p_config_len) += uint16_encode(tempData16, &hvx_encoded_buffer[hvx_p_config_len]);

				// Add the Water value in the sending msg
				cfgReadConfig(&salinity_water[msg_sensor_depth], &tempData16, sizeof(tempData16));
				(hvx_p_config_len) += uint16_encode(tempData16, &hvx_encoded_buffer[hvx_p_config_len]);

				// If app have requested specific data which is not read start then need to create the temp msg
				if(app_request == true) {
					ble_agsensor_create_temp_msg(0, &hvx_encoded_buffer, hvx_p_config_len);
				}
			    APPL_LOG("Salinity sensor AirWater data created %d\r\n", msg_sensor_depth);
			}
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_SALINITY_D:
			if (write && data_len >=5 && p_data != NULL)
			{
			    APPL_LOG("Salinity sensor D write request\r\n");
				sensor_depth = p_data[0];
				// Write the D value in the config
				tempData32 = uint32_decode(&p_data[1]);
				cfgWriteConfig(&salinity_D[sensor_depth], &tempData32, sizeof(tempData32));

				// Need to create response msg so application get the response to update the UI.
				ble_agsensor_create_temp_msg(op_code, p_data, data_len);
			    return;
			}
			else
			{
				if(read_start)
				{
					msg_sensor_depth = MAX_SENSOR_COUNT;
				    APPL_LOG("Salinity sensor D read request\r\n");
				    // Job is done so need to return msg will be created on the ACK call back
				    return;
				}
				else
				{
					msg_sensor_depth--;
					if (msg_sensor_depth == 0) {
				    	opcode_inRead = BLE_AGSENSOR_CONFIGURATION_OPCODE_DATETIME;
					}
				}
				// Add the sensor count in the sending msg
				hvx_encoded_buffer[hvx_p_config_len] = msg_sensor_depth;
				hvx_p_config_len ++;

				// Add the D value in the sending msg
				cfgReadConfig(&salinity_D[msg_sensor_depth], &tempData32, sizeof(tempData32));
				(hvx_p_config_len) += uint32_encode(tempData32, &hvx_encoded_buffer[hvx_p_config_len]);

				// If app have requested specific data which is not read start then need to create the temp msg
				if(app_request == true) {
					ble_agsensor_create_temp_msg(0, &hvx_encoded_buffer, hvx_p_config_len);
				}
			    APPL_LOG("Salinity sensor D data created %d\r\n", msg_sensor_depth);
			}
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_START_MEASUREMENT:
			isMeasuringSensor = true;
		    sentek_sensor_measurement_type_set(SENSOR_MEASUREMENT_CONTINUOUS);
		    APPL_LOG("Start Measurement\r\n");
			return;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_STOP_MEASUREMENT:
			isMeasuringSensor = false;
		    sentek_sensor_measurement_type_set(SENSOR_MEASUREMENT_NONE);
		    APPL_LOG("Stop doing Measurement\r\n");
		    return;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_AIR_NORMALIZE:
		    sentek_sensor_measurement_type_set(SENSOR_MEASUREMENT_AIR_NORMALIZATION);
		    airNormalizationInProgress = true;
		    APPL_LOG("Air Normalization Request\r\n");
			return;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_WATER_NORMALIZE:
		    sentek_sensor_measurement_type_set(SENSOR_MEASUREMENT_WATER_NORMALIZATION);
		    waterNormalizationInProgress = true;
		    APPL_LOG("Water Normalization Request\r\n");
		    return;

        default:
            APPL_LOG("Default msg created %d\r\n", (int)op_code);
			datetimeReadEnable = read_start;
			opcode_inRead = BLE_AGSENSOR_CONFIGURATION_OPCODE_DATETIME;
			tempData32 = getTimeInSec();
//			tempData32 = SwapByte4(tempData32);
		    (hvx_p_config_len) += uint32_encode(tempData32, &hvx_encoded_buffer[hvx_p_config_len]);
            break;
    }
	if (isConnected == true && configIndicationEnable == true) {
        isConfigSendWaiting = true;
	    return;
	}
//    APPL_LOG("read_request 6 \r\n");
	return;
}
예제 #21
0
파일: main.c 프로젝트: xueliu/nRF51822
/**@brief Timer callback used for transmitting Echo Request and UDP6 packets depending on
 *        application state.
 *
 * @param[in]   p_context   Pointer used for passing context. No context used in this application.
 */
static void tx_timeout_handler(void * p_context)
{
    uint32_t err_code;

    switch (m_node_state)
    {
        case APP_STATE_IPV6_IF_DOWN:
        {
            return;
        }
        case APP_STATE_IPV6_IF_UP:
        {
            APPL_LOG("[APPL]: Ping remote node. \r\n");

            iot_pbuffer_alloc_param_t   pbuff_param;
            iot_pbuffer_t             * p_buffer;

            pbuff_param.flags  = PBUFFER_FLAG_DEFAULT;
            pbuff_param.type   = ICMP6_PACKET_TYPE;
            pbuff_param.length = ICMP6_ECHO_REQUEST_PAYLOAD_OFFSET + 10;

            // Allocate packet buffer.
            err_code = iot_pbuffer_allocate(&pbuff_param, &p_buffer);
            APP_ERROR_CHECK(err_code);

            ipv6_addr_t dest_ipv6_addr;
            memcpy(&dest_ipv6_addr.u8[0], (uint8_t[]){SERVER_IPV6_ADDRESS}, IPV6_ADDR_SIZE);

            iot_interface_t * p_interface;
            ipv6_addr_t       src_ipv6_addr;
            err_code = ipv6_address_find_best_match(&p_interface,
                                                    &src_ipv6_addr,
                                                    &dest_ipv6_addr);
            APP_ERROR_CHECK(err_code);

            memset(p_buffer->p_payload + ICMP6_ECHO_REQUEST_PAYLOAD_OFFSET, 'A', 10);

            // Send Echo Request to peer.
            err_code = icmp6_echo_request(p_interface, &src_ipv6_addr, &dest_ipv6_addr, p_buffer);
            APP_ERROR_CHECK(err_code);

            err_code = app_timer_start(m_tx_node_timer, APP_PING_INTERVAL, NULL);
            APP_ERROR_CHECK(err_code);

            break;
        }
        case APP_STATE_PEER_REACHABLE:
        {
            uint32_t ind_buff = 0;
            err_code = get_packet_buffer_index(&ind_buff, (uint32_t *)&m_invalid_pkt_seq_num);
            if (err_code == NRF_ERROR_NOT_FOUND)
            {
                // Buffer of expected packets full, checking if peer is reachable.
                APPL_LOG("[APPL]: %ld packets transmitted, %d packets lost. Resetting counter. \r\n", \
                             m_pkt_seq_num, PACKET_BUFFER_LEN);
                m_node_state    = APP_STATE_IPV6_IF_UP;
                m_display_state = LEDS_TX_ECHO_REQUEST;
                m_pkt_seq_num = 0;
                memset(&m_packet_buffer[0][0], 0x00, sizeof(m_packet_buffer));
                err_code = app_timer_start(m_tx_node_timer, APP_PING_INTERVAL, NULL);
                APP_ERROR_CHECK(err_code);
                return;
            }

            ++m_pkt_seq_num;
            if (m_pkt_seq_num == INVALID_PACKET_SEQ_NUMBER)
            {
                ++m_pkt_seq_num;
            }

            test_packet_payload_t packet;
            uint8_t encoded_seq_num[TEST_PACKET_NUM_LEN];
            UNUSED_VARIABLE(uint32_encode(m_pkt_seq_num, &encoded_seq_num[0]));
            // The first 4 bytes of the payload is the packet sequence number.
            memcpy(&packet.packet_seq_num[0], &encoded_seq_num[0], TEST_PACKET_NUM_LEN);
            // The rest of the payload is random bytes.
            do
            {
                err_code = sd_rand_application_vector_get(&packet.packet_data[0], \
                                                          sizeof(packet.packet_data));
            }
            while (err_code == NRF_ERROR_SOC_RAND_NOT_ENOUGH_VALUES);
            APP_ERROR_CHECK(err_code);

            iot_pbuffer_alloc_param_t   pbuff_param;
            iot_pbuffer_t             * p_buffer;

            pbuff_param.flags  = PBUFFER_FLAG_DEFAULT;
            pbuff_param.type   = UDP6_PACKET_TYPE;
            pbuff_param.length = TEST_PACKET_PAYLOAD_LEN;

            // Allocate packet buffer.
            err_code = iot_pbuffer_allocate(&pbuff_param, &p_buffer);
            APP_ERROR_CHECK(err_code);

            memcpy(p_buffer->p_payload, &packet.packet_seq_num[0], TEST_PACKET_NUM_LEN);
            memcpy(p_buffer->p_payload+TEST_PACKET_NUM_LEN, &packet.packet_data[0], TEST_PACKET_DATA_LEN);

            ipv6_addr_t dest_ipv6_addr;
            memset(&dest_ipv6_addr, 0x00, sizeof(ipv6_addr_t));
            memcpy(&dest_ipv6_addr.u8[0], (uint8_t[]){SERVER_IPV6_ADDRESS}, IPV6_ADDR_SIZE);

            // Transmit UDP6 packet.
            err_code = udp6_socket_sendto(&m_udp_socket, &dest_ipv6_addr, HTONS(UDP_PORT), p_buffer);
            APP_ERROR_CHECK(err_code);

            APPL_LOG("[APPL]: Transmitted UDP packet sequence number: %ld\r\n", m_pkt_seq_num);

            // Store sent packet amongst expected packets.
            memcpy(&m_packet_buffer[ind_buff][0], &packet.packet_seq_num[0], TEST_PACKET_NUM_LEN);
            memcpy(&m_packet_buffer[ind_buff][TEST_PACKET_NUM_LEN], &packet.packet_data[0], TEST_PACKET_DATA_LEN);

            if (m_pkt_seq_num == 1)
            {
                err_code = app_timer_start(m_tx_node_timer, (TX_INTERVAL*5), NULL); // Slow start.
                APP_ERROR_CHECK(err_code);
            }
            else
            {
                err_code = app_timer_start(m_tx_node_timer, TX_INTERVAL, NULL);
                APP_ERROR_CHECK(err_code);
            }

            break;
        }
        default:
        {
            break;
        }
    }
}