1726 lines
52 KiB
C
1726 lines
52 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.
|
||
|
||
****************************************************************************/
|
||
/* os_ship header files */
|
||
#include "os_timer_api.h"
|
||
#include "os_utils_api.h"
|
||
#include "iot_app_api.h"
|
||
#include "iot_io_api.h"
|
||
#include "iot_task_api.h"
|
||
|
||
#include "iot_proto_ge.h"
|
||
#include "iot_board_api.h"
|
||
#include "iot_proto_cctt.h"
|
||
#include "iot_plc_msg_cco_api.h"
|
||
#include "iot_gpio_api.h"
|
||
|
||
#if PLC_SUPPORT_CCO_ROLE
|
||
|
||
/* iot concentrator module, version 3.0 */
|
||
#ifndef HW_VERSION_IOT_CCTT_V3_0
|
||
#define HW_VERSION_IOT_CCTT_V3_0 0x720A0100 //114.10.01.00
|
||
#endif
|
||
|
||
/* iot concentrator module, version 3.5 */
|
||
#ifndef HW_VERSION_IOT_CCTT_V3_5
|
||
#define HW_VERSION_IOT_CCTT_V3_5 0x760A0100 //118.10.01.00
|
||
#endif
|
||
|
||
|
||
#define PLC_NW_OPEN (0xAA)
|
||
#define PLC_NW_CLOSE (0x55)
|
||
|
||
/* timeout period if rs485 device has no response */
|
||
#define RS485_DEV_RESP_TO_MS (2000)
|
||
/* timeout period to judge rs485 data receive done */
|
||
#define RS485_DEV_IDLE_TO_MS (20)
|
||
/* fn of reporting sta join/leave state */
|
||
#define RPT_STA_STATE_FN (0x07)
|
||
/* event to report sta joined */
|
||
#define EVENT_RPT_STA_JOINED (0x01)
|
||
|
||
/* for cco */
|
||
static cctt_context_t g_cctt_context = {0};
|
||
|
||
/* local rs485 manager object */
|
||
static cctt_local_rs485_t g_local_rs485 = {0};
|
||
|
||
/**
|
||
* @brief cctt_resp_cmd_ack() - dl645 query err、set cmd ack
|
||
* @param ctrl: read or write cmd
|
||
* @param err: error number,see DL645_ERR_XXX
|
||
* @return: 0 success, others false
|
||
*/
|
||
static uint8_t cctt_resp_cmd_ack(uint8_t ctrl, uint8_t err)
|
||
{
|
||
uint8_t *send_cmd;
|
||
uint8_t data_len = DL645_PARSE_FRM_MIN_LEN;
|
||
iot_pkt_t *pkt = NULL;
|
||
|
||
iot_cus_printf("cctt resp ack:%lu\n", err);
|
||
if (err > 0) {
|
||
data_len += 1;
|
||
}
|
||
|
||
pkt = iot_pkt_alloc(data_len, IOT_GREE_APP_MID);
|
||
if (pkt == NULL) {
|
||
iot_cus_printf("[err]cctt pkt alloc fail\n");
|
||
return 1;
|
||
}
|
||
send_cmd = iot_pkt_put(pkt, data_len);
|
||
iot_proto_645_build_resp_msg((proto_645_header_t *)send_cmd, NULL, 0,
|
||
err, ctrl);
|
||
|
||
iot_proto_send_to_mainboard(pkt);
|
||
return 0;
|
||
}
|
||
|
||
/* set whitelist */
|
||
uint8_t iot_cctt_set_whitelist(uint8_t *data, uint8_t len, uint8_t action)
|
||
{
|
||
uint8_t i;
|
||
int32_t mac_in_dev, mac_in_dev_tmp;
|
||
proto_dev_t wlist;
|
||
cctt_set_whitelist_t *cmd = (cctt_set_whitelist_t*)data;
|
||
uint8_t reason = DL645_ERR_OTHER_ERROR;
|
||
|
||
if (sizeof(cctt_set_whitelist_t) + cmd->cnt * IOT_MAC_ADDR_LEN != len ||
|
||
cmd->cnt == 0) {
|
||
/* length or count err */
|
||
reason = DL645_ERR_OTHER_ERROR;
|
||
} else if ((action == GE_PROTO_ACTION_ADD) ||
|
||
(action == GE_PROTO_ACTION_DEL)) {
|
||
iot_cus_printf("cctt_set_whitelist act:%d seq:%d cnt:%d\n", action,
|
||
cmd->seq, cmd->cnt);
|
||
|
||
for (i = 0; i < cmd->cnt; i++) {
|
||
iot_mac_addr_reverse(cmd->mac[i]);
|
||
mac_in_dev = iot_proto_check_mac_exists(cmd->mac[i],
|
||
prototask_contxt.dev_lst.dev,
|
||
prototask_contxt.dev_lst.valid_dev_cnt);
|
||
mac_in_dev_tmp = iot_proto_check_mac_exists(cmd->mac[i],
|
||
prototask_contxt.dev_lst.dev_tmp,
|
||
prototask_contxt.dev_lst.valid_dev_tmp_cnt);
|
||
if (((action == GE_PROTO_ACTION_ADD) && (mac_in_dev < 0) &&
|
||
(mac_in_dev_tmp < 0)) || ((action == GE_PROTO_ACTION_DEL) &&
|
||
(mac_in_dev>= 0) && (mac_in_dev_tmp < 0))) {
|
||
/* mac is not in dev_tmp and dev,which will be added if need,
|
||
or is in dev and not in dev_tmp, which will be deleted if need */
|
||
os_mem_set(&wlist, 0x00, sizeof(wlist));
|
||
iot_mac_addr_cpy(wlist.mac, cmd->mac[i]);
|
||
iot_proto_add_wl_to_tmp(&wlist);
|
||
}
|
||
}
|
||
|
||
if (cmd->seq == 0) {
|
||
if (action == GE_PROTO_ACTION_ADD) {
|
||
iot_proto_add_wl_tmp2formal();
|
||
} else {
|
||
iot_proto_del_wl_from_formal();
|
||
}
|
||
iot_proto_whitelist_add_remove(action, NULL, false);
|
||
iot_proto_wl_save2flash();
|
||
iot_proto_whitelist_state_init();
|
||
}
|
||
reason = DL645_ERR_OK;
|
||
}
|
||
|
||
iot_cus_printf("cctt_set_whitelist end\n");
|
||
cctt_resp_cmd_ack(PROTO_645_2007_FN_WRITE_DATA, reason);
|
||
return (reason != DL645_ERR_OK);
|
||
}
|
||
|
||
/* reboot cco */
|
||
uint8_t iot_cctt_reboot_cco(uint8_t *data, uint8_t len)
|
||
{
|
||
(void)data;
|
||
uint8_t reason = DL645_ERR_OTHER_ERROR;
|
||
|
||
if (len != sizeof(cctt_reboot_cco_t)) {
|
||
reason = DL645_ERR_PARAMETER_ERROR;
|
||
} else {
|
||
os_start_timer(prototask_contxt.reboot_tmr,
|
||
PROTO_TIMER_REBOOT_DELAY_INTVL);
|
||
reason = DL645_ERR_OK;
|
||
}
|
||
iot_cus_printf("cctt reboot cco end\n");
|
||
cctt_resp_cmd_ack(PROTO_645_2007_FN_WRITE_DATA, reason);
|
||
return (reason != DL645_ERR_OK);
|
||
}
|
||
|
||
static void iot_cctt_build_reboot_sta_frame(uint8_t *ge_data, uint8_t *dst_mac)
|
||
{
|
||
ge_frame_reboot_sta_set_subfn18_t *data_frm;
|
||
|
||
data_frm = (ge_frame_reboot_sta_set_subfn18_t *)ge_data;
|
||
data_frm->hdr.hdr.preamble = GE_FRM_PREAMBLE_CODE;
|
||
data_frm->hdr.hdr.data_len = sizeof(ge_frame_reboot_sta_set_subfn18_t) -
|
||
GE_FRM_MIN_LEN;
|
||
data_frm->hdr.hdr.fn = PROTO_GE_PLC_SET_CMD;
|
||
data_frm->hdr.subfn = PROTO_REBOOT_STA_CMD;
|
||
data_frm->nid = prototask_contxt.local_dev.nid;
|
||
data_frm->reboot_type = REBOOT_NORMAL;
|
||
data_frm->seq = 0;
|
||
|
||
iot_mac_addr_cpy(data_frm->src_mac, prototask_contxt.local_dev.mac);
|
||
iot_mac_addr_cpy(data_frm->dst_mac, dst_mac);
|
||
|
||
data_frm->tail.check_sum =
|
||
ge_frm_checksum_calc(ge_data, data_frm->hdr.hdr.data_len +
|
||
GE_FRM_CHECK_SUM_FIELD_POS);;
|
||
data_frm->tail.tail = GE_FRM_TAIL_CODE;
|
||
}
|
||
|
||
static void iot_reboot_sta(uint8_t *dst_mac)
|
||
{
|
||
iot_pkt_t *pkt;
|
||
uint8_t *cmd_data;
|
||
protpkt_tx_info_t txinfo = { 0 };
|
||
|
||
iot_cus_printf("reboot sta:%02X%02X%02X%02X%02X%02X\n",
|
||
dst_mac[0], dst_mac[1], dst_mac[2],
|
||
dst_mac[3], dst_mac[4], dst_mac[5]);
|
||
pkt = iot_pkt_alloc(sizeof(ge_frame_reboot_sta_set_subfn18_t),
|
||
IOT_GREE_APP_MID);
|
||
if (pkt == NULL) {
|
||
iot_cus_printf("[err]cctt pkt alloc fail\n");
|
||
return;
|
||
}
|
||
cmd_data = iot_pkt_put(pkt, sizeof(ge_frame_reboot_sta_set_subfn18_t));
|
||
iot_cctt_build_reboot_sta_frame(cmd_data, dst_mac);
|
||
iot_proto_fill_txinfo(&txinfo, false, PLCTXRX_UNICAST,
|
||
PROTO_UNICAST_RETRY_DEFAULT_CNT, PROTO_UNICAST_RETRY_DEFAULT_INTVL, 1,
|
||
prototask_contxt.local_dev.mac, dst_mac);
|
||
iot_proto_remote_cmd_send_to_plctxrx(cmd_data,
|
||
sizeof(ge_frame_reboot_sta_set_subfn18_t), &txinfo);
|
||
}
|
||
|
||
/* reboot sta */
|
||
uint8_t iot_cctt_reboot_sta(uint8_t *cmd, uint8_t len)
|
||
{
|
||
uint8_t reason = DL645_ERR_OTHER_ERROR;
|
||
cctt_reboot_sta_t *reboot_cmd;
|
||
|
||
if (len != sizeof(cctt_reboot_sta_t)) {
|
||
goto out;
|
||
}
|
||
|
||
// TODO: check dst mac is in whitelist
|
||
reboot_cmd = (cctt_reboot_sta_t*)cmd;
|
||
iot_mac_addr_reverse(reboot_cmd->mac);
|
||
iot_reboot_sta(reboot_cmd->mac);
|
||
|
||
reason = DL645_ERR_OK;
|
||
|
||
out:
|
||
iot_cus_printf("cctt reboot sta end\n");
|
||
cctt_resp_cmd_ack(PROTO_645_2007_FN_WRITE_DATA, reason);
|
||
return (reason != DL645_ERR_OK);
|
||
}
|
||
|
||
/* set whitelist state */
|
||
uint8_t iot_cctt_set_wl_state(uint8_t *data, uint8_t len)
|
||
{
|
||
uint8_t reason = DL645_ERR_PARAMETER_ERROR;
|
||
cctt_set_wl_state_t *set_cmd;
|
||
|
||
if (len != sizeof(cctt_set_wl_state_t)) {
|
||
goto out;
|
||
}
|
||
|
||
set_cmd = (cctt_set_wl_state_t*)data;
|
||
if (set_cmd->state == 0) {
|
||
iot_proto_whitelist_en_disable(GE_PROTO_WL_DISABLE, false);
|
||
} else if (set_cmd->state == 1) {
|
||
iot_proto_whitelist_en_disable(GE_PROTO_WL_ENABLE, false);
|
||
} else {
|
||
/* error state */
|
||
goto out;
|
||
}
|
||
|
||
reason = DL645_ERR_OK;
|
||
|
||
out:
|
||
iot_cus_printf("cctt set wl state end\n");
|
||
cctt_resp_cmd_ack(PROTO_645_2007_FN_WRITE_DATA, reason);
|
||
return (reason != DL645_ERR_OK);
|
||
}
|
||
|
||
/* clear whitelist */
|
||
uint8_t iot_cctt_clear_whitelist(uint8_t *data, uint8_t len)
|
||
{
|
||
(void)data;
|
||
uint8_t reason;
|
||
|
||
if (sizeof(cctt_clear_whitelist_t) != len) {
|
||
/* cmd length error */
|
||
reason = DL645_ERR_PARAMETER_ERROR;
|
||
} else {
|
||
if (prototask_contxt.dev_lst.valid_dev_cnt > 0) {
|
||
prototask_contxt.dev_lst.valid_dev_cnt = 0;
|
||
os_mem_set(prototask_contxt.dev_lst.dev, 0,
|
||
sizeof(proto_dev_t) * STA_DEV_MAX);
|
||
iot_proto_wl_save2flash();
|
||
iot_proto_whitelist_remove_all(false);
|
||
}
|
||
reason = DL645_ERR_OK;
|
||
}
|
||
iot_cus_printf("cctt clear whitelist end\n");
|
||
cctt_resp_cmd_ack(PROTO_645_2007_FN_WRITE_DATA, reason);
|
||
return (reason != DL645_ERR_OK);
|
||
}
|
||
|
||
/* check address in whitelist */
|
||
uint8_t iot_cctt_check_whitelist_mac(uint8_t *data, uint8_t len)
|
||
{
|
||
uint16_t i;
|
||
uint8_t reason = DL645_ERR_NO_REQ_DATA;
|
||
cctt_check_whitelist_mac_t *cmd;
|
||
|
||
if (sizeof(cctt_check_whitelist_mac_t) != len) {
|
||
/* cmd length error */
|
||
reason = DL645_ERR_PARAMETER_ERROR;
|
||
} else {
|
||
cmd = (cctt_check_whitelist_mac_t*)data;
|
||
iot_mac_addr_reverse(cmd->mac);
|
||
if (prototask_contxt.dev_lst.valid_dev_cnt > 0) {
|
||
for (i = 0; i < STA_DEV_MAX; i++) {
|
||
if (iot_mac_addr_cmp(cmd->mac,
|
||
prototask_contxt.dev_lst.dev[i].mac)) {
|
||
reason = DL645_ERR_OK;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
iot_cus_printf("cctt check whitelist mac cco end\n");
|
||
cctt_resp_cmd_ack(PROTO_645_2007_FN_WRITE_DATA, reason);
|
||
return (reason != DL645_ERR_OK);
|
||
}
|
||
|
||
/* resp whitelist */
|
||
static void cco_resp_whitelist_to_cctt(uint16_t start, uint8_t resp_cnt)
|
||
{
|
||
uint8_t flow = 0;
|
||
uint8_t *send_cmd;
|
||
uint16_t out_len;
|
||
uint8_t ctrl, i;
|
||
uint8_t *tmp_mac;
|
||
uint8_t dst_mac[IOT_MAC_ADDR_LEN];
|
||
proto_645_header_t *hdr;
|
||
iot_pkt_t *pkt;
|
||
|
||
out_len = DL645_PARSE_FRM_MIN_LEN + IOT_MAC_ADDR_LEN * resp_cnt;
|
||
|
||
if (g_cctt_context.q_wl_seq) {
|
||
ctrl = PROTO_645_2007_FN_READ_DATA_C;
|
||
out_len += sizeof(cctt_resp_whitelist_withseq_t) + sizeof(uint8_t);
|
||
} else {
|
||
ctrl = PROTO_645_2007_FN_READ_DATA;
|
||
out_len += sizeof(cctt_resp_whitelist_t);
|
||
}
|
||
|
||
if ((g_cctt_context.q_wl_cnt == 0xFFFF &&
|
||
(start + resp_cnt < prototask_contxt.dev_lst.valid_dev_cnt)) ||
|
||
(g_cctt_context.q_wl_cnt != 0xFFFF &&
|
||
(start + resp_cnt < g_cctt_context.q_wl_cnt))) {
|
||
g_cctt_context.q_wl_pos += resp_cnt;
|
||
flow = 1;
|
||
}
|
||
|
||
iot_cus_printf("cco_resp_whitelist_to_cctt start:%d cnt:%d "
|
||
"ctrl:0x%02X seq:%d flow:%d out_len:%d\n", start, resp_cnt, ctrl,
|
||
g_cctt_context.q_wl_seq, flow, out_len);
|
||
pkt = iot_pkt_alloc(out_len, IOT_GREE_APP_MID);
|
||
if (pkt == NULL) {
|
||
iot_cus_printf("[err]cctt pkt alloc fail\n");
|
||
return ;
|
||
}
|
||
send_cmd = iot_pkt_put(pkt, out_len);
|
||
hdr = (proto_645_header_t*)send_cmd;
|
||
iot_mac_addr_cpy(dst_mac, prototask_contxt.local_dev.mac);
|
||
iot_mac_addr_reverse(dst_mac);
|
||
|
||
iot_proto_645_header_init(hdr, dst_mac, ctrl, PROTO_645_DIR_SLAVE,
|
||
PROTO_645_2007_ERR_OK, flow);
|
||
if (g_cctt_context.q_wl_seq == 0) {
|
||
hdr->len = sizeof(cctt_resp_whitelist_t);
|
||
((cctt_resp_whitelist_t*)(hdr->data))->total_cnt =
|
||
prototask_contxt.dev_lst.valid_dev_cnt;
|
||
tmp_mac = hdr->data + sizeof(cctt_resp_whitelist_t);
|
||
} else {
|
||
hdr->len = sizeof(cctt_resp_whitelist_withseq_t);
|
||
tmp_mac = hdr->data + sizeof(cctt_resp_whitelist_withseq_t);
|
||
}
|
||
proto_645_2007_di_to_byte(DL645_07_DI_QUERY_WHITELIST, hdr->data);
|
||
|
||
hdr->len += IOT_MAC_ADDR_LEN * resp_cnt;
|
||
for (i = 0; i < resp_cnt; i++) {
|
||
iot_mac_addr_cpy(tmp_mac + i * IOT_MAC_ADDR_LEN,
|
||
prototask_contxt.dev_lst.dev[start + i - 1].mac);
|
||
iot_mac_addr_reverse(tmp_mac + i * IOT_MAC_ADDR_LEN);
|
||
}
|
||
if (g_cctt_context.q_wl_seq) {
|
||
*(hdr->data + hdr->len) = g_cctt_context.q_wl_seq;
|
||
hdr->len += 1;
|
||
}
|
||
|
||
if (flow == 0) {
|
||
os_mem_set(&g_cctt_context, 0, sizeof(cctt_context_t));
|
||
}
|
||
|
||
iot_proto_645_ext_add33_handle(hdr->data, hdr->len);
|
||
iot_proto_645_tail_init(hdr);
|
||
|
||
iot_proto_send_to_mainboard(pkt);
|
||
}
|
||
|
||
/* read whitelist */
|
||
uint8_t iot_cctt_read_whitelist(uint8_t *data, uint8_t len)
|
||
{
|
||
uint8_t ctrl;
|
||
uint8_t read_cnt;
|
||
cctt_query_whitelist_t *read_cmd;
|
||
|
||
read_cnt = (DL645_FRM_DATA_MAX_LEN - DL645_PARSE_FRM_MIN_LEN -
|
||
sizeof(cctt_resp_whitelist_t)) / IOT_MAC_ADDR_LEN;
|
||
|
||
if (len == sizeof(cctt_query_whitelist_t)) {
|
||
ctrl = PROTO_645_2007_FN_READ_DATA;
|
||
read_cmd = (cctt_query_whitelist_t*)data;
|
||
iot_cus_printf("cctt_read_whitelist start:%d cnt:%d q_cnt:%d total:%d\n",
|
||
read_cmd->start, read_cnt, read_cmd->cnt,
|
||
prototask_contxt.dev_lst.valid_dev_cnt);
|
||
|
||
os_mem_set(&g_cctt_context, 0, sizeof(cctt_context_t));
|
||
|
||
g_cctt_context.q_wl_cnt = read_cmd->cnt;
|
||
if (read_cmd->start > 0) {
|
||
g_cctt_context.q_wl_pos = read_cmd->start;
|
||
if (g_cctt_context.q_wl_pos + read_cnt - 1 >
|
||
prototask_contxt.dev_lst.valid_dev_cnt) {
|
||
read_cnt = prototask_contxt.dev_lst.valid_dev_cnt -
|
||
g_cctt_context.q_wl_pos + 1;
|
||
}
|
||
} else {
|
||
goto err;
|
||
}
|
||
} else {
|
||
ctrl = PROTO_645_2007_FN_READ_DATA_C;
|
||
/* check query topo for next frame */
|
||
if (g_cctt_context.q_wl_seq + 1 == data[DL645_DI_LEN] &&
|
||
g_cctt_context.q_wl_pos > 0) {
|
||
g_cctt_context.q_wl_seq = data[DL645_DI_LEN];
|
||
/* q_topo_cnt will be change after topo resp */
|
||
} else {
|
||
goto err;
|
||
}
|
||
iot_cus_printf("cctt_read_whitelist start:%d seq:%d cnt:%d total:%d\n",
|
||
g_cctt_context.q_wl_pos, g_cctt_context.q_wl_seq,
|
||
g_cctt_context.q_wl_cnt, prototask_contxt.dev_lst.valid_dev_cnt);
|
||
|
||
if (g_cctt_context.q_wl_pos > prototask_contxt.dev_lst.valid_dev_cnt) {
|
||
read_cnt = 0;
|
||
} else if (g_cctt_context.q_wl_pos + read_cnt - 1 >
|
||
prototask_contxt.dev_lst.valid_dev_cnt) {
|
||
read_cnt = prototask_contxt.dev_lst.valid_dev_cnt -
|
||
g_cctt_context.q_wl_pos + 1;
|
||
}
|
||
}
|
||
|
||
if (read_cnt > g_cctt_context.q_wl_cnt) {
|
||
read_cnt = g_cctt_context.q_wl_cnt;
|
||
}
|
||
|
||
cco_resp_whitelist_to_cctt(g_cctt_context.q_wl_pos, read_cnt);
|
||
return 0;
|
||
|
||
err:
|
||
/* read cmd error */
|
||
os_mem_set(&g_cctt_context, 0, sizeof(cctt_context_t));
|
||
iot_cus_printf("cctt read whitelist err\n");
|
||
cctt_resp_cmd_ack(ctrl, DL645_ERR_PARAMETER_ERROR);
|
||
return 1;
|
||
}
|
||
|
||
/**
|
||
* @brief: report sta join or leave event
|
||
*
|
||
* @param p_mac: mac address of sta device
|
||
* @param evt : event of sta device, 1=join, 2=leave
|
||
* @return : 0 if success, 1 when failed
|
||
*/
|
||
uint8_t iot_cctt_report_sta_event(uint8_t *p_mac, uint8_t evt)
|
||
{
|
||
uint8_t *send_cmd;
|
||
uint16_t out_len;
|
||
uint8_t dst_mac[IOT_MAC_ADDR_LEN];
|
||
iot_pkt_t *pkt;
|
||
proto_645_header_t *hdr;
|
||
cctt_rpt_sta_evt_t *rpt;
|
||
|
||
out_len = DL645_PARSE_FRM_MIN_LEN + sizeof(cctt_rpt_sta_evt_t);
|
||
pkt = iot_pkt_alloc(out_len, IOT_GREE_APP_MID);
|
||
if (pkt == NULL) {
|
||
iot_cus_printf("[err]cctt pkt alloc fail\n");
|
||
return 1;
|
||
}
|
||
|
||
send_cmd = iot_pkt_put(pkt, out_len);
|
||
hdr = (proto_645_header_t*)send_cmd;
|
||
iot_mac_addr_cpy(dst_mac, prototask_contxt.local_dev.mac);
|
||
iot_mac_addr_reverse(dst_mac);
|
||
|
||
iot_proto_645_header_init(hdr, dst_mac, RPT_STA_STATE_FN, 0,
|
||
PROTO_645_2007_ERR_OK, 0);
|
||
hdr->len = sizeof(cctt_rpt_sta_evt_t);
|
||
rpt = (cctt_rpt_sta_evt_t *)hdr->data;
|
||
rpt->event = evt;
|
||
iot_mac_addr_cpy(rpt->mac, p_mac);
|
||
iot_mac_addr_reverse(rpt->mac);
|
||
iot_proto_645_tail_init(hdr);
|
||
iot_proto_send_to_mainboard(pkt);
|
||
return 0;
|
||
}
|
||
|
||
|
||
uint8_t iot_cctt_report_sta_online(plctxrx_cmd_topov2_t *resp_node,
|
||
uint16_t total_cnt, uint16_t cur_cnt)
|
||
{
|
||
uint8_t i = 0;
|
||
|
||
if (iot_mac_addr_cmp(resp_node[0].mac, prototask_contxt.local_dev.mac)){
|
||
/* skip cco device report */
|
||
i++;
|
||
}
|
||
|
||
for (; i < cur_cnt; i++) {
|
||
iot_cus_printf("sta %02X:%02X:%02X:%02X:%02X:%02X report online\n",
|
||
resp_node[i].mac[0], resp_node[i].mac[1], resp_node[i].mac[2],
|
||
resp_node[i].mac[3], resp_node[i].mac[4], resp_node[i].mac[5]);
|
||
iot_cctt_report_sta_event(resp_node[i].mac, EVENT_RPT_STA_JOINED);
|
||
}
|
||
if (total_cnt == cur_cnt) {
|
||
iot_cus_printf("topo report online done, total = %u\n", total_cnt);
|
||
g_cctt_context.q_topo_rpt_online = 0;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/* report topo info as DL645 frame */
|
||
uint8_t iot_cctt_report_topo(plctxrx_cmd_topov2_t *resp_node,
|
||
uint16_t total_cnt, uint16_t cur_cnt, uint8_t flow)
|
||
{
|
||
uint8_t ctrl, i;
|
||
uint8_t resp_cnt;
|
||
uint8_t *send_cmd;
|
||
uint16_t out_len;
|
||
uint8_t dst_mac[IOT_MAC_ADDR_LEN];
|
||
iot_pkt_t *pkt;
|
||
node_t *node;
|
||
proto_645_header_t *hdr;
|
||
|
||
resp_cnt = cur_cnt;
|
||
|
||
out_len = DL645_PARSE_FRM_MIN_LEN + sizeof(node_t) * resp_cnt;
|
||
|
||
if (g_cctt_context.q_topo_seq) {
|
||
ctrl = PROTO_645_2007_FN_READ_DATA_C;
|
||
out_len += DL645_DI_LEN + 1;
|
||
} else {
|
||
ctrl = PROTO_645_2007_FN_READ_DATA;
|
||
out_len += sizeof(cctt_resp_topo_t) ;
|
||
}
|
||
|
||
iot_cus_printf("topo_resp cnt:%d ctrl:0x%02X seq:%d flow:%d out_len:%d\n",
|
||
resp_cnt, ctrl, g_cctt_context.q_topo_seq, flow, out_len);
|
||
pkt = iot_pkt_alloc(out_len, IOT_GREE_APP_MID);
|
||
if (pkt == NULL) {
|
||
iot_cus_printf("[err]cctt pkt alloc fail\n");
|
||
cctt_resp_cmd_ack(ctrl, DL645_ERR_OTHER_ERROR);
|
||
return 1;
|
||
}
|
||
|
||
send_cmd = iot_pkt_put(pkt, out_len);
|
||
hdr = (proto_645_header_t*)send_cmd;
|
||
iot_mac_addr_cpy(dst_mac, prototask_contxt.local_dev.mac);
|
||
iot_mac_addr_reverse(dst_mac);
|
||
|
||
iot_proto_645_header_init(hdr, dst_mac, ctrl, PROTO_645_DIR_SLAVE,
|
||
PROTO_645_2007_ERR_OK, flow);
|
||
|
||
proto_645_2007_di_to_byte(DL645_07_DI_QUERY_TOPO, hdr->data);
|
||
|
||
if (g_cctt_context.q_topo_seq) {
|
||
hdr->len = DL645_DI_LEN;
|
||
node = (node_t*)(hdr->data + DL645_DI_LEN);
|
||
} else {
|
||
hdr->len = sizeof(cctt_resp_topo_t);
|
||
((cctt_resp_topo_t*)(hdr->data))->total_cnt = total_cnt;
|
||
((cctt_resp_topo_t*)(hdr->data))->q_ver = 0;
|
||
node = ((cctt_resp_topo_t*)(hdr->data))->node;
|
||
}
|
||
hdr->len += sizeof(node_t) * resp_cnt;
|
||
|
||
for (i = 0; i < resp_cnt; i++) {
|
||
node->level = resp_node[i].level;
|
||
iot_mac_addr_cpy(node->mac, resp_node[i].mac);
|
||
iot_mac_addr_reverse(node->mac);
|
||
node++;
|
||
}
|
||
|
||
if (g_cctt_context.q_topo_seq) {
|
||
*(hdr->data + hdr->len) = g_cctt_context.q_topo_seq;
|
||
hdr->len += 1;
|
||
}
|
||
|
||
/* check end */
|
||
if (flow == 0) {
|
||
os_mem_set(&g_cctt_context, 0, sizeof(cctt_context_t));
|
||
}
|
||
|
||
iot_proto_645_ext_add33_handle(hdr->data, hdr->len);
|
||
iot_proto_645_tail_init(hdr);
|
||
iot_proto_send_to_mainboard(pkt);
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
/* response topo info */
|
||
uint8_t iot_cco_resp_topo_to_cctt(plctxrx_cmd_topov2_t *resp_node,
|
||
uint16_t total_cnt, uint16_t cur_cnt, uint8_t flow)
|
||
{
|
||
if (g_cctt_context.q_topo_rpt_online) {
|
||
/* request to report sta online by iot_cctt_req_online_sta_report */
|
||
return iot_cctt_report_sta_online(resp_node, total_cnt, cur_cnt);
|
||
} else {
|
||
return iot_cctt_report_topo(resp_node, total_cnt, cur_cnt, flow);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief: send cmd to txrx to request topo info
|
||
*
|
||
* @param start: start of topo to request
|
||
* @param count: number of topo to request
|
||
* @param seq : frame sequence
|
||
* @return 0 if success, 1 when failed
|
||
*/
|
||
uint8_t iot_cctt_req_txrx_topo(uint16_t start, uint16_t count, uint8_t seq)
|
||
{
|
||
uint8_t txrx_cmd_len;
|
||
iot_pkt_t *pkt;
|
||
plctxrx_cmd_arg_t *cmd;
|
||
plctxrx_cmd_query_topo_t *topo_cmd;
|
||
proto_cmd_hdl_state_t *sm = iot_proto_cmd_handle_state_get();
|
||
|
||
iot_cus_printf("cctt_query_topo seq=%d pos:%d cnt:%d\n",
|
||
g_cctt_context.q_topo_seq, g_cctt_context.q_topo_pos, count);
|
||
|
||
txrx_cmd_len = sizeof(plctxrx_cmd_arg_t) + sizeof(plctxrx_cmd_query_topo_t);
|
||
|
||
/* send txrx cmd */
|
||
pkt = iot_pkt_alloc(txrx_cmd_len, IOT_GREE_APP_MID);
|
||
if (pkt == NULL) {
|
||
iot_cus_printf("[err]cctt pkt alloc fail\n");
|
||
goto err;
|
||
}
|
||
cmd = (plctxrx_cmd_arg_t*)iot_pkt_put(pkt, txrx_cmd_len);
|
||
|
||
cmd->cid.cid = PLCTXRX_CID_TOPO;
|
||
cmd->cid.opcode = PLCTXRX_OP_QUERY;
|
||
cmd->need_ack = true;
|
||
cmd->prio = 0;
|
||
cmd->dlen = sizeof(plctxrx_cmd_query_topo_t);
|
||
topo_cmd = (plctxrx_cmd_query_topo_t*)cmd->arg;
|
||
topo_cmd->ver = IOT_PLC_CCO_TOPO_REQ_DATA_VER_V2;
|
||
topo_cmd->start = start;
|
||
topo_cmd->cnt = count;
|
||
|
||
sm->state = PROTO_CMD_DL645_WAIT_TOPO_INFO_RESP;
|
||
sm->dir = CMD_LOCAL_UP_LINK;
|
||
sm->seq = seq;
|
||
iot_proto_cmd_send_to_plctxrx(pkt);
|
||
return 0;
|
||
err:
|
||
return 1;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief: request online sta device report online to server
|
||
*
|
||
* @param none
|
||
* @return 0 if success, 1 when failed
|
||
*/
|
||
uint8_t iot_cctt_req_online_sta_report(void)
|
||
{
|
||
os_mem_set(&g_cctt_context, 0, sizeof(cctt_context_t));
|
||
g_cctt_context.q_topo_type = 0;
|
||
g_cctt_context.q_topo_pos = 1;
|
||
g_cctt_context.q_topo_cnt = 0xFFFF;
|
||
g_cctt_context.q_topo_rpt_online = 1;
|
||
return iot_cctt_req_txrx_topo(1, 0xFFFF, 0);
|
||
}
|
||
|
||
|
||
/* query topo, only send cmd to query topo */
|
||
uint8_t iot_cctt_query_topo(uint8_t *data, uint8_t len)
|
||
{
|
||
uint8_t ctrl;
|
||
uint8_t err_num;
|
||
uint8_t query_cnt;
|
||
cctt_query_topo_t *query_cmd;
|
||
|
||
query_cnt = (DL645_FRM_DATA_MAX_LEN - DL645_PARSE_FRM_MIN_LEN -
|
||
sizeof(cctt_resp_topo_t)) / sizeof(node_t);
|
||
|
||
if (len == sizeof(cctt_query_topo_t) ) {
|
||
ctrl = PROTO_645_2007_FN_READ_DATA;
|
||
query_cmd = (cctt_query_topo_t*)data;
|
||
os_mem_set(&g_cctt_context, 0, sizeof(cctt_context_t));
|
||
if (query_cmd->start > 0) {
|
||
g_cctt_context.q_topo_type = query_cmd->q_ver;
|
||
g_cctt_context.q_topo_pos = query_cmd->start;
|
||
g_cctt_context.q_topo_cnt = query_cmd->cnt;
|
||
} else {
|
||
err_num = DL645_ERR_PARAMETER_ERROR;
|
||
goto err;
|
||
}
|
||
} else {
|
||
ctrl = PROTO_645_2007_FN_READ_DATA_C;
|
||
/* check query topo for next frame */
|
||
if (g_cctt_context.q_topo_seq + 1 == data[DL645_DI_LEN] &&
|
||
g_cctt_context.q_topo_pos > 0) {
|
||
g_cctt_context.q_topo_seq = data[DL645_DI_LEN];
|
||
/* q_topo_cnt will be change after topo resp */
|
||
} else {
|
||
err_num = DL645_ERR_PARAMETER_ERROR;
|
||
goto err;
|
||
}
|
||
}
|
||
|
||
if (query_cnt > g_cctt_context.q_topo_cnt) {
|
||
query_cnt = g_cctt_context.q_topo_cnt;
|
||
}
|
||
|
||
if (g_cctt_context.q_topo_rpt_online) {
|
||
iot_cus_printf("cctt query topo, and reporting online, wait...\n");
|
||
err_num = DL645_ERR_OTHER_ERROR;
|
||
goto err;
|
||
}
|
||
|
||
if (0 != iot_cctt_req_txrx_topo(g_cctt_context.q_topo_pos,
|
||
query_cnt, g_cctt_context.q_topo_seq)) {
|
||
err_num = DL645_ERR_OTHER_ERROR;
|
||
goto err;
|
||
}
|
||
return 0;
|
||
|
||
err:
|
||
iot_cus_printf("cctt query topo end\n");
|
||
cctt_resp_cmd_ack(ctrl, err_num);
|
||
return 1;
|
||
}
|
||
|
||
void iot_cctt_set_plc_nw(uint8_t *data, uint8_t len)
|
||
{
|
||
uint8_t reason = DL645_ERR_OK;
|
||
cctt_set_plc_net_t *nw_handle = (cctt_set_plc_net_t *)data;
|
||
|
||
if (nw_handle->action == 0) {
|
||
iot_plc_stop_nw_fmt(greeapp->app_handle);
|
||
g_cctt_context.plc_nw_state = PLC_NW_CLOSE;
|
||
} else {
|
||
iot_plc_start_nw_fmt(greeapp->app_handle, 1);
|
||
g_cctt_context.plc_nw_state = PLC_NW_OPEN;
|
||
}
|
||
|
||
iot_cus_printf("ccct set nw :%d\n", nw_handle->action);
|
||
cctt_resp_cmd_ack(PROTO_645_2007_FN_WRITE_DATA, reason);
|
||
}
|
||
|
||
void iot_cctt_get_plc_nw(void)
|
||
{
|
||
uint8_t *send_cmd;
|
||
uint8_t datalen = DL645_DI_LEN + sizeof(uint8_t);
|
||
uint8_t out_len = DL645_PARSE_FRM_MIN_LEN + datalen;
|
||
uint8_t dst_mac[IOT_MAC_ADDR_LEN];
|
||
iot_pkt_t *pkt;
|
||
proto_645_header_t *hdr;
|
||
|
||
pkt = iot_pkt_alloc(out_len, IOT_GREE_APP_MID);
|
||
if (pkt == NULL) {
|
||
iot_cus_printf("[err]read plc nw fail\n");
|
||
return ;
|
||
}
|
||
|
||
send_cmd = iot_pkt_put(pkt, out_len);
|
||
hdr = (proto_645_header_t*)send_cmd;
|
||
iot_mac_addr_cpy(dst_mac, prototask_contxt.local_dev.mac);
|
||
iot_mac_addr_reverse(dst_mac);
|
||
hdr->len = datalen;
|
||
iot_proto_645_header_init(hdr, dst_mac, PROTO_645_2007_FN_READ_DATA,
|
||
PROTO_645_DIR_SLAVE, PROTO_645_2007_ERR_OK, 0);
|
||
proto_645_2007_di_to_byte(DL645_07_DI_HANDLE_PLC_NW, hdr->data);
|
||
hdr->data[DL645_DI_LEN] = g_cctt_context.plc_nw_state;
|
||
iot_cus_printf("ccct read nw :0x%x\n", g_cctt_context.plc_nw_state);
|
||
iot_proto_645_ext_add33_handle(hdr->data, datalen);
|
||
iot_proto_645_tail_init(hdr);
|
||
iot_proto_send_to_mainboard(pkt);
|
||
}
|
||
|
||
static void iot_cctt_add_pco(uint8_t *mac)
|
||
{
|
||
uint8_t i;
|
||
|
||
iot_cus_printf("add pco mac:%02X%02X%02X%02X%02X%02X\n",
|
||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||
|
||
if (iot_mac_addr_cmp(mac, prototask_contxt.local_dev.mac)) {
|
||
/* pco is cco, not add */
|
||
return;
|
||
}
|
||
|
||
for (i = 0; i < IOT_CCTT_CACHE_PCO_CNT; i++) {
|
||
if (!iot_mac_addr_valid(g_cctt_context.pco_list[i])) {
|
||
/* store pco in blank */
|
||
iot_mac_addr_cpy(g_cctt_context.pco_list[i], mac);
|
||
g_cctt_context.pco_cnt++;
|
||
break;
|
||
}
|
||
if (iot_mac_addr_cmp(mac, g_cctt_context.pco_list[i])) {
|
||
/* check pco have stored */
|
||
break;
|
||
}
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
void iot_cctt_reboot_mac_list_pco(uint8_t *data, uint8_t len)
|
||
{
|
||
uint8_t i;
|
||
uint16_t j;
|
||
uint8_t reason = DL645_ERR_OK;
|
||
cctt_reboot_mac_list_pco_t *cmd = (cctt_reboot_mac_list_pco_t *)data;
|
||
|
||
if (sizeof(cctt_reboot_mac_list_pco_t) + cmd->cnt * IOT_MAC_ADDR_LEN != len
|
||
|| cmd->cnt == 0) {
|
||
reason = DL645_ERR_PARAMETER_ERROR;
|
||
goto out;
|
||
}
|
||
|
||
/* find pco */
|
||
for (i = 0; i < cmd->cnt; i++) {
|
||
if (!iot_mac_addr_valid(cmd->mac[i])) {
|
||
continue;
|
||
}
|
||
iot_mac_addr_reverse(cmd->mac[i]);
|
||
for (j = 0; j < STA_DEV_MAX; j++) {
|
||
if (!iot_mac_addr_valid(prototask_contxt.dev_lst.dev[j].mac)) {
|
||
continue;
|
||
}
|
||
if (iot_mac_addr_cmp(cmd->mac[i],
|
||
prototask_contxt.dev_lst.dev[j].mac)) {
|
||
iot_cus_printf("find mac:%02x%02x%02x%02x%02x%02x role=%d\n",
|
||
cmd->mac[i][0], cmd->mac[i][1], cmd->mac[i][2],
|
||
cmd->mac[i][3], cmd->mac[i][4], cmd->mac[i][5],
|
||
prototask_contxt.dev_lst.dev[j].dev_role);
|
||
if (prototask_contxt.dev_lst.dev[j].dev_role ==
|
||
IOT_PLC_DEV_ROLE_STA) {
|
||
/* only add sta's pco, not add pco's pco */
|
||
iot_cctt_add_pco(prototask_contxt.dev_lst.dev_pco[j]);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
iot_cus_printf("[cctt]find pco cnt=%d\n", g_cctt_context.pco_cnt);
|
||
/* reboot pco */
|
||
if (cmd->seq == 0 && g_cctt_context.pco_cnt > 0) {
|
||
for (i = 0; i < g_cctt_context.pco_cnt; i++) {
|
||
iot_reboot_sta(g_cctt_context.pco_list[i]);
|
||
os_delay(50);
|
||
}
|
||
/* reset param */
|
||
g_cctt_context.pco_cnt = 0;
|
||
os_mem_set(g_cctt_context.pco_list, 0,
|
||
IOT_CCTT_CACHE_PCO_CNT * IOT_MAC_ADDR_LEN);
|
||
}
|
||
|
||
out:
|
||
cctt_resp_cmd_ack(PROTO_645_2007_FN_WRITE_DATA, reason);
|
||
return;
|
||
}
|
||
|
||
#if IOT_APP_SELECTION == IOT_APP_DEF_22_GE_MICRO_CCTT
|
||
void iot_cctt_init_rs485_led_pin(void)
|
||
{
|
||
switch (iot_board_hw_version_hex()) {
|
||
case HW_VERSION_IOT_CCTT_V3_0: /* micro cctt 3.0 hardware */
|
||
g_local_rs485.rs485_led_pin = 0xFF;
|
||
break;
|
||
case HW_VERSION_IOT_CCTT_V3_5: /* micro cctt 3.5 hardware */
|
||
default:
|
||
g_local_rs485.rs485_led_pin = 54;
|
||
break;
|
||
}
|
||
|
||
if (g_local_rs485.rs485_led_pin != 0xFF) {
|
||
iot_gpio_open_as_output(g_local_rs485.rs485_led_pin);
|
||
iot_gpio_value_set(g_local_rs485.rs485_led_pin, 1);
|
||
}
|
||
iot_cus_printf("g_local_rs485.rs485_led_pin=%u\n",
|
||
g_local_rs485.rs485_led_pin);
|
||
}
|
||
#else
|
||
void iot_cctt_init_rs485_led_pin(void)
|
||
{
|
||
g_local_rs485.rs485_led_pin = 0xFF;
|
||
}
|
||
#endif
|
||
|
||
void iot_cctt_rs485_led_blink(void)
|
||
{
|
||
if (g_local_rs485.rs485_led_pin != 0xFF) {
|
||
iot_gpio_value_set(g_local_rs485.rs485_led_pin, 0);
|
||
os_delay(1);
|
||
iot_gpio_value_set(g_local_rs485.rs485_led_pin, 1);
|
||
}
|
||
}
|
||
|
||
void iot_cctt_delaytime(uint8_t *data, uint8_t len)
|
||
{
|
||
uint8_t err_num = DL645_ERR_OK;
|
||
uint16_t pkt_len;
|
||
iot_pkt_t *data_pkt;
|
||
|
||
proto_645_header_t *header = (proto_645_header_t *)data;
|
||
cctt_delaytime_t *data_info = (cctt_delaytime_t *)header->data;
|
||
ge_frame_delay_time_subfn166_t *ge_frame = NULL;
|
||
uint16_t rsv_data_len = data_info->time_info.datalen;
|
||
|
||
pkt_len = sizeof(ge_frame_delay_time_subfn166_t) +
|
||
data_info->time_info.datalen + sizeof(ge_frm_tail_t);
|
||
if (pkt_len > DL645_FRM_DATA_MAX_LEN) {
|
||
err_num = DL645_ERR_PARAMETER_ERROR;
|
||
goto err;
|
||
}
|
||
|
||
data_pkt = iot_pkt_alloc(pkt_len, IOT_GREE_APP_MID);
|
||
if (data_pkt == NULL) {
|
||
iot_cus_printf("%s alloc pkt err\n", __FUNCTION__);
|
||
err_num = DL645_ERR_OTHER_ERROR;
|
||
goto err;
|
||
}
|
||
|
||
/* pack a ge delaytime frame */
|
||
ge_frame = (ge_frame_delay_time_subfn166_t *)iot_pkt_put(data_pkt, pkt_len);
|
||
ge_frm_tail_t *tail_data = (ge_frm_tail_t *)(iot_pkt_data(data_pkt) +
|
||
sizeof(ge_frame_delay_time_subfn166_t) + rsv_data_len);
|
||
os_mem_set((uint8_t *)ge_frame, 0, pkt_len);
|
||
g_cctt_context.q_delaytime_seq++;
|
||
ge_frame->seq = g_cctt_context.q_delaytime_seq;
|
||
ge_frame->resv = DL645_07_RESV0_RESV;
|
||
iot_mac_addr_cpy(ge_frame->dest_mac, header->addr);
|
||
iot_mac_addr_reverse(ge_frame->dest_mac);
|
||
data_info->time_info.level = iot_plctxrx_get_node_level(ge_frame->dest_mac);
|
||
if (data_info->time_info.level == -1) {
|
||
iot_cus_printf("%s query level failed\n", __FUNCTION__);
|
||
}
|
||
os_mem_cpy((uint8_t *)&ge_frame->tm_test,(uint8_t *)&data_info->time_info,
|
||
sizeof(ge_delay_tm_test_t));
|
||
iot_delay_timer_get(&ge_frame->tm_test.mcu_tx_time, CCO_TX_TIME, 0);
|
||
EXT_FN_TWO_PART_FRM_PREPARE(ge_frame, tail_data, rsv_data_len,
|
||
PROTO_GE_PLC_SET_CMD, PROTO_GE_DELAY_TM_CMD);
|
||
tail_data->check_sum = ge_frm_checksum_calc((uint8_t *)ge_frame,
|
||
pkt_len - sizeof(ge_frm_tail_t));
|
||
iot_proto_delay_time_send(data_pkt, prototask_contxt.local_dev.mac,
|
||
ge_frame->dest_mac);
|
||
return;
|
||
|
||
err:
|
||
cctt_resp_cmd_ack(PROTO_645_2007_FN_READ_DATA, err_num);
|
||
return;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief: set parameter of rs485 interface
|
||
*
|
||
* @param baudrate: baudrate of rs485
|
||
* @param parity : parity of rs485
|
||
* @param databits: data bit number of rs485
|
||
* @param stopbits: stopbits of rs485
|
||
* @return ERR_OK if success, ERR_FAIL otherwise
|
||
*/
|
||
uint8_t iot_cctt_set_rs485_config_impl(uint32_t baudrate, uint8_t parity,
|
||
uint8_t databits, uint8_t stopbits)
|
||
{
|
||
ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo;
|
||
uint32_t baud_val[] = PROTO_GE_UART_BAUD_VALUE;
|
||
|
||
if (NULL == g_local_rs485.handler) {
|
||
return ERR_FAIL;
|
||
}
|
||
|
||
if (!iot_proto_uart_param_check(baudrate, parity, databits, stopbits)) {
|
||
iot_cus_printf("%s: invalid rs485 param:%u,%u,%u,%u\n",
|
||
__FUNCTION__, baudrate, parity, databits, stopbits);
|
||
return ERR_FAIL;
|
||
}
|
||
|
||
if ((baud_val[p_flash->public.pub.baudidx] != baudrate) ||
|
||
(p_flash->public.pub.parity != parity) ||
|
||
(p_flash->public.pub.data != databits) ||
|
||
(p_flash->public.pub.stop != stopbits)) {
|
||
iot_cus_printf("%s: rs485 param:%u,%u,%u,%u changed, save it\n",
|
||
__FUNCTION__, baudrate, parity, databits, stopbits);
|
||
p_flash->public.pub.baudidx = uart_baud_find_index(baudrate);
|
||
p_flash->public.pub.parity = parity;
|
||
p_flash->public.pub.data = databits;
|
||
p_flash->public.pub.stop = stopbits;
|
||
iot_proto_flashsave(p_flash);
|
||
}
|
||
|
||
iot_uart_set_config(g_local_rs485.handler,
|
||
baudrate, parity, databits, stopbits);
|
||
iot_cus_printf("%s: success to set rs485 param: %u,%u,%u,%u\n",
|
||
__FUNCTION__, baudrate, parity, databits, stopbits);
|
||
return ERR_OK;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief: callback function to receive rs485 data
|
||
*
|
||
* @param buffer : pointer buffer of storing rs485 data
|
||
* @param len : received data length
|
||
* @param is_full_frame: unused
|
||
* @param invalid_data_len: unused
|
||
* @return none
|
||
*/
|
||
static void iot_cctt_rs485_recv_callback(uint8_t *buffer, uint32_t len,
|
||
bool_t is_full_frame, uint32_t invalid_data_len)
|
||
{
|
||
uint8_t *p_dst = g_local_rs485.cache;
|
||
uint32_t total_len;
|
||
|
||
os_acquire_mutex(g_local_rs485.cache_mutex);
|
||
total_len = g_local_rs485.cache_len + len;
|
||
if (total_len <= IOT_CCTT_RS485_CACHE_SIZE) {
|
||
p_dst += g_local_rs485.cache_len;
|
||
os_mem_cpy(p_dst, buffer, len);
|
||
g_local_rs485.cache_len += len;
|
||
g_local_rs485.recv_ts = os_boot_time64();
|
||
} else {
|
||
iot_cus_printf("%s: rs485 cache overflow\n", __FUNCTION__);
|
||
}
|
||
os_release_mutex(g_local_rs485.cache_mutex);
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief: init rs485 interface
|
||
*
|
||
* @param none
|
||
* @return ERR_OK if success, ERR_FAIL otherwise
|
||
*/
|
||
uint8_t iot_cctt_init_rs485_intf(void)
|
||
{
|
||
uint8_t uart_port = iot_board_get_uart(UART_RS485_PORT);
|
||
int32_t rs485_txe = iot_board_get_gpio(GPIO_RS485_TXE);
|
||
ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo;
|
||
uint32_t baud_val[] = PROTO_GE_UART_BAUD_VALUE;
|
||
uint8_t ret = ERR_OK;
|
||
|
||
if (true == g_local_rs485.ready) {
|
||
goto out;
|
||
}
|
||
|
||
iot_cctt_init_rs485_led_pin();
|
||
|
||
/* open rs485 uart interface */
|
||
g_local_rs485.handler = iot_uart_open(uart_port,
|
||
iot_cctt_rs485_recv_callback, 256, NULL);
|
||
if (NULL == g_local_rs485.handler) {
|
||
iot_cus_printf("%s: open rs485 uart failed!\n", __FUNCTION__);
|
||
ret = ERR_FAIL;
|
||
goto out;
|
||
}
|
||
|
||
/* set rs485 mode and rs485 txe pin */
|
||
iot_cus_printf("rs485_txe pin = %u\n", rs485_txe);
|
||
iot_uart_enable_rs485(g_local_rs485.handler, rs485_txe);
|
||
|
||
/* create mutex to protect rs485 receive cache */
|
||
g_local_rs485.cache_mutex = os_create_mutex(IOT_GREE_APP_MID);
|
||
IOT_ASSERT(NULL != g_local_rs485.cache_mutex);
|
||
|
||
if (false == iot_proto_uart_param_check(
|
||
baud_val[p_flash->public.pub.baudidx], p_flash->public.pub.parity,
|
||
p_flash->public.pub.data, p_flash->public.pub.stop)) {
|
||
p_flash->public.pub.baudidx = 2; // default baudrate = 2400
|
||
p_flash->public.pub.parity = IOT_UART_PARITY_EVEN;
|
||
p_flash->public.pub.data = IOT_UART_DLEN_8_BITS;
|
||
p_flash->public.pub.stop = IOT_UART_STOP_1_BITS;
|
||
}
|
||
|
||
iot_cctt_set_rs485_config_impl(baud_val[p_flash->public.pub.baudidx],
|
||
p_flash->public.pub.parity, p_flash->public.pub.data,
|
||
p_flash->public.pub.stop);
|
||
g_local_rs485.ready = true;
|
||
|
||
out:
|
||
return ret;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief: set configuration of rs485 interface by dl645 protocol
|
||
*
|
||
* @param data: dl645 request data
|
||
* @param len : length of dl645 request data
|
||
* @return none
|
||
*/
|
||
void iot_cctt_set_rs485_config(uint8_t *data, uint8_t len)
|
||
{
|
||
cctt_set_rs485_cfg_t *rs485_cfg = (cctt_set_rs485_cfg_t*)data;
|
||
uint8_t reason = DL645_ERR_PARAMETER_ERROR;
|
||
|
||
if ((false == g_local_rs485.ready) &&
|
||
(ERR_OK != iot_cctt_init_rs485_intf())) {
|
||
iot_cus_printf("can not set rs485 config, rs485 not ready!\n");
|
||
cctt_resp_cmd_ack(PROTO_645_2007_FN_READ_DATA, DL645_ERR_OTHER_ERROR);
|
||
return;
|
||
}
|
||
|
||
/* protocol compatibility conversion */
|
||
if (2 == rs485_cfg->stopbits) {
|
||
rs485_cfg->stopbits = IOT_UART_STOP_2_BITS;
|
||
}
|
||
|
||
if (ERR_OK == iot_cctt_set_rs485_config_impl(rs485_cfg->baudrate,
|
||
rs485_cfg->parity, rs485_cfg->databits, rs485_cfg->stopbits)) {
|
||
reason = DL645_ERR_OK;
|
||
}
|
||
cctt_resp_cmd_ack(PROTO_645_2007_FN_WRITE_DATA, reason);
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief: readout configuration of rs485 interface by dl645 protocol
|
||
*
|
||
* @param data: dl645 request data
|
||
* @param len : length of dl645 request data
|
||
* @return none
|
||
*/
|
||
void iot_cctt_read_rs485_config(uint8_t *data, uint8_t len)
|
||
{
|
||
iot_pkt_t *p_pkt;
|
||
proto_645_header_t *p_hdr;
|
||
cctt_read_rs485_cfg_t *p_rs485_cfg;
|
||
uint8_t dst_mac[IOT_MAC_ADDR_LEN];
|
||
uint32_t pkt_len = DL645_PARSE_FRM_MIN_LEN + sizeof(cctt_read_rs485_cfg_t);
|
||
uint32_t baud_val[] = PROTO_GE_UART_BAUD_VALUE;
|
||
ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo;
|
||
|
||
if ((false == g_local_rs485.ready) &&
|
||
(ERR_OK != iot_cctt_init_rs485_intf())) {
|
||
iot_cus_printf("can not read rs485 config, rs485 not ready!\n");
|
||
cctt_resp_cmd_ack(PROTO_645_2007_FN_READ_DATA, DL645_ERR_OTHER_ERROR);
|
||
return;
|
||
}
|
||
|
||
p_pkt = iot_pkt_alloc(pkt_len, IOT_GREE_APP_MID);
|
||
if (NULL == p_pkt) {
|
||
iot_cus_printf("%s: memory runout!\n", __FUNCTION__);
|
||
cctt_resp_cmd_ack(PROTO_645_2007_FN_READ_DATA, DL645_ERR_OTHER_ERROR);
|
||
return;
|
||
}
|
||
|
||
p_hdr = (proto_645_header_t *)iot_pkt_put(p_pkt, pkt_len);
|
||
p_rs485_cfg = (cctt_read_rs485_cfg_t *)p_hdr->data;
|
||
iot_mac_addr_cpy(dst_mac, prototask_contxt.local_dev.mac);
|
||
iot_mac_addr_reverse(dst_mac);
|
||
|
||
iot_proto_645_header_init(p_hdr, dst_mac, PROTO_645_2007_FN_READ_DATA,
|
||
PROTO_645_DIR_SLAVE, PROTO_645_2007_ERR_OK, 0);
|
||
p_hdr->len = sizeof(cctt_read_rs485_cfg_t);
|
||
proto_645_2007_di_to_byte(DL645_07_DI_RS485_CONFIG,
|
||
(uint8_t*)&p_rs485_cfg->di);
|
||
p_rs485_cfg->baudrate = baud_val[p_flash->public.pub.baudidx];
|
||
p_rs485_cfg->parity = p_flash->public.pub.parity;
|
||
p_rs485_cfg->databits = p_flash->public.pub.data;
|
||
p_rs485_cfg->stopbits = p_flash->public.pub.stop;
|
||
|
||
/* protocol compatibility conversion */
|
||
if (IOT_UART_STOP_2_BITS == p_rs485_cfg->stopbits) {
|
||
p_rs485_cfg->stopbits = 2;
|
||
}
|
||
|
||
iot_proto_645_ext_add33_handle(p_hdr->data, p_hdr->len);
|
||
iot_proto_645_tail_init(p_hdr);
|
||
|
||
iot_proto_send_to_mainboard(p_pkt);
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief: send data to rs485 interface
|
||
*
|
||
* @param buff : data buffer to send
|
||
* @param buff_len: length of buff
|
||
* @return none
|
||
*/
|
||
static void iot_cctt_rs485_send(uint8_t *buff, uint32_t buff_len)
|
||
{
|
||
iot_pkt_t *pkt;
|
||
uint8_t *data;
|
||
|
||
if (NULL == g_local_rs485.handler) {
|
||
iot_cus_printf("%s: rs485 handler null!\n", __FUNCTION__);
|
||
return;
|
||
}
|
||
|
||
pkt = iot_pkt_alloc(buff_len, IOT_GREE_APP_MID);
|
||
if (NULL == pkt) {
|
||
iot_cus_printf("%s rs485 send fail, pkt alloc fail!\n", __FUNCTION__);
|
||
return;
|
||
}
|
||
data = iot_pkt_put(pkt, buff_len);
|
||
os_mem_cpy(data, buff, buff_len);
|
||
iot_uart_send(g_local_rs485.handler, pkt, NULL);
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief: dump bin data to log
|
||
*
|
||
* @param desc : description of bin data
|
||
* @param p_data: data to dump
|
||
* @param len : length of p_data
|
||
* @return none
|
||
*/
|
||
static void iot_cctt_bin_dump(char *desc, uint8_t *p_data, uint32_t len)
|
||
{
|
||
iot_cus_printf("%s:", desc);
|
||
while (len > 0) {
|
||
iot_cus_printf("%02X ", *p_data);
|
||
p_data++;
|
||
len--;
|
||
}
|
||
iot_cus_printf("\n");
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief: wait data reply from rs485 interface
|
||
*
|
||
* @param p_buff : buffer used to store received reply
|
||
* @param len : length of p_buff
|
||
* @return length of received data
|
||
*/
|
||
static uint32_t iot_cctt_wait_rs485_reply(uint8_t *p_buff, uint32_t len)
|
||
{
|
||
uint64_t time_end = RS485_DEV_RESP_TO_MS + os_boot_time64();
|
||
uint64_t time_idle;
|
||
uint32_t ret = 0;
|
||
|
||
while (os_boot_time64() < time_end) {
|
||
os_acquire_mutex(g_local_rs485.cache_mutex);
|
||
time_idle = os_boot_time64() - g_local_rs485.recv_ts;
|
||
if ((g_local_rs485.cache_len > 0) &&
|
||
(time_idle >= RS485_DEV_IDLE_TO_MS)) {
|
||
if (g_local_rs485.cache_len < len) {
|
||
len = g_local_rs485.cache_len;
|
||
}
|
||
os_mem_cpy(p_buff, g_local_rs485.cache, len);
|
||
ret = g_local_rs485.cache_len;
|
||
}
|
||
os_release_mutex(g_local_rs485.cache_mutex);
|
||
if (ret > 0) {
|
||
iot_cus_printf("iot_cctt_wait_rs485_reply ret = %u\n", ret);
|
||
break;
|
||
} else {
|
||
os_delay(10);
|
||
}
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief: report specified data with specified di with DL645 protocol
|
||
*
|
||
* @param di : di of dl645 protocol
|
||
* @param data : data to send
|
||
* @param len : length of data
|
||
* @return none
|
||
*/
|
||
static void iot_cctt_report_local_data(uint32_t di, uint8_t *data, uint8_t len)
|
||
{
|
||
iot_pkt_t *p_pkt;
|
||
uint32_t pkt_len;
|
||
proto_645_header_t *p_hdr;
|
||
uint8_t dst_mac[IOT_MAC_ADDR_LEN];
|
||
|
||
pkt_len = DL645_PARSE_FRM_MIN_LEN + DL645_DI_LEN + len;
|
||
p_pkt = iot_pkt_alloc(pkt_len, IOT_GREE_APP_MID);
|
||
if (NULL == p_pkt) {
|
||
iot_cus_printf("%s: can not alloc modbus reply frame!\n", __FUNCTION__);
|
||
cctt_resp_cmd_ack(PROTO_645_2007_FN_READ_DATA, DL645_ERR_OTHER_ERROR);
|
||
return;
|
||
}
|
||
p_hdr = (proto_645_header_t*)iot_pkt_put(p_pkt, pkt_len);
|
||
iot_mac_addr_cpy(dst_mac, prototask_contxt.local_dev.mac);
|
||
iot_mac_addr_reverse(dst_mac);
|
||
|
||
iot_proto_645_header_init(p_hdr, dst_mac, PROTO_645_2007_FN_READ_DATA,
|
||
PROTO_645_DIR_SLAVE, PROTO_645_2007_ERR_OK, 0);
|
||
p_hdr->len = DL645_DI_LEN + len;
|
||
proto_645_2007_di_to_byte(di, p_hdr->data);
|
||
os_mem_cpy(p_hdr->data + DL645_DI_LEN, data, len);
|
||
|
||
iot_proto_645_ext_add33_handle(p_hdr->data, p_hdr->len);
|
||
iot_proto_645_tail_init(p_hdr);
|
||
iot_proto_send_to_mainboard(p_pkt);
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief: check whether the specified data is a complete dl645 frame
|
||
*
|
||
* @param p_data: data to check
|
||
* @param len : length of data
|
||
* @param p_frm_offset: pointer to store 645 frame offset in p_data
|
||
* @param p_frm_length: pointer to store 645 frame length in p_data
|
||
* @return ERR_OK if check pass, ERR_FAIL otherwise
|
||
*/
|
||
uint8_t proto_645_format_check(uint8_t *p_data, uint16_t len,
|
||
uint8_t *p_frm_offset, uint8_t *p_frm_lenth)
|
||
{
|
||
proto_645_header_t * hdr_645 = (proto_645_header_t*)p_data;
|
||
proto_645_tailer_t * tail_645 = NULL;
|
||
uint8_t frm_offset = 0;
|
||
uint8_t err_code = 0;
|
||
uint8_t ret = ERR_OK;
|
||
|
||
if ((NULL == p_data) || (len == 0) ||
|
||
(NULL == p_frm_offset) || (NULL == p_frm_lenth)) {
|
||
err_code = 9;
|
||
goto out;
|
||
}
|
||
|
||
/* skip preamble code before dl645 frame */
|
||
frm_offset = 0;
|
||
while ((frm_offset < len) && (p_data[frm_offset] != PROTO_645_START_CHAR)) {
|
||
frm_offset++;
|
||
}
|
||
|
||
len -= frm_offset;
|
||
p_data += frm_offset;
|
||
hdr_645 = (proto_645_header_t*)p_data;
|
||
|
||
if ((len == 0) || (p_data[0] != PROTO_645_START_CHAR)) {
|
||
err_code = 1;
|
||
goto out;
|
||
}
|
||
|
||
if (len <= PROTO_645_SECOND_HEAD_POS ||
|
||
p_data[PROTO_645_SECOND_HEAD_POS] != PROTO_645_START_CHAR) {
|
||
err_code = 2;
|
||
goto out;
|
||
}
|
||
|
||
if (len < sizeof(proto_645_header_t)) {
|
||
err_code = 3;
|
||
goto out;
|
||
}
|
||
|
||
if (hdr_645->start_char_2 != PROTO_645_START_CHAR) {
|
||
err_code = 4;
|
||
goto out;
|
||
}
|
||
|
||
if (len < hdr_645->len + sizeof(proto_645_header_t) +
|
||
sizeof(proto_645_tailer_t)) {
|
||
err_code = 5;
|
||
goto out;
|
||
}
|
||
|
||
tail_645 = (proto_645_tailer_t*)(p_data + sizeof(proto_645_header_t) +
|
||
hdr_645->len);
|
||
if (tail_645->end_char != PROTO_645_END_CHAR) {
|
||
err_code = 6;
|
||
goto out;
|
||
}
|
||
|
||
if (tail_645->cs != iot_proto_645_calc_cs(hdr_645)) {
|
||
err_code = 7;
|
||
goto out;
|
||
}
|
||
|
||
*p_frm_offset = frm_offset;
|
||
*p_frm_lenth = sizeof(proto_645_header_t) + hdr_645->len +
|
||
sizeof(proto_645_tailer_t);
|
||
|
||
out:
|
||
if (err_code > 0) {
|
||
ret = ERR_FAIL;
|
||
iot_cus_printf("%s: error_code=%d\n", __FUNCTION__, err_code);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief: transparent transmit dl645 frame to rs485, reply dl645 response
|
||
*
|
||
* @param data : data to transparent transmit to rs485
|
||
* @param len : length of data
|
||
* @return none
|
||
*/
|
||
void iot_cctt_rs485_trans_dl645(uint8_t *data, uint8_t len)
|
||
{
|
||
static uint8_t recv_buff[256];
|
||
uint32_t recv_len;
|
||
uint8_t frm_offset = 0, frm_length = 0;
|
||
|
||
if ((NULL == data) || (len < DL645_DI_LEN)) {
|
||
return;
|
||
}
|
||
|
||
if ((false == g_local_rs485.ready) &&
|
||
(ERR_OK != iot_cctt_init_rs485_intf())) {
|
||
iot_cus_printf("can not trans dl645, rs485 not ready!\n");
|
||
cctt_resp_cmd_ack(PROTO_645_2007_FN_READ_DATA, DL645_ERR_OTHER_ERROR);
|
||
return;
|
||
}
|
||
|
||
data += DL645_DI_LEN;
|
||
len -= DL645_DI_LEN;
|
||
os_acquire_mutex(g_local_rs485.cache_mutex);
|
||
g_local_rs485.cache_len = 0;
|
||
os_release_mutex(g_local_rs485.cache_mutex);
|
||
|
||
iot_cctt_rs485_led_blink();
|
||
iot_cctt_bin_dump("dl645 to rs485", data, len);
|
||
iot_cctt_rs485_send(data, len);
|
||
recv_len = iot_cctt_wait_rs485_reply(recv_buff, sizeof(recv_buff));
|
||
if (recv_len > 0) {
|
||
iot_cctt_bin_dump("rs485 reply", recv_buff, recv_len);
|
||
}
|
||
|
||
if (ERR_OK != proto_645_format_check(
|
||
recv_buff, recv_len, &frm_offset, &frm_length)) {
|
||
cctt_resp_cmd_ack(PROTO_645_2007_FN_READ_DATA, DL645_ERR_NO_REQ_DATA);
|
||
return;
|
||
}
|
||
|
||
iot_cctt_rs485_led_blink();
|
||
iot_cctt_report_local_data(DL645_07_DI_TRANS_DL645,
|
||
recv_buff + frm_offset, frm_length);
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief check the validity of modbus frame.
|
||
* @param data: point to the data
|
||
* @param len: the number of input data
|
||
* @return: ERR_OK --> success; ERR_FAIL --> failed.
|
||
*/
|
||
static uint8_t iot_cctt_modbus_frame_check(uint8_t *data, uint32_t len)
|
||
{
|
||
uint8_t i;
|
||
uint32_t pos;
|
||
uint16_t crc = 0xFFFF;
|
||
|
||
for (pos = 0; pos < len; pos++) {
|
||
/* XOR byte into least sig. byte of crc */
|
||
crc ^= (uint16_t)data[pos];
|
||
/* Loop over each bit */
|
||
for (i = 8; i != 0; i--) {
|
||
/* If the LSB is set */
|
||
if ((crc & 0x0001) != 0) {
|
||
/* Shift right and XOR 0xA001 */
|
||
crc >>= 1;
|
||
/* Else LSB is not set */
|
||
crc ^= 0xA001;
|
||
} else {
|
||
/* Just shift right */
|
||
crc >>= 1;
|
||
}
|
||
}
|
||
}
|
||
/* Note, this number has low and high bytes swapped,
|
||
so use it accordingly (or swap bytes) */
|
||
return (0x0 == crc) ? ERR_OK : ERR_FAIL;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief: transparent transmit modbus frame to rs485, reply modbus response
|
||
*
|
||
* @param data : data to transparent transmit to rs485
|
||
* @param len : length of data
|
||
* @return none
|
||
*/
|
||
void iot_cctt_rs485_trans_modbus(uint8_t *data, uint8_t len)
|
||
{
|
||
static uint8_t recv_buff[256];
|
||
uint32_t recv_len;
|
||
|
||
if ((NULL == data) || (len < DL645_DI_LEN)) {
|
||
return;
|
||
}
|
||
|
||
if ((false == g_local_rs485.ready) &&
|
||
(ERR_OK != iot_cctt_init_rs485_intf())) {
|
||
iot_cus_printf("can not trans modbus, rs485 not ready!\n");
|
||
cctt_resp_cmd_ack(PROTO_645_2007_FN_READ_DATA, DL645_ERR_OTHER_ERROR);
|
||
return;
|
||
}
|
||
|
||
data += DL645_DI_LEN;
|
||
len -= DL645_DI_LEN;
|
||
os_acquire_mutex(g_local_rs485.cache_mutex);
|
||
g_local_rs485.cache_len = 0;
|
||
os_release_mutex(g_local_rs485.cache_mutex);
|
||
|
||
iot_cctt_rs485_led_blink();
|
||
iot_cctt_bin_dump("modbus to rs485", data, len);
|
||
iot_cctt_rs485_send(data, len);
|
||
recv_len = iot_cctt_wait_rs485_reply(recv_buff, sizeof(recv_buff));
|
||
|
||
if (0 != recv_len) {
|
||
iot_cctt_bin_dump("rs485 reply", recv_buff, recv_len);
|
||
} else {
|
||
iot_cus_printf("%s: rs485 device no reply!\n", __FUNCTION__);
|
||
}
|
||
|
||
if(ERR_OK != iot_cctt_modbus_frame_check(recv_buff, recv_len)) {
|
||
cctt_resp_cmd_ack(PROTO_645_2007_FN_READ_DATA, DL645_ERR_NO_REQ_DATA);
|
||
return;
|
||
}
|
||
|
||
iot_cctt_rs485_led_blink();
|
||
iot_cctt_report_local_data(DL645_07_DI_TRANS_MODBUS, recv_buff, recv_len);
|
||
}
|
||
|
||
static void cctt_read_data_cmd_handle(proto_645_header_t *header)
|
||
{
|
||
uint32_t di;
|
||
iot_pkt_t *p_pkt;
|
||
uint16_t msg_id = 0xff;
|
||
uint16_t pkt_len;
|
||
|
||
proto_645_2007_byte_to_di(header->data, di);
|
||
iot_cus_printf("cctt_read_data_cmd_handle di:%08X\n", di);
|
||
|
||
switch (di) {
|
||
case DL645_07_DI_QUERY_WHITELIST:
|
||
{
|
||
msg_id = CCTT_QUERY_WHITELIST;
|
||
break;
|
||
}
|
||
case DL645_07_DI_QUERY_TOPO:
|
||
{
|
||
msg_id = CCTT_QUERY_TOPO;
|
||
break;
|
||
}
|
||
case DL645_07_DI_RS485_CONFIG:
|
||
{
|
||
msg_id = CCTT_READ_RS485_CONFIG;
|
||
break;
|
||
}
|
||
case DL645_07_DI_TRANS_DL645:
|
||
{
|
||
msg_id = CCTT_RS485_TRANS_DL645;
|
||
break;
|
||
}
|
||
case DL645_07_DI_TRANS_MODBUS:
|
||
{
|
||
msg_id = CCTT_RS485_TRANS_MODBUS;
|
||
break;
|
||
}
|
||
case DL645_07_DI_HANDLE_PLC_NW:
|
||
{
|
||
msg_id = CCTT_READ_PLC_NW;
|
||
break;
|
||
}
|
||
case DL645_07_DI_DELAYTIME:
|
||
{
|
||
msg_id = CCTT_DELAYTIME;
|
||
break;
|
||
}
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if (msg_id != 0xFF) {
|
||
if (msg_id == CCTT_DELAYTIME) {
|
||
/* need post dst_mac */
|
||
pkt_len = header->len + sizeof(header);
|
||
} else {
|
||
pkt_len = header->len;
|
||
}
|
||
|
||
p_pkt = iot_pkt_alloc(header->len , IOT_GREE_APP_MID);
|
||
if (!p_pkt) {
|
||
iot_cus_printf("[dl645][err]No Mem!\n");
|
||
return;
|
||
}
|
||
|
||
if (msg_id == CCTT_DELAYTIME) {
|
||
os_mem_cpy(iot_pkt_put(p_pkt, pkt_len), (uint8_t *)header, pkt_len);
|
||
} else {
|
||
os_mem_cpy(iot_pkt_put(p_pkt, pkt_len), header->data, pkt_len);
|
||
}
|
||
iot_proto_task_post_msg(PROTO_CCTT_MSG, msg_id, p_pkt,
|
||
0, IOT_PROTO_TASK_QUEUE_LP);
|
||
}
|
||
}
|
||
|
||
static void cctt_write_data_cmd_handle(proto_645_header_t *header)
|
||
{
|
||
uint32_t di;
|
||
iot_pkt_t *p_pkt;
|
||
uint16_t msg_id = 0xff;
|
||
|
||
proto_645_2007_byte_to_di(header->data, di);
|
||
iot_cus_printf("cctt_write_data_cmd_handle di:%08X\n", di);
|
||
|
||
switch (di) {
|
||
case DL645_07_DI_ADD_WHITELISET:
|
||
{
|
||
msg_id = CCTT_ADD_WHITELIST;
|
||
break;
|
||
}
|
||
case DL645_07_DI_DEL_WHITELISET:
|
||
{
|
||
msg_id = CCTT_DEL_WHITELIST;
|
||
break;
|
||
}
|
||
case DL645_07_DI_REBOOT_CCTT:
|
||
case DL645_07_DI_REBOOT_CCO:
|
||
{
|
||
msg_id = CCTT_REBOOT_CCO;
|
||
break;
|
||
}
|
||
case DL645_07_DI_REBOOT_STA:
|
||
{
|
||
msg_id = CCTT_REBOOT_STA;
|
||
break;
|
||
}
|
||
case DL645_07_DI_WL_STATE:
|
||
{
|
||
msg_id = CCTT_SET_WL_STATE;
|
||
break;
|
||
}
|
||
case DL645_07_DI_CLEAR_WL:
|
||
{
|
||
msg_id = CCTT_CLR_WHITELIST;
|
||
break;
|
||
}
|
||
case DL645_07_DI_CHECK_WL_ADDR:
|
||
{
|
||
msg_id = CCTT_CHECK_WL_MAC;
|
||
break;
|
||
}
|
||
case DL645_07_DI_HANDLE_PLC_NW:
|
||
{
|
||
msg_id = CCTT_SET_PLC_NW;
|
||
break;
|
||
}
|
||
case DL645_07_DI_REBOOT_MAC_LIST_PCO:
|
||
{
|
||
msg_id = CCTT_REBOOT_MAC_LIST_PCO;
|
||
break;
|
||
}
|
||
case DL645_07_DI_RS485_CONFIG:
|
||
{
|
||
msg_id = CCTT_SET_RS485_CONFIG;
|
||
break;
|
||
}
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if (msg_id != 0xFF) {
|
||
p_pkt = iot_pkt_alloc(header->len, IOT_GREE_APP_MID);
|
||
|
||
if (!p_pkt) {
|
||
iot_cus_printf("[dl645][err]No Mem!\n");
|
||
return;
|
||
}
|
||
os_mem_cpy(iot_pkt_put(p_pkt, header->len), header->data, header->len);
|
||
iot_proto_task_post_msg(PROTO_CCTT_MSG, msg_id, p_pkt,
|
||
0, IOT_PROTO_TASK_QUEUE_LP);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief iot_cctt_handle_local_dl645_cmd() - handle the local cmd
|
||
* data is del 0x33
|
||
* @param pkt: point to the dl645 pkt data
|
||
*/
|
||
uint8_t iot_cctt_handle_local_dl645_cmd(iot_pkt_t *pkt)
|
||
{
|
||
proto_645_header_t *header = (proto_645_header_t*)iot_pkt_data(pkt);
|
||
|
||
switch (header->control.fn) {
|
||
case PROTO_645_2007_FN_READ_DATA:
|
||
case PROTO_645_2007_FN_READ_DATA_C:
|
||
{
|
||
cctt_read_data_cmd_handle(header);
|
||
break;
|
||
}
|
||
case PROTO_645_2007_FN_WRITE_DATA:
|
||
{
|
||
cctt_write_data_cmd_handle(header);
|
||
break;
|
||
}
|
||
default:
|
||
break;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
uint8_t iot_cco_resp_topo_set_query_info(uint8_t done, uint16_t resp_cnt)
|
||
{
|
||
if (done) {
|
||
os_mem_set(&g_cctt_context, 0, sizeof(cctt_context_t));
|
||
} else {
|
||
g_cctt_context.q_topo_pos += resp_cnt;
|
||
if (g_cctt_context.q_topo_cnt != 0xFFFF) {
|
||
g_cctt_context.q_topo_cnt -= resp_cnt;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
void cctt_init(void)
|
||
{
|
||
g_cctt_context.plc_nw_state = PLC_NW_OPEN;
|
||
g_local_rs485.ready = false;
|
||
}
|
||
|
||
#endif /* PLC_SUPPORT_CCO_ROLE */
|