3373 lines
114 KiB
C
Executable File
3373 lines
114 KiB
C
Executable File
/****************************************************************************
|
|
|
|
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
|
|
|
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
|
be copied by any method or incorporated into another program without
|
|
the express written consent of Aerospace C.Power. This Information or any portion
|
|
thereof remains the property of Aerospace C.Power. The Information contained herein
|
|
is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
|
liability for its use in any way and conveys no license or title under
|
|
any patent or copyright and makes no representation or warranty that this
|
|
Information is free from patent or copyright infringement.
|
|
|
|
****************************************************************************/
|
|
|
|
/* os_ship header files */
|
|
#include "os_task_api.h"
|
|
#include "os_event_api.h"
|
|
#include "os_timer_api.h"
|
|
#include "os_utils_api.h"
|
|
|
|
/* iot common header files */
|
|
#include "iot_plc_api.h"
|
|
#include "iot_module_api.h"
|
|
#include "iot_queue_api.h"
|
|
#include "iot_config_api.h"
|
|
#include "iot_plc_msg_api.h"
|
|
#include "iot_board_api.h"
|
|
|
|
#include "iot_mem_pool_api.h"
|
|
#include "iot_config_api.h"
|
|
#include "iot_app_api.h"
|
|
#include "iot_errno_api.h"
|
|
#include "iot_sg_drv_api.h"
|
|
#include "iot_pib_api.h"
|
|
#include "iot_ntoh_api.h"
|
|
#include "iot_oem_api.h"
|
|
|
|
#include "proto_645.h"
|
|
#include "proto_645_vendor.h"
|
|
#include "proto_69845.h"
|
|
#include "proto_69845_vendor.h"
|
|
#include "proto_crc16.h"
|
|
#include "proto_conn_less.h"
|
|
#include "iot_frame_parse_api.h"
|
|
#include "proto_dlms.h"
|
|
#include "proto_qsxj.h"
|
|
#include "proto_gw_app.h"
|
|
|
|
#include "iot_io_api.h"
|
|
#include "iot_dbglog_api.h"
|
|
#include "iot_uart_api.h"
|
|
#include "iot_utils_api.h"
|
|
#include "iot_dev_test.h"
|
|
#include "iot_proto_dev_test.h"
|
|
|
|
/* define the length of the packet used for ppm detect */
|
|
#define IOT_DEV_TEST_PPM_DETCT_PKG_LEN 400
|
|
|
|
#if IOT_DEV_TEST_BROADCAST_MODD_CFG
|
|
|
|
/* ppm detect function switch, for the normal controller, this is always off */
|
|
#define IOT_DEV_TEST_PPM_DETECT_EN 0
|
|
|
|
#else
|
|
|
|
/* ppm detect function switch, for HX applications, turn on this function when
|
|
* ppm detect is needed.
|
|
* for example, some CIU factories have problems in production test, you can
|
|
* try to open this function
|
|
*/
|
|
#define IOT_DEV_TEST_PPM_DETECT_EN 0
|
|
|
|
#endif
|
|
|
|
|
|
#if (IOT_STA_CONTROL_MODE == 2) || (IOT_DEV_TEST_CCO_MODE)
|
|
|
|
static iot_dev_test_task_data_t *dev_test_task_data;
|
|
|
|
static uint8_t iot_dev_test_send_mode_config(uint8_t *dst_mac);
|
|
|
|
static void iot_dev_test_flash_info_init(void);
|
|
|
|
static void iot_dev_test_close_uart(iot_uart_h uart);
|
|
|
|
static bool_t iot_dev_test_set_uart_config(iot_uart_h uart);
|
|
|
|
static uint8_t iot_dev_test_flash_save(iot_dev_test_pib_t *p_info);
|
|
|
|
#if (IOT_DEV_TEST_DEBUG_EN == 1)
|
|
|
|
static char dev_test_log_buf[IOT_DEV_TEST_LOG_BUF_LEN] = { 0 };
|
|
|
|
void iot_dev_test_data_print(const char* str, uint8_t* buf, uint16_t len)
|
|
{
|
|
uint32_t offset = 0;
|
|
|
|
offset = iot_sprintf(dev_test_log_buf, "%s[len:%d]", str, len);
|
|
for (uint32_t i = 0; i < len; ++i) {
|
|
offset += iot_sprintf(dev_test_log_buf + offset, "%02X ", buf[i]);
|
|
if (IOT_DEV_TEST_LOG_BUF_LEN <= offset + 4) {
|
|
break;
|
|
}
|
|
}
|
|
dev_test_log_buf[offset] = 0;
|
|
iot_cus_printf("%s\n", dev_test_log_buf);
|
|
}
|
|
|
|
#else /* IOT_DEV_TEST_DEBUG_EN == 1 */
|
|
|
|
void iot_dev_test_data_print(const char* str, uint8_t* buf, uint16_t len)
|
|
{
|
|
(void)str;
|
|
(void)buf;
|
|
(void)len;
|
|
return;
|
|
}
|
|
|
|
#endif
|
|
|
|
#if IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_METER
|
|
|
|
/* mac addr of CIU TESTER */
|
|
static const uint8_t ciu_tester_mac[IOT_MAC_ADDR_LEN] =
|
|
{ 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x01 };
|
|
|
|
/* UART baudrate lookup table */
|
|
static const uint32_t baud_tbl[SUPPORTED_BAUD_CNT] = {
|
|
2400, // baudidx 0
|
|
4800, // baudidx 1
|
|
9600, // baudidx 2
|
|
115200, // baudidx 3
|
|
};
|
|
|
|
#endif
|
|
|
|
static void iot_dev_test_post_task_msg(uint16_t msg_type, uint16_t msg_id,
|
|
void *data)
|
|
{
|
|
iot_task_msg_t *msg;
|
|
iot_dev_test_task_msg_t *task_msg;
|
|
iot_task_h task_hdl = dev_test_task_data->task_handle;
|
|
|
|
msg = iot_task_alloc_msg_with_reserved(task_hdl, 0);
|
|
if (!msg) {
|
|
IOT_ASSERT(0);
|
|
return;
|
|
}
|
|
|
|
task_msg = (iot_dev_test_task_msg_t*)msg;
|
|
task_msg->msg.type = msg_type;
|
|
task_msg->msg.id = msg_id;
|
|
task_msg->data = data;
|
|
iot_task_queue_msg(dev_test_task_data->task_handle, &task_msg->msg, 1);
|
|
|
|
}
|
|
|
|
/* send mode config to all the sta and lock the stas' band */
|
|
static void iot_dev_test_config_all_sta_test_mode(void)
|
|
{
|
|
static uint8_t check_cnt = IOT_DEV_TEST_BCAST_TIMER_CNT;
|
|
|
|
check_cnt++;
|
|
if (check_cnt >= IOT_DEV_TEST_BCAST_TIMER_CNT) {
|
|
iot_dev_test_send_mode_config((uint8_t *)bcast_mac);
|
|
check_cnt = 0;
|
|
}
|
|
}
|
|
|
|
#if (IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_METER)
|
|
|
|
/* define the max tool ppm value, which the tool may config */
|
|
#define IOT_DEV_TEST_MAX_TOOL_PPM 15
|
|
|
|
static uint8_t spec_mac[IOT_MAC_ADDR_LEN] = {0xAA, 0xBB,0xCC, 0xCC,0xBB, 0xAA};
|
|
|
|
static void iot_dev_test_uart_send(iot_pkt_t *pkt);
|
|
static bool_t iot_dev_test_frame_rpt_check(uint8_t *mac, uint16_t sn);
|
|
static uint16_t iot_dev_test_app_get_sn(void);
|
|
|
|
static iot_uart_h iot_dev_test_open_uart(uint8_t port);
|
|
|
|
static void iot_dev_test_set_mac(uint8_t *mac);
|
|
|
|
static bool_t iot_dev_test_app_pkt_report_check(uint8_t *mac, uint32_t in_sn) {
|
|
bool_t need_rpt = false;
|
|
|
|
iot_cus_printf("dst mac[%02x:%02x:%02x:%02x:%02x:%02x], stored sn[%lu], "
|
|
"recv sn[%lu]\n", mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],
|
|
dev_test_task_data->stored_app_sn, in_sn);
|
|
|
|
iot_cus_printf("local mac[%02x:%02x:%02x:%02x:%02x:%02x]\n",
|
|
dev_test_task_data->mac_addr[0], dev_test_task_data->mac_addr[1],
|
|
dev_test_task_data->mac_addr[2], dev_test_task_data->mac_addr[3],
|
|
dev_test_task_data->mac_addr[4], dev_test_task_data->mac_addr[5]);
|
|
|
|
if (iot_mac_addr_cmp(mac, dev_test_task_data->mac_addr)
|
|
|| iot_mac_is_bcast(mac)) {
|
|
need_rpt = true;
|
|
if (dev_test_task_data->stored_app_sn != in_sn) {
|
|
// need_rpt = true;
|
|
dev_test_task_data->stored_app_sn = in_sn;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return need_rpt;
|
|
}
|
|
|
|
static uint8_t iot_dev_test_fullfil_rsp_snr_cmd(uint8_t *data, uint16_t len,
|
|
int8_t snr, int8_t rssi)
|
|
{
|
|
proto_645_header_t *hdr_645 = NULL;
|
|
uint8_t *t_ptr;
|
|
uint32_t di = 0;
|
|
uint8_t reason = 0;
|
|
uint8_t ret = ERR_FAIL;
|
|
proto_645_07_ext_signal_resp_t *signal_attr;
|
|
proto_645_tailer_t *tail;
|
|
proto_69845_frame_head_info_t *hdr_698;
|
|
proto_dlms_hdlc_head_t *hdr_dlms;
|
|
proto_dlms_hdlc_cache_t cache_dlms;
|
|
|
|
hdr_645 = proto_645_format_check(data, len, PROTO_645_DIR_SLAVE);
|
|
if (NULL == hdr_645) {
|
|
hdr_698 = proto_69845_sanity_check(data, len);
|
|
if (NULL != hdr_698) {
|
|
iot_cus_printf("RECV_PLC_69845 frame, fn 0x%04x, "
|
|
"data_len %lu\n", hdr_698->len, hdr_698->ctrl.fn);
|
|
} else {
|
|
hdr_dlms = proto_dlms_hdlc_parse(data, len, &cache_dlms);
|
|
if (hdr_dlms) {
|
|
iot_cus_printf("RECV_PLC_DLMS frame, type %lu, \n",
|
|
hdr_dlms->frame_format.bit.frame_type);
|
|
} else {
|
|
iot_cus_printf("RECV_PLC_unknown frame, len %lu\n", len);
|
|
}
|
|
}
|
|
reason = 1;
|
|
goto out;
|
|
}
|
|
|
|
if (ERR_OK != proto_645_get_di_by_sub33(hdr_645->data,
|
|
PROTO_645_2007_DI_LEN, PROTO_645_2007_ID, &di)) {
|
|
iot_cus_printf("RECV_PLC_645 frame, di 0x%04x, data_len %lu\n", di,
|
|
hdr_645->len);
|
|
reason = 2;
|
|
goto out;
|
|
}
|
|
|
|
if (di != PROTO_645_2007_EXT_QUERY_SIGNAL_ID) {
|
|
reason = 3;
|
|
goto out;
|
|
}
|
|
|
|
iot_cus_printf("uplink snr %d, rssi %lu\n", snr, rssi);
|
|
|
|
t_ptr = &hdr_645->data[PROTO_645_2007_DI_LEN];
|
|
signal_attr = (proto_645_07_ext_signal_resp_t *)t_ptr;
|
|
signal_attr->ul_rssi = rssi + 0x33;
|
|
signal_attr->ul_snr = snr + 0x33;
|
|
tail = (proto_645_tailer_t *)&hdr_645->data[hdr_645->len];
|
|
tail->cs = proto_645_calc_cs(hdr_645);
|
|
ret = ERR_OK;
|
|
out:
|
|
if (reason != 0) {
|
|
iot_cus_printf("fuillfil frame failed for reason %lu\n", reason);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* get the address from the response message, until now, dev_test app only
|
|
* support DL/T 645-2007, DL/T 698.45 and dlms
|
|
*/
|
|
static uint8_t iot_dev_test_addr_in_data_check(uint8_t *data, uint32_t len,
|
|
uint16_t sn)
|
|
{
|
|
uint8_t ret = ERR_FAIL;
|
|
uint8_t addr[IOT_MAC_ADDR_LEN] = {0};
|
|
proto_645_header_t *hdr_645;
|
|
proto_69845_frame_head_info_t *hdr_698;
|
|
proto_dlms_hdlc_head_t *hdr_dlms;
|
|
proto_dlms_hdlc_cache_t cache_dlms;
|
|
|
|
if (!data || !len) {
|
|
goto out;
|
|
}
|
|
hdr_645 = proto_645_format_check_ext(data, len, PROTO_645_DIR_SLAVE);
|
|
if (hdr_645) {
|
|
iot_mac_addr_cpy(addr, hdr_645->addr);
|
|
} else {
|
|
hdr_698 = proto_69845_sanity_check_ext(data, (uint16_t)len);
|
|
if (hdr_698) {
|
|
iot_mac_addr_cpy(addr, proto_69845_get_ser_addr(hdr_698));
|
|
} else {
|
|
hdr_dlms = proto_dlms_hdlc_parse(data, len, &cache_dlms);
|
|
if (hdr_dlms) {
|
|
if (cache_dlms.dest_addr.type != PROTO_DLMS_HDLC_ADD_TYPE_4) {
|
|
goto out;
|
|
}
|
|
proto_dlms_hdlc_type_4_addr_to_bcd_addr(addr,
|
|
&cache_dlms.dest_addr);
|
|
} else {
|
|
goto out;
|
|
}
|
|
}
|
|
}
|
|
iot_mac_addr_reverse(addr);
|
|
if (iot_dev_test_frame_rpt_check(addr, sn)) {
|
|
ret = ERR_OK;
|
|
}
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
/* update the collector's mac */
|
|
static void iot_dev_test_update_collector_mac(uint8_t *mac)
|
|
{
|
|
#if IOT_DEV_TEST_SUPPORT_CT_MR_EN
|
|
|
|
if (!dev_test_task_data->collector_vaild) {
|
|
if (!iot_mac_addr_valid(mac) || iot_mac_is_bcast(mac)) {
|
|
return;
|
|
}
|
|
iot_mac_addr_cpy(dev_test_task_data->collector, mac);
|
|
dev_test_task_data->collector_vaild = 1;
|
|
iot_cus_printf("%s: collector mac[%02x:%02x:%02x:%02x:%02x:"
|
|
"%02x] updated\n", __FUNCTION__,
|
|
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
|
}
|
|
/* clear the cnt for expand the span of collector's address */
|
|
dev_test_task_data->collector_vaild_cnt = 0;
|
|
|
|
#else
|
|
|
|
(void)mac;
|
|
|
|
#endif
|
|
}
|
|
|
|
static uint8_t iot_dev_test_handle_normal_data(iot_pkt_t *pkt)
|
|
{
|
|
uint8_t consumed = 0;
|
|
uint8_t *ptr = NULL;
|
|
iot_plc_msdu_recv_t *msdu = NULL;
|
|
proto_conn_less_mr_t *meter;
|
|
uint8_t *mac;
|
|
uint16_t app_sn;
|
|
uint16_t offset_sz;
|
|
|
|
iot_plc_msg_header_t *hdr =
|
|
(iot_plc_msg_header_t*)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA);
|
|
msdu = (iot_plc_msdu_recv_t*)(hdr + 1);
|
|
|
|
ptr = msdu->data;
|
|
|
|
meter = (proto_conn_less_mr_t *)(ptr + sizeof(proto_conn_less_hdr_t));
|
|
app_sn = meter->seq;
|
|
if (dev_test_task_data->m2m_sub_mode == IOT_DEV_TEST_M2M_SUBMODE_CIU
|
|
&& meter->m2m_switch_mode == IOT_DEV_TEST_M2M_MODE_SWITCH_ENABLE
|
|
&& dev_test_task_data->dev_mode == IOT_DEV_TEST_APP_MODE_M2S) {
|
|
dev_test_task_data->dev_mode = IOT_DEV_TEST_APP_MODE_M2M;
|
|
iot_cus_printf("%s: set dev mode from M2S to M2M\n", __FUNCTION__);
|
|
/* If M2M CIU mode, need to query addr from CIU */
|
|
os_start_timer(dev_test_task_data->query_addr_tm,
|
|
IOT_DEV_TEST_QUERY_ADDR_TIMER_INTERVAL);
|
|
}
|
|
|
|
if (dev_test_task_data->dev_mode == IOT_DEV_TEST_APP_MODE_M2S) {
|
|
/* data direction must: slave->master */
|
|
if (meter->dir != CONN_LESS_APP_DIR_SLAVE) {
|
|
iot_cus_printf("%s:M2S MODE -- invalid direction\n", __FUNCTION__);
|
|
return consumed;
|
|
}
|
|
/* when conditions satisfied, send the response data to UART:
|
|
* rule 1: the msdu source address is matched with the address
|
|
* stored in the frame data infor pool;
|
|
* rule 2: the address field of the response message is same as
|
|
the address stored in the frame data infor pool.
|
|
* any one of the rule 1 and rule 2 is effective, together with the
|
|
* sequnce number matched, the reponse message should be reported.
|
|
*/
|
|
mac = msdu->src;
|
|
if (iot_dev_test_frame_rpt_check(mac, app_sn)
|
|
|| (iot_dev_test_addr_in_data_check(meter->data, meter->data_len,
|
|
app_sn) == ERR_OK)) {
|
|
iot_cus_printf("%s: rpt condition satisfied, sn %lu,"
|
|
"mac[%02x:%02x:%02x:%02x:%02x:%02x]\n", __FUNCTION__, app_sn,
|
|
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
|
offset_sz = sizeof(*msdu) + sizeof(*hdr) + sizeof(*meter) +
|
|
sizeof(proto_conn_less_hdr_t);
|
|
iot_pkt_pull(pkt, offset_sz);
|
|
/* update the collector'a address if neccessory */
|
|
iot_dev_test_update_collector_mac(mac);
|
|
|
|
/* check the frame is a signal attr response command or not */
|
|
iot_dev_test_fullfil_rsp_snr_cmd(iot_pkt_data(pkt),
|
|
iot_pkt_data_len(pkt), msdu->snr, msdu->rssi);
|
|
|
|
iot_dev_test_data_print("m2s msdu recv", iot_pkt_data(pkt),
|
|
(uint16_t)iot_pkt_data_len(pkt));
|
|
|
|
iot_dev_test_uart_send(pkt);
|
|
consumed = 1;
|
|
} else {
|
|
iot_cus_printf("%s: pkt dropped for info mismatch, sn %lu, mac"
|
|
"[%02x:%02x:%02x:%02x:%02x:%02x]\n", __FUNCTION__, app_sn,
|
|
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
|
}
|
|
} else if (dev_test_task_data->dev_mode == IOT_DEV_TEST_APP_MODE_M2M) {
|
|
if (IOT_DEV_TEST_BROADCAST_MODD_CFG) {
|
|
if (meter->dir != CONN_LESS_APP_DIR_M2M) {
|
|
iot_cus_printf("%s:M2M MODE -- invalid direction\n",
|
|
__FUNCTION__);
|
|
return consumed;
|
|
}
|
|
}
|
|
|
|
mac = msdu->dst;
|
|
if (iot_dev_test_app_pkt_report_check(mac, app_sn)) {
|
|
iot_cus_printf("%s: received master -> master pkt from"
|
|
"[%02x:%02x:%02x:%02x:%02x:%02x]\n", __FUNCTION__,
|
|
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
|
offset_sz = sizeof(*msdu) + sizeof(*hdr) + sizeof(*meter) +
|
|
sizeof(proto_conn_less_hdr_t);
|
|
iot_pkt_pull(pkt, offset_sz);
|
|
iot_dev_test_uart_send(pkt);
|
|
consumed = 1;
|
|
} else {
|
|
iot_cus_printf("%s: pkt drooped for local addr is set "
|
|
"and dst addr is not matched with local addr", __FUNCTION__);
|
|
}
|
|
}
|
|
|
|
return consumed;
|
|
|
|
}
|
|
|
|
static int8_t iot_dev_test_get_fix_ppm(void)
|
|
{
|
|
iot_dev_test_pib_t *pib = &dev_test_task_data->flashinfo;
|
|
iot_dev_test_ppm_detec_desc_t * ppm_desc = &dev_test_task_data->ppm_desc;
|
|
int8_t ppm = ppm_desc->fix_ppm;
|
|
|
|
if (pib->tool_ppm_valid) {
|
|
ppm = ppm_desc->fix_ppm - pib->tool_ppm;
|
|
}
|
|
return ppm;
|
|
}
|
|
|
|
#if (IOT_DEV_TEST_HANDLE_PUSH_DATA_EN == 1) || (IOT_DEV_TEST_BROADCAST_MODD_CFG == 0)
|
|
|
|
/* ask for mac to indicate the modual is ready to handle cmd from CIU */
|
|
static void iot_dev_test_send_bootup_indication(void)
|
|
{
|
|
|
|
iot_pkt_t *pkt = NULL;
|
|
static uint8_t boot_ind_cnt = 0;
|
|
static uint8_t intvl_cnt = 0;
|
|
|
|
if (dev_test_task_data->boot_ind_en) {
|
|
intvl_cnt++;
|
|
if (intvl_cnt >= IOT_DEV_TEST_BOOT_IND_RETRY_INTV) {
|
|
pkt = proto_645_2007_build_ra_msg();
|
|
|
|
if (NULL != pkt) {
|
|
iot_dev_test_data_print("send bootup indicatio: ",
|
|
iot_pkt_data(pkt), (uint16_t)iot_pkt_data_len(pkt));
|
|
iot_dev_test_uart_send(pkt);
|
|
boot_ind_cnt++;
|
|
if (boot_ind_cnt > IOT_DEV_TEST_BOOT_IND_RETRY_MAX_CNT) {
|
|
dev_test_task_data->boot_ind_en = 0;
|
|
}
|
|
intvl_cnt = 0;
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* stop sending indication after received the response from CIU */
|
|
static void iot_dev_test_stop_send_bootup_ind(void)
|
|
{
|
|
if (dev_test_task_data->boot_ind_en == 1) {
|
|
dev_test_task_data->boot_ind_en = 0;
|
|
iot_cus_printf("stop sending the ind\n", __FUNCTION__);
|
|
}
|
|
}
|
|
|
|
static uint8_t iot_dev_test_pushed_data_rpt_check(uint8_t *mac, uint16_t seq)
|
|
{
|
|
uint8_t ret = 0;
|
|
uint8_t *match_mac = dev_test_task_data->flashinfo.match_mac;
|
|
if (iot_mac_addr_cmp(mac, match_mac)
|
|
&& (seq != dev_test_task_data->pushed_seq) && (seq != 0)) {
|
|
/* update pushed-data's seq */
|
|
dev_test_task_data->pushed_seq = seq;
|
|
ret = 1;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* handle pushed-data from PLC */
|
|
static uint8_t iot_dev_test_handle_pushed_data(iot_pkt_t *pkt)
|
|
{
|
|
uint8_t consumed = 0;
|
|
uint8_t *ptr = NULL;
|
|
iot_plc_msdu_recv_t *msdu = NULL;
|
|
proto_conn_less_push_data_t *p_data;
|
|
uint8_t *mac;
|
|
uint16_t seq;
|
|
uint16_t offset_sz;
|
|
|
|
iot_plc_msg_header_t *hdr =
|
|
(iot_plc_msg_header_t*)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA);
|
|
msdu = (iot_plc_msdu_recv_t*)(hdr + 1);
|
|
|
|
ptr = msdu->data;
|
|
|
|
p_data =
|
|
(proto_conn_less_push_data_t *)(ptr + sizeof(proto_conn_less_hdr_t));
|
|
seq = p_data->seq;
|
|
|
|
iot_dev_test_data_print("pushed msdu recv all", iot_pkt_data(pkt),
|
|
(uint16_t)iot_pkt_data_len(pkt));
|
|
|
|
if (dev_test_task_data->dev_mode == IOT_DEV_TEST_APP_MODE_M2S) {
|
|
/* data direction must: master->slave */
|
|
if (p_data->dir != CONN_LESS_APP_DIR_SLAVE) {
|
|
iot_cus_printf("%s:invalid direction\n", __FUNCTION__);
|
|
return consumed;
|
|
}
|
|
|
|
mac = p_data->addr;
|
|
iot_mac_addr_reverse(mac);
|
|
if (iot_dev_test_pushed_data_rpt_check(mac, seq)) {
|
|
iot_cus_printf("%s: pushed data rpt condition satisfied, seq %lu,"
|
|
"mac[%02x:%02x:%02x:%02x:%02x:%02x]\n", __FUNCTION__, seq,
|
|
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
|
offset_sz = sizeof(*msdu) + sizeof(*hdr) + sizeof(*p_data) +
|
|
sizeof(proto_conn_less_hdr_t);
|
|
iot_pkt_pull(pkt, offset_sz);
|
|
|
|
iot_dev_test_data_print("pushed msdu recv", iot_pkt_data(pkt),
|
|
(uint16_t)iot_pkt_data_len(pkt));
|
|
|
|
iot_dev_test_uart_send(pkt);
|
|
consumed = 1;
|
|
} else {
|
|
iot_cus_printf("%s: pkt dropped for info mismatch: seq[%lu], from"
|
|
"[%02x:%02x:%02x:%02x:%02x:%02x]\n", __FUNCTION__, seq,
|
|
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
|
}
|
|
}
|
|
|
|
return consumed;
|
|
|
|
}
|
|
|
|
/* handle pushed-data's ack from CIU */
|
|
static uint8_t iot_dev_test_handle_ack_data_from_host(
|
|
proto_645_header_t *hdr_645)
|
|
{
|
|
uint16_t total_sz, payload_sz;
|
|
proto_conn_less_hdr_t *hdr;
|
|
proto_conn_less_push_data_t *p_data;
|
|
iot_pkt_t *msdu_pkt;
|
|
uint8_t dst_mac[IOT_MAC_ADDR_LEN] = { 0 };
|
|
uint8_t *ptr = NULL;
|
|
uint8_t ret = ERR_FAIL;
|
|
uint8_t reason = 0;
|
|
|
|
if (0 == dev_test_task_data->collector_vaild) {
|
|
iot_mac_addr_cpy(dst_mac,(uint8_t *)bcast_mac);
|
|
} else {
|
|
iot_mac_addr_cpy(dst_mac, dev_test_task_data->collector);
|
|
}
|
|
|
|
if (!iot_mac_addr_valid(dst_mac)) {
|
|
reason = 1;
|
|
goto out;
|
|
}
|
|
|
|
payload_sz = sizeof(*hdr_645) + hdr_645->len + sizeof(proto_645_tailer_t);
|
|
total_sz = sizeof(*hdr) + sizeof(*p_data) + payload_sz;
|
|
|
|
msdu_pkt = iot_plc_alloc_conn_less_msdu(dev_test_task_data->app_handle,
|
|
IOT_PLC_MSG_TYPE_CONN_LESS_DATA, dst_mac, dev_test_task_data->mac_addr,
|
|
CONN_LESS_APP_PRIO_METER_READ, total_sz, IOT_PLC_MAX_RETRY_CNT);
|
|
if (msdu_pkt) {
|
|
ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_TAIL);
|
|
/* fill in header */
|
|
hdr = (proto_conn_less_hdr_t *)ptr;
|
|
hdr->id = CONN_LESS_APP_ID_DATA_PUSH;
|
|
hdr->port = CONN_LESS_APP_PORT;
|
|
|
|
p_data = (proto_conn_less_push_data_t *)(hdr + 1);
|
|
p_data->seq = iot_dev_test_app_get_sn();
|
|
p_data->data_len = payload_sz;
|
|
p_data->dir = CONN_LESS_APP_DIR_MASTER;
|
|
/* fill in payload */
|
|
os_mem_cpy(p_data->data, hdr_645, payload_sz);
|
|
iot_pkt_put(msdu_pkt, total_sz);
|
|
iot_plc_send_msdu(dev_test_task_data->app_handle, msdu_pkt);
|
|
ret = ERR_OK;
|
|
} else {
|
|
reason = 2;
|
|
}
|
|
|
|
out:
|
|
iot_cus_printf("%s result %lu, reason %lu\n", __FUNCTION__, ret, reason);
|
|
return ret;
|
|
}
|
|
|
|
/* set module address once the meter address changed */
|
|
static void iot_dev_test_config_mac(uint8_t *mac)
|
|
{
|
|
iot_plc_cfg_set_req_t cfg = {0};
|
|
iot_plc_app_h app_hdl = dev_test_task_data->app_handle;
|
|
|
|
if (!iot_mac_addr_valid(mac) || iot_mac_is_bcast(mac)) {
|
|
return;
|
|
}
|
|
|
|
iot_mac_addr_cpy(cfg.addr, mac);
|
|
cfg.addr_valid = 1;
|
|
cfg.reset = 1;
|
|
cfg.dev_type_valid = 1;
|
|
cfg.dev_type = IOT_PLC_DEV_TYPE_METER_CONTROLLER;
|
|
iot_plc_set_cfg(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT, &cfg);
|
|
iot_cus_printf("%s: config local mac[%02x:%02x:%02x:%02x:%02x:%02x] "
|
|
"successfully\n", __FUNCTION__, cfg.addr[0], cfg.addr[1],
|
|
cfg.addr[2], cfg.addr[3], cfg.addr[4], cfg.addr[5]);
|
|
os_delay (500);
|
|
|
|
/* here, update the local MAC in advance to avoid dropping the
|
|
* first packet.
|
|
*/
|
|
iot_mac_addr_cpy(dev_test_task_data->mac_addr, mac);
|
|
|
|
/* set default frequnce band */
|
|
#if (IOT_DEV_TEST_SUPPORT_MUTIBAND == 1)
|
|
iot_plc_set_freq_band(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT,
|
|
PLC_LIB_FREQ_BAND_MULTI_1_2);
|
|
#else
|
|
iot_plc_set_freq_band(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT,
|
|
dev_test_task_data->band_id);
|
|
#endif
|
|
}
|
|
|
|
/* update the matching mac when a new cmd received */
|
|
static void iot_dev_test_update_match_mac(uint8_t *mac)
|
|
{
|
|
uint8_t reason = 0;
|
|
iot_dev_test_pib_t *p_info = &dev_test_task_data->flashinfo;
|
|
|
|
if (!iot_mac_addr_valid(mac) || iot_mac_is_bcast(mac)) {
|
|
reason = 1;
|
|
goto out;
|
|
}
|
|
if (iot_mac_addr_cmp(mac, p_info->match_mac)) {
|
|
reason = 2;
|
|
goto out;
|
|
}
|
|
|
|
iot_mac_addr_cpy(p_info->match_mac, mac);
|
|
iot_dev_test_flash_save(p_info);
|
|
iot_dev_test_config_mac(mac);
|
|
dev_test_task_data->collector_vaild = 0;
|
|
|
|
iot_cus_printf("%s: matching mac[%02x:%02x:%02x:%02x:%02x:%02x] "
|
|
"successfully, collector address vaild: %d\n", __FUNCTION__, mac[0],
|
|
mac[1], mac[2],mac[3], mac[4], mac[5],
|
|
dev_test_task_data->collector_vaild);
|
|
out:
|
|
iot_cus_printf("%s reason %lu\n", __FUNCTION__, reason);
|
|
}
|
|
|
|
#else /* IOT_DEV_TEST_HANDLE_PUSH_DATA_EN == 1 */
|
|
|
|
static void iot_dev_test_send_bootup_indication(void)
|
|
{
|
|
return;
|
|
}
|
|
|
|
static void iot_dev_test_stop_send_bootup_ind(void)
|
|
{
|
|
return;
|
|
}
|
|
|
|
static uint8_t iot_dev_test_handle_pushed_data(iot_pkt_t *pkt)
|
|
{
|
|
(void)pkt;
|
|
return ERR_OK;
|
|
}
|
|
|
|
static uint8_t iot_dev_test_handle_ack_data_from_host(
|
|
proto_645_header_t *hdr_645)
|
|
{
|
|
(void)hdr_645;
|
|
return ERR_OK;
|
|
}
|
|
|
|
static void iot_dev_test_update_match_mac(uint8_t *mac)
|
|
{
|
|
(void)mac;
|
|
}
|
|
|
|
#endif /* IOT_DEV_TEST_HANDLE_PUSH_DATA_EN == 0 */
|
|
|
|
static uint8_t iot_dev_test_config_data_hdl_check(uint8_t *mac, uint16_t seq)
|
|
{
|
|
uint8_t ret = 0;
|
|
uint8_t *local_mac = dev_test_task_data->mac_addr;
|
|
|
|
if (!mac || !seq) {
|
|
goto out;
|
|
}
|
|
if (seq == dev_test_task_data->config_seq) {
|
|
goto out;
|
|
}
|
|
if (iot_mac_addr_cmp(mac, local_mac)) {
|
|
dev_test_task_data->config_seq = seq;
|
|
ret = 1;
|
|
}
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static uint8_t iot_dev_test_config_pack_plc_rsp_data(uint8_t *dst, uint16_t sn,
|
|
uint8_t *data, uint16_t len)
|
|
{
|
|
uint32_t buflen = 0;
|
|
uint8_t *ptr = NULL;
|
|
iot_pkt_t *msdu_pkt;
|
|
proto_conn_less_hdr_t *proto_hdr;
|
|
proto_conn_less_mr_t *meter;
|
|
iot_dev_test_task_data_t *dev_glb = dev_test_task_data;
|
|
int8_t fix_ppm;
|
|
|
|
if(!dst || !data || !len) {
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
fix_ppm = iot_dev_test_get_fix_ppm();
|
|
buflen = sizeof(proto_conn_less_hdr_t) + sizeof(proto_conn_less_mr_t) + len;
|
|
msdu_pkt = iot_plc_alloc_conn_less_msdu_ext(dev_glb->app_handle,
|
|
IOT_PLC_MSG_TYPE_CONN_LESS_DATA, dst, dev_glb->mac_addr,
|
|
dev_glb->link_id, (uint16_t)buflen, IOT_PLC_MAX_RETRY_CNT,
|
|
fix_ppm, 0, dev_glb->tx_link_type);
|
|
|
|
if (msdu_pkt == NULL) {
|
|
iot_cus_printf("allocate msdu fail\n");
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_TAIL);
|
|
iot_pkt_put(msdu_pkt, buflen);
|
|
proto_hdr = (proto_conn_less_hdr_t *)ptr;
|
|
proto_hdr->id = CONN_LESS_APP_ID_CONFIG;
|
|
proto_hdr->port = CONN_LESS_APP_PORT;
|
|
|
|
ptr += sizeof(proto_conn_less_hdr_t);
|
|
meter = (proto_conn_less_mr_t *)ptr;
|
|
meter->data_len = len;
|
|
meter->mr_timeout = IOT_DEV_TEST_CFG_MR_TIMEOUT;
|
|
|
|
meter->seq = sn;
|
|
meter->dir = CONN_LESS_APP_DIR_SLAVE;
|
|
meter->option.dl_ppm_desc.value = 0;
|
|
meter->data_type = GW_APP_DATA_TYPE_645_2007;
|
|
meter->retry_cnt = 0;
|
|
os_mem_cpy(meter->data, data, len);
|
|
|
|
iot_cus_printf("app conn_less send to[%02x:%02x:%02x:%02x:%02x:%02x]"
|
|
", sn %lu, len %lu, fix ppm %d\n", dst[0], dst[1],
|
|
dst[2], dst[3], dst[4], dst[5], sn, buflen, fix_ppm);
|
|
iot_plc_send_msdu(dev_test_task_data->app_handle, msdu_pkt);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief: creat a rsponse frame based on 645 protocal.
|
|
* @param rsp_fn: response Fn code
|
|
* @param data: pointer to data that fullfiled into the frame's data field
|
|
* @param len: data lenth that fullfiled into the frame's data field
|
|
* @retval: 0 -- success
|
|
* @retval: others -- failed
|
|
*/
|
|
static uint8_t iot_dev_test_form_rsp_data_frame(uint8_t rsp_fn, uint8_t *data,
|
|
uint8_t len)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
proto_645_header_t *hdr_645;
|
|
proto_645_tailer_t *tail_645;
|
|
uint8_t pkt_len;
|
|
uint8_t *ptr = NULL;
|
|
uint8_t ret = ERR_OK;
|
|
|
|
pkt_len = IOT_DEV_TEST_RSP_FRAME_LEN_MIN + len;
|
|
pkt = iot_pkt_alloc(pkt_len, IOT_APP_DEV_TEST_MID);
|
|
if (pkt != NULL) {
|
|
ptr = iot_pkt_data(pkt);
|
|
hdr_645 = (proto_645_header_t *)ptr;
|
|
|
|
hdr_645->start_char_1 = PROTO_645_START_CHAR;
|
|
iot_mac_addr_cpy(hdr_645->addr, spec_mac);
|
|
iot_mac_addr_reverse(hdr_645->addr);
|
|
hdr_645->len = len;
|
|
hdr_645->control.fn = rsp_fn;
|
|
hdr_645->control.dir = PROTO_645_DIR_SLAVE;
|
|
hdr_645->control.ack = PROTO_645_ACK_NORMAL;
|
|
hdr_645->control.follow = PROTO_645_FOLLOW_INVALID;
|
|
hdr_645->start_char_2 = PROTO_645_START_CHAR;
|
|
os_mem_cpy(hdr_645->data, data, len);
|
|
proto_645_add33_handle(hdr_645->data, len);
|
|
ptr += sizeof(proto_645_header_t) + len;
|
|
tail_645 = (proto_645_tailer_t *)ptr;
|
|
tail_645->cs = proto_645_calc_cs(hdr_645);
|
|
tail_645->end_char = PROTO_645_END_CHAR;
|
|
iot_pkt_put (pkt, (sizeof(*hdr_645) + len + sizeof(*tail_645)));
|
|
iot_dev_test_uart_send(pkt);
|
|
} else {
|
|
iot_cus_printf("%s: alloc pkt failed!\n", __FUNCTION__);
|
|
ret = ERR_FAIL;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief: creat a confirm frame based on 645 protocal.
|
|
* @param result: 0-no error, 1-error
|
|
* @param reason: error reason
|
|
* @param len: data lenth that fullfiled into the frame's data field
|
|
* @retval: 0 -- success
|
|
* @retval: others -- failed
|
|
*/
|
|
static uint8_t iot_dev_test_form_rsp_cfm_frame(uint8_t fn, uint8_t result,
|
|
uint8_t reason)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
proto_645_header_t *hdr_645;
|
|
proto_645_tailer_t *tail_645;
|
|
uint8_t pkt_len;
|
|
uint8_t *ptr = NULL;
|
|
uint8_t ret = ERR_OK;
|
|
|
|
if (result != 0) {
|
|
pkt_len = IOT_DEV_TEST_RSP_FRAME_LEN_MIN + 1;
|
|
} else {
|
|
pkt_len = IOT_DEV_TEST_RSP_FRAME_LEN_MIN;
|
|
}
|
|
|
|
pkt = iot_pkt_alloc(pkt_len, IOT_APP_DEV_TEST_MID);
|
|
if (pkt != NULL) {
|
|
ptr = iot_pkt_data(pkt);
|
|
hdr_645 = (proto_645_header_t *)ptr;
|
|
hdr_645->control.fn = fn;
|
|
hdr_645->start_char_1 = PROTO_645_START_CHAR;
|
|
iot_mac_addr_cpy(hdr_645->addr, spec_mac);
|
|
iot_mac_addr_reverse(hdr_645->addr);
|
|
hdr_645->control.dir = PROTO_645_DIR_SLAVE;
|
|
hdr_645->control.follow = PROTO_645_FOLLOW_INVALID;
|
|
hdr_645->start_char_2 = PROTO_645_START_CHAR;
|
|
|
|
if (result == 0) {
|
|
/* ack normal */
|
|
hdr_645->len = 0;
|
|
hdr_645->control.ack = PROTO_645_ACK_NORMAL;
|
|
} else {
|
|
hdr_645->len = 1;
|
|
hdr_645->control.ack = PROTO_645_ACK_ABNORMAL;
|
|
hdr_645->data[0] = reason + 0x33;
|
|
}
|
|
|
|
ptr += sizeof(proto_645_header_t) + hdr_645->len;
|
|
tail_645 = (proto_645_tailer_t *)ptr;
|
|
tail_645->cs = proto_645_calc_cs(hdr_645);
|
|
tail_645->end_char = PROTO_645_END_CHAR;
|
|
iot_pkt_put (pkt, (sizeof(*hdr_645) + hdr_645->len +
|
|
sizeof(*tail_645)));
|
|
iot_dev_test_data_print("SEND_UART frame:", iot_pkt_data(pkt),
|
|
(uint16_t)iot_pkt_data_len(pkt));
|
|
|
|
iot_cus_printf("SEND_UART_CMD_RSP frame: fn 0x%02x, result 0x%02x\n",
|
|
fn, result);
|
|
|
|
iot_dev_test_uart_send(pkt);
|
|
} else {
|
|
iot_cus_printf("%s: alloc pkt failed!\n", __FUNCTION__);
|
|
ret = ERR_FAIL;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief: set frequnce band
|
|
* @param bandid: band index
|
|
*/
|
|
static void iot_dev_test_set_band(uint8_t bandid)
|
|
{
|
|
if (bandid > IOT_DEV_TEST_MAX_BAND) {
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_BAND,
|
|
IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_OUT_RNG);
|
|
iot_cus_printf("%s [err]band setting out of range\n", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
if (dev_test_task_data->band_id == bandid) {
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_BAND,
|
|
IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_DUP_SET);
|
|
iot_cus_printf("%s [err]Already in band-%lu\n", __FUNCTION__, bandid);
|
|
return;
|
|
}
|
|
dev_test_task_data->band_id = bandid;
|
|
iot_plc_set_freq_band(dev_test_task_data->app_handle,
|
|
IOT_PLC_API_REQ_ID_DEFAULT, bandid);
|
|
iot_printf("%s set freq-band to band-%lu ok\n",__FUNCTION__, bandid);
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_BAND,
|
|
IOT_DEV_TEST_RSP_OK, IOT_DEV_TEST_REASON_OK);
|
|
}
|
|
|
|
/* get the band's ID and creat a respons frame then send to mointor */
|
|
static void iot_dev_test_querry_band_handle(void)
|
|
{
|
|
uint8_t rsp_data[IOT_DEV_TEST_DATA_FIELD_LEN] = { 0 };
|
|
rsp_data[0] = dev_test_task_data->band_id;
|
|
iot_cus_printf("%s rsponse band id: %lu\n", __FUNCTION__, rsp_data[0]);
|
|
iot_dev_test_form_rsp_data_frame(IOT_DEV_TEST_FN_QUERRY_BAND_RSP,
|
|
rsp_data, IOT_DEV_TEST_DATA_FIELD_LEN);
|
|
}
|
|
|
|
/* get the software version and creat a respons frame then send to mointor */
|
|
static void iot_dev_test_querry_ver_handle(void)
|
|
{
|
|
uint32_t ver = 0;
|
|
uint8_t rsp_data[IOT_DEV_TEST_DATA_FIELD_LEN] = { 0 };
|
|
ver = iot_version_hex();
|
|
rsp_data[0] = ver & 0xFF;
|
|
rsp_data[1] = (ver >> 8) & 0xFF;
|
|
rsp_data[2] = (ver >> 16) & 0xFF;
|
|
rsp_data[3] = (ver >> 24) & 0xFF;
|
|
iot_cus_printf("%s software verison: 0x%x\n", __FUNCTION__, ver);
|
|
iot_dev_test_form_rsp_data_frame(IOT_DEV_TEST_FN_QUERRY_VER_RSP,
|
|
rsp_data, IOT_DEV_TEST_DATA_FIELD_LEN);
|
|
}
|
|
|
|
/**
|
|
* @brief: set mac address
|
|
* @param mac: pointer to mac address which will be set
|
|
*/
|
|
static void iot_dev_test_set_mac(uint8_t *mac)
|
|
{
|
|
iot_plc_cfg_set_req_t cfg;
|
|
iot_plc_app_h app_hdl = dev_test_task_data->app_handle;
|
|
|
|
if (!iot_mac_addr_valid(mac) || iot_mac_is_bcast(mac)) {
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_MAC,
|
|
IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_MAC_INVALID);
|
|
iot_cus_printf("%s [err]mac invalid, all zero or boardcast mac will "
|
|
"not be set!\n", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
if (iot_mac_addr_cmp(dev_test_task_data->mac_addr, mac))
|
|
{
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_MAC,
|
|
IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_DUP_SET);
|
|
iot_cus_printf("%s [err]new mac is same as the using one\n",
|
|
__FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
os_mem_set(&cfg, 0, sizeof(cfg));
|
|
cfg.addr_valid = 1;
|
|
cfg.addr_type = IOT_PLC_MAC_ADDR_TYPE_METER;
|
|
iot_mac_addr_cpy(cfg.addr, mac);
|
|
cfg.reset = 1;
|
|
cfg.dev_type_valid = 1;
|
|
cfg.dev_type = IOT_PLC_DEV_TYPE_METER_CONTROLLER;
|
|
iot_plc_set_cfg(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT, &cfg);
|
|
|
|
iot_printf("%s set mac to [%02x:%02x:%02x:%02x:%02x:%02x] successfully\n",
|
|
__FUNCTION__, mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
|
|
dev_test_task_data->m2m_check_addr = IOT_DEV_TEST_ADDR_SET;
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_MAC,
|
|
IOT_DEV_TEST_RSP_OK, IOT_DEV_TEST_REASON_OK);
|
|
}
|
|
|
|
/* get the local mac address and creat a respons frame then send to mointor */
|
|
static void iot_dev_test_querry_mac_handle(void)
|
|
{
|
|
uint8_t rsp_data[IOT_DEV_TEST_DATA_FIELD_LEN + 2] = { 0 };
|
|
iot_mac_addr_cpy(rsp_data, dev_test_task_data->mac_addr);
|
|
iot_cus_printf("%s rsponse local mac:[%02x:%02x:%02x:%02x:%02x:%02x]\n",
|
|
__FUNCTION__, rsp_data[0], rsp_data[1], rsp_data[2], rsp_data[3],
|
|
rsp_data[4], rsp_data[5]);
|
|
iot_mac_addr_reverse (rsp_data);
|
|
iot_dev_test_form_rsp_data_frame(IOT_DEV_TEST_FN_QUERRY_MAC_RSP,
|
|
rsp_data, IOT_DEV_TEST_DATA_FIELD_LEN + 2);
|
|
}
|
|
|
|
/* set dev test op mode and creat a respons frame then send to mointor */
|
|
static void iot_dev_test_set_op_mode(uint8_t op_mode)
|
|
{
|
|
if (op_mode >= IOT_DEV_TEST_APP_MODE_MAX) {
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_OP_MODE,
|
|
IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_OUT_RNG);
|
|
iot_cus_printf("%s [err]invalid op mode\n", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
if (dev_test_task_data->dev_mode == op_mode) {
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_OP_MODE,
|
|
IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_DUP_SET);
|
|
iot_cus_printf("%s [err]new op mode is same as the using one\n",
|
|
__FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
dev_test_task_data->dev_mode = op_mode;
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_OP_MODE,
|
|
IOT_DEV_TEST_RSP_OK, IOT_DEV_TEST_REASON_OK);
|
|
}
|
|
|
|
/* query CKQ current operation mode */
|
|
static void iot_dev_test_query_op_mode()
|
|
{
|
|
uint8_t rsp_data[IOT_DEV_TEST_DATA_FIELD_LEN] = { 0 };
|
|
/* rsp_data is a 4-byte array, refer to 645 frame format */
|
|
rsp_data[0] = dev_test_task_data->dev_mode;
|
|
iot_dev_test_form_rsp_data_frame(IOT_DEV_TEST_FN_QUERY_OP_MODE_RSP,
|
|
rsp_data, IOT_DEV_TEST_DATA_FIELD_LEN);
|
|
}
|
|
|
|
/* set the compensation ppm value, */
|
|
static uint32_t proto_handle_645_set_tool_ppm(uint8_t *in_data,
|
|
uint8_t in_len, uint8_t* out_buf, uint8_t *out_len)
|
|
{
|
|
iot_dev_test_pib_t *pib = &dev_test_task_data->flashinfo;
|
|
int8_t tool_ppm;
|
|
uint8_t *ptr = NULL;
|
|
uint32_t di = PROTO_645_2007_EXT_WRITE_TOOL_PPM;
|
|
|
|
ptr = in_data + PROTO_645_2007_DI_LEN;
|
|
tool_ppm = (int8_t)*ptr;
|
|
if (IOT_ABS(tool_ppm) > IOT_DEV_TEST_MAX_TOOL_PPM) {
|
|
iot_cus_printf("%s invalid tool_ppm %d\n", __FUNCTION__, tool_ppm);
|
|
return PROTO_645_2007_ERR_OTHER;
|
|
}
|
|
|
|
if ((tool_ppm != pib->tool_ppm) || !pib->tool_ppm_valid) {
|
|
pib->tool_ppm = tool_ppm;
|
|
pib->tool_ppm_valid = 1;
|
|
iot_dev_test_flash_save(pib);
|
|
iot_cus_printf("tool ppm %d saved into PIB\n", tool_ppm);
|
|
} else {
|
|
iot_cus_printf("Duplicated ppm %d setting, skip saving\n", tool_ppm);
|
|
|
|
}
|
|
|
|
proto_645_2007_di_to_byte(di, out_buf);
|
|
*out_len = PROTO_645_2007_DI_LEN;
|
|
|
|
return PROTO_645_2007_ERR_OK;
|
|
}
|
|
|
|
static uint32_t proto_handle_645_read_pt_info(uint8_t *in_data,
|
|
uint8_t in_len, uint8_t* out_buf, uint8_t *out_len)
|
|
{
|
|
proto_645_ext_read_pt_info_rsp_t *rsp_info = NULL;
|
|
iot_dev_test_pib_t *pib = &dev_test_task_data->flashinfo;
|
|
iot_dev_test_ppm_detec_desc_t *ppm_desc = &dev_test_task_data->ppm_desc;
|
|
iot_board_pt_info_t pt_info = {0};
|
|
|
|
iot_board_get_pt_info(&pt_info);
|
|
|
|
rsp_info = (proto_645_ext_read_pt_info_rsp_t *)(out_buf);
|
|
os_mem_set(rsp_info, 0, sizeof(*rsp_info));
|
|
|
|
/* production test ppm */
|
|
if (pt_info.ppm_valid) {
|
|
rsp_info->local_pt_ppm_valid = 1;
|
|
rsp_info->local_pt_ppm = pt_info.ppm;
|
|
}
|
|
/* compensation ppm, configured by the tool */
|
|
if (pib->tool_ppm_valid) {
|
|
rsp_info->local_tool_ppm_valid = 1;
|
|
rsp_info->local_tool_ppm = pib->tool_ppm;
|
|
}
|
|
/* basic production test info */
|
|
if (pt_info.basic_info_valid) {
|
|
rsp_info->basic_data_valid = 1;
|
|
iot_mac_addr_cpy(rsp_info->basic_data.golden_mac,
|
|
pt_info.basic_info.golden_mac);
|
|
rsp_info->basic_data.year = pt_info.basic_info.year;
|
|
rsp_info->basic_data.month = pt_info.basic_info.month;
|
|
rsp_info->basic_data.day = pt_info.basic_info.day;
|
|
rsp_info->basic_data.hour = pt_info.basic_info.hour;
|
|
rsp_info->basic_data.min = pt_info.basic_info.min;
|
|
rsp_info->basic_data.golden_fw_ver = pt_info.basic_info.golden_fw_ver;
|
|
rsp_info->basic_data.pt_tool_ver = pt_info.basic_info.pt_tool_ver;
|
|
rsp_info->basic_data.pt_board_ver = pt_info.basic_info.pt_board_ver;
|
|
}
|
|
/* the dut firmware version, which supported the production test */
|
|
if (pt_info.pt_dut_ver_valid) {
|
|
rsp_info->pt_dut_fw_valid = 1;
|
|
rsp_info->pt_dut_fw_ver = pt_info.pt_dut_ver;
|
|
}
|
|
/* fix ppm */
|
|
rsp_info->local_fix_ppm = ppm_desc->fix_ppm;
|
|
rsp_info->local_fix_ppm_valid = 1;
|
|
|
|
*out_len = sizeof(*rsp_info);
|
|
|
|
return PROTO_645_2007_ERR_OK;
|
|
}
|
|
|
|
static iot_pkt_t *iot_dev_test_config_cmd_handle(proto_645_header_t *hdr)
|
|
{
|
|
uint8_t fn, err_code = 0;
|
|
uint32_t len;
|
|
uint8_t out_len;
|
|
iot_pkt_t *pkt_645 = NULL;
|
|
uint32_t pkt_len, di;
|
|
uint8_t *out_ds, *out_buf;
|
|
uint8_t follow = PROTO_645_FOLLOW_INVALID;
|
|
uint8_t addr[IOT_MAC_ADDR_LEN] = {0};
|
|
|
|
if (!hdr ) {
|
|
goto out;
|
|
}
|
|
proto_645_get_di_by_sub33(hdr->data, PROTO_645_2007_DI_LEN,
|
|
PROTO_645_2007_ID, &di);
|
|
proto_645_sub33_handle(hdr->data, hdr->len);
|
|
pkt_len = PROTO_645_READ_DATA_MAX_LEN + sizeof(hdr)
|
|
+ sizeof(proto_645_tailer_t);
|
|
pkt_645 = iot_pkt_alloc(pkt_len, IOT_APP_DEV_TEST_MID);
|
|
out_ds = iot_pkt_data(pkt_645);
|
|
os_mem_set(dev_test_task_data->data_buf, 0, IOT_DEV_TEST_DATA_BUFF_LEN);
|
|
out_buf = dev_test_task_data->data_buf;
|
|
out_len = IOT_DEV_TEST_DATA_BUFF_LEN;
|
|
fn = hdr->control.fn;
|
|
iot_mac_addr_cpy(addr, hdr->addr);
|
|
|
|
switch (fn) {
|
|
case PROTO_645_2007_FN_READ_DATA:
|
|
{
|
|
switch (di) {
|
|
case PROTO_645_2007_EXT_QUERY_PT_INFO:
|
|
{
|
|
err_code = proto_handle_645_read_pt_info(hdr->data,
|
|
hdr->len, out_buf, &out_len);
|
|
break;
|
|
}
|
|
default:
|
|
err_code = PROTO_645_2007_ERR_NO_REQ_DATA;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case PROTO_645_2007_FN_WRITE_DATA:
|
|
{
|
|
switch (di) {
|
|
case PROTO_645_2007_EXT_WRITE_TOOL_PPM:
|
|
{
|
|
err_code = proto_handle_645_set_tool_ppm(hdr->data,
|
|
hdr->len, out_buf, &out_len);
|
|
break;
|
|
}
|
|
default:
|
|
err_code = PROTO_645_2007_ERR_NO_REQ_DATA;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
err_code = PROTO_645_2007_ERR_NO_REQ_DATA;
|
|
break;
|
|
}
|
|
|
|
if (err_code) {
|
|
len = proto_645_fill_frame(out_ds, PROTO_645_2007_ID,
|
|
addr, PROTO_645_DIR_SLAVE, PROTO_645_ACK_ABNORMAL,
|
|
follow, fn, PROTO_645_INVALID_DI, 1, &err_code);
|
|
} else {
|
|
iot_cus_printf("di 0x%04x, out len %d\n", di, out_len);
|
|
len = proto_645_fill_frame(out_ds, PROTO_645_2007_ID,
|
|
addr, PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
|
|
follow, fn, di, out_len, out_buf);
|
|
}
|
|
iot_pkt_put(pkt_645, len);
|
|
|
|
iot_dev_test_data_print("uplink 645: ", iot_pkt_data(pkt_645),
|
|
iot_pkt_data_len(pkt_645));
|
|
out:
|
|
return pkt_645;
|
|
}
|
|
|
|
/* set UART baudrate */
|
|
static void iot_dev_test_set_baudrate(uint8_t baud_index)
|
|
{
|
|
iot_dev_test_pib_t *p_info = &dev_test_task_data->flashinfo;
|
|
iot_uart_h uart_hdl = NULL;
|
|
|
|
if (baud_index >= SUPPORTED_BAUD_CNT) {
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_UART_BAUDRATE,
|
|
IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_OUT_RNG);
|
|
iot_cus_printf("%s [err]invalid input val\n", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
if (p_info->baud_index == baud_index) {
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_UART_BAUDRATE,
|
|
IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_DUP_SET);
|
|
iot_cus_printf("%s [err]new baudrate is same as the using one\n",
|
|
__FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
p_info->baud_index = baud_index;
|
|
if (iot_dev_test_flash_save(p_info)) {
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_UART_BAUDRATE,
|
|
IOT_DEV_TEST_RSP_OK, IOT_DEV_TEST_REASON_OK);
|
|
} else {
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_UART_BAUDRATE,
|
|
IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_SAVE_ERR);
|
|
}
|
|
|
|
os_delay (2000);
|
|
|
|
iot_dev_test_close_uart(dev_test_task_data->host_com);
|
|
|
|
os_delay (1000);
|
|
uart_hdl = iot_dev_test_open_uart(iot_board_get_uart(UART_METER_PORT));
|
|
if (uart_hdl == NULL) {
|
|
iot_cus_printf("open uart meter port failed!\n");
|
|
} else {
|
|
if (iot_dev_test_set_uart_config(uart_hdl)) {
|
|
iot_cus_printf("open uart meter port successfully!\n");
|
|
}
|
|
}
|
|
dev_test_task_data->host_com = uart_hdl;
|
|
|
|
}
|
|
|
|
/* query UART baudrate */
|
|
static void iot_dev_test_query_baudrate()
|
|
{
|
|
uint8_t rsp_data[IOT_DEV_TEST_DATA_FIELD_LEN] = { 0 };
|
|
/* rsp_data is a 4-byte array, refer to 645 frame format */
|
|
rsp_data[0] = dev_test_task_data->flashinfo.baud_index;
|
|
iot_dev_test_form_rsp_data_frame(IOT_DEV_TEST_FN_QUERY_BAUD_RSP,
|
|
rsp_data, IOT_DEV_TEST_DATA_FIELD_LEN);
|
|
}
|
|
|
|
/**
|
|
* @brief: set rf
|
|
* @param rf_option: rf option
|
|
* @param rf_channel: rf channel
|
|
* @param need_rsp: if need to response
|
|
*/
|
|
static void iot_dev_test_set_rf(uint8_t rf_option, uint8_t rf_channel,
|
|
uint8_t need_rsp)
|
|
{
|
|
uint8_t rf_valid = 0;
|
|
|
|
if (rf_option == IOT_PLC_RF_OPTION_1) {
|
|
rf_valid = (rf_channel < IOT_PLC_OPTION1_CHANNEL_ID_MAX);
|
|
} else if (rf_option == IOT_PLC_RF_OPTION_2) {
|
|
rf_valid = (rf_channel < IOT_PLC_OPTION2_CHANNEL_ID_MAX);
|
|
} else if (rf_option == IOT_PLC_RF_OPTION_3) {
|
|
rf_valid = (rf_channel < IOT_PLC_OPTION3_CHANNEL_ID_MAX);
|
|
}
|
|
|
|
if (!rf_valid) {
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_RF,
|
|
IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_OUT_RNG);
|
|
iot_cus_printf("%s [err]rf setting out of range\n", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
if (dev_test_task_data->ext_cfg.rf_valid &&
|
|
dev_test_task_data->ext_cfg.rf_option == rf_option &&
|
|
dev_test_task_data->ext_cfg.rf_channel == rf_channel) {
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_RF,
|
|
IOT_DEV_TEST_RSP_OK, IOT_DEV_TEST_REASON_DUP_SET);
|
|
iot_cus_printf("%s already in option-%lu channel-%lu\n",
|
|
__FUNCTION__, rf_option, rf_channel);
|
|
return;
|
|
}
|
|
|
|
dev_test_task_data->ext_cfg.rf_valid = 1;
|
|
dev_test_task_data->ext_cfg.rf_option = rf_option;
|
|
dev_test_task_data->ext_cfg.rf_channel = rf_channel;
|
|
iot_plc_set_rf_channel(dev_test_task_data->app_handle,
|
|
IOT_PLC_API_REQ_ID_DEFAULT, rf_option, rf_channel, 0);
|
|
iot_printf("%s set option to %lu channel to %lu ok\n", __FUNCTION__,
|
|
rf_option, rf_channel);
|
|
if (need_rsp) {
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_RF,
|
|
IOT_DEV_TEST_RSP_OK, IOT_DEV_TEST_REASON_OK);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief: set rf tx power
|
|
* @param rf_power: rf tx power
|
|
*/
|
|
static void iot_dev_test_set_rf_tx_power(int8_t rf_power)
|
|
{
|
|
if (!(rf_power >= IOT_PLC_RF_TX_POWER_MIN_DBM &&
|
|
rf_power <= IOT_PLC_RF_TX_POWER_MAX_DBM)) {
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_RF_TX_POWER,
|
|
IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_OUT_RNG);
|
|
iot_cus_printf("%s [err]rf tx power setting out of range\n",
|
|
__FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
if (dev_test_task_data->ext_cfg.rf_power_valid &&
|
|
dev_test_task_data->ext_cfg.rf_tx_power == rf_power) {
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_RF_TX_POWER,
|
|
IOT_DEV_TEST_RSP_OK, IOT_DEV_TEST_REASON_DUP_SET);
|
|
iot_cus_printf("%s already in rf tx power-%d\n", __FUNCTION__,
|
|
rf_power);
|
|
return;
|
|
}
|
|
|
|
dev_test_task_data->ext_cfg.rf_power_valid = 1;
|
|
dev_test_task_data->ext_cfg.rf_tx_power = rf_power;
|
|
iot_plc_set_tx_power_cap(dev_test_task_data->app_handle,
|
|
IOT_PLC_API_REQ_ID_DEFAULT, NULL,
|
|
&dev_test_task_data->ext_cfg.rf_tx_power);
|
|
iot_printf("%s set to rf tx power: %d ok\n", __FUNCTION__, rf_power);
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_RF_TX_POWER,
|
|
IOT_DEV_TEST_RSP_OK, IOT_DEV_TEST_REASON_OK);
|
|
}
|
|
|
|
/**
|
|
* @brief: set hplc tx power
|
|
* @param hplc_power: hplc tx power
|
|
*/
|
|
static void iot_dev_test_set_hplc_tx_power(uint8_t hplc_power)
|
|
{
|
|
if (!(hplc_power >= IOT_PLC_HPLC_TX_POWER_MIN_DBUV &&
|
|
hplc_power <= IOT_PLC_HPLC_TX_POWER_MAX_DBUV)) {
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_HPLC_TX_POWER,
|
|
IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_OUT_RNG);
|
|
iot_cus_printf("%s [err]hplc tx power setting out of range\n",
|
|
__FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
if (dev_test_task_data->ext_cfg.hplc_power_valid &&
|
|
dev_test_task_data->ext_cfg.hplc_tx_power == hplc_power) {
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_HPLC_TX_POWER,
|
|
IOT_DEV_TEST_RSP_OK, IOT_DEV_TEST_REASON_DUP_SET);
|
|
iot_cus_printf("%s already in hplc tx power-%lu\n", __FUNCTION__,
|
|
hplc_power);
|
|
return;
|
|
}
|
|
|
|
dev_test_task_data->ext_cfg.hplc_power_valid = 1;
|
|
dev_test_task_data->ext_cfg.hplc_tx_power = hplc_power;
|
|
iot_plc_set_tx_power_cap(dev_test_task_data->app_handle,
|
|
IOT_PLC_API_REQ_ID_DEFAULT, &dev_test_task_data->ext_cfg.hplc_tx_power,
|
|
NULL);
|
|
iot_printf("%s set to hplc tx power: %lu ok\n", __FUNCTION__, hplc_power);
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_HPLC_TX_POWER,
|
|
IOT_DEV_TEST_RSP_OK, IOT_DEV_TEST_REASON_OK);
|
|
}
|
|
|
|
/**
|
|
* @brief: set tx link type
|
|
* @param link_type: link type, see IOT_DEV_TEST_LINK_TYPE_XXX.
|
|
* @param need_rsp: if need to response
|
|
*/
|
|
static void iot_dev_test_set_tx_link_type(uint8_t link_type, uint8_t need_rsp)
|
|
{
|
|
if (link_type > IOT_PLC_TX_LINK_TYPE_MAX) {
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_TX_LINK_TYPE,
|
|
IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_OUT_RNG);
|
|
iot_cus_printf("%s [err]link type setting out of range\n",
|
|
__FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
if ((link_type == IOT_PLC_TX_LINK_TYPE_RF ||
|
|
link_type == IOT_PLC_TX_LINK_TYPE_DUAL) &&
|
|
(!dev_test_task_data->ext_cfg.rf_valid ||
|
|
!dev_test_task_data->ext_cfg_en)) {
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_TX_LINK_TYPE,
|
|
IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_CFG_INVALID);
|
|
iot_cus_printf("%s [err]invalid configuration for link type setting\n",
|
|
__FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
dev_test_task_data->tx_link_type = link_type;
|
|
iot_printf("%s set to link type: %lu ok\n", __FUNCTION__, link_type);
|
|
if (need_rsp) {
|
|
iot_dev_test_form_rsp_cfm_frame(IOT_DEV_TEST_FN_SET_TX_LINK_TYPE,
|
|
IOT_DEV_TEST_RSP_OK, IOT_DEV_TEST_REASON_OK);
|
|
}
|
|
}
|
|
|
|
static int8_t iot_dev_test_info_buf_find_slot(uint8_t *mac)
|
|
{
|
|
int8_t index;
|
|
info_pool_t *pool = &dev_test_task_data->info_pool;
|
|
uint8_t slot_found = 0;
|
|
int8_t found_indx = -1;
|
|
/* rule 1: frames' infor stored in the buffer should have different dst
|
|
* address, if one frame has same dst address with others, the new one
|
|
* should replace the old one.
|
|
* rule 2: if the flag -- send_cnt is 0, that means slot found!
|
|
*/
|
|
for (index = 0; index < IOT_DEV_TEST_POOL_NUM; index++) {
|
|
if (pool->frm_info[index].send_cnt != 0) {
|
|
if (iot_mac_addr_cmp(pool->frm_info[index].frm.dst_mac, mac)) {
|
|
found_indx = index;
|
|
iot_cus_printf("duplicated frame found, mac[%02x:%02x:%02x:"
|
|
"%02x:%02x:%02x], stored sn %lu!\n", mac[0], mac[1], mac[2],
|
|
mac[3], mac[4], mac[5], pool->frm_info[index].frm.app_sn);
|
|
break;
|
|
}
|
|
} else {
|
|
if (slot_found == 0) {
|
|
slot_found = 1;
|
|
found_indx = index;
|
|
}
|
|
}
|
|
}
|
|
|
|
return found_indx;
|
|
}
|
|
|
|
/**
|
|
* @brief: send pkt at M2M mode.
|
|
* @param frm_pkt: pkt for fullfil the msdu pkt
|
|
* @retval: 0 -- success
|
|
* @retval: others -- failed
|
|
*/
|
|
static uint8_t iot_dev_test_msdu_m2m_send(frame_pkt_t* frm_pkt)
|
|
{
|
|
uint32_t buflen = 0;
|
|
uint8_t *ptr = NULL;
|
|
iot_pkt_t *msdu_pkt;
|
|
proto_conn_less_hdr_t *proto_hdr;
|
|
proto_conn_less_mr_t *meter;
|
|
uint8_t dst_mac[IOT_MAC_ADDR_LEN] = { 0 };
|
|
|
|
buflen = sizeof(proto_conn_less_hdr_t) + sizeof(proto_conn_less_mr_t)
|
|
+ iot_pkt_data_len(frm_pkt->data);
|
|
|
|
if (IOT_DEV_TEST_M2M_SUBMODE_CIU == dev_test_task_data->m2m_sub_mode) {
|
|
iot_mac_addr_cpy(dst_mac, (uint8_t *)ciu_tester_mac);
|
|
} else {
|
|
if (iot_mac_addr_cmp(frm_pkt->dst_mac, proto_645_any_addr)) {
|
|
iot_set_bcast_mac(dst_mac);
|
|
} else {
|
|
iot_mac_addr_cpy(dst_mac, frm_pkt->dst_mac);
|
|
}
|
|
}
|
|
|
|
msdu_pkt = iot_plc_alloc_conn_less_msdu_ext(dev_test_task_data->app_handle,
|
|
IOT_PLC_MSG_TYPE_CONN_LESS_DATA, dst_mac, dev_test_task_data->mac_addr,
|
|
dev_test_task_data->link_id, (uint16_t)buflen, 0, 0, 0,
|
|
dev_test_task_data->tx_link_type);
|
|
|
|
if (msdu_pkt == NULL) {
|
|
iot_cus_printf("allocate msdu fail\n");
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_TAIL);
|
|
iot_pkt_put(msdu_pkt, buflen);
|
|
proto_hdr = (proto_conn_less_hdr_t *)ptr;
|
|
proto_hdr->id = CONN_LESS_APP_ID_METER_R;
|
|
proto_hdr->port = CONN_LESS_APP_PORT;
|
|
|
|
ptr += sizeof(proto_conn_less_hdr_t);
|
|
meter = (proto_conn_less_mr_t *)ptr;
|
|
meter->data_len = iot_pkt_data_len(frm_pkt->data);
|
|
meter->mr_timeout = IOT_DEV_TEST_CFG_MR_TIMEOUT;
|
|
meter->seq = iot_dev_test_app_get_sn();
|
|
/* Check the dev operation mode to set DIR */
|
|
meter->dir = CONN_LESS_APP_DIR_M2M;
|
|
if (dev_test_task_data->m2m_sub_mode ==IOT_DEV_TEST_M2M_SUBMODE_CIUTESTER) {
|
|
meter->m2m_switch_mode = IOT_DEV_TEST_M2M_MODE_SWITCH_ENABLE;
|
|
}
|
|
meter->option.dl_ppm_desc.value = 0;
|
|
|
|
if (frm_pkt->data) {
|
|
ptr = iot_pkt_data(frm_pkt->data);
|
|
os_mem_cpy(meter->data, ptr, iot_pkt_data_len(frm_pkt->data));
|
|
iot_pkt_free(frm_pkt->data);
|
|
}
|
|
|
|
iot_cus_printf("%s: app conn_less send to[%02x:%02x:%02x:%02x:%02x:%02x],"
|
|
" len %lu, link_type %lu\n", __FUNCTION__, frm_pkt->dst_mac[0],
|
|
frm_pkt->dst_mac[1], frm_pkt->dst_mac[2], frm_pkt->dst_mac[3],
|
|
frm_pkt->dst_mac[4], frm_pkt->dst_mac[5], buflen,
|
|
dev_test_task_data->tx_link_type);
|
|
iot_plc_send_msdu(dev_test_task_data->app_handle, msdu_pkt);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief: send pkt at m2s mode.
|
|
* @param frm_pkt: pkt for fullfil the msdu pkt
|
|
* @retval: 0 -- success
|
|
* @retval: others -- failed
|
|
*/
|
|
static uint8_t iot_dev_test_msdu_m2s_send(frame_pkt_t* frm_pkt)
|
|
{
|
|
uint32_t buflen = 0;
|
|
uint8_t *ptr = NULL;
|
|
iot_pkt_t *msdu_pkt;
|
|
proto_conn_less_hdr_t *proto_hdr;
|
|
proto_conn_less_mr_t *meter;
|
|
uint8_t *dst_mac = NULL;
|
|
iot_dev_test_task_data_t *dev_glb = dev_test_task_data;
|
|
iot_dev_test_ppm_detec_desc_t *ppm_desc = &dev_glb->ppm_desc;
|
|
int8_t fix_ppm, temp;
|
|
|
|
if (IOT_DEV_TEST_SUPPORT_CT_MR_EN) {
|
|
if (0 == dev_glb->collector_vaild) {
|
|
dst_mac = (uint8_t *)bcast_mac;
|
|
} else {
|
|
dst_mac = dev_glb->collector;
|
|
}
|
|
} else {
|
|
dst_mac = frm_pkt->dst_mac;
|
|
}
|
|
|
|
buflen = sizeof(proto_conn_less_hdr_t) + sizeof(proto_conn_less_mr_t)
|
|
+ iot_pkt_data_len(frm_pkt->data);
|
|
if (frm_pkt->ppm_detect) {
|
|
if (buflen < IOT_DEV_TEST_PPM_DETCT_PKG_LEN) {
|
|
buflen = IOT_DEV_TEST_PPM_DETCT_PKG_LEN;
|
|
}
|
|
}
|
|
|
|
if (frm_pkt->ppm_detect) {
|
|
temp = ppm_desc->ppm_detect_cnt + 1;
|
|
fix_ppm = (temp >> 1) * PPM_DETECT_STEP_VALUE;
|
|
fix_ppm *= (temp & 0x01 ? 1 : -1);
|
|
ppm_desc->fix_ppm = fix_ppm;
|
|
ppm_desc->ppm_detect_cnt++;
|
|
if (ppm_desc->ppm_detect_cnt >= ((PPM_DETECT_STEP_MAX_CNT * 2) + 1))
|
|
ppm_desc->ppm_detect_cnt = 0;
|
|
}
|
|
fix_ppm = iot_dev_test_get_fix_ppm();
|
|
|
|
msdu_pkt = iot_plc_alloc_conn_less_msdu_ext(dev_glb->app_handle,
|
|
IOT_PLC_MSG_TYPE_CONN_LESS_DATA, dst_mac, dev_glb->mac_addr,
|
|
dev_glb->link_id, (uint16_t)buflen, IOT_PLC_MAX_RETRY_CNT,
|
|
fix_ppm, 0, dev_glb->tx_link_type);
|
|
|
|
if (msdu_pkt == NULL) {
|
|
iot_cus_printf("allocate msdu fail\n");
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_TAIL);
|
|
iot_pkt_put(msdu_pkt, buflen);
|
|
proto_hdr = (proto_conn_less_hdr_t *)ptr;
|
|
proto_hdr->id = CONN_LESS_APP_ID_METER_R;
|
|
proto_hdr->port = CONN_LESS_APP_PORT;
|
|
|
|
ptr += sizeof(proto_conn_less_hdr_t);
|
|
meter = (proto_conn_less_mr_t *)ptr;
|
|
meter->data_len = iot_pkt_data_len(frm_pkt->data);
|
|
meter->mr_timeout = IOT_DEV_TEST_CFG_MR_TIMEOUT;
|
|
|
|
if (!frm_pkt->sn_valid || frm_pkt->ppm_detect) {
|
|
frm_pkt->app_sn = iot_dev_test_app_get_sn();
|
|
frm_pkt->sn_valid = 1;
|
|
}
|
|
|
|
meter->seq = frm_pkt->app_sn;
|
|
meter->dir = CONN_LESS_APP_DIR_MASTER;
|
|
meter->option.dl_ppm_desc.value = 0;
|
|
meter->data_type = frm_pkt->p_type;
|
|
meter->retry_cnt = 1;
|
|
|
|
ptr = iot_pkt_data(frm_pkt->data);
|
|
os_mem_cpy(meter->data, ptr, iot_pkt_data_len(frm_pkt->data));
|
|
|
|
if (frm_pkt->ppm_detect) {
|
|
ppm_desc->ppm_detect_rec[ppm_desc->ppm_detect_rec_idx].sn =
|
|
frm_pkt->app_sn;
|
|
ppm_desc->ppm_detect_rec[ppm_desc->ppm_detect_rec_idx].fix_ppm =
|
|
fix_ppm;
|
|
ppm_desc->ppm_detect_rec_idx++;
|
|
if (ppm_desc->ppm_detect_rec_idx >= IOT_DEV_TEST_PPM_DETECT_REC_MAX) {
|
|
ppm_desc->ppm_detect_rec_idx = 0;
|
|
}
|
|
if (ppm_desc->ppm_detect_rec_cnt < IOT_DEV_TEST_PPM_DETECT_REC_MAX)
|
|
ppm_desc->ppm_detect_rec_cnt++;
|
|
}
|
|
|
|
iot_cus_printf("app conn_less send to[%02x:%02x:%02x:%02x:%02x:%02x], sn "
|
|
"%lu, len %lu, link_type %lu, fix ppm %d\n", frm_pkt->dst_mac[0],
|
|
frm_pkt->dst_mac[1], frm_pkt->dst_mac[2], frm_pkt->dst_mac[3],
|
|
frm_pkt->dst_mac[4], frm_pkt->dst_mac[5], frm_pkt->app_sn, buflen,
|
|
dev_glb->tx_link_type, fix_ppm);
|
|
iot_plc_send_msdu(dev_glb->app_handle, msdu_pkt);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
static uint16_t iot_dev_test_app_get_sn(void)
|
|
{
|
|
dev_test_task_data->app_sn++;
|
|
if (dev_test_task_data->app_sn == 0) {
|
|
dev_test_task_data->app_sn = 1;
|
|
}
|
|
return dev_test_task_data->app_sn;
|
|
}
|
|
|
|
static void iot_dev_test_fullfill_info_buf(uint8_t index, frame_pkt_t *frm)
|
|
{
|
|
info_pool_t *pool = &dev_test_task_data->info_pool;
|
|
|
|
/* if the send_cnt is none-zero, that means, a duplicated frame is
|
|
* found, the remain_cnt should not be updated.
|
|
*/
|
|
|
|
if (pool->frm_info[index].send_cnt == 0) {
|
|
pool->remain_cnt--;
|
|
}
|
|
/* if the old data would be replaced by new one, free the pkt first, just in
|
|
* case of memory leakage.
|
|
*/
|
|
if (pool->frm_info[index].frm.data) {
|
|
iot_pkt_free(pool->frm_info[index].frm.data);
|
|
}
|
|
|
|
os_mem_set(&pool->frm_info[index], 0, sizeof(frame_info_t));
|
|
os_mem_cpy(&pool->frm_info[index].frm, frm, sizeof(frame_pkt_t));
|
|
pool->frm_info[index].send_cnt++;
|
|
}
|
|
|
|
void iot_dev_test_buf_info_del(frame_info_t *frame)
|
|
{
|
|
info_pool_t *pool = &dev_test_task_data->info_pool;
|
|
frame_pkt_t *frm = &frame->frm;
|
|
if (frm->data) {
|
|
iot_pkt_free(frm->data);
|
|
}
|
|
os_mem_set(frame, 0, sizeof(*frame));
|
|
if (pool->remain_cnt < IOT_DEV_TEST_POOL_NUM) {
|
|
pool->remain_cnt++;
|
|
}
|
|
}
|
|
|
|
void iot_dev_tset_buf_info_clean()
|
|
{
|
|
iot_dev_test_task_data_t *dev_glb = dev_test_task_data;
|
|
info_pool_t *info_pool = &dev_glb->info_pool;
|
|
uint8_t i;
|
|
if (info_pool->remain_cnt == IOT_DEV_TEST_POOL_NUM) {
|
|
return;
|
|
}
|
|
for (i = 0; i < IOT_DEV_TEST_POOL_NUM; i++) {
|
|
if (iot_mac_addr_valid(info_pool->frm_info[i].frm.dst_mac)) {
|
|
iot_dev_test_buf_info_del(&info_pool->frm_info[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 1. allocate a msdu SN for all frame stored in sending pool.
|
|
* 2. find slot to cache the frame info in sending pool
|
|
* 3. copy the frame info into the sending pool.
|
|
* 4. send the frame data to plc
|
|
*/
|
|
static uint32_t iot_dev_test_msdu_send_handle(frame_pkt_t *frm)
|
|
{
|
|
int8_t index;
|
|
uint32_t ret = ERR_OK;
|
|
if (dev_test_task_data->dev_mode == IOT_DEV_TEST_APP_MODE_M2M) {
|
|
/* In M2M mode, no retry, so no need app_sn from slot */
|
|
if (ERR_OK != iot_dev_test_msdu_m2m_send(frm)) {
|
|
ret = ERR_FAIL;
|
|
}
|
|
} else if (dev_test_task_data->dev_mode == IOT_DEV_TEST_APP_MODE_M2S) {
|
|
index = iot_dev_test_info_buf_find_slot(frm->dst_mac);
|
|
if (index >= 0) {
|
|
iot_dev_test_send_mode_config(frm->dst_mac);// send mode config
|
|
if (!iot_dev_test_msdu_m2s_send(frm)) {
|
|
iot_dev_test_fullfill_info_buf(index, frm);
|
|
}
|
|
} else {
|
|
iot_cus_printf("NO buffer slot, frame sent to [%02x:%02x:%02x:%02x:"
|
|
"%02x:%02x]failed!\n", frm->dst_mac[0], frm->dst_mac[1],
|
|
frm->dst_mac[2], frm->dst_mac[3], frm->dst_mac[4],
|
|
frm->dst_mac[5]);
|
|
ret = ERR_FAIL;
|
|
}
|
|
} else {
|
|
iot_cus_printf("%s: invalid dev_mode[%d]\n", __FUNCTION__,
|
|
dev_test_task_data->dev_mode);
|
|
ret = ERR_FAIL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void iot_dev_test_ppm_detect_done_handle(int8_t *fix_ppm)
|
|
{
|
|
iot_dev_test_pib_t *pib = &dev_test_task_data->flashinfo;
|
|
iot_dev_test_ppm_detec_desc_t *ppm_desc = &dev_test_task_data->ppm_desc;
|
|
if (!IOT_DEV_TEST_PPM_DETECT_EN) {
|
|
return;
|
|
}
|
|
ppm_desc->ppm_detect_rec_idx = 0;
|
|
ppm_desc->ppm_detect_rec_cnt = 0;
|
|
if (fix_ppm) {
|
|
ppm_desc->ppm_detect_state = PPM_DETECT_STATE_DONE;
|
|
ppm_desc->fix_ppm = *fix_ppm;
|
|
pib->fix_ppm = ppm_desc->fix_ppm;
|
|
pib->ppm_valid = 1;
|
|
iot_mac_addr_cpy(pib->ppm_target_mac, ppm_desc->ppm_target_mac);
|
|
iot_dev_test_flash_save(pib);
|
|
iot_cus_printf("%s ok, ppm value %d\n", __FUNCTION__,
|
|
ppm_desc->fix_ppm);
|
|
} else {
|
|
ppm_desc->ppm_detect_state = PPM_DETECT_STATE_IDLE;
|
|
ppm_desc->fix_ppm = 0;
|
|
iot_cus_printf("%s fail\n", __FUNCTION__);
|
|
}
|
|
}
|
|
|
|
static void iot_dev_test_ppm_detect_restart(void)
|
|
{
|
|
iot_dev_test_ppm_detec_desc_t *ppm_desc = &dev_test_task_data->ppm_desc;
|
|
|
|
if ((!IOT_DEV_TEST_PPM_DETECT_EN) ||
|
|
(PPM_DETECT_STATE_DONE != ppm_desc->ppm_detect_state)){
|
|
return;
|
|
}
|
|
|
|
ppm_desc->ppm_detect_state = PPM_DETECT_STATE_IDLE;
|
|
}
|
|
|
|
static void iot_dev_test_ppm_detect_load(uint8_t *addr)
|
|
{
|
|
iot_dev_test_ppm_detec_desc_t *ppm_desc = &dev_test_task_data->ppm_desc;
|
|
if (!IOT_DEV_TEST_PPM_DETECT_EN) {
|
|
return;
|
|
}
|
|
if (!iot_mac_addr_cmp(ppm_desc->ppm_target_mac, addr)) {
|
|
/* if the target address changes, PPM needs to be
|
|
* detected again.
|
|
*/
|
|
iot_mac_addr_cpy(ppm_desc->ppm_target_mac, addr);
|
|
iot_dev_tset_buf_info_clean();
|
|
ppm_desc->ppm_detect_state = PPM_DETECT_STATE_IDLE;
|
|
ppm_desc->ppm_detect_rec_idx = 0;
|
|
ppm_desc->ppm_detect_rec_cnt = 0;
|
|
ppm_desc->ppm_detect_cnt = 0;
|
|
ppm_desc->fix_ppm = 0;
|
|
}
|
|
}
|
|
|
|
static void iot_dev_test_ppm_detect_init(void)
|
|
{
|
|
iot_dev_test_ppm_detec_desc_t *ppm_desc = &dev_test_task_data->ppm_desc;
|
|
iot_dev_test_pib_t *pib = &dev_test_task_data->flashinfo;
|
|
os_mem_set(ppm_desc, 0x0, sizeof(*ppm_desc));
|
|
if (!IOT_DEV_TEST_PPM_DETECT_EN) {
|
|
ppm_desc->ppm_detect_state = PPM_DETECT_STATE_DONE;
|
|
ppm_desc->fix_ppm = 0;
|
|
} else if (pib->ppm_valid) {
|
|
ppm_desc->ppm_detect_state = PPM_DETECT_STATE_DONE;
|
|
iot_mac_addr_cpy(ppm_desc->ppm_target_mac,
|
|
pib->ppm_target_mac);
|
|
ppm_desc->fix_ppm = pib->fix_ppm;
|
|
}
|
|
iot_cus_printf("%s en %lu, ppm_detect_state %lu, ppm %d\n",
|
|
__FUNCTION__, IOT_DEV_TEST_PPM_DETECT_EN,
|
|
ppm_desc->ppm_detect_state, ppm_desc->fix_ppm);
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief: check if the mac and sn are both in the same queue node, if so,
|
|
* return true if not, return false.
|
|
* @param mac: mac address of meter who sent the msdu pkt
|
|
* @param sn: meter sent back, originally assigned by sta control
|
|
* @retval: true -- sn and mac both matched
|
|
* @retval: false -- info mismached
|
|
*/
|
|
static bool_t iot_dev_test_frame_rpt_check(uint8_t *mac, uint16_t sn)
|
|
{
|
|
bool_t ret = false;
|
|
uint8_t i, j;
|
|
iot_dev_test_task_data_t *dev_glb = dev_test_task_data;
|
|
iot_dev_test_ppm_detec_desc_t *ppm_desc = &dev_glb->ppm_desc;
|
|
info_pool_t *info_pool = &dev_glb->info_pool;
|
|
|
|
if (info_pool->remain_cnt != IOT_DEV_TEST_POOL_NUM) {
|
|
for (i = 0; i < IOT_DEV_TEST_POOL_NUM; i++) {
|
|
if (iot_mac_is_bcast(info_pool->frm_info[i].frm.dst_mac) ||
|
|
iot_mac_addr_cmp(mac, info_pool->frm_info[i].frm.dst_mac)) {
|
|
if (info_pool->frm_info[i].frm.ppm_detect) {
|
|
for (j = 0; j < ppm_desc->ppm_detect_rec_cnt; j ++) {
|
|
if (ppm_desc->ppm_detect_rec[j].sn == sn) {
|
|
iot_dev_test_ppm_detect_done_handle(
|
|
&ppm_desc->ppm_detect_rec[j].fix_ppm);
|
|
ret = true;
|
|
goto done;
|
|
}
|
|
}
|
|
} else if (sn == info_pool->frm_info[i].frm.app_sn) {
|
|
ret = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
done:
|
|
if (ret) {
|
|
iot_dev_test_buf_info_del(&info_pool->frm_info[i]);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
uint16_t iot_dev_get_mr_retry_intval(frame_info_t *frame)
|
|
{
|
|
if (frame->frm.ppm_detect) {
|
|
return 8;
|
|
} else {
|
|
return IOT_DEV_TEST_APP_MAX_RETRY_INTV_CNT;
|
|
}
|
|
}
|
|
|
|
uint16_t iot_dev_get_mr_max_age(frame_info_t *frame)
|
|
{
|
|
if (frame->frm.ppm_detect) {
|
|
return ((PPM_DETECT_STEP_MAX_CNT * 2 + 1) *
|
|
iot_dev_get_mr_retry_intval(frame));
|
|
} else {
|
|
return IOT_DEV_TEST_MAX_LIFE_SPAN_CNT;
|
|
}
|
|
}
|
|
|
|
|
|
/* once the periodicly timer is fired up, we should check the frame's
|
|
* life-span counter, if the counter reaches the limit, the stored info
|
|
* should be wiped out.
|
|
*/
|
|
static void iot_dev_test_buf_refresh(void)
|
|
{
|
|
uint8_t i;
|
|
info_pool_t *pool = &dev_test_task_data->info_pool;
|
|
iot_dev_test_ppm_detec_desc_t *ppm_desc = &dev_test_task_data->ppm_desc;
|
|
frame_pkt_t *frm = NULL;
|
|
uint16_t intval, max_age;
|
|
|
|
if ((dev_test_task_data->collector_vaild) &&
|
|
IOT_DEV_TEST_SUPPORT_CT_MR_EN &&
|
|
IOT_DEV_TEST_COLLECTOR_AUTO_CLR) {
|
|
dev_test_task_data->collector_vaild_cnt++;
|
|
if (dev_test_task_data->collector_vaild_cnt >=
|
|
IOT_DEV_TEST_COLLECTOR_VAILID_CNT) {
|
|
dev_test_task_data->collector_vaild = 0;
|
|
dev_test_task_data->collector_vaild_cnt = 0;
|
|
}
|
|
}
|
|
|
|
if (pool->remain_cnt != IOT_DEV_TEST_POOL_NUM) {
|
|
for (i = 0; i < IOT_DEV_TEST_POOL_NUM; i++) {
|
|
if (pool->frm_info[i].send_cnt != 0) {
|
|
intval = iot_dev_get_mr_retry_intval(&pool->frm_info[i]);
|
|
max_age = iot_dev_get_mr_max_age(&pool->frm_info[i]);
|
|
frm = &pool->frm_info[i].frm;
|
|
pool->frm_info[i].span_cnt++;
|
|
if (pool->frm_info[i].span_cnt >= max_age) {
|
|
iot_cus_printf("%s: frame mac[%02x:%02x:%02x:%02x:%02x:%02x"
|
|
"], app_sn %lu is dropped for timeout\n", __FUNCTION__,
|
|
frm->dst_mac[0], frm->dst_mac[1], frm->dst_mac[2],
|
|
frm->dst_mac[3], frm->dst_mac[4], frm->dst_mac[5],
|
|
frm->app_sn);
|
|
if (PPM_DETECT_STATE_DOING == ppm_desc->ppm_detect_state) {
|
|
iot_dev_test_ppm_detect_done_handle(NULL);
|
|
} else if (PPM_DETECT_STATE_DONE == ppm_desc->ppm_detect_state) {
|
|
iot_dev_test_ppm_detect_restart();
|
|
}
|
|
iot_dev_test_buf_info_del(&pool->frm_info[i]);
|
|
continue;
|
|
} else if ((pool->frm_info[i].span_cnt % intval) == 0) {
|
|
if (!iot_dev_test_msdu_m2s_send(frm)) {
|
|
pool->frm_info[i].send_cnt++;
|
|
iot_cus_printf("%s: sending retry, app_sn %lu, "
|
|
"retry cnt %lu\n", __FUNCTION__, frm->app_sn,
|
|
pool->frm_info[i].send_cnt - 1);
|
|
}
|
|
}
|
|
/* send the mode config to sta at every 750ms in unicast way */
|
|
if (pool->frm_info[i].span_cnt %
|
|
(IOT_DEV_TEST_APP_MAX_RETRY_INTV_CNT - 1) == 0) {
|
|
iot_dev_test_send_mode_config(frm->dst_mac);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* once received a uart data, allocate a pkt, then post a msg to handle
|
|
* the data
|
|
*/
|
|
static void iot_dev_test_uart_meter_port_func(uint8_t* buffer,
|
|
uint32_t buffer_len, bool_t is_full_frame,uint32_t invalid_data_len)
|
|
{
|
|
iot_pkt_t *pkt;
|
|
|
|
(void)invalid_data_len;
|
|
(void)is_full_frame;
|
|
|
|
if (dev_test_task_data->dev_ready == 0) {
|
|
iot_cus_printf("%s: Device is not ready, pkt dropped!\n", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
pkt = iot_pkt_alloc(buffer_len, IOT_APP_DEV_TEST_MID);
|
|
if (pkt) {
|
|
os_mem_cpy(iot_pkt_put(pkt, buffer_len), buffer, buffer_len);
|
|
iot_dev_test_post_task_msg(IOT_DEV_TEST_UART_RECV_MSG, 0, pkt);
|
|
} else {
|
|
iot_cus_printf("%s: alloc failed\n", __FUNCTION__);
|
|
}
|
|
}
|
|
|
|
static void iot_dev_test_handle_mr_req(uint8_t proto_type,
|
|
uint8_t *ds, uint32_t len, uint8_t *dst)
|
|
{
|
|
frame_pkt_t frm = { 0 };
|
|
iot_pkt_t *buf;
|
|
uint8_t *data;
|
|
iot_dev_test_ppm_detec_desc_t * ppm_desc = &dev_test_task_data->ppm_desc;
|
|
iot_mac_addr_cpy(frm.dst_mac, dst);
|
|
iot_dev_test_ppm_detect_load(dst);
|
|
frm.p_type = proto_type;
|
|
|
|
if ((NULL == ds) || (!len)) {
|
|
return;
|
|
}
|
|
|
|
if (ppm_desc->ppm_detect_state != PPM_DETECT_STATE_DONE) {
|
|
frm.ppm_detect = 1;
|
|
ppm_desc->ppm_detect_state = PPM_DETECT_STATE_DOING;
|
|
}
|
|
|
|
buf = iot_pkt_alloc(len, IOT_APP_DEV_TEST_MID);
|
|
if (buf == NULL) {
|
|
IOT_ASSERT(0);
|
|
}
|
|
data = iot_pkt_data(buf);
|
|
os_mem_cpy(data, ds, len);
|
|
iot_pkt_put(buf, len);
|
|
frm.data = buf;
|
|
if (ERR_OK != iot_dev_test_msdu_send_handle(&frm)) {
|
|
iot_pkt_free(buf);
|
|
}
|
|
}
|
|
|
|
/* handle config data from PLC */
|
|
static uint8_t iot_dev_test_handle_config_data(iot_pkt_t *pkt)
|
|
{
|
|
uint8_t *ptr = NULL;
|
|
iot_plc_msdu_recv_t *msdu = NULL;
|
|
proto_conn_less_mr_t *meter;
|
|
uint8_t *mac;
|
|
uint16_t app_sn;
|
|
uint16_t offset_sz;
|
|
proto_645_header_t *hdr_645 = NULL;
|
|
uint8_t t_mac[IOT_MAC_ADDR_LEN];
|
|
iot_pkt_t *msg_645 = NULL;
|
|
|
|
iot_plc_msg_header_t *hdr = (iot_plc_msg_header_t*)iot_pkt_data(pkt);
|
|
msdu = (iot_plc_msdu_recv_t*)(hdr + 1);
|
|
|
|
ptr = msdu->data;
|
|
iot_dev_test_data_print("msdu data", msdu->data, msdu->len);
|
|
meter = (proto_conn_less_mr_t *)(ptr + sizeof(proto_conn_less_hdr_t));
|
|
app_sn = meter->seq;
|
|
|
|
/* data direction must: master ->slave */
|
|
if (meter->dir != CONN_LESS_APP_DIR_MASTER) {
|
|
iot_cus_printf("%s: invalid direction\n", __FUNCTION__);
|
|
goto out;
|
|
}
|
|
|
|
mac = msdu->src;
|
|
offset_sz = sizeof(*msdu) + sizeof(*hdr) + sizeof(*meter) +
|
|
sizeof(proto_conn_less_hdr_t);
|
|
iot_pkt_pull(pkt, offset_sz);
|
|
|
|
hdr_645 = proto_645_format_check(iot_pkt_data(pkt),
|
|
iot_pkt_data_len(pkt), PROTO_645_DIR_MASTER);
|
|
if (NULL == hdr_645) {
|
|
goto out;
|
|
}
|
|
|
|
iot_mac_addr_cpy(t_mac, hdr_645->addr);
|
|
iot_mac_addr_reverse(t_mac);
|
|
|
|
if (iot_dev_test_config_data_hdl_check(t_mac, app_sn)) {
|
|
iot_cus_printf("Received config data, sn %lu, mac[%02x:%02x:"
|
|
"%02x:%02x:%02x:%02x]\n", app_sn, t_mac[0], t_mac[1],
|
|
t_mac[2], t_mac[3], t_mac[4], t_mac[5]);
|
|
iot_dev_test_data_print("dlt645 data:", iot_pkt_data(pkt),
|
|
(uint16_t)iot_pkt_data_len(pkt));
|
|
|
|
msg_645 = iot_dev_test_config_cmd_handle(hdr_645);
|
|
if (NULL != msg_645) {
|
|
iot_dev_test_config_pack_plc_rsp_data(mac, app_sn,
|
|
iot_pkt_data(msg_645), iot_pkt_data_len(msg_645));
|
|
iot_pkt_free(msg_645);
|
|
}
|
|
} else {
|
|
iot_cus_printf("config data dropped, sn %lu, mac"
|
|
"[%02x:%02x:%02x:%02x:%02x:%02x]\n", app_sn,
|
|
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
|
}
|
|
out:
|
|
return 0;
|
|
}
|
|
|
|
static
|
|
uint8_t iot_dev_test_check_addr_set_condition(proto_645_header_t *hdr_645)
|
|
{
|
|
if (!hdr_645) {
|
|
iot_cus_printf("%s invalid hdr_645\n", __FUNCTION__);
|
|
return false;
|
|
}
|
|
|
|
return (dev_test_task_data->dev_mode == IOT_DEV_TEST_APP_MODE_M2M
|
|
&& dev_test_task_data->m2m_sub_mode == IOT_DEV_TEST_M2M_SUBMODE_CIU
|
|
&& dev_test_task_data->m2m_ciu_query_addr !=
|
|
IOT_DEV_TEST_QUERY_CIU_ADDR_SUCC
|
|
&& (hdr_645->control.fn == PROTO_645_2007_FN_READ_ADDR)
|
|
&& (hdr_645->control.ack == PROTO_645_ACK_NORMAL)
|
|
&& (hdr_645->control.dir == PROTO_645_DIR_SLAVE));
|
|
}
|
|
|
|
static void iot_dev_test_uart_qsxj_hw_ver_resp()
|
|
{
|
|
uint16_t pkt_len, i, hw_ver_hex;
|
|
iot_pkt_t *pkt, *resp_pkt;
|
|
proto_qsxj_data_t *qsxj_data;
|
|
proto_qsxj_hw_ver_t *hw_ver;
|
|
iot_oem_hw_ver_info_t hw_ver_info = { 0 };
|
|
|
|
pkt_len = sizeof(*qsxj_data) + sizeof(*hw_ver);
|
|
pkt = iot_pkt_alloc(pkt_len, IOT_APP_DEV_TEST_MID);
|
|
if (!pkt) {
|
|
return;
|
|
}
|
|
qsxj_data = (proto_qsxj_data_t *)iot_pkt_put(pkt, pkt_len);
|
|
proto_qsxj_di_to_byte(PROTO_QSXJ_DI_HARDWARE_VER, &qsxj_data->di);
|
|
qsxj_data->len = PROTO_QSXJ_MODE_INFO_LEN_HW_VER;
|
|
hw_ver = (proto_qsxj_hw_ver_t *)qsxj_data->data;
|
|
iot_oem_get_hw_ver_info(&hw_ver_info);
|
|
hw_ver_hex = hw_ver_info.module_version[1];
|
|
hw_ver_hex = hw_ver_hex << 8;
|
|
hw_ver_hex |= hw_ver_info.module_version[0];
|
|
for (i = 0; i < PROTO_QSXJ_MODE_INFO_LEN_HW_VER; i++) {
|
|
hw_ver->hw_ver[i] = iot_byte_to_ascii(hw_ver_hex & 0x0f, 1);
|
|
hw_ver_hex >>= 4;
|
|
}
|
|
iot_data_reverse(hw_ver->hw_ver, PROTO_QSXJ_MODE_INFO_LEN_HW_VER);
|
|
/* ver/flag_follow/channel fields is meaningless for qsxj dev_test proto */
|
|
resp_pkt = proto_qsxj_build_msg((uint8_t *)qsxj_data, pkt_len,
|
|
PROTO_QSXJ_COMMAND_SET_RESP, PROTO_QSXJ_VER_SX_V04, 0,
|
|
PROTO_QSXJ_CHANNEL_NUM0);
|
|
if (resp_pkt) {
|
|
iot_dev_test_uart_send(resp_pkt);
|
|
}
|
|
if (pkt) {
|
|
iot_pkt_free(pkt);
|
|
}
|
|
}
|
|
|
|
static void iot_dev_test_uart_qsxj_sw_ver_resp()
|
|
{
|
|
uint16_t pkt_len, sw_ver_hex, i;
|
|
iot_pkt_t *pkt, *resp_pkt;
|
|
proto_qsxj_data_t *qsxj_data;
|
|
proto_qsxj_sw_ver_t *sw_ver;
|
|
iot_build_info_t build_info = { 0 };
|
|
|
|
pkt_len = sizeof(*qsxj_data) + sizeof(*sw_ver);
|
|
pkt = iot_pkt_alloc(pkt_len, IOT_APP_DEV_TEST_MID);
|
|
if (!pkt) {
|
|
return;
|
|
}
|
|
qsxj_data = (proto_qsxj_data_t *)iot_pkt_put(pkt, pkt_len);
|
|
proto_qsxj_di_to_byte(PROTO_QSXJ_DI_SOFTWARE_VER, &qsxj_data->di);
|
|
qsxj_data->len = PROTO_QSXJ_MODE_INFO_LEN_SW_VER_FIX +
|
|
PROTO_QSXJ_MODE_INFO_LEN_SW_VER_FILL;
|
|
sw_ver = (proto_qsxj_sw_ver_t *)qsxj_data->data;
|
|
os_mem_cpy(sw_ver->ver_fix, fixed_ver, PROTO_QSXJ_MODE_INFO_LEN_SW_VER_FIX);
|
|
iot_version_get_user_build_info(&build_info);
|
|
sw_ver_hex = build_info.sw_ver;
|
|
for (i = 0; i < PROTO_QSXJ_MODE_INFO_LEN_SW_VER_FILL; i++) {
|
|
if (i == 2) {
|
|
sw_ver->ver_fill[i] = '.';
|
|
continue;
|
|
}
|
|
sw_ver->ver_fill[i] = iot_byte_to_ascii(sw_ver_hex & 0x0f, 1);
|
|
sw_ver_hex >>= 4;
|
|
}
|
|
iot_data_reverse(sw_ver->ver_fill, PROTO_QSXJ_MODE_INFO_LEN_SW_VER_FILL);
|
|
/* ver/flag_follow/channel fields is meaningless for qsxj dev_test proto */
|
|
resp_pkt = proto_qsxj_build_msg((uint8_t *)qsxj_data, pkt_len,
|
|
PROTO_QSXJ_COMMAND_SET_RESP, PROTO_QSXJ_VER_SX_V04, 0,
|
|
PROTO_QSXJ_CHANNEL_NUM0);
|
|
if (resp_pkt) {
|
|
iot_dev_test_uart_send(resp_pkt);
|
|
}
|
|
if (pkt) {
|
|
iot_pkt_free(pkt);
|
|
}
|
|
}
|
|
|
|
static void iot_dev_test_uart_qsxj_data_handle(iot_pkt_t *pkt)
|
|
{
|
|
uint8_t *data, flag_nack = 0, addr_len, i;
|
|
uint8_t di_data_len, addr, meter_addr[IOT_MAC_ADDR_LEN] = { 0 };
|
|
uint16_t di, data_len;
|
|
uint32_t len;
|
|
proto_qsxj_head_t *head;
|
|
proto_qsxj_data_t *qsxj_data;
|
|
iot_pkt_t *resp_pkt;
|
|
frame_pkt_t frm = {0};
|
|
|
|
data = iot_pkt_data(pkt);
|
|
len = iot_pkt_data_len(pkt);
|
|
iot_cus_printf("%s received uart data, len %lu\n", __FUNCTION__, len);
|
|
iot_dev_test_data_print("uart recv", data, len);
|
|
head = proto_qsxj_sanity_check(data, (uint16_t)len);
|
|
if (head) {
|
|
if (head->command != PROTO_QSXJ_COMMAND_SET_REQ) {
|
|
flag_nack = 1;
|
|
goto ack;
|
|
}
|
|
data_len = proto_qsxj_len_get(head) - sizeof(head->command) -
|
|
PROTO_QSXJ_CRC16_LEN;
|
|
if (data_len < sizeof(di)) {
|
|
flag_nack = 1;
|
|
goto ack;
|
|
}
|
|
di = iot_bytes_to_uint16(head->data, 1);
|
|
switch (di) {
|
|
case PROTO_QSXJ_DI_METER_NUM:
|
|
{
|
|
if (data_len < sizeof(*qsxj_data)) {
|
|
flag_nack = 1;
|
|
goto ack;
|
|
}
|
|
data_len -= sizeof(*qsxj_data);
|
|
qsxj_data = (proto_qsxj_data_t *)head->data;
|
|
di_data_len = qsxj_data->len;
|
|
if (data_len < di_data_len) {
|
|
flag_nack = 1;
|
|
goto ack;
|
|
}
|
|
addr_len = min(di_data_len, IOT_MAC_ADDR_LEN * 2);
|
|
for (i = 0; i < addr_len; i++) {
|
|
addr = iot_ascii_to_byte(qsxj_data->data[addr_len - 1 - i]) &
|
|
0x0f;
|
|
if (i % 2) {
|
|
meter_addr[i / 2] |= (addr << 4);
|
|
} else {
|
|
meter_addr[i / 2] |= addr;
|
|
}
|
|
}
|
|
if (!iot_mac_addr_valid(meter_addr) ||
|
|
iot_mac_is_bcast(meter_addr)) {
|
|
flag_nack = 1;
|
|
goto ack;
|
|
}
|
|
iot_mac_addr_reverse(meter_addr);
|
|
iot_mac_addr_cpy(dev_test_task_data->qsxj_addr, meter_addr);
|
|
goto ack;
|
|
}
|
|
case PROTO_QSXJ_DI_HARDWARE_VER:
|
|
{
|
|
iot_dev_test_uart_qsxj_hw_ver_resp();
|
|
break;
|
|
}
|
|
case PROTO_QSXJ_DI_SOFTWARE_VER:
|
|
{
|
|
iot_dev_test_uart_qsxj_sw_ver_resp();
|
|
break;
|
|
}
|
|
default:
|
|
flag_nack = 1;
|
|
goto ack;
|
|
}
|
|
} else {
|
|
if (iot_mac_addr_valid(dev_test_task_data->qsxj_addr) &&
|
|
!iot_mac_is_bcast(dev_test_task_data->qsxj_addr)) {
|
|
frm.data = pkt;
|
|
frm.p_type = CONN_LESS_PROTO_TYPE_TRANSPARENT;
|
|
iot_mac_addr_cpy(frm.dst_mac, dev_test_task_data->qsxj_addr);
|
|
if (ERR_OK == iot_dev_test_msdu_send_handle(&frm)) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
goto out;
|
|
ack:
|
|
resp_pkt = proto_qsxj_build_ack(PROTO_QSXJ_VER_SX_V04,
|
|
PROTO_QSXJ_COMMAND_SET_RESP, flag_nack);
|
|
if (resp_pkt) {
|
|
iot_dev_test_uart_send(resp_pkt);
|
|
}
|
|
out:
|
|
if (pkt) {
|
|
iot_pkt_free(pkt);
|
|
}
|
|
}
|
|
|
|
static uint32_t iot_dev_test_69845_control_cmd(proto_69845_frame_head_info_t *hdr_698)
|
|
{
|
|
uint8_t reason;
|
|
uint32_t ret = ERR_OK;
|
|
apdu_info_t apdu = {0};
|
|
proto_69845_apdu_t *req_apdu;
|
|
proto_69845_app_set_req_t *set;
|
|
proto_69845_app_set_req_normal_t *normal_data;
|
|
uint32_t oad_value;
|
|
proto_69845_app_ele_data_t *ele_data;
|
|
proto_69845_ext_rf_param_t *rf_param;
|
|
proto_69845_ext_work_mode_t *control_mode;
|
|
addr_info_t addr_info = {0};
|
|
iot_pkt_t *pkt;
|
|
proto_69845_app_oad_t app_oad = {0};
|
|
|
|
if (hdr_698->ctrl.fn != PROTO_69845_FN_USER_DATA) {
|
|
reason = 1;
|
|
ret = ERR_INVAL;
|
|
goto err;
|
|
}
|
|
if (hdr_698->ctrl.dir_prm != PROTO_69845_D_P_CLIENT_RESPONSE
|
|
&& hdr_698->ctrl.dir_prm != PROTO_69845_D_P_CLIENT_REQUEST) {
|
|
reason = 2;
|
|
ret = ERR_INVAL;
|
|
goto err;
|
|
}
|
|
|
|
if (proto_69845_get_apdu(hdr_698, hdr_698->len + PROTO_69845_START_END_LEN,
|
|
&apdu) != ERR_OK) {
|
|
reason = 3;
|
|
ret = ERR_INVAL;
|
|
goto err;
|
|
}
|
|
|
|
req_apdu = (proto_69845_apdu_t *)apdu.ptr;
|
|
if (req_apdu->type != PROTO_69845_C_APP_SET_REQ) {
|
|
reason = 4;
|
|
ret = ERR_INVAL;
|
|
goto err;
|
|
}
|
|
|
|
set = (proto_69845_app_set_req_t *)req_apdu->data;
|
|
if (set->data_type != PROTO_69845_APP_SET_NORMAL) {
|
|
reason = 5;
|
|
ret = ERR_INVAL;
|
|
goto err;
|
|
}
|
|
|
|
normal_data = (proto_69845_app_set_req_normal_t *)set->data;
|
|
oad_value = iot_bytes_to_uint32((uint8_t *)&normal_data->oad.oi, 1);
|
|
ele_data = (proto_69845_app_ele_data_t *)(&normal_data->data);
|
|
if (ele_data->data_type != PROTO_69845_APP_DATA_OCTET_STRING) {
|
|
reason = 6;
|
|
ret = ERR_INVAL;
|
|
goto err;
|
|
}
|
|
|
|
switch (oad_value) {
|
|
case PROTO_69845_EXT_APP_OAD_BROADCAST_RF_PARAM:
|
|
{
|
|
rf_param = (proto_69845_ext_rf_param_t *)ele_data->data;
|
|
iot_dev_test_set_rf(rf_param->option, rf_param->channel, 0);
|
|
ret = ERR_EXIST;
|
|
break;
|
|
}
|
|
case PROTO_69845_EXT_APP_OAD_HRF_MODE:
|
|
{
|
|
uint8_t link_type;
|
|
control_mode = (proto_69845_ext_work_mode_t *)ele_data->data;
|
|
if (control_mode->mode == PROTO_69845_CONTROLLER_MODE_HPLC) {
|
|
link_type = IOT_PLC_TX_LINK_TYPE_HPLC;
|
|
} else {
|
|
link_type = IOT_PLC_TX_LINK_TYPE_RF;
|
|
}
|
|
iot_dev_test_set_tx_link_type(link_type, 0);
|
|
break;
|
|
}
|
|
default:
|
|
reason = 7;
|
|
ret = ERR_INVAL;
|
|
goto err;
|
|
}
|
|
|
|
addr_info.ser_info.type = PROTO_69845_SA_TYPE_SIG;
|
|
addr_info.ser_info.len = IOT_MAC_ADDR_LEN;
|
|
addr_info.ser_info.logical_addr = 0;
|
|
iot_mac_addr_cpy(addr_info.ser_info.addr, dev_test_task_data->mac_addr);
|
|
addr_info.cli_addr = PROTO_69845_CA_INVAILD_ADD;
|
|
app_oad.oi = iot_bytes_to_uint16((uint8_t *)&normal_data->oad.oi, 1);
|
|
app_oad.attribute_id = normal_data->oad.attribute_id;
|
|
app_oad.attribute_char = normal_data->oad.attribute_char;
|
|
app_oad.element_index = normal_data->oad.element_index;
|
|
|
|
pkt = proto_69845_set_normal_ack(&addr_info, &normal_data->piid,
|
|
&app_oad, PROTO_69845_APP_DAR_SUCCESS);
|
|
if (pkt == NULL) {
|
|
reason = 8;
|
|
ret = ERR_INVAL;
|
|
goto err;
|
|
}
|
|
iot_dev_test_uart_send(pkt);
|
|
goto out;
|
|
err:
|
|
if (reason >= 7) {
|
|
iot_cus_printf("%s error reason:%lu", __FUNCTION__, reason);
|
|
}
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static void iot_dev_test_uart_data_handle(iot_pkt_t *pkt)
|
|
{
|
|
uint16_t len = 0;
|
|
proto_645_header_t *hdr_645;
|
|
proto_69845_frame_head_info_t *hdr_698;
|
|
proto_dlms_hdlc_head_t *hdr_dlms;
|
|
proto_dlms_hdlc_cache_t cache_dlms;
|
|
union proto_dlms_hdlc_format frame_format = {0};
|
|
addr_info_t svr_info = {0};
|
|
uint8_t *data;
|
|
uint16_t fe_cnt = 0;
|
|
uint16_t pkt_len;
|
|
uint8_t band_id;
|
|
uint8_t op_mode;
|
|
uint8_t baud_index;
|
|
uint8_t t_mac[IOT_MAC_ADDR_LEN] = { 0 };
|
|
uint8_t dst_mac[IOT_MAC_ADDR_LEN] = { 0 };
|
|
uint32_t di;
|
|
uint8_t rf_option, rf_channel;
|
|
int8_t rf_tx_power;
|
|
uint8_t hplc_tx_power, link_type;
|
|
|
|
len = (uint16_t)iot_pkt_block_len(pkt, IOT_PKT_BLOCK_DATA);
|
|
data = iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA);
|
|
|
|
iot_cus_printf("%s received uart data, len %lu\n", __FUNCTION__, len);
|
|
iot_dev_test_data_print("uart recv", data, len);
|
|
|
|
again:
|
|
if (dev_test_task_data->m2m_sub_mode == IOT_DEV_TEST_M2M_SUBMODE_CIU
|
|
&& dev_test_task_data->dev_mode == IOT_DEV_TEST_APP_MODE_M2M) {
|
|
hdr_645 = proto_645_format_check(data, len, PROTO_645_DIR_SLAVE);
|
|
} else {
|
|
hdr_645 = proto_645_format_check(data, len, PROTO_645_DIR_MASTER);
|
|
}
|
|
|
|
if (hdr_645) {
|
|
pkt_len = sizeof(*hdr_645) + hdr_645->len + sizeof(proto_645_tailer_t);
|
|
if (iot_mac_addr_cmp(hdr_645->addr, spec_mac)) {
|
|
iot_cus_printf("RECV_UART_CMD frame, fn: 0x%02x\n",
|
|
hdr_645->control.fn);
|
|
proto_645_sub33_handle(hdr_645->data, hdr_645->len);
|
|
switch (hdr_645->control.fn) {
|
|
case IOT_DEV_TEST_FN_SET_BAND:
|
|
band_id = hdr_645->data[0];
|
|
iot_cus_printf("[dev_test]recved set band cmd, band-id: "
|
|
"%lu\n", band_id);
|
|
iot_dev_test_set_band(band_id);
|
|
break;
|
|
case IOT_DEV_TEST_FN_QUERRY_VER:
|
|
iot_dev_test_querry_ver_handle();
|
|
break;
|
|
case IOT_DEV_TEST_FN_QUERRY_BAND:
|
|
iot_dev_test_querry_band_handle();
|
|
break;
|
|
case IOT_DEV_TEST_FN_SET_MAC:
|
|
iot_mac_addr_cpy(t_mac, hdr_645->data);
|
|
iot_mac_addr_reverse(t_mac);
|
|
iot_dev_test_set_mac(t_mac);
|
|
break;
|
|
case IOT_DEV_TEST_FN_QUERRY_MAC:
|
|
iot_dev_test_querry_mac_handle();
|
|
break;
|
|
case IOT_DEV_TEST_FN_SET_OP_MODE:
|
|
op_mode = hdr_645->data[0];
|
|
iot_dev_test_set_op_mode(op_mode);
|
|
break;
|
|
case IOT_DEV_TEST_FN_QUERY_OP_MODE:
|
|
iot_dev_test_query_op_mode();
|
|
break;
|
|
case IOT_DEV_TEST_FN_SET_UART_BAUDRATE:
|
|
baud_index = hdr_645->data[0];
|
|
iot_dev_test_set_baudrate(baud_index);
|
|
break;
|
|
case IOT_DEV_TEST_FN_QUERY_BAUDRATE:
|
|
iot_dev_test_query_baudrate();
|
|
break;
|
|
case IOT_DEV_TEST_FN_SET_RF:
|
|
rf_option = hdr_645->data[0];
|
|
rf_channel = hdr_645->data[1];
|
|
iot_dev_test_set_rf(rf_option, rf_channel, 1);
|
|
break;
|
|
case IOT_DEV_TEST_FN_SET_RF_TX_POWER:
|
|
rf_tx_power = hdr_645->data[0];
|
|
iot_dev_test_set_rf_tx_power(rf_tx_power);
|
|
break;
|
|
case IOT_DEV_TEST_FN_SET_HPLC_TX_POWER:
|
|
hplc_tx_power = hdr_645->data[0];
|
|
iot_dev_test_set_hplc_tx_power(hplc_tx_power);
|
|
break;
|
|
case IOT_DEV_TEST_FN_SET_TX_LINK_TYPE:
|
|
link_type = hdr_645->data[0];
|
|
iot_dev_test_set_tx_link_type(link_type, 1);
|
|
break;
|
|
default:
|
|
iot_dev_test_form_rsp_cfm_frame(hdr_645->control.fn,
|
|
IOT_DEV_TEST_RSP_ERR, IOT_DEV_TEST_REASON_NOT_SUPPORT);
|
|
iot_cus_printf("[err]cmd fn: %lu not supported!\n",
|
|
hdr_645->control.fn);
|
|
break;
|
|
}
|
|
proto_645_add33_handle(hdr_645->data, hdr_645->len);
|
|
} else {
|
|
proto_645_get_di_by_sub33(hdr_645->data, PROTO_645_2007_DI_LEN,
|
|
PROTO_645_2007_ID, &di);
|
|
iot_cus_printf("RECV_UART_645 frame, di 0x%04x, data_len %lu\n",
|
|
di, hdr_645->len);
|
|
|
|
if (iot_dev_test_check_addr_set_condition(hdr_645)) {
|
|
iot_mac_addr_cpy(t_mac, hdr_645->data);
|
|
proto_645_sub33_handle(t_mac, IOT_MAC_ADDR_LEN);
|
|
iot_mac_addr_reverse(t_mac);
|
|
iot_dev_test_set_mac(t_mac);
|
|
|
|
dev_test_task_data->m2m_ciu_query_addr =
|
|
IOT_DEV_TEST_QUERY_CIU_ADDR_SUCC;
|
|
}
|
|
if (iot_mac_addr_valid(hdr_645->addr) &&
|
|
!iot_mac_is_bcast(hdr_645->addr)) {
|
|
if (iot_mac_addr_cmp(hdr_645->addr, proto_645_any_addr)) {
|
|
iot_set_bcast_mac(t_mac);
|
|
} else {
|
|
iot_mac_addr_cpy(t_mac, hdr_645->addr);
|
|
}
|
|
iot_mac_addr_reverse(t_mac);
|
|
/* only if the dev_test support pushed-data handling,
|
|
* matching mac can be updated.
|
|
*/
|
|
iot_dev_test_update_match_mac(t_mac);
|
|
iot_dev_test_stop_send_bootup_ind();
|
|
|
|
iot_dev_test_handle_mr_req(GW_APP_DATA_TYPE_645_2007,
|
|
(uint8_t *)hdr_645, pkt_len, t_mac);
|
|
}
|
|
}
|
|
fe_cnt = (uint16_t)((uint8_t*)hdr_645 - data);
|
|
data = pkt_len + (uint8_t*)hdr_645;
|
|
} else {
|
|
hdr_698 = proto_69845_sanity_check(data, len);
|
|
if (hdr_698) {
|
|
iot_cus_printf("RECV_UART_69845 frame, fn 0x%04x, data_len %lu\n",
|
|
hdr_698->len, hdr_698->ctrl.fn);
|
|
|
|
proto_69845_get_addr_info(hdr_698, &svr_info);
|
|
iot_mac_addr_cpy(t_mac, svr_info.ser_info.addr);
|
|
iot_mac_addr_reverse(t_mac);
|
|
if (iot_dev_test_69845_control_cmd(hdr_698) == ERR_OK) {
|
|
goto out;
|
|
}
|
|
pkt_len = (uint8_t)(hdr_698->len + PROTO_69845_START_END_LEN);
|
|
iot_dev_test_handle_mr_req(GW_APP_DATA_TYPE_69845,
|
|
(uint8_t *)hdr_698, hdr_698->len + PROTO_69845_START_END_LEN,
|
|
t_mac);
|
|
fe_cnt = (uint16_t)((uint8_t*)hdr_698 - data);
|
|
data = pkt_len + (uint8_t*)hdr_698;
|
|
} else {
|
|
hdr_645 = proto_645_format_check(data, len, PROTO_645_DIR_SLAVE);
|
|
if (hdr_645) {
|
|
pkt_len = sizeof(*hdr_645) + hdr_645->len +
|
|
sizeof(proto_645_tailer_t);
|
|
switch (hdr_645->control.fn) {
|
|
case IOT_DEV_TEST_645_FN_ACK_FROM_CIU:
|
|
{
|
|
iot_dev_test_handle_ack_data_from_host(hdr_645);
|
|
break;
|
|
}
|
|
case IOT_DEV_TEST_645_FN_RSP_BOOTUP_IND:
|
|
{
|
|
iot_dev_test_stop_send_bootup_ind();
|
|
break;
|
|
}
|
|
default:
|
|
iot_cus_printf("%s FN not supported!\n", __FUNCTION__);
|
|
break;
|
|
}
|
|
fe_cnt = (uint16_t)((uint8_t*)hdr_645 - data);
|
|
data = pkt_len + (uint8_t*)hdr_645;
|
|
} else {
|
|
hdr_dlms = proto_dlms_hdlc_parse(data, len, &cache_dlms);
|
|
if (hdr_dlms) {
|
|
iot_cus_printf("RECV_UART_DLMS frame, type %lu, "
|
|
"data_len %lu\n", hdr_dlms->frame_format.bit.frame_type,
|
|
hdr_dlms->frame_format.bit.len);
|
|
if (cache_dlms.dest_addr.type !=
|
|
PROTO_DLMS_HDLC_ADD_TYPE_4) {
|
|
goto out;
|
|
}
|
|
proto_dlms_hdlc_type_4_addr_to_bcd_addr(dst_mac,
|
|
&cache_dlms.dest_addr);
|
|
if (!iot_mac_addr_valid(dst_mac)) {
|
|
goto out;
|
|
}
|
|
iot_mac_addr_reverse(dst_mac);
|
|
iot_mac_addr_cpy(t_mac, dst_mac);
|
|
frame_format.value =
|
|
iot_ntohs(hdr_dlms->frame_format.value);
|
|
pkt_len = frame_format.bit.len +
|
|
PROTO_DLMS_HDLC_START_END_LEN;
|
|
iot_dev_test_handle_mr_req(GW_APP_DATA_TYPE_TRANSPARENT,
|
|
(uint8_t *)hdr_dlms, pkt_len, t_mac);
|
|
} else {
|
|
iot_cus_printf("%s No more valid frame found!\n",
|
|
__FUNCTION__);
|
|
goto out;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
len = len - pkt_len - fe_cnt;
|
|
|
|
if (len) {
|
|
goto again;
|
|
}
|
|
out:
|
|
iot_pkt_free(pkt);
|
|
}
|
|
|
|
static void iot_dev_test_uart_send(iot_pkt_t *pkt)
|
|
{
|
|
iot_uart_send(dev_test_task_data->host_com, pkt, NULL);
|
|
return;
|
|
}
|
|
|
|
static iot_uart_h iot_dev_test_open_uart(uint8_t port)
|
|
{
|
|
iot_uart_h uart = 0;
|
|
|
|
uart = iot_uart_open(port, iot_dev_test_uart_meter_port_func,
|
|
IOT_DEV_TEST_UART_RECV_BUF_SIZE, NULL);
|
|
|
|
return uart;
|
|
}
|
|
|
|
static bool_t iot_dev_test_set_uart_config(iot_uart_h uart)
|
|
{
|
|
bool_t ret = false;
|
|
uint8_t parity;
|
|
uint32_t uart_baud = baud_tbl[dev_test_task_data->flashinfo.baud_index];
|
|
iot_frame_fmt fmt = { 0 };
|
|
iot_cus_printf("desire baudrate:[%lu]\n", uart_baud);
|
|
if (dev_test_task_data->user_type == USER_TYPE_STATE_GRID_OVERSEAS_SX) {
|
|
parity = IOT_UART_PARITY_NONE;
|
|
} else {
|
|
parity = IOT_UART_PARITY_EVEN;
|
|
}
|
|
ret = iot_uart_set_config(uart, uart_baud, parity, IOT_UART_DLEN_8_BITS,
|
|
IOT_UART_STOP_1_BITS);
|
|
/* config the UART port settings */
|
|
fmt.preamble_code[0] = PROTO_645_START_CHAR;
|
|
fmt.preamble_codelen = 1;
|
|
fmt.datalen_offset = 8;
|
|
fmt.datalen_size = 1;
|
|
fmt.backcode_offset = 1;
|
|
fmt.backcode_len = 1;
|
|
fmt.datalen_fix = 0;
|
|
fmt.backcode[0] = PROTO_645_END_CHAR;
|
|
fmt.frame_timeout = 30;
|
|
fmt.timeout_mode = TIMEOUT_PERDATA;
|
|
fmt.check_frame_func = proto_645_check_frame_handler;
|
|
iot_uart_set_frame(uart, &fmt);
|
|
|
|
/* report the data to app after 3 bytes' interval */
|
|
iot_uart_set_threshold(uart, UART_THR_RXTIMEOUT, 3);
|
|
/* report the data to app once received 100 bytes */
|
|
iot_uart_set_threshold(uart, UART_THR_RXFULL, 100);
|
|
return ret;
|
|
}
|
|
|
|
static void iot_dev_test_close_uart(iot_uart_h uart)
|
|
{
|
|
iot_uart_close(uart);
|
|
}
|
|
|
|
static void iot_dev_test_query_ciu_addr(void)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
uint32_t length = 0;
|
|
|
|
if (dev_test_task_data->query_addr_cnt >= IOT_DEV_TEST_QUERY_ADDR_CNT_MAX
|
|
|| dev_test_task_data->m2m_ciu_query_addr ==
|
|
IOT_DEV_TEST_QUERY_CIU_ADDR_SUCC) {
|
|
os_stop_timer(dev_test_task_data->query_addr_tm);
|
|
dev_test_task_data->query_addr_cnt = 0;
|
|
return;
|
|
}
|
|
|
|
dev_test_task_data->query_addr_cnt++;
|
|
|
|
pkt = iot_pkt_alloc(PROTO_645_2007_READ_ADDR_PKT_LEN, IOT_APP_DEV_TEST_MID);
|
|
if (!pkt) {
|
|
iot_cus_printf("%s failed to alloc pkt\n", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
iot_pkt_reserve(pkt, PROTO_645_PREAMBLE_LEN);
|
|
length = proto_645_fill_frame(iot_pkt_data(pkt), PROTO_645_2007_ID,
|
|
proto_645_any_addr, PROTO_645_DIR_MASTER, PROTO_645_ACK_NORMAL,
|
|
PROTO_645_FOLLOW_INVALID, PROTO_645_2007_FN_READ_ADDR,
|
|
PROTO_645_INVALID_DI, 0, NULL);
|
|
IOT_ASSERT(length);
|
|
iot_pkt_put(pkt, length);
|
|
iot_dev_test_uart_send(pkt);
|
|
|
|
return;
|
|
}
|
|
|
|
static uint8_t iot_dev_test_handle_msdu_data_recv(iot_pkt_t *pkt)
|
|
{
|
|
uint8_t consumed = 0;
|
|
uint8_t *ptr = NULL;
|
|
iot_plc_msdu_recv_t *msdu = NULL;
|
|
proto_conn_less_hdr_t *frm_hdr = NULL;
|
|
|
|
iot_plc_msg_header_t *hdr =
|
|
(iot_plc_msg_header_t*)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA);
|
|
msdu = (iot_plc_msdu_recv_t*)(hdr + 1);
|
|
|
|
ptr = msdu->data;
|
|
frm_hdr = (proto_conn_less_hdr_t *)ptr;
|
|
|
|
if (CONN_LESS_APP_PORT != frm_hdr->port) {
|
|
iot_cus_printf("received msdu data: wrong port\n");
|
|
return consumed;
|
|
}
|
|
|
|
switch (frm_hdr->id) {
|
|
case CONN_LESS_APP_ID_METER_R:
|
|
consumed = iot_dev_test_handle_normal_data(pkt);
|
|
break;
|
|
case CONN_LESS_APP_ID_DATA_PUSH:
|
|
consumed = iot_dev_test_handle_pushed_data(pkt);
|
|
break;
|
|
case CONN_LESS_APP_ID_CONFIG:
|
|
consumed = iot_dev_test_handle_config_data(pkt);
|
|
break;
|
|
default:
|
|
iot_cus_printf("received msdu data id 0x%04x "
|
|
"is not supported by app\n", frm_hdr->id);
|
|
break;
|
|
}
|
|
|
|
return consumed;
|
|
}
|
|
|
|
#else /* IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_METER */
|
|
|
|
static void iot_dev_test_buf_refresh(void)
|
|
{
|
|
return;
|
|
}
|
|
|
|
static void iot_dev_test_uart_qsxj_data_handle(iot_pkt_t *pkt)
|
|
{
|
|
iot_pkt_free(pkt);
|
|
}
|
|
|
|
static void iot_dev_test_uart_data_handle(iot_pkt_t *pkt)
|
|
{
|
|
iot_pkt_free(pkt);
|
|
}
|
|
|
|
static uint8_t iot_dev_test_handle_msdu_data_recv(iot_pkt_t *pkt)
|
|
{
|
|
(void)pkt;
|
|
return 0;
|
|
}
|
|
|
|
static void iot_dev_test_close_uart(iot_uart_h uart)
|
|
{
|
|
(void)uart;
|
|
}
|
|
|
|
static bool_t iot_dev_test_set_uart_config(iot_uart_h uart)
|
|
{
|
|
(void)uart;
|
|
return true;
|
|
}
|
|
|
|
static void iot_dev_test_query_ciu_addr(void)
|
|
{
|
|
return;
|
|
}
|
|
|
|
static void iot_dev_test_send_bootup_indication(void)
|
|
{
|
|
return;
|
|
}
|
|
|
|
static void iot_dev_test_ppm_detect_init()
|
|
{
|
|
|
|
}
|
|
|
|
static int8_t iot_dev_test_get_fix_ppm(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
#endif /* IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_METER */
|
|
|
|
/* Load config from PIB. */
|
|
static uint8_t iot_dev_test_flash_load(void)
|
|
{
|
|
uint8_t *rw = NULL;
|
|
uint8_t temp_pt = MAX_PIB_TYPE;
|
|
iot_pib_get_app_section(&rw, &temp_pt, IOT_PIB_APP_GET_WRITE_SECTION);
|
|
IOT_ASSERT(rw);
|
|
|
|
IOT_ASSERT(temp_pt == STA_PIB_TYPE);
|
|
|
|
os_mem_cpy(&dev_test_task_data->flashinfo, rw, sizeof(iot_dev_test_pib_t));
|
|
dev_test_task_data->section = rw;
|
|
|
|
iot_dev_test_pib_t *info = &dev_test_task_data->flashinfo;
|
|
iot_cus_printf("boot cnt: %lu, loaded mac[%02x:%02x:%02x:%02x:%02x:%02x],"
|
|
"baud index: %lu\n",
|
|
info->boot_cnt, info->match_mac[0], info->match_mac[1],
|
|
info->match_mac[2], info->match_mac[3], info->match_mac[4],
|
|
info->match_mac[5], info->baud_index);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
/* Check the magic code to tell if the flash infor is damaged. */
|
|
static uint8_t iot_dev_test_flashinfo_check(iot_dev_test_pib_t *p_info)
|
|
{
|
|
uint32_t magic1, magic2;
|
|
uint8_t ret = ERR_OK;
|
|
|
|
magic1 = p_info->magic1;
|
|
|
|
magic2 = p_info->magic2;
|
|
|
|
iot_cus_printf("Magic = 0x%08x, 0x%08x!\n", magic1, magic2);
|
|
|
|
if ((IOT_DEV_TEST_FLASHINFO_MAGIC1 != magic1)
|
|
||(IOT_DEV_TEST_FLASHINFO_MAGIC2 != magic2)) {
|
|
ret = ERR_FAIL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* This will store config into PIB area. */
|
|
static uint8_t iot_dev_test_flash_save(iot_dev_test_pib_t *p_info)
|
|
{
|
|
uint8_t ref;
|
|
uint16_t ticket;
|
|
|
|
iot_pib_acquire_app_commit_ref(&ref);
|
|
os_mem_cpy(dev_test_task_data->section, p_info, sizeof(*p_info));
|
|
iot_pib_release_app_commit_ref(&ref);
|
|
iot_pib_app_commit(&ticket);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
/* load flash infor and update local infor */
|
|
static void iot_dev_test_flash_info_init(void)
|
|
{
|
|
iot_dev_test_pib_t *p_info = &dev_test_task_data->flashinfo;
|
|
|
|
if (ERR_FAIL == iot_dev_test_flash_load() ||
|
|
ERR_FAIL == iot_dev_test_flashinfo_check(p_info)) {
|
|
iot_cus_printf("get flash info failed\n!");
|
|
os_mem_set(p_info, 0x0, sizeof(*p_info));
|
|
p_info->baud_index = DEFAULT_BAUDRATE_INDEX;
|
|
p_info->magic1 = IOT_DEV_TEST_FLASHINFO_MAGIC1;
|
|
p_info->magic2 = IOT_DEV_TEST_FLASHINFO_MAGIC2;
|
|
iot_dev_test_flash_save(p_info);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/* get start-up app SN from boot cnt and rondom data */
|
|
static uint16_t iot_dev_test_startup_app_sn_create(void) {
|
|
uint16_t app_sn;
|
|
uint16_t boot_cnt = dev_test_task_data->flashinfo.boot_cnt;
|
|
|
|
app_sn = (boot_cnt << 12) + (uint16_t)(os_rand() & 0xFFF);
|
|
iot_cus_printf("[dev_test]boot_cnt %lu, created SN %lu\n",
|
|
dev_test_task_data->flashinfo.boot_cnt, app_sn);
|
|
/* update the boot cnt then store into flash */
|
|
iot_counter_inc(dev_test_task_data->flashinfo.boot_cnt);
|
|
iot_dev_test_flash_save(&dev_test_task_data->flashinfo);
|
|
return app_sn;
|
|
}
|
|
|
|
/* allocte a conn_less_msdu, then fill the msdu pkt with
|
|
* conn_less mode config data
|
|
*/
|
|
static uint8_t iot_dev_test_send_mode_config(uint8_t *dst_mac)
|
|
{
|
|
uint16_t buflen = 0;
|
|
uint8_t *ptr = NULL;
|
|
iot_pkt_t *msdu_pkt;
|
|
dev_test_mode_cfg_t *cfg;
|
|
uint8_t *msdu_dst_mac = NULL;
|
|
int8_t fix_ppm;
|
|
|
|
if (dev_test_task_data->user_type == USER_TYPE_YNS) {
|
|
return ERR_OK;
|
|
}
|
|
if (!iot_mac_addr_valid(dst_mac)) {
|
|
iot_cus_printf("%s: dst mac is invalid!\n", __FUNCTION__);
|
|
return ERR_INVAL;
|
|
}
|
|
|
|
#if (IOT_DEV_TEST_BROADCAST_MODD_CFG == 1)
|
|
if (!iot_mac_is_bcast(dst_mac)) {
|
|
return ERR_INVAL;
|
|
}
|
|
#else
|
|
if (iot_mac_is_bcast(dst_mac)) {
|
|
return ERR_INVAL;
|
|
}
|
|
#endif
|
|
|
|
fix_ppm = iot_dev_test_get_fix_ppm();
|
|
|
|
if (IOT_DEV_TEST_SUPPORT_CT_MR_EN && !dev_test_task_data->collector_vaild) {
|
|
msdu_dst_mac = (uint8_t *)bcast_mac;
|
|
} else if (dev_test_task_data->collector_vaild) {
|
|
msdu_dst_mac = dev_test_task_data->collector;
|
|
} else {
|
|
msdu_dst_mac = dst_mac;
|
|
}
|
|
|
|
buflen = sizeof(dev_test_mode_cfg_t) + sizeof(dev_test_ext_cfg_t);
|
|
|
|
msdu_pkt = iot_plc_alloc_conn_less_msdu_ext(dev_test_task_data->app_handle,
|
|
IOT_PLC_MSG_TYPE_CONN_LESS_CMD, dst_mac, dev_test_task_data->mac_addr,
|
|
dev_test_task_data->link_id, buflen, IOT_PLC_LOCAL_RETRY_CNT,
|
|
fix_ppm, 0, dev_test_task_data->tx_link_type);
|
|
|
|
if (msdu_pkt == NULL) {
|
|
iot_cus_printf("%s:allocate msdu failed!\n", __FUNCTION__);
|
|
return ERR_NOMEM;
|
|
}
|
|
|
|
ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_TAIL);
|
|
iot_pkt_put(msdu_pkt, buflen);
|
|
cfg = (dev_test_mode_cfg_t *)ptr;
|
|
cfg->band_id = dev_test_task_data->band_id;
|
|
cfg->dur = IOT_DEV_TEST_MODE_CFG_DUR;
|
|
cfg->ext_cfg_en = dev_test_task_data->ext_cfg_en;
|
|
os_mem_cpy((uint8_t *)&cfg->ext_cfg,
|
|
(uint8_t *)&dev_test_task_data->ext_cfg, sizeof(dev_test_ext_cfg_t));
|
|
#if IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_METER
|
|
cfg->target_id_mask = IOT_DEV_TEST_TARGET_ID_MSK_STA;
|
|
#elif IOT_DEV_TEST_CCO_MODE
|
|
cfg->target_id_mask = IOT_DEV_TEST_TARGET_ID_MSK_CCO;
|
|
#endif
|
|
|
|
iot_cus_printf("send mode config to [%02x:%02x:%02x:%02x:%02x:%02x]"
|
|
" band id-%lu, duration-%lu sec, mask-%lu, ext en-%lu, [valid-%lu] "
|
|
"rf option-%lu rf channel-%lu, [valid-%lu]rf power-(%d)dbm, "
|
|
"[valid-%lu]hplc power-(%lu)dbuv\n",
|
|
msdu_dst_mac[0], msdu_dst_mac[1], msdu_dst_mac[2], msdu_dst_mac[3],
|
|
msdu_dst_mac[4], msdu_dst_mac[5], cfg->band_id, cfg->dur,
|
|
cfg->target_id_mask, cfg->ext_cfg_en, cfg->ext_cfg[0].rf_valid,
|
|
cfg->ext_cfg[0].rf_option, cfg->ext_cfg[0].rf_channel,
|
|
cfg->ext_cfg[0].rf_power_valid, cfg->ext_cfg[0].rf_tx_power,
|
|
cfg->ext_cfg[0].hplc_power_valid, cfg->ext_cfg[0].hplc_tx_power);
|
|
iot_plc_send_msdu(dev_test_task_data->app_handle, msdu_pkt);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
static void iot_dev_test_msdu_recv(void *param, iot_pkt_t *pkt)
|
|
{
|
|
(void)param;
|
|
iot_dev_test_post_task_msg(IOT_DEV_TEST_MAC_MSG, 0, pkt);
|
|
return;
|
|
}
|
|
|
|
static void iot_dev_test_periodic_timer_func(timer_id_t timer_id,
|
|
void * arg)
|
|
{
|
|
(void)timer_id;
|
|
(void)arg;
|
|
|
|
iot_dev_test_post_task_msg(IOT_DEV_TEST_TIMER_MSG,
|
|
IOT_DEV_TEST_TIMER_CHECK, NULL);
|
|
}
|
|
|
|
static void iot_dev_test_query_addr_timer_func (timer_id_t timer_id, void * arg)
|
|
{
|
|
(void)timer_id;
|
|
(void)arg;
|
|
|
|
iot_dev_test_post_task_msg(IOT_DEV_TEST_TIMER_MSG,
|
|
IOT_DEV_TEST_TIMER_QUERY_ADDR, NULL);
|
|
}
|
|
|
|
static void iot_dev_test_handle_timer_msg(
|
|
iot_dev_test_task_msg_t* task_msg)
|
|
{
|
|
switch (task_msg->msg.id) {
|
|
case IOT_DEV_TEST_TIMER_CHECK:
|
|
{
|
|
iot_dev_test_config_all_sta_test_mode();
|
|
|
|
iot_dev_test_buf_refresh();
|
|
|
|
iot_dev_test_send_bootup_indication();
|
|
break;
|
|
}
|
|
case IOT_DEV_TEST_TIMER_QUERY_ADDR:
|
|
{
|
|
iot_dev_test_query_ciu_addr();
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void iot_dev_test_set_cfg_after_app_reg(void)
|
|
{
|
|
iot_plc_cfg_set_req_t cfg = {0};
|
|
iot_plc_app_h app_hdl = dev_test_task_data->app_handle;
|
|
|
|
/* enable whitelist */
|
|
iot_plc_set_whitelist(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT,
|
|
IOT_PLC_WL_ENABLE, 0, NULL);
|
|
|
|
/* stop network formation */
|
|
iot_plc_stop_nw_fmt(app_hdl);
|
|
|
|
/* set configuration of local device */
|
|
iot_dev_test_pib_t *p_flash = &dev_test_task_data->flashinfo;
|
|
|
|
#if IOT_DEV_TEST_BUILD_CIU_TESTER && (IOT_DEV_TEST_BROADCAST_MODD_CFG == 0)
|
|
iot_mac_addr_cpy( p_flash->match_mac, (uint8_t *)ciu_tester_mac);
|
|
#endif
|
|
|
|
if (!iot_mac_is_bcast(p_flash->match_mac)
|
|
&& iot_mac_addr_valid(p_flash->match_mac)) {
|
|
iot_mac_addr_cpy(cfg.addr, p_flash->match_mac);
|
|
cfg.addr_valid = 1;
|
|
iot_cus_printf("%s: set local mac[%02x:%02x:%02x:%02x:%02x:%02x] "
|
|
"successfully\n", __FUNCTION__, cfg.addr[0], cfg.addr[1],
|
|
cfg.addr[2], cfg.addr[3], cfg.addr[4], cfg.addr[5]);
|
|
}
|
|
cfg.reset = 1;
|
|
cfg.dev_type_valid = 1;
|
|
cfg.dev_type = IOT_PLC_DEV_TYPE_METER_CONTROLLER;
|
|
iot_plc_set_cfg(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT, &cfg);
|
|
|
|
/* set default frequnce band */
|
|
#if (IOT_DEV_TEST_SUPPORT_MUTIBAND == 1)
|
|
iot_plc_set_freq_band(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT,
|
|
PLC_LIB_FREQ_BAND_MULTI_1_2);
|
|
#else
|
|
iot_plc_set_freq_band(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT,
|
|
dev_test_task_data->band_id);
|
|
#endif
|
|
/* query device infor */
|
|
iot_plc_query_dev_info(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT);
|
|
|
|
/* disable watchdog */
|
|
iot_plc_wdg_set(app_hdl, 0, 0);
|
|
/* get the app SN and update the boot counter */
|
|
dev_test_task_data->app_sn = iot_dev_test_startup_app_sn_create();
|
|
|
|
#if IOT_DEV_TEST_CCO_MODE
|
|
int8_t rf_power = 16;
|
|
if (dev_test_task_data->user_type == USER_TYPE_STATE_GRID_LIAONING) {
|
|
dev_test_task_data->ext_cfg.rf_power_valid = 1;
|
|
dev_test_task_data->ext_cfg.rf_tx_power = 16;
|
|
iot_plc_set_tx_power_cap(app_hdl, IOT_PLC_API_REQ_ID_DEFAULT,
|
|
NULL, &rf_power);
|
|
}
|
|
#endif
|
|
|
|
/* start reload timer */
|
|
os_start_timer(dev_test_task_data->periodic_tm,
|
|
IOT_DEV_TEST_PERIODIC_TIMER_INTERVAL);
|
|
|
|
}
|
|
|
|
static void iot_dev_test_handle_mac_msg(iot_pkt_t *pkt)
|
|
{
|
|
iot_plc_msg_header_t *hdr =
|
|
(iot_plc_msg_header_t*)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA);
|
|
uint8_t consumed = 0;
|
|
uint8_t app_id;
|
|
|
|
#if (IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_METER)
|
|
app_id = IOT_PLC_APP_SMART_GRID;
|
|
#elif IOT_DEV_TEST_CCO_MODE
|
|
app_id = IOT_PLC_APP_DEV_TEST;
|
|
#endif
|
|
|
|
if (hdr->app_id != IOT_PLC_APP_ID_BCAST &&
|
|
hdr->app_id != app_id) {
|
|
iot_pkt_free(pkt);
|
|
return;
|
|
}
|
|
|
|
if (dev_test_task_data->app_registered == 0 &&
|
|
hdr->msg_id != IOT_PLC_MSG_APP_REG_CONF) {
|
|
// only handle app register confirm message before app registered
|
|
iot_pkt_free(pkt);
|
|
return;
|
|
}
|
|
|
|
switch (hdr->msg_id) {
|
|
case IOT_PLC_MSG_APP_REG_CONF:
|
|
{
|
|
iot_plc_app_reg_conf_t* rpt = (iot_plc_app_reg_conf_t*)(hdr + 1);
|
|
iot_cus_printf("%s: IOT_PLC_MSG_APP_REG_CONF result:%d\n", __FUNCTION__,
|
|
rpt->result);
|
|
if (rpt->result == IOT_PLC_SUCCESS ||
|
|
rpt->result == IOT_PLC_SUCCESS_MODIFIED) {
|
|
dev_test_task_data->app_registered = 1;
|
|
iot_dev_test_set_cfg_after_app_reg();
|
|
}
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_DEV_STATE_CHANGE_RPT:
|
|
{
|
|
iot_plc_dev_state_change_rpt_t* rpt =
|
|
(iot_plc_dev_state_change_rpt_t*)(hdr + 1);
|
|
iot_cus_printf("[dev_test]IOT_PLC_MSG_DEV_STATE_CHANGE_RPT: "
|
|
"local mac[%02X:%02X:%02X:%02X:%02X:%02X], role:%lu, ready:%lu\n",
|
|
rpt->local_mac[0], rpt->local_mac[1], rpt->local_mac[2],
|
|
rpt->local_mac[3], rpt->local_mac[4], rpt->local_mac[5],
|
|
rpt->dev_role, rpt->is_ready);
|
|
if (iot_mac_addr_valid(rpt->local_mac)) {
|
|
dev_test_task_data->dev_role = rpt->dev_role;
|
|
iot_mac_addr_cpy(dev_test_task_data->mac_addr, rpt->local_mac);
|
|
dev_test_task_data->dev_ready = 1;
|
|
iot_dev_test_send_bootup_indication();
|
|
}
|
|
#if IOT_DEV_TEST_CCO_MODE
|
|
/* dev_test_cco is fixed band, but when SG app configures plc, band
|
|
* information is lost and needs to be reconfigured.
|
|
*/
|
|
iot_plc_set_freq_band(dev_test_task_data->app_handle,
|
|
IOT_PLC_API_REQ_ID_DEFAULT, dev_test_task_data->band_id);
|
|
#endif
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_DEV_INFO_RPT:
|
|
{
|
|
iot_plc_dev_info_rpt_t* rpt = (iot_plc_dev_info_rpt_t*)(hdr + 1);
|
|
iot_cus_printf("%s: infor report--role %lu, dev type %lu, local mac"
|
|
"[%02x:%02x:%02x:%02x:%02x:%02x]\n", __FUNCTION__,
|
|
rpt->dev_role, rpt->dev_type, rpt->local_mac[0], rpt->local_mac[1],
|
|
rpt->local_mac[2], rpt->local_mac[3], rpt->local_mac[4],
|
|
rpt->local_mac[5]);
|
|
if (iot_mac_addr_valid(rpt->local_mac)) {
|
|
dev_test_task_data->dev_role = rpt->dev_role;
|
|
dev_test_task_data->dev_type = rpt->dev_type;
|
|
iot_mac_addr_cpy(dev_test_task_data->mac_addr, rpt->local_mac);
|
|
dev_test_task_data->dev_ready = 1;
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
break;
|
|
}
|
|
case IOT_PLC_MSG_CONN_LESS_RECV:
|
|
{
|
|
consumed = iot_dev_test_handle_msdu_data_recv(pkt);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
if (consumed == 0) {
|
|
iot_pkt_free(pkt);
|
|
}
|
|
}
|
|
|
|
static void iot_dev_test_task_handle_msg(iot_task_h task_h,
|
|
iot_task_msg_t *msg)
|
|
{
|
|
iot_dev_test_task_msg_t *task_msg;
|
|
IOT_ASSERT(task_h == dev_test_task_data->task_handle);
|
|
IOT_ASSERT(msg);
|
|
|
|
task_msg = (iot_dev_test_task_msg_t*)msg;
|
|
switch (task_msg->msg.type) {
|
|
case IOT_DEV_TEST_MAC_MSG:
|
|
{
|
|
iot_dev_test_handle_mac_msg(task_msg->data);
|
|
break;
|
|
}
|
|
case IOT_DEV_TEST_TIMER_MSG:
|
|
{
|
|
iot_dev_test_handle_timer_msg(task_msg);
|
|
break;
|
|
}
|
|
case IOT_DEV_TEST_UART_RECV_MSG:
|
|
{
|
|
if (dev_test_task_data->user_type ==
|
|
USER_TYPE_STATE_GRID_OVERSEAS_SX) {
|
|
iot_dev_test_uart_qsxj_data_handle(task_msg->data);
|
|
} else {
|
|
iot_dev_test_uart_data_handle(task_msg->data);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
iot_task_free_msg(dev_test_task_data->task_handle, &task_msg->msg);
|
|
}
|
|
|
|
static void iot_dev_test_task_handle_msg_cancel(iot_task_h task_h,
|
|
iot_task_msg_t *msg)
|
|
{
|
|
iot_dev_test_task_msg_t *task_msg;
|
|
IOT_ASSERT(task_h == dev_test_task_data->task_handle);
|
|
IOT_ASSERT(msg);
|
|
|
|
task_msg = (iot_dev_test_task_msg_t*)msg;
|
|
switch (task_msg->msg.type) {
|
|
case IOT_DEV_TEST_MAC_MSG:
|
|
case IOT_DEV_TEST_UART_RECV_MSG:
|
|
{
|
|
if (task_msg->data) {
|
|
iot_pkt_free(task_msg->data);
|
|
}
|
|
break;
|
|
}
|
|
case IOT_DEV_TEST_TIMER_MSG:
|
|
{
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
iot_task_free_msg(dev_test_task_data->task_handle, &task_msg->msg);
|
|
}
|
|
|
|
static uint32_t iot_dev_test_task_init()
|
|
{
|
|
uint32_t ret = ERR_OK;
|
|
iot_plc_app_t dev_test_app = {0};
|
|
iot_task_config_t task_cfg;
|
|
iot_uart_h uart_hdl = NULL;
|
|
|
|
#if (IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_METER)
|
|
|
|
/* when IOT_STA_CONTROL_MODE equals 2, if uart port0 could not be opened,
|
|
* that means sta controller app is running, dev_test app should not run.
|
|
* when IOT_DEV_TEST_CCO_MODE equals 1, dev_test no longer using uart port,
|
|
* check uart port is not neccesary.
|
|
* when IOT_STA_CONTROL_MODE equals 2, the IOT_DEV_TEST_CCO_MODE
|
|
* must be 0.
|
|
*/
|
|
uart_hdl = iot_dev_test_open_uart(iot_board_get_uart(UART_METER_PORT));
|
|
if (uart_hdl == NULL) {
|
|
iot_cus_printf("open uart meter port failed!\n");
|
|
goto out;
|
|
} else {
|
|
iot_cus_printf("open uart meter port successfully!\n");
|
|
}
|
|
|
|
#endif /* IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_METER */
|
|
|
|
dev_test_task_data = os_mem_malloc(IOT_APP_DEV_TEST_MID,
|
|
sizeof(*dev_test_task_data));
|
|
if (!dev_test_task_data) {
|
|
ret = ERR_NOMEM;
|
|
goto error_1;
|
|
}
|
|
|
|
os_mem_set(dev_test_task_data, 0, sizeof(iot_dev_test_task_data_t));
|
|
|
|
dev_test_task_data->host_com = uart_hdl;
|
|
dev_test_task_data->link_id = IOT_DEV_TEST_TASK_LINK_ID;
|
|
dev_test_task_data->dev_role = IOT_PLC_DEV_ROLE_INVALID;
|
|
dev_test_task_data->dev_mode = IOT_DEV_TEST_APP_MODE_M2S;
|
|
dev_test_task_data->flashinfo.baud_index = DEFAULT_BAUDRATE_INDEX;
|
|
dev_test_task_data->user_type = iot_oem_get_user_type();
|
|
if ((dev_test_task_data->user_type == USER_TYPE_STATE_GRID_CQ) ||
|
|
(dev_test_task_data->user_type == USER_TYPE_STATE_GRID_JIBEI)) {
|
|
dev_test_task_data->band_id = PLC_LIB_FREQ_BAND_1;
|
|
} else {
|
|
dev_test_task_data->band_id = PLC_LIB_FREQ_BAND_2;
|
|
}
|
|
dev_test_task_data->ext_cfg_en = 1;
|
|
|
|
#if IOT_DEV_TEST_HANDLE_PUSH_DATA_EN
|
|
dev_test_task_data->boot_ind_en = 1;
|
|
#else
|
|
dev_test_task_data->boot_ind_en = 0;
|
|
#endif
|
|
|
|
iot_dev_test_flash_info_init();
|
|
iot_dev_test_ppm_detect_init();
|
|
|
|
/* Default is for China sg market use.
|
|
* For outsea market, below need to do:
|
|
* 1. build CIU binary.
|
|
* 2. set IOT_DEV_TEST_BUILD_CIU_TESTER = 1 and
|
|
* set dev_mode = IOT_DEV_TEST_APP_MODE_M2M, build CIU tester binary.
|
|
*/
|
|
#if IOT_DEV_TEST_BUILD_CIU_TESTER
|
|
dev_test_task_data->m2m_sub_mode = IOT_DEV_TEST_M2M_SUBMODE_CIUTESTER;
|
|
dev_test_task_data->dev_mode = IOT_DEV_TEST_APP_MODE_M2M;
|
|
#else
|
|
dev_test_task_data->m2m_sub_mode = IOT_DEV_TEST_M2M_SUBMODE_CIU;
|
|
#endif
|
|
dev_test_task_data->m2m_check_addr = IOT_DEV_TEST_ADDR_NOT_SET;
|
|
dev_test_task_data->m2m_ciu_query_addr = IOT_DEV_TEST_QUERY_CIU_ADDR_FAIL;
|
|
dev_test_task_data->query_addr_cnt = 0;
|
|
dev_test_task_data->tx_link_type = IOT_PLC_TX_LINK_TYPE_HPLC;
|
|
|
|
task_cfg.stack_size = 0;
|
|
task_cfg.task_prio = IOT_DEV_TEST_TASK_PRIO;
|
|
task_cfg.msg_size = sizeof(iot_dev_test_task_msg_t);
|
|
task_cfg.msg_cnt = IOT_DEV_TEST_TASK_POOL_SIZE;
|
|
task_cfg.queue_cnt = IOT_DEV_TEST_TASK_QUEUE_MAX_PRIO;
|
|
task_cfg.queue_cfg[IOT_DEV_TEST_TASK_QUEUE_HP].quota = 0;
|
|
task_cfg.msg_exe_func = iot_dev_test_task_handle_msg;
|
|
task_cfg.msg_cancel_func = iot_dev_test_task_handle_msg_cancel;
|
|
|
|
dev_test_task_data->task_handle =
|
|
iot_task_create(IOT_APP_DEV_TEST_MID, &task_cfg);
|
|
|
|
if (dev_test_task_data->task_handle == NULL) {
|
|
ret = ERR_FAIL;
|
|
goto error_2;
|
|
}
|
|
|
|
dev_test_task_data->periodic_tm = os_create_timer(
|
|
IOT_APP_DEV_TEST_MID, true, iot_dev_test_periodic_timer_func,
|
|
dev_test_task_data);
|
|
if (dev_test_task_data->periodic_tm == 0) {
|
|
ret = ERR_FAIL;
|
|
goto error_3;
|
|
}
|
|
|
|
dev_test_task_data->query_addr_tm = os_create_timer(
|
|
IOT_APP_DEV_TEST_MID, true, iot_dev_test_query_addr_timer_func,
|
|
dev_test_task_data);
|
|
if (dev_test_task_data->query_addr_tm == 0) {
|
|
ret = ERR_FAIL;
|
|
goto error_4;
|
|
}
|
|
|
|
if (dev_test_task_data->host_com) {
|
|
if (iot_dev_test_set_uart_config(dev_test_task_data->host_com)) {
|
|
iot_cus_printf("host uart config success\n");
|
|
} else {
|
|
iot_cus_printf("host uart config fail\n");
|
|
goto error_5;
|
|
}
|
|
}
|
|
|
|
#if IOT_DEV_TEST_CCO_MODE
|
|
dev_test_app.app_id = IOT_PLC_APP_DEV_TEST;
|
|
#elif (IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_METER)
|
|
dev_test_app.app_id = IOT_PLC_APP_SMART_GRID;
|
|
#endif
|
|
|
|
dev_test_app.param = NULL;
|
|
dev_test_app.prio = 3;
|
|
dev_test_app.recv = iot_dev_test_msdu_recv;
|
|
|
|
dev_test_task_data->app_handle = iot_plc_register_app(&dev_test_app);
|
|
if (dev_test_task_data->app_handle == NULL) {
|
|
ret = ERR_FAIL;
|
|
goto error_5;
|
|
}
|
|
|
|
dev_test_task_data->info_pool.remain_cnt = IOT_DEV_TEST_POOL_NUM;
|
|
|
|
#if (IOT_DEV_TEST_BUILD_CIU_TESTER && IOT_DEV_TEST_BROADCAST_MODD_CFG)
|
|
iot_dev_test_set_mac((uint8_t *)ciu_tester_mac);
|
|
#endif
|
|
|
|
goto out;
|
|
|
|
error_5:
|
|
os_delete_timer(dev_test_task_data->query_addr_tm);
|
|
dev_test_task_data->query_addr_tm = 0;
|
|
error_4:
|
|
os_delete_timer(dev_test_task_data->periodic_tm);
|
|
dev_test_task_data->periodic_tm = 0;
|
|
error_3:
|
|
iot_task_delete(dev_test_task_data->task_handle);
|
|
dev_test_task_data->task_handle = NULL;
|
|
error_2:
|
|
os_mem_free(dev_test_task_data);
|
|
dev_test_task_data = NULL;
|
|
error_1:
|
|
if (uart_hdl) {
|
|
iot_dev_test_close_uart(uart_hdl);
|
|
uart_hdl = NULL;
|
|
}
|
|
out:
|
|
iot_cus_printf("[dev_test]Initializing task done, ret: %lu\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
uint32_t app_dev_test_entry()
|
|
{
|
|
uint32_t ret = ERR_NOT_READY;
|
|
/* if the firmware is release version(0), disabel log printing, if not,
|
|
* enable the log printing
|
|
*/
|
|
if (iot_version_type() == 1) {
|
|
iot_cus_print_config(true);
|
|
} else {
|
|
iot_cus_print_config(false);
|
|
}
|
|
|
|
if (iot_dev_test_task_init()) {
|
|
return ERR_OK;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#endif /* (IOT_STA_CONTROL_MODE == 2) || (IOT_DEV_TEST_CCO_MODE) */
|
|
|