Files
kunlun/app/iot_cus_at_app/common/app_main.c
2024-09-28 14:24:04 +08:00

1283 lines
39 KiB
C

/****************************************************************************
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.
****************************************************************************/
#include "app_uart.h"
#include "app_main.h"
#include "iot_app_meta_api.h"
#include "iot_plc_sync_api.h"
#include "app_cus_task.h"
#include "iot_app_pib_cco_api.h"
#include "iot_app_pib_sta_api.h"
#include "iot_plc_led_api.h"
#include "iot_oem_api.h"
#include "iot_app_meta_api.h"
#include "app_1901.h"
#include "app_upg.h"
#if (IOT_APP_SELECTION == IOT_APP_DEF_18_AT_APP)
#include "app_bypass_proc.h"
#include "app_atcmd_proc.h"
#include "app_atcmd_handle.h"
#endif
#if (IOT_APP_SELECTION == IOT_APP_DEF_25_AT_MICRO_CCTT)
#include "app_atcmd_proc.h"
#include "app_atcmd_handle.h"
#endif
#if APP_IO_OPERATION_ENABLE
#include "app_gpio.h"
#endif /* end APP_IO_OPERATION_ENABLE */
extern void iot_print_config(uint8_t enable);
app_entity_t g_app_entry;
static timer_id_t pkt_info_timer;
inline app_entity_t *app_get_main_entry()
{
return &g_app_entry;
}
uint8_t app_work_mode_register(uint8_t work_mode, void *parser_func,
void *data_handle_func, void* reporter_func)
{
uint16_t ret = ERR_FAIL;
app_entity_t *app_entry = NULL;
if (work_mode > APP_WORK_MODE_MAX) {
goto out;
}
app_entry = app_get_main_entry();
if (app_entry->work_mode_reg[work_mode].enable == APP_WORK_MODE_DISABLE) {
app_entry->work_mode_reg[work_mode].data_parser = (app_data_parser_func
) parser_func;
app_entry->work_mode_reg[work_mode].data_handle = (app_data_handle_func
) data_handle_func;
app_entry->work_mode_reg[work_mode].on_off_report = (
app_onoffline_stat_report ) reporter_func;
app_entry->work_mode_reg[work_mode].enable = APP_WORK_MODE_ENABLE;
ret = ERR_OK;
}
out:
if (ret) {
APP_PRINTF("[ERR] register work mode = %d failed!!!", work_mode);
}
return ret;
}
uint8_t app_work_mode_unregister(uint8_t work_mode)
{
uint16_t ret = ERR_FAIL;
app_entity_t *app_entry = NULL;
if (work_mode > APP_WORK_MODE_MAX) {
goto out;
}
app_entry = app_get_main_entry();
if (app_entry->work_mode_reg[work_mode].enable == APP_WORK_MODE_ENABLE) {
app_entry->work_mode_reg[work_mode].enable = APP_WORK_MODE_DISABLE;
ret = ERR_OK;
goto out;
}
out:
if (ret) {
APP_PRINTF("[ERR] unregister work mode = %d failed!!!", work_mode);
}
return ret;
}
uint8_t app_set_work_mode(uint8_t work_mode)
{
app_entity_t *app_entry = NULL;
if (work_mode > APP_WORK_MODE_MAX) {
APP_PRINTF("[ERR] set work mode = %d failed, invalid work mode.", work_mode);
return ERR_FAIL;
}
app_entry = app_get_main_entry();
app_entry->work_mode_now = work_mode;
APP_PRINTF("[INF] set work mode = %d successrully ...", work_mode);
return ERR_OK;
}
uint8_t app_get_work_mode()
{
app_entity_t *app_entry = NULL;
app_entry = app_get_main_entry();
return app_entry->work_mode_now;
}
static uint16_t app_data_frame_parse(uint8_t * buffer, uint32_t buffer_len,
app_source_e source)
{
uint8_t work_mode = 0;
uint16_t ret = ERR_FAIL;
app_entity_t *app_entry = NULL;
#if (IOT_APP_SELECTION == IOT_APP_DEF_18_AT_APP)
/* if uart rx '+++', switch to AT cmd mode */
if ((APP_WORK_MODE_AT != app_get_work_mode()) &&
(buffer_len == CHECK_ATCMD_BUF_SIZE) &&
iot_strstr((char*)buffer, "+++")) {
AT_RESP_OK();
app_set_work_mode(APP_WORK_MODE_AT);
return ERR_FAIL;
}
#endif
app_entry = app_get_main_entry();
work_mode = app_get_work_mode();
if (app_entry->work_mode_reg[work_mode].enable == APP_WORK_MODE_ENABLE ) {
app_entry->work_mode_reg[work_mode].data_parser(buffer, buffer_len, source);
ret = ERR_OK;
}
if (ret) {
APP_PRINTF("[ERR] %s - unregistered work mode = %d!!!", __FUNCTION__,
work_mode);
}
return ret;
}
static uint16_t app_onoffline_state_report(uint8_t *dev_mac, uint8_t status)
{
uint8_t work_mode = 0;
uint16_t ret = ERR_FAIL;
app_entity_t *app_entry = NULL;
if (false == app_get_sta_join_notify()) {
return ERR_NOSUPP;
}
app_entry = app_get_main_entry();
work_mode = app_get_work_mode();
if (app_entry->work_mode_reg[work_mode].enable == APP_WORK_MODE_ENABLE ) {
app_entry->work_mode_reg[work_mode].on_off_report(dev_mac, status);
ret = ERR_OK;
}
if (ret) {
APP_PRINTF("[ERR] %s - unregistered work mode = %d!!!", __FUNCTION__,
work_mode);
}
return ret;
}
uint32_t app_post_msg(uint16_t msg_type, uint16_t msg_id, void *data)
{
iot_task_msg_t *msg;
app_msg_t *task_msg;
app_entity_t *app_entry = NULL;
app_entry = app_get_main_entry();
msg = iot_task_alloc_msg_with_reserved(app_entry->msg_task.handle, 0);
if (NULL == msg) {
APP_PRINTF("[ERR] %s Alloc MSG Buffer Failed !!", __FUNCTION__);
return ERR_FAIL;
}
task_msg = (app_msg_t *)msg;
task_msg->msg.type = msg_type;
task_msg->msg.id = msg_id;
task_msg->data = data;
iot_task_queue_msg(app_entry->msg_task.handle, &task_msg->msg, APP_TASK_MSG_PRIO);
return ERR_OK;
}
/* recv cli message post to task */
uint32_t app_demo_post_msg_cli(void *data)
{
app_post_msg(E_APP_MSG_PROCESS, E_CMD_ID_RCV_FROM_CLI, data);
return ERR_OK;
}
/* handle message recv from plc */
static uint16_t iot_app_plc_msg_handle(iot_pkt_t *pkt)
{
iot_plc_msg_header_t *hdr;
iot_plc_msdu_recv_t *msdu;
uint16_t ret = ERR_FAIL;
uint8_t work_mode;
uint8_t *frame;
uint32_t frame_len = 0;
app_entity_t *app_entry = NULL;
recv_info_t rx_info = {0};
#if SUPPORT_IEEE_1901
app_plc_frame_data_hi *app_data;
#else
app_custom_data *app_data;
#endif /* end SUPPORT_IEEE_1901 */
app_entry = app_get_main_entry();
app_entry->receivetime = iot_plc_get_ntb(app_entry->app_hdl);
hdr = (iot_plc_msg_header_t*)iot_pkt_data(pkt);
msdu = (iot_plc_msdu_recv_t*)(hdr + 1);
work_mode = app_get_work_mode();
APP_PRINTF("msdu->len=%d pkt_len=%d", msdu->len, iot_pkt_data_len(pkt));
#if SUPPORT_IEEE_1901
app_data = (app_plc_frame_data_hi*)msdu->data;
frame = (uint8_t *)(app_data + 1);
frame_len = msdu->len - sizeof(app_plc_frame_data_hi);
#else
app_data = (app_custom_data*)msdu->data;
frame = (uint8_t *)(app_data + 1);
frame_len = msdu->len - sizeof(app_custom_data);
#endif /* end SUPPORT_IEEE_1901 */
APP_PRINT_BUF("[INF] BINARY DATA FORWORD TO UART: ", frame, frame_len);
APP_PRINTF("plc_id = %x mode=%d",app_data->id, work_mode);
if (app_entry->work_mode_reg[work_mode].enable == APP_WORK_MODE_ENABLE) {
iot_mac_addr_cpy(rx_info.mac, msdu->src);
/* 0: connless 1: conn */
rx_info.recv_flag = (hdr->msg_id == IOT_PLC_MSG_MSDU_RECV);
rx_info.recv_snr = msdu->snr;
rx_info.recv_rssi = msdu->rssi;
if (rx_info.recv_rssi == APP_INV_RSSI) {
rx_info.recv_rssi = BEST_RSSI;
}
app_entry->work_mode_reg[work_mode].data_handle(app_data->id,
APP_SOURCE_PLC,
frame, frame_len, &rx_info);
ret = ERR_OK;
}
iot_pkt_free(pkt);
if (ret) {
APP_PRINTF("[ERR] %s - unregistered work mode = %d!!!", __FUNCTION__,
work_mode);
}
return ret;
}
static void iot_app_send_plc_msg(iot_pkt_t *pkt)
{
iot_pkt_t *msdu_pkt;
uint8_t *ptr;
app_custom_data *app_data;
append_tx_info_t *tx_info;
uint8_t msg_type = IOT_PLC_MSG_TYPE_BCAST;
uint16_t data_len;
uint16_t msdu_len;
uint16_t meta_len = 0;
uint8_t is_connless = false;
uint8_t is_sta = false;
uint8_t is_bcast = false;
iot_plc_topo_info * topo_info = NULL;
iot_plc_app_h app_handle;
app_entity_t *app_entry = NULL;
uint8_t retry_cnt = 0;
app_entry = app_get_main_entry();
app_handle = app_entry->app_hdl;
#if SUPPORT_IEEE_1901
data_len = iot_pkt_data_len(pkt) - sizeof(append_tx_info_t) -
sizeof(app_custom_data) + sizeof(app_plc_frame_data_hi);
#else
data_len = iot_pkt_data_len(pkt) - sizeof(append_tx_info_t);
#endif /* end SUPPORT_IEEE_1901 */
tx_info = (append_tx_info_t *)iot_pkt_data(pkt);
app_data = (app_custom_data *)(tx_info + 1);
if (app_entry->dev.dev_role != IOT_PLC_DEV_ROLE_CCO) {
is_sta = true;
}
is_bcast = iot_mac_is_bcast(app_data->mac);
if (tx_info->force_type == SEND_FORCE_TYPE_CONNLESS) {
/* custom force send connless */
is_connless = true;
} else if (tx_info->force_type == SEND_FORCE_TYPE_CONNECT) {
/* custom force send connected */
is_connless = false;
if ((!is_sta) && (!iot_plc_sta_is_online(app_data->mac))) {
/* if the sta is offline, bcast send msdu pkt */
is_bcast = true;
}
} else {
if ((!is_sta) && (is_bcast)) {
/* the cco bcast, if sta num is 0 should offline bcast */
iot_plc_cco_query_nw_topo(&topo_info, 0, 2);
if (topo_info->total_cnt <= 1) {
is_connless = true;
}
} else if ((!is_sta) && (!iot_plc_sta_is_online(app_data->mac))) {
/* if the sta is offline, send conncet_less msdu pkt */
is_connless = true;
} else if (is_sta && is_bcast) {
/* sta send broadcast, need send connless */
is_connless = true;
} else if (is_sta && (!app_entry->dev.dev_ready)) {
/* sta not joined network, need send connless*/
is_connless = true;
} else if (is_sta && app_entry->dev.dev_ready &&
!iot_mac_addr_cmp(app_data->mac, app_entry->dev.cco_addr)) {
/* joined network sta not send data to cco, need send connless */
is_connless = true;
}
}
msdu_len = iot_plc_calc_msdu_len_with_pad_info(data_len, is_connless,
&meta_len);
if (is_connless) {
/* if the sta is offline, send conncet_less msdu pkt */
if (is_sta || (!is_bcast)) {
msg_type = IOT_PLC_MSG_TYPE_CONN_LESS_DATA;
} else {
msg_type = IOT_PLC_MSG_TYPE_CONN_LESS_DATA_ALL;
}
#if SUPPORT_IEEE_1901
/* when in SILA APP, send connectionless none
head mode data to one sta */
#if (IOT_APP_SELECTION == IOT_APP_DEF_18_AT_APP)
if (is_sta || (!is_bcast)) {
msg_type = IOT_PLC_MSG_TYPE_CONN_LESS_DATA;
} else {
msg_type = IOT_PLC_MSG_TYPE_CONN_LESS_DATA_ALL;
}
#elif (IOT_APP_SELECTION == IOT_APP_DEF_24_SILA_AT_APP)
if (is_sta || (!is_bcast)) {
msg_type = IOT_PLC_MSG_TYPE_NHM_DATA;
} else {
msg_type = IOT_PLC_MSG_TYPE_NHM_DATA_ALL;
}
app_handle = app_entry->sila_nhm_hdl;
#endif
#else
#endif /* end SUPPORT_IEEE_1901 */
APP_PRINTF("Broadcast pkt type %d sent by offline sta " MAC_FMT,
msg_type, MAC_ARG(app_entry->dev.mac_addr));
msdu_pkt = iot_plc_alloc_conn_less_msdu(app_handle,
msg_type, app_data->mac, app_entry->dev.mac_addr,
app_entry->dev.link_id, msdu_len, retry_cnt);
} else {
if (is_bcast) {
if ((!is_sta) && (app_entry->user_type == USER_TYPE_SUNSOLAR1)) {
retry_cnt = 2;
msg_type = IOT_PLC_MSG_TYPE_BCAST_ALL;
}
} else {
msg_type = IOT_PLC_MSG_TYPE_UNICAST;
}
msdu_pkt = iot_plc_alloc_msdu(app_handle,
msg_type, IOT_PLC_ACK_TYPE_NONE,
app_data->mac,
app_entry->dev.mac_addr,
app_entry->dev.link_id, msdu_len, retry_cnt);
}
if (NULL == msdu_pkt) {
iot_pkt_free(pkt);
APP_PRINTF("[ERR] %s Alloc Packet Failed !!", __FUNCTION__);
return;
}
ptr = iot_pkt_block_ptr(msdu_pkt, IOT_PKT_BLOCK_TAIL);
#if SUPPORT_IEEE_1901
/* extend append_tx_info_t data block in front */
iot_pkt_pull(pkt, sizeof(append_tx_info_t));
package_1901_frame(ptr, pkt);
#else
os_mem_cpy(ptr, app_data, data_len);
#endif /* end SUPPORT_IEEE_1901 */
iot_pkt_put(msdu_pkt, data_len);
iot_pkt_free(pkt);
iot_plc_add_meta_info(msdu_pkt, meta_len);
APP_PRINT_BUF("[INF] BINARY DATA FORWORD TO PLC:",
iot_pkt_data(msdu_pkt), iot_pkt_data_len(msdu_pkt));
/* Forword to PLC. */
iot_plc_send_msdu(app_handle, msdu_pkt);
}
/* This is the handle for messages from this module. */
static void app_msg_process_handle(uint16_t id, void *data)
{
iot_pkt_t *pkt = (iot_pkt_t *)data;
uint32_t data_len = iot_pkt_data_len(pkt);
if ((NULL == pkt) || ((0 == data_len) && E_CMD_ID_RCV_FROM_CLI != id)) {
APP_PRINTF("[ERR] %s Packet is NULL !!", __FUNCTION__);
return;
}
if (E_CMD_ID_RCV_FROM_PLC == id) {
iot_app_plc_msg_handle(pkt);
} else if (E_CMD_ID_RCV_FROM_CLI == id) {
iot_app_handle_cli_msg(pkt);
} else if(E_CMD_ID_SEND_DATA_TO_PLC == id) {
/* send data to plc */
iot_app_send_plc_msg(pkt);
} else if (E_CMD_ID_RCV_FROM_UART == id) {
app_data_frame_parse(iot_pkt_data(pkt), data_len, APP_SOURCE_UART);
iot_pkt_free(pkt);
} else {
iot_pkt_free(pkt);
}
return;
}
static void app_msg_from_mac_handle(iot_pkt_t *pkt)
{
iot_plc_msg_header_t *hdr = (iot_plc_msg_header_t*)iot_pkt_data(pkt);
app_entity_t *app_entry = NULL;
app_entry = app_get_main_entry();
/* Check if this packet belongs to me. */
#if SUPPORT_IEEE_1901
if ((IOT_PLC_APP_ID_BCAST != hdr->app_id)
&& (IOT_PLC_APP_SMART_GRID != hdr->app_id)
&& (IOT_PLC_SILA_NHM_ID != hdr->app_id)) {
#else
if ((IOT_PLC_APP_ID_BCAST != hdr->app_id)
&& (IOT_PLC_APP_DEMO_ID != hdr->app_id)) {
#endif /* end SUPPORT_IEEE_1901 */
APP_PRINTF("[ERR] INVALID PACKET FROM MAC,APP ID#%d.", hdr->app_id);
iot_pkt_free(pkt);
return;
}
/* Check if I'm registerd before handling msg. */
if ((!app_entry->app_reg) &&
(IOT_PLC_MSG_APP_REG_CONF != hdr->msg_id)) {
APP_PRINTF("[ERR] INVALID PACKET FROM MAC,MSG ID#%d.", hdr->msg_id);
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);
if ((IOT_PLC_SUCCESS == rpt->result) ||
(IOT_PLC_SUCCESS_MODIFIED == rpt->result)) {
app_entry->app_reg = true;
iot_plc_query_dev_info(app_entry->app_hdl, IOT_PLC_API_REQ_ID_DEFAULT);
APP_PRINTF("[INF] APP REGISTERED SUCCESSFULLY.");
}
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);
if (rpt->is_ready) {
APP_PRINTF("[INF] STATE CHANGE REPORT MAC GET READY, MY ROLE TYPE#%d.",
rpt->dev_role);
APP_PRINTF("CCO MAC "MAC_FMT, MAC_ARG(rpt->cco_mac));
APP_PRINTF("LOCAL MAC "MAC_FMT, MAC_ARG(rpt->local_mac));
if (app_entry->dev.dev_ready == false) {
app_entry->dev.dev_ready = true;
}
if (IOT_PLC_DEV_ROLE_CCO != rpt->dev_role) {
iot_mac_addr_cpy(app_entry->dev.rmt_addr, rpt->cco_mac);
app_onoffline_state_report(rpt->cco_mac, STA_ONLINE_EVENT);
}
app_entry->dev.dev_role = rpt->dev_role;
app_entry->dev.nid = rpt->nid;
iot_mac_addr_cpy(app_entry->dev.mac_addr, rpt->local_mac);
iot_mac_addr_cpy(app_entry->dev.cco_addr, rpt->cco_mac);
} else {
APP_PRINTF("[INF] MAC IS NOT READY #%d.", hdr->msg_id);
if (app_entry->dev.dev_ready) {
app_entry->dev.dev_ready = false;
if (IOT_PLC_DEV_ROLE_CCO != rpt->dev_role) {
APP_PRINTF("[INF] STA leave net reason:%d.",
rpt->leave_net_reason);
/* Notify Offline Event (local) */
if (iot_mac_addr_valid(rpt->cco_mac)) {
app_onoffline_state_report(rpt->cco_mac,
STA_OFFLINE_EVENT);
} else {
app_onoffline_state_report(app_entry->dev.cco_addr,
STA_OFFLINE_EVENT);
os_mem_set(app_entry->dev.cco_addr, 0,
IOT_MAC_ADDR_LEN);
}
}
}
}
break;
}
case IOT_PLC_MSG_DEV_INFO_RPT :
{
iot_plc_dev_info_rpt_t* rpt =
(iot_plc_dev_info_rpt_t*)(hdr + 1);
app_entry->dev.dev_ready = rpt->is_ready;
app_entry->u_snr = rpt->snr;
iot_mac_addr_cpy(app_entry->dev.mac_addr, rpt->local_mac);
if (rpt->is_ready) {
APP_PRINTF("[INF] DEVICE INFO REPORT MAC GET READY, MY ROLE TYPE#%d.",
rpt->dev_role);
APP_PRINTF("CCO MAC "MAC_FMT, MAC_ARG(rpt->cco_mac));
APP_PRINTF("LOCAL MAC "MAC_FMT, MAC_ARG(rpt->local_mac));
app_entry->dev.dev_role = rpt->dev_role;
iot_mac_addr_cpy(app_entry->dev.cco_addr, rpt->cco_mac);
} else {
APP_PRINTF("[INF] MAC IS NOT READY #%d.", hdr->msg_id);
}
break;
}
case IOT_PLC_MSG_STA_JOIN_INFO :
{
iot_plc_sta_join_info_t* rpt = (iot_plc_sta_join_info_t*)(hdr + 1);
APP_PRINTF("STA JOINED : MAC#"MAC_FMT, MAC_ARG(rpt->sta_info.addr));
if (IOT_PLC_DEV_ROLE_CCO == app_entry->dev.dev_role) {
iot_plc_led_request(IOT_PLC_LED_ASSOCIATED);
/* Keep the remote device as the last one we got. */
iot_mac_addr_cpy(app_entry->dev.rmt_addr, rpt->sta_info.addr);
/* Notify Online Event */
app_onoffline_state_report(rpt->sta_info.addr, STA_ONLINE_EVENT);
}
break;
}
case IOT_PLC_MSG_STA_LEAVE_INFO :
{
uint32_t cnt;
iot_plc_sta_leave_info_t* rpt =
(iot_plc_sta_leave_info_t*)(hdr + 1);
for (cnt = 0; cnt < rpt->sta_count; cnt++) {
APP_PRINTF("STA LEAVED : MAC#"MAC_FMT, MAC_ARG(rpt->sta[cnt].mac_addr));
if (IOT_PLC_DEV_ROLE_CCO == app_entry->dev.dev_role) {
iot_plc_led_request(IOT_PLC_LED_DIS_ASSOCIATED);
/* Notify Offline Event */
app_onoffline_state_report(rpt->sta[cnt].mac_addr, STA_OFFLINE_EVENT);
}
}
break;
}
case IOT_PLC_MSG_CONN_LESS_RECV :
case IOT_PLC_MSG_MSDU_RECV :
{
iot_plc_msdu_recv_t *msdu = (iot_plc_msdu_recv_t*)(hdr + 1);
app_entry->u_snr = msdu->snr;
APP_PRINTF("MSDU RECEIVED FROM MAC#"MAC_FMT, MAC_ARG(msdu->src));
iot_check_meta_data(pkt);
#if PLC_SUPPORT_STA_ROLE
iot_meta_rcd_app_msdu_info(msdu,
hdr->msg_id == IOT_PLC_MSG_MSDU_RECV);
#endif
if (!iot_mac_addr_cmp(msdu->src, app_entry->dev.mac_addr)) {
app_post_msg(E_APP_MSG_PROCESS, E_CMD_ID_RCV_FROM_PLC, (void*)pkt);
/* Packet will not be freed here. */
pkt = NULL;
}
break;
}
default :
{
break;
}
}
if (pkt) {
iot_pkt_free(pkt);
}
return;
}
void app_end_idf(void)
{
uint8_t i, add_cnt = 0;
uint16_t start = 0;
uint8_t * data;
iot_pkt_t *pkt;
iot_plc_topo_info * topo_info = NULL;
iot_plc_cco_query_nw_topo(&topo_info, start, APP_WHITELIST_SETUP_MAX);
pkt = iot_pkt_alloc(APP_WHITELIST_SETUP_MAX * IOT_MAC_ADDR_LEN, IOT_APP_DEMO_MID);
if (pkt == NULL) {
APP_PRINTF("[ERR] %s Packet Alloc Failed !!", __FUNCTION__);
return;
}
data = (uint8_t *)iot_pkt_put(pkt, APP_WHITELIST_SETUP_MAX * IOT_MAC_ADDR_LEN);
if (topo_info->total_cnt) {
do {
add_cnt = 0;
for (i = 0; i < topo_info->cur_cnt; i++) {
if ((start + i) > 0) {
iot_mac_addr_reverse(topo_info->topo_info[i].mac);
iot_mac_addr_cpy(data + add_cnt * IOT_MAC_ADDR_LEN, topo_info->topo_info[i].mac);
add_cnt++;
}
}
if (add_cnt) {
// add whitelist
iot_plc_cco_set_whitelist_func(IOT_PLC_WL_ADD, add_cnt, data);
}
start += topo_info->cur_cnt;
if (topo_info->total_cnt >= start) {
break;
}
iot_plc_cco_query_nw_topo(&topo_info, start, APP_WHITELIST_SETUP_MAX);
if (0 == topo_info->cur_cnt) {
break;
}
} while (1);
}
iot_pkt_free(pkt);
// enable whitelist
iot_plc_cco_set_whitelist_func(IOT_PLC_WL_ENABLE, 0, NULL);
app_set_idf_status(false);
iot_cus_printf("IDFEND\n");
}
static void app_sta_signal_led_timer_func(void)
{
app_entity_t *app_entry = NULL;
app_entry = app_get_main_entry();
if (app_entry->u_snr >= IOT_SNR_STRONG_MIN_THR) {
iot_plc_led_request(IOT_PLC_LED_SIGNAL_STRONG);
} else if (app_entry->u_snr >= IOT_SNR_GOOD_MIN_THR) {
iot_plc_led_request(IOT_PLC_LED_SIGNAL_GOOD);
} else {
iot_plc_led_request(IOT_PLC_LED_SIGNAL_WEAK);
}
iot_plc_query_dev_info(app_entry->app_hdl, IOT_PLC_API_REQ_ID_DEFAULT);
return;
}
static void app_cco_net_done_check_or_bcast_func(void)
{
uint8_t bcast_mac[IOT_MAC_ADDR_LEN] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF };
uint8_t wl_state;
uint16_t topo_num;
uint16_t wl_cnt;
iot_plc_topo_info *topo = NULL;
app_entity_t *app_entry = NULL;
append_tx_info_t tx_info = {0};
app_entry = app_get_main_entry();
if (IOT_PLC_DEV_ROLE_CCO == app_entry->dev.dev_role) {
/* the timer period is 500ms, when the cco_bcast_per_cnt count to the
period, cco broadcast data and clear cco_bcast_per_cnt */
if (app_entry->app_cfg.bcast.status == APP_BCAST_STATUS_ON &&
app_entry->app_cfg.bcast.period != 0 &&
app_entry->app_cfg.bcast.len != 0) {
app_entry->cco_bcast_per_cnt++;
if (0 == (app_entry->cco_bcast_per_cnt %
app_entry->app_cfg.bcast.period)) {
app_entry->cco_bcast_per_cnt = 0;
if (app_entry->app_cfg.bcast.send_flag) {
tx_info.force_type = SEND_FORCE_TYPE_CONNLESS;
} else {
tx_info.force_type = SEND_FORCE_TYPE_DEF;
}
app_plc_tx(app_entry->app_cfg.bcast.data,
app_entry->app_cfg.bcast.len, bcast_mac, ID_PLC_AT_DATA,
&tx_info);
}
}
/* check and change cco network done state */
wl_state = iot_plc_cco_get_whiltlist_state_func();
iot_plc_cco_query_nw_topo(&topo, 0, 5);
if (NULL == topo) {
return;
}
topo_num = topo->total_cnt;
wl_cnt = iot_app_get_wl_cnt();
if (wl_state && (topo_num > 1) && (topo_num -1 == wl_cnt)) {
if (app_entry->dev.cco_net_done == 0) {
app_entry->dev.cco_net_done = 1;
iot_plc_led_request(IOT_PLC_LED_NET_FORMAT_DONE);
APP_PRINTF("[info]%s network done !", __FUNCTION__);
}
} else {
if (app_entry->dev.cco_net_done == 1) {
app_entry->dev.cco_net_done = 0;
iot_plc_led_request(IOT_PLC_LED_DIS_ASSOCIATED);
}
}
}
}
/**
* @brief handle timer message
* @param id: timer msg id
* @param data: timer_id can use for restart or delete
*/
static void app_on_msg_timer(app_timer_id_e id, void *data)
{
switch (id) {
case APP_TIMER_ID_REBOOT:
iot_system_restart(IOT_SYS_RST_REASON_APP_REQ);
os_delete_timer((timer_id_t)data);
break;
case APP_TIMER_ID_IDF_CHECK:
app_end_idf();
os_delete_timer((timer_id_t)data);
break;
case APP_TIMER_ID_SIGNAL_LED:
app_sta_signal_led_timer_func();
break;
case APP_TIMER_ID_NET_DONE_CHECK_OR_BCAST:
app_cco_net_done_check_or_bcast_func();
break;
default:
break;
}
}
static void app_event_handle(iot_task_h task_h, uint32_t event)
{
(void)task_h;
(void)event;
#if 0
if(BIT(E_DEMO_EV_TIMR) & event)
{
app_demo_led_blink();
app_demo_stamp_running_time();
app_demo_device_query();
#if IOT_ADC_DEMO_ENABLE
if(g_adc_info)
{
app_demo_adc_periodic_sample();
}
#endif
}
#endif
APP_PRINTF("[INF] %s", __FUNCTION__);
return;
}
static void app_msg_handle(iot_task_h task_h, iot_task_msg_t *msg)
{
app_msg_t *dm_msg = (app_msg_t *)msg;
(void)task_h;
if ((NULL == dm_msg) || (!APP_MSG_VALID(dm_msg->msg.type))) {
/* Maybe this can cause memory overflow! */
APP_PRINTF("[ERR] %s Invalid MSG !!", __FUNCTION__);
return;
}
if (E_APP_MSG_PROCESS == dm_msg->msg.type) {
app_msg_process_handle(dm_msg->msg.id, dm_msg->data);
} else if(E_APP_MSG_FROM_MAC == dm_msg->msg.type) {
app_msg_from_mac_handle((iot_pkt_t *)dm_msg->data);
} else if (E_APP_MSG_TIMER == dm_msg->msg.type) {
app_on_msg_timer(dm_msg->msg.id, dm_msg->data);
}
iot_task_free_msg(task_h, &(dm_msg->msg));
return;
}
/* As all message data is a packet, so just free() it. */
static void app_msg_common_cancel(uint16_t id, void *data)
{
(void)id;
iot_pkt_t *pkt = (iot_pkt_t*)data;
if (pkt) {
iot_pkt_free(pkt);
}
return;
}
static void app_msg_cancel(iot_task_h task_h, iot_task_msg_t *msg)
{
app_msg_t *dm_msg = (app_msg_t *)msg;
(void)task_h;
if ((NULL == dm_msg) || (!APP_MSG_VALID(dm_msg->msg.type))) {
/* Maybe this can cause memory overflow! */
APP_PRINTF("[ERR] CANCEL AN INVALID MSG !!");
return;
}
if ((E_APP_MSG_PROCESS == dm_msg->msg.type)
|| (E_APP_MSG_FROM_MAC == dm_msg->msg.type)) {
app_msg_common_cancel(dm_msg->msg.id, dm_msg->data);
}
iot_task_free_msg(task_h, &(dm_msg->msg));
return;
}
static uint16_t app_msg_task_init(void)
{
app_entity_t *app_entry = NULL;
app_entry = app_get_main_entry();
app_msg_task_h *msg_task = &(app_entry->msg_task);
iot_task_config_t *t_cfg = &(msg_task->cfg);
t_cfg->stack_size = 0;
t_cfg->task_prio = APP_MSG_HANDLE_TASK_PRIO;
t_cfg->msg_size = sizeof(app_msg_t);
t_cfg->msg_cnt = APP_MSG_PENDING_LIMIT;
t_cfg->queue_cnt = APP_MSG_TASK_PRIO_QUE;
t_cfg->queue_cfg[0].quota = 0;
t_cfg->task_event_func = app_event_handle;
t_cfg->msg_exe_func = app_msg_handle;
t_cfg->msg_cancel_func = app_msg_cancel;
msg_task->handle = iot_task_create(IOT_APP_DEMO_MID, t_cfg);
if (NULL == msg_task->handle) {
APP_PRINTF("[ERR] %s Create Task Failed !!", __FUNCTION__);
return ERR_FAIL;
}
return ERR_OK;
}
/* Post the packet from plc-layer to message queue. */
static void app_plc_rcv(void *param, iot_pkt_t *pkt)
{
(void)param;
if (false == sync_api_msg_from_mac_handle(pkt)) {
app_post_msg(E_APP_MSG_FROM_MAC, E_CMD_ID_RCV_FROM_PLC, (void *)pkt);
}
return;
}
#if SUPPORT_IEEE_1901
static void app_sila_nhm_plc_rcv(void *param, iot_pkt_t *pkt)
{
(void)param;
iot_plc_msg_header_t *hdr = (iot_plc_msg_header_t*)iot_pkt_data(pkt);
if (IOT_PLC_SILA_NHM_ID == hdr->app_id) {
app_post_msg(E_APP_MSG_FROM_MAC, E_CMD_ID_RCV_FROM_PLC, (void *)pkt);
} else {
iot_pkt_free(pkt);
}
return;
}
#else
#endif /* end SUPPORT_IEEE_1901 */
/* Register an APP to PLC-layer,so we can transmit/receive packet from it. */
uint32_t app_plc_reg(void)
{
iot_plc_app_t app;
app_entity_t *app_entry = NULL;
app_entry = app_get_main_entry();
#if SUPPORT_IEEE_1901
/* if support ieee 1901 protocol, we register an extra app handle for non
* header mode.
*/
app.app_id = IOT_PLC_SILA_NHM_ID;
app.param = NULL;
app.prio = APP_PLC_CMD_PRIO;
app.recv = app_sila_nhm_plc_rcv;
app_entry->sila_nhm_hdl = iot_plc_register_app(&app);
if (NULL == app_entry->sila_nhm_hdl) {
APP_PRINTF("[ERR] REGISTER NHM FAILED !!");
return ERR_FAIL;
}
/* register app handle for cus_at app. */
app.app_id = IOT_PLC_APP_SMART_GRID;
#else
app.app_id = IOT_PLC_APP_DEMO_ID;
#endif /* end SUPPORT_IEEE_1901 */
app.param = NULL;
app.prio = APP_PLC_CMD_PRIO;
app.recv = app_plc_rcv;
app_entry->app_hdl = iot_plc_register_app(&app);
if (NULL == app_entry->app_hdl) {
APP_PRINTF("[ERR] REGISTER APP FAILED !!");
return ERR_FAIL;
}
return ERR_OK;
}
/* set sta scan band */
void app_set_sta_scan_band(uint8_t band_id)
{
app_entity_t *app_entry = NULL;
app_entry = app_get_main_entry();
iot_cus_printf("%s: set scan band to band %d\n", __FUNCTION__, band_id);
uint8_t fb_bitmap[IOT_PLC_BAND_BITMAP_SIZE] = { 0 };
fb_bitmap[band_id / 8] |= 1 << (band_id % 8);
iot_plc_set_scan_band_bitmap(app_entry->app_hdl,
IOT_PLC_API_REQ_ID_DEFAULT, fb_bitmap, IOT_PLC_BAND_BITMAP_SIZE);
}
void app_band_init(void)
{
uint8_t band = 0;
uint8_t fb_bitmap[IOT_PLC_BAND_BITMAP_SIZE] = { 0 };
uint8_t *p_fb_bitmap;
app_entity_t *app_entry = NULL;
app_entry = app_get_main_entry();
if (iot_plc_is_client_mode()) {
if (0 == iot_app_get_scan_band_in_pib(&p_fb_bitmap)) {
/* default set sta only scan band 1, freq: 2.4M to 5.6M */
fb_bitmap[APP_DEFAULT_FREQ_BAND / 8] |=
1 << (APP_DEFAULT_FREQ_BAND % 8);
if (app_entry->user_type == USER_TYPE_SUNSOLAR1) {
fb_bitmap[PLC_LIB_FREQ_BAND_8 / 8] |=
1 << (PLC_LIB_FREQ_BAND_8 % 8);
}
iot_plc_set_scan_band_bitmap(app_entry->app_hdl,
IOT_PLC_API_REQ_ID_DEFAULT, fb_bitmap, IOT_PLC_BAND_BITMAP_SIZE);
iot_app_save_scan_band_to_pib(fb_bitmap, IOT_PLC_BAND_BITMAP_SIZE);
} else {
iot_plc_set_scan_band_bitmap(app_entry->app_hdl,
IOT_PLC_API_REQ_ID_DEFAULT, p_fb_bitmap,
IOT_PLC_BAND_BITMAP_SIZE);
}
} else {
/* set frequency band, default set band 1 */
band = iot_app_get_work_band_in_pib();
if (0 == band) {
app_set_freq_band(APP_DEFAULT_FREQ_BAND);
iot_app_save_work_band_to_pib(APP_DEFAULT_FREQ_BAND);
} else {
app_set_freq_band(band - 1);
}
}
}
/* Report the basic information of this board. */
void app_board_info_report(void)
{
uint32_t size;
app_entity_t *app_entry = NULL;
app_entry = app_get_main_entry();
size = custom_dev_query_rw_size();
iot_cus_printf("\r\n************************** INFORMATION ****************"
"*******");
iot_cus_printf("\r\n* This application is designed by Aerospace C.Power");
iot_cus_printf("\r\n* And it's a guide to show how to use PLC-communication"
" module");
iot_cus_printf("\r\n* and periphera devices.");
iot_cus_printf("\r\n* MAC ADDRS : "MAC_FMT, MAC_ARG(app_entry->dev.mac_addr));
iot_cus_printf("\r\n* USER FLASH SIZE : %dbytes.(Size is optional.)", size);
iot_cus_printf("\r\n* FREE MEM SIZE : %dbytes.", os_mem_free_get());
iot_cus_printf("\r\n*******************************************************"
"*******");
return;
}
#if APP_ENABLE_DUMP_PKT_INFO
static void app_pkt_info_timer_exe(timer_id_t timer_id, void * arg)
{
uint8_t i;
uint32_t bufsz, freenum, totalnum;
(void)arg;
if (timer_id == pkt_info_timer) {
APP_PRINTF("pkt info:");
for (i = 0; i < 8; i++) {
iot_pkt_pktpool_status(i, &bufsz, &freenum, &totalnum);
if (bufsz == 0) {
break;
}
iot_cus_printf("pkt size(%4lu) free_n:%2lu total_n:%2lu\n",
bufsz, freenum, totalnum);
}
}
return;
}
#endif
#if PLC_SUPPORT_CCO_ROLE
void app_check_idf(void)
{
/* check need auto networking */
APP_PRINTF("IDFSTATUS %d", app_get_idf_status());
if (app_get_idf_status()) {
/* disable whitelist */
iot_plc_cco_set_whitelist_func(IOT_PLC_WL_DISABLE, 0, NULL);
/* clear whitelist */
iot_plc_cco_set_whitelist_func(IOT_PLC_WL_DEL_ALL, 0, NULL);
/* start timer for end group, enable whitelist */
app_timer_start(APP_TIMER_ID_IDF_CHECK,
APP_TIMER_IDF_CHECK_PERIOD, TIMER_TYPE_ONCE);
}
}
#else
void app_check_idf(void)
{
}
#endif
/* alloc outbuf pkt for response */
uint8_t app_outbuf_init(void)
{
app_entity_t *app_entry = app_get_main_entry();
iot_pkt_t *out_pkt = iot_pkt_alloc(MAX_RSP_DATA_LEN, IOT_APP_DEMO_MID);
if (out_pkt == NULL) {
APP_PRINTF("[ERR] %s Packet Alloc Failed !!", __FUNCTION__);
return ERR_FAIL;
}
app_entry->out_buf = iot_pkt_put(out_pkt, MAX_RSP_DATA_LEN);
return ERR_OK;
}
uint16_t app_module_init(void)
{
uint16_t ret = ERR_FAIL;
app_dev_info *dev;
app_entity_t *app_entry = NULL;
app_entry = app_get_main_entry();
os_mem_set(app_entry, 0x0, sizeof(*app_entry));
app_outbuf_init();
/* Enable the customer-printf(). */
iot_cus_print_config(true);
iot_print_config(ENABLE_PLC_LIB_LOG);
iot_oem_get_module_mac(app_entry->dev.mac_addr);
app_entry->user_type = iot_oem_get_user_type();
app_board_info_report();
APP_PRINTF("\r\n MODULE INITIALIZING...");
/* load custom config */
app_load_nv_conf();
do {
app_entry->app_hdl = NULL;
app_entry->app_reg = false;
app_entry->net_enable = 1;
dev = &(app_entry->dev);
dev->link_id = APP_LINK_ID;
dev->nid = 1;
dev->rmt_valid = false;
dev->dev_role = IOT_PLC_DEV_ROLE_INVALID;
dev->dev_ready = false;
APP_PRINTF(" MESSAGE TASK INITIALIZING...");
if (ERR_OK != (ret = app_msg_task_init())) {
APP_PRINTF("[ERR] MSG TASK INIT FAILED !!");
break;
}
APP_PRINTF(" APP REGISTERING...");
if (ERR_OK != (ret = app_plc_reg())) {
APP_PRINTF("[ERR] APP REGISTER FAILED !!");
break;
}
iot_sync_api_init_app_hdl(app_entry->app_hdl, IOT_APP_DEMO_MID,
app_demo_post_msg_cli);
/* initialize pib config */
app_pib_conf_init();
APP_PRINTF(" USER TASK INITIALIZING...");
if (ERR_OK != (ret = app_cus_task_init())) {
APP_PRINTF("[ERR] USER TASK INIT FAILED !!");
break;
}
#if APP_ENABLE_DUMP_PKT_INFO
pkt_info_timer = os_create_timer(IOT_APP_DEMO_MID, true,
app_pkt_info_timer_exe, NULL);
if (0 == pkt_info_timer) {
iot_cus_printf("[cus_task]create cmd timer failed.\n");
break;
}
os_start_timer(pkt_info_timer, APP_PKT_INFO_TIMER_PERIOD);
#endif
#if PLC_SUPPORT_STA_ROLE
/* creat and start a timer for signal led show */
if (0 == app_timer_start(APP_TIMER_ID_SIGNAL_LED,
IOT_PLC_SIGNAL_LED_SHOW_INTVAL, TIMER_TYPE_PERIOD)) {
APP_PRINTF("[ERR] CREATE SIGNAL LED TIMER FAILED !!");
break;
}
#endif
#if PLC_SUPPORT_CCO_ROLE
/* creat and start a timer to check if network done or broadcast data */
if (0 == app_timer_start(APP_TIMER_ID_NET_DONE_CHECK_OR_BCAST,
IOT_PLC_NET_DONE_CHECK_INTVAL, TIMER_TYPE_PERIOD)) {
APP_PRINTF("[ERR] CREATE NET DONE TIMER FAILED !!");
break;
}
#endif
#if (IOT_APP_SELECTION == IOT_APP_DEF_18_AT_APP)
app_work_mode_register(APP_WORK_MODE_BYPASS, app_bypass_data_parse,
app_bypass_data_handle, app_atcmd_onoffline_rsp);
app_work_mode_register(APP_WORK_MODE_AT, app_atcmd_data_parse,
app_atcmd_data_handle, app_atcmd_onoffline_rsp);
#endif
#if (IOT_APP_SELECTION == IOT_APP_DEF_25_AT_MICRO_CCTT)
app_work_mode_register(APP_WORK_MODE_AT, app_atcmd_data_parse,
app_atcmd_data_handle, app_atcmd_onoffline_rsp);
#endif
if (iot_plc_is_client_mode()) {
/* close watchdog */
iot_plc_wdg_set(app_entry->app_hdl, 0, 0);
}
#if APP_IO_OPERATION_ENABLE
/* gpio initialize */
app_io_init();
#endif /* end APP_IO_OPERATION_ENABLE */
/* band initialize */
app_band_init();
/* set work mode */
#if (IOT_AT_ONLY == 1)
if (APP_WORK_MODE_AT != app_entry->app_cfg.factory.work_mode &&
APP_WORK_MODE_BYPASS != app_entry->app_cfg.factory.work_mode) {
app_set_work_mode_to_nv(APP_WORK_MODE_AT);
}
#endif /* end IOT_AT_ONLY for set mode */
app_set_work_mode(app_get_init_work_mode());
#if (IOT_APP_SELECTION == IOT_APP_DEF_18_AT_APP)
/* AT mode initialize */
app_atcmd_init();
#endif
#if PLC_SUPPORT_STA_ROLE
/* load group info */
app_load_group_from_nv();
/* initialize meta information */
iot_meta_init(IOT_APP_DEF_18_AT_APP, IOT_APP_DEMO_MID);
#endif
/* check cco auto grouping */
app_check_idf();
app_proto_upgrd_contxt_init();
#if (IOT_AT_ONLY == 0)
extern void app_proto_init();
/* sub system initialize */
app_proto_init();
#endif /* end IOT_AT_ONLY */
ret = ERR_OK;
}while(0);
APP_PRINTF("MODULE INITIALIZED %s.", ret ? "WITH ERROR" : "SUCCESSFULLY");
return ret;
}
uint32_t app_at_entry(void)
{
uint32_t ret = ERR_FAIL;
iot_cus_printf("\r\n APP ENTRY FUNCTIONS-SHOW...\r\n");
ret = app_module_init();
if (ERR_OK != ret) {
ret = ERR_PENDING;
}
return ret;
}