Files
kunlun/app/dev_test/iot_app_dev_test.c
2024-09-28 14:24:04 +08:00

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) */