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

2024 lines
70 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_timer_api.h"
#include "os_utils_api.h"
#include "iot_app_api.h"
#include "iot_gpio_api.h"
#include "iot_adc_api.h"
#include "iot_board_api.h"
#include "iot_io_api.h"
#include "iot_task_api.h"
#include "iot_proto_dl645.h"
#include "iot_proto_ge.h"
#include "iot_edge_compute.h"
#include "iot_proto_modbus.h"
#include "iot_plc_msg_cco_api.h"
mcu_data_handle_t mcu_data_dl645;
extern uint8_t ge_buf[];
uint8_t g_dl645_local_mode_state = DL645_LOCAL_MODE_INIT;
proto_645_localmode_data_cache_t g_local_dl645_cache;
static uint8_t proto_645_any_addr[IOT_MAC_ADDR_LEN] =
{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA};
#if PLC_SUPPORT_STA_ROLE
static void iot_proto_645_handle_edge_resp(uint8_t *in_data,
uint16_t in_data_len, uint8_t type);
static uint8_t iot_edge_dl645_send_plc_msg(uint8_t *data, uint16_t len);
static uint8_t iot_sta_check_local_dl645_cmd(uint8_t *data_input,
uint32_t *di, uint8_t *mac);
static void iot_sta_handle_local_dl645_cmd(uint8_t *data_input,
uint16_t data_len, uint8_t fn, uint32_t di, uint8_t source,
uint8_t *req_mac);
#endif /* end PLC_SUPPORT_STA_ROLE */
extern void iot_common_bin_dump(uint8_t *data, uint32_t dlen);
/**
* @brief iot_proto_645_calc_cs() - To calculate a DL645 crc
* @param hdr: point to a proto_645_header_t struct
* @retval: the value of DL645 crc
*/
uint8_t iot_proto_645_calc_cs(proto_645_header_t *hdr)
{
uint8_t i, len, ret = 0;
uint8_t *data = (uint8_t *)hdr;
len = sizeof(*hdr) + hdr->len;
for (i = 0; i < len; i++){
ret += data[i];
}
return ret;
}
void iot_proto_dl645_read_addr(uint8_t *data)
{
proto_645_header_t *hdr = (proto_645_header_t*)data;
proto_645_tailer_t *tail = NULL;
hdr->start_char_1 = PROTO_645_START_CHAR;
iot_mac_addr_cpy(hdr->addr, proto_645_any_addr);
hdr->control.fn = PROTO_645_2007_FN_READ_ADDR;
hdr->len = 0;
hdr->start_char_2 = PROTO_645_START_CHAR;
tail = (proto_645_tailer_t*)hdr->data;
tail->cs = iot_proto_645_calc_cs(hdr);
tail->end_char = PROTO_645_END_CHAR;
}
void iot_proto_645_ext_add33_handle(uint8_t *ds, uint32_t size)
{
uint8_t *ptr = ds;
while (size--)
{
(*ptr++) += 0x33;
}
return;
}
void iot_proto_645_ext_sub33_handle(uint8_t *ds, uint32_t size)
{
uint8_t *ptr = ds;
while (size--)
{
(*ptr++) -= 0x33;
}
return;
}
uint32_t iot_proto_645_get_di_by_sub33(uint8_t *data, uint8_t len, uint32_t *di)
{
uint8_t di_t[DL645_DI_LEN] = {0};
if (len < DL645_DI_LEN) {
return ERR_FAIL;
}
os_mem_cpy(di_t, data, DL645_DI_LEN);
iot_proto_645_ext_sub33_handle(di_t, DL645_DI_LEN);
proto_645_2007_byte_to_di(di_t, *di);
return ERR_OK;
}
void iot_pack_dl645_to_ge(uint8_t *data_input, uint8_t *ge_data,
uint16_t *data_len, uint8_t *mac, bool_t b_conless)
{
uint16_t crc;
ge_frame_data_send_set_subfn160_t *data_frm;
ge_frm_tail_t *tail_frm;
data_frm = (ge_frame_data_send_set_subfn160_t *)ge_data;
data_frm->hdr.hdr.preamble = GE_FRM_PREAMBLE_CODE;
data_frm->hdr.hdr.data_len = *data_len + IOT_MAC_ADDR_LEN;
data_frm->hdr.hdr.fn = PROTO_GE_PLC_SET_CMD;
data_frm->hdr.subfn = PROTO_GE_DATA_CMD;
data_frm->force_tx_connless = b_conless;
data_frm->force_noaggr = 0;
data_frm->recv_connless = 0;
data_frm->resv = DL645_07_RESV0_RESV;
iot_mac_addr_cpy(&data_frm->dest_mac[0], mac);
if (data_input) {
os_mem_cpy(&data_frm->data[0], &data_input[0], *data_len);
}
crc = ge_frm_checksum_calc(ge_data, data_frm->hdr.hdr.data_len +
GE_FRM_CHECK_SUM_FIELD_POS);
tail_frm = (ge_frm_tail_t*)&data_frm->data[*data_len];
tail_frm->check_sum = crc;
tail_frm->tail = GE_FRM_TAIL_CODE;
*data_len = *data_len + sizeof(ge_frame_data_send_set_subfn160_t) +
sizeof(ge_frm_tail_t);
#if (IOT_GE_CKQ_MODE_ENABLE == 0)
iot_common_bin_dump(ge_data, *data_len);
#endif
}
/* init dl645 header, fill mac, ctrl ... */
void iot_proto_645_header_init(proto_645_header_t *hdr,
uint8_t *addr, uint8_t fn, uint8_t dir, uint8_t ack, uint8_t follow)
{
IOT_ASSERT(addr);
IOT_ASSERT(ack <= PROTO_645_2007_ERR_OTHER);
IOT_ASSERT(follow <= DL645_FOLLOW_AVAILABLE);
IOT_ASSERT(dir <= PROTO_645_DIR_SLAVE);
hdr->start_char_1 = PROTO_645_START_CHAR;
iot_mac_addr_cpy(hdr->addr, addr);
hdr->control.fn = fn;
hdr->control.dir = dir;
hdr->control.ack = ack;
hdr->control.follow = follow;
hdr->start_char_2 = PROTO_645_START_CHAR;
}
/* init dl645 tail, fill cs and end char */
void iot_proto_645_tail_init(proto_645_header_t *hdr)
{
uint8_t *data = hdr->data, len = hdr->len;
proto_645_tailer_t *tail = (proto_645_tailer_t*)(data + len);
tail->cs = iot_proto_645_calc_cs(hdr);
tail->end_char = PROTO_645_END_CHAR;
}
/**
* @brief iot_proto_645_build_resp_msg() dl645 pack response frame.
* @param hdr: point to data which should pack a frame.
* @param in_data: to fill in the data of 645 fram
* @param len: in_data len
* @param reason: error reason, 0 is no error
* @param fn: function control code
*/
void iot_proto_645_build_resp_msg(proto_645_header_t *hdr,
uint8_t *in_data, uint8_t len, uint8_t reason, uint8_t fn)
{
proto_645_header_t *dl645_frm = hdr;
uint8_t revert_mac[IOT_MAC_ADDR_LEN];
if (dl645_frm == NULL) {
return;
}
iot_mac_addr_cpy(revert_mac, prototask_contxt.local_dev.mac);
iot_mac_addr_reverse(revert_mac);
iot_proto_645_header_init(dl645_frm, revert_mac, fn, PROTO_645_DIR_SLAVE,
(reason == 0 ? PROTO_645_2007_ERR_OK : PROTO_645_2007_ERR_OTHER),
DL645_FOLLOW_INVALID);
if ((in_data != NULL) && (len != 0)) {
os_mem_cpy(dl645_frm->data, in_data, len);
dl645_frm->len = len;
} else if (reason) {
dl645_frm->data[0] = reason;
dl645_frm->len = sizeof(reason);
} else {
dl645_frm->len = 0;
}
iot_proto_645_ext_add33_handle(dl645_frm->data, dl645_frm->len);
iot_proto_645_tail_init(dl645_frm);
}
uint8_t iot_proto_645_frm_format_check(uint8_t *data, uint16_t len,
uint8_t *integrity)
{
uint8_t test_crc;
uint8_t err_code = 0;
proto_645_header_t *hdr_645 = NULL;
proto_645_tailer_t *tail_645 = NULL;
uint16_t dl645_len = 0;
uint8_t frame_check_result = GET_NO_FRAME;
if (data[0] != PROTO_645_START_CHAR) {
err_code = 1;
goto out;
}
if (len < PROTO_645_SECOND_HEAD_POS + 1) {
err_code = 2;
frame_check_result = GET_HALF_FRAME;
goto out;
}
hdr_645 = (proto_645_header_t*)data;
if (hdr_645->start_char_2 != PROTO_645_START_CHAR) {
err_code = 3;
goto out;
}
dl645_len = hdr_645->len + DL645_PARSE_FRM_MIN_LEN;
if (len < dl645_len) {
err_code = 4;
frame_check_result = GET_HALF_FRAME;
goto out;
}
tail_645 = (proto_645_tailer_t*)(data + sizeof(proto_645_header_t) +
hdr_645->len);
if (tail_645->end_char != PROTO_645_END_CHAR) {
err_code = 5;
goto out;
}
test_crc = iot_proto_645_calc_cs(hdr_645);
if (tail_645->cs != test_crc) {
iot_cus_printf("[DL645] crc:%02x\n", test_crc);
err_code = 6;
goto out;
}
frame_check_result = GET_ONE_FRAME;
if (len > dl645_len) {
err_code = 7;
}
out:
if (err_code > 0) {
iot_cus_printf("645_frm_check err_code:%x\n", err_code);
}
if (NULL != integrity) {
*integrity = frame_check_result;
}
return err_code;
}
#if PLC_SUPPORT_STA_ROLE
void iot_proto_edge_msg_output_msg_handler(uint8_t msg_id, void *arg)
{
void **p_data = NULL;
uint16_t data_len = 0;
edge_inner_time_info_t time_info;
edge_delay_time_info_inner_t *p_edge_time_inner;
if (arg != NULL) {
p_data = (void **)iot_pkt_data(arg);
data_len = iot_pkt_data_len(arg);
}
switch(msg_id) {
case EDGE_OUTPUT_STOPPED_ID:
{
greeapp->uart_com = *p_data;
iot_proto_resume_pkt_2_mainboard();
os_start_timer(prototask_contxt.edge_monitor_start_tmr,
prototask_contxt.flashinfo.public.pub.edge_start_tm);
break;
}
case EDGE_OUTPUT_DL645_PKT_ID:
{
iot_edge_dl645_send_plc_msg((uint8_t *)p_data, data_len);
break;
}
case EDGE_OUTPUT_RESP_CACHE_INFO_ID:
{
iot_proto_645_handle_edge_resp((uint8_t *)p_data, data_len,
EDGE_RESP_EDGE_CMD_INFO);
break;
}
case EDGE_OUTPUT_RESP_CACHE_CNT_ID:
{
iot_proto_645_handle_edge_resp((uint8_t *)p_data, data_len,
EDGE_RESP_EDGE_CMD_CNT);
break;
}
case EDGE_OUTPUT_RESP_DELAY_TIME_ID:
{
iot_proto_645_handle_edge_resp((uint8_t *)p_data, data_len,
EDGE_RESP_TIME_PARAM);
break;
}
case EDGE_OUTPUT_RESP_DELAY_TIME_INNER_ID:
{
p_edge_time_inner = (edge_delay_time_info_inner_t *)p_data;
time_info.cmd_starting_stopping_tm =
p_edge_time_inner->cmd_starting_stopping_tm;
time_info.cmd_each_tm = p_edge_time_inner->cmd_each_tm;
time_info.edge_start_tm =
prototask_contxt.flashinfo.public.pub.edge_start_tm;
iot_proto_645_handle_edge_resp((uint8_t *)&time_info,
sizeof(time_info), EDGE_RESP_TIME_PARAM_INNER);
break;
}
case EDGE_OUTPUT_RESP_BAUD_ID:
{
iot_proto_645_handle_edge_resp((uint8_t *)p_data, data_len,
EDGE_RESP_CMD_BAUD);
break;
}
default:
break;
}
if (arg != NULL) {
iot_pkt_free(arg);
}
}
/**
* @brief iot_edge_dl645_send_plc_msg() - dl645 send data to cco by PLC
* @param data: the data
* @param len: the len of the data
* @retval: true or false
*/
static uint8_t iot_edge_dl645_send_plc_msg(uint8_t *data, uint16_t len)
{
uint8_t ret = false;
protpkt_tx_info_t txinfo = { 0 };
if (data == NULL) {
ret = false;
goto out;
}
iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST, 0,
PROTO_UNICAST_RETRY_DEFAULT_INTVL, 1,
prototask_contxt.local_dev.mac, prototask_contxt.cco_dev.mac);
iot_proto_remote_cmd_send_to_plctxrx(data, len, &txinfo);
ret = true;
out:
return ret;
}
/* @brief iot_proto_send_dl645_ack() - send dl645 ack, from uart resp dl645,
* from plc resp ge + dl545
* @param fn: command ctrl
* @param reason error reason
* @param source source plc or uart
* @param dst_mac if plc resp dst mac
* @retval: success return 0, others error.
*/
static uint8_t iot_proto_send_dl645_ack(uint8_t fn, uint8_t reason,
uint8_t source, uint8_t *dst_mac)
{
uint8_t *pkt_data;
uint16_t pkt_len;
uint16_t dl645_len;
uint16_t fea0_hdr_len;
iot_pkt_t *pkt;
proto_645_header_t *dl645_frm;
protpkt_tx_info_t txinfo = { 0 };
fea0_hdr_len = sizeof(ge_frame_data_send_set_subfn160_t);
pkt_len = DL645_PARSE_FRM_MIN_LEN + (reason == 0 ? 0 : 1);
if (source == FROM_PLC) {
dl645_len = pkt_len;
pkt_len += sizeof(ge_frm_tail_t) + fea0_hdr_len;
}
pkt = iot_pkt_alloc(pkt_len, IOT_GREE_APP_MID);
if (!pkt) {
return 1;
}
pkt_data = iot_pkt_put(pkt, pkt_len);
if (source == FROM_PLC) {
dl645_frm = (proto_645_header_t *)(pkt_data + fea0_hdr_len);
iot_proto_645_build_resp_msg(dl645_frm, NULL, 0,
reason, fn);
iot_pack_dl645_to_ge(NULL, pkt_data, &dl645_len, dst_mac, false);
iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST, 0,
PROTO_UNICAST_RETRY_DEFAULT_INTVL, 1,
prototask_contxt.local_dev.mac, dst_mac);
iot_proto_remote_cmd_send_to_plctxrx(pkt_data, pkt_len, &txinfo);
iot_pkt_free(pkt);
} else {
iot_proto_645_build_resp_msg((proto_645_header_t *)pkt_data, NULL, 0,
reason, fn);
iot_proto_send_to_mainboard(pkt);
}
return 0;
}
void iot_proto_pack_data_to_dl645(uint8_t *data_input, uint8_t *dl645_data,
uint16_t *data_len, uint32_t di, uint8_t *mac, uint8_t fn, uint8_t dir)
{
proto_645_header_t *dl645_frm = NULL;
if (data_input == NULL || dl645_data == NULL) {
iot_cus_printf("%s data err!\n", __FUNCTION__);
return;
}
if (*data_len + DL645_DI_LEN > DL645_FRM_DATA_MAX_LEN) {
iot_cus_printf("%s out of max length\n", __FUNCTION__);
return;
}
dl645_frm = (proto_645_header_t *)dl645_data;
iot_proto_645_header_init(dl645_frm, mac, fn, dir, PROTO_645_2007_ERR_OK,
DL645_FOLLOW_INVALID);
dl645_frm->len = *data_len + DL645_DI_LEN;
proto_645_2007_di_to_byte(di, dl645_frm->data);
os_mem_cpy(dl645_frm->data + DL645_DI_LEN, data_input, (*data_len));
iot_proto_645_ext_add33_handle(dl645_frm->data, dl645_frm->len);
iot_proto_645_tail_init(dl645_frm);
*data_len = dl645_frm->len + DL645_PARSE_FRM_MIN_LEN;
}
/**
* @brief iot_proto_645_handle_edge_resp() - fill data to the data position
* of 645 frame,then packet into one ge frame, finally send the packet to PLC
* @param in_data: point to the data of the edge resp pkt
* @param in_data_len: the len of the in_data
* @param type: resp type
*/
static void iot_proto_645_handle_edge_resp(uint8_t *in_data,
uint16_t in_data_len, uint8_t type)
{
uint16_t pkt_len;
uint8_t ret = 0;
uint8_t *pkt_data, *dl645_data;
uint8_t dl645_data_len = 0;
uint16_t dl645_len, cmd_len;
uint32_t di;
iot_pkt_t *pkt = NULL;
uint8_t ge_data_pos = sizeof(ge_frame_data_send_set_subfn160_t);
proto_645_header_t *dl645_frm;
edge_cache_cmd_info_t *edge_cmd;
uint8_t revert_mac[IOT_MAC_ADDR_LEN];
dl645_data_len = DL645_DI_LEN + in_data_len;
if (type == EDGE_RESP_TIME_PARAM) {
di = DL645_07_DI_EDGE_TIME_PARAM;
} else if (type == EDGE_RESP_TIME_PARAM_INNER) {
di = DL645_07_DI_EDGE_TIME_PARAM_INNER;
} else if (type == EDGE_RESP_EDGE_CMD_CNT) {
di = DL645_07_DI_QUERY_EDGE_CMD_CNT;
} else if (type == EDGE_RESP_EDGE_CMD_INFO) {
dl645_data_len -= sizeof(edge_cache_cmd_info_t);
edge_cmd = (edge_cache_cmd_info_t *)in_data;
if (edge_cmd->cmd_type == EDGE_QUERY_EDGE_CMD_645) {
di = DL645_07_DI_EDGE_645_MIN_CMD + edge_cmd->idx;
} else if (edge_cmd->cmd_type == EDGE_QUERY_EDGE_CMD_MODBUS) {
di = DL645_07_DI_EDGE_MODBUS_MIN_CMD + edge_cmd->idx;
}
/* if edge response cmd data of the in_data, the dl645_data_len value
isn't only DL645_DI_LEN, otherwise only resp di */
if (dl645_data_len != DL645_DI_LEN) {
cmd_len = in_data_len - sizeof(edge_cache_cmd_info_t);
in_data += sizeof(edge_cache_cmd_info_t);
if (iot_proto_645_frm_format_check(edge_cmd->data, cmd_len, NULL) &&
iot_proto_modbus_frm_format_check(edge_cmd->data, cmd_len)) {
dl645_data_len = DL645_DI_LEN;
}
}
} else if (type == EDGE_RESP_CMD_BAUD) {
di = DL645_07_DI_EDGE_CMD_BAUD;
}
dl645_len = DL645_PARSE_FRM_MIN_LEN + dl645_data_len;
pkt_len = dl645_len + sizeof(ge_frm_tail_t) +
sizeof(ge_frame_data_send_set_subfn160_t);
pkt = iot_pkt_alloc(pkt_len, IOT_GREE_APP_MID);
if (!pkt) {
ret = 1;
goto out;
}
pkt_data = iot_pkt_put(pkt, pkt_len);
dl645_frm = (proto_645_header_t *)(pkt_data + ge_data_pos);
dl645_data = dl645_frm->data;
os_mem_cpy(dl645_data, &di, DL645_DI_LEN);
if (dl645_data_len > DL645_DI_LEN) {
os_mem_cpy(dl645_data + DL645_DI_LEN, in_data,
dl645_data_len - DL645_DI_LEN);
}
dl645_frm->len = dl645_data_len;
iot_mac_addr_cpy(revert_mac, prototask_contxt.local_dev.mac);
iot_mac_addr_reverse(revert_mac);
iot_proto_645_header_init(dl645_frm, revert_mac, PROTO_645_2007_FN_READ_DATA,
PROTO_645_DIR_SLAVE, PROTO_645_2007_ERR_OK, DL645_FOLLOW_INVALID);
iot_proto_645_ext_add33_handle(dl645_frm->data, dl645_frm->len);
iot_proto_645_tail_init(dl645_frm);
iot_pack_dl645_to_ge(NULL, pkt_data, &dl645_len,
prototask_contxt.cco_dev.mac, 0);
iot_edge_dl645_send_plc_msg(pkt_data, pkt_len);
iot_pkt_free(pkt);
out:
iot_cus_printf("645_handle_edge_resp ret:%x\n", ret);
}
/**
* @brief iot_resp_uart_mac_query() - To response the module read the mac
of device
* @param source: from uart or plc
* @param req_mac: the address represents where the cmd came from and the
* response data will be sent to
*/
static void iot_resp_uart_mac_query(uint8_t source, uint8_t *req_mac)
{
uint8_t revert_mac[IOT_MAC_ADDR_LEN], ret = 0;
uint16_t dl645_len = DL645_PARSE_FRM_MIN_LEN + IOT_MAC_ADDR_LEN;
uint8_t ge_data_pos = sizeof(ge_frame_data_send_set_subfn160_t);
iot_pkt_t *pkt;
uint8_t *pkt_data, data_pos = 0;
uint16_t pkt_len;
protpkt_tx_info_t txinfo = { 0 };
if ((source != FROM_PLC) && (source != FROM_UART)) {
ret = 1;
goto out;
}
if ((source == FROM_PLC) && (req_mac == NULL)) {
ret = 2;
goto out;
}
/* for cmd from uart pkt_len is dl645 frame length;
for cmd from plc, pkt_len is FEA0 length */
if (source == FROM_UART) {
pkt_len = dl645_len;
} else {
pkt_len = dl645_len + sizeof(ge_frm_tail_t) +
sizeof(ge_frame_data_send_set_subfn160_t);
data_pos = ge_data_pos;
}
pkt = iot_pkt_alloc(pkt_len, IOT_GREE_APP_MID);
if (!pkt) {
ret = 3;
goto out;
}
pkt_data = iot_pkt_put(pkt, pkt_len);
iot_mac_addr_cpy(revert_mac, prototask_contxt.local_dev.mac);
iot_mac_addr_reverse(revert_mac);
iot_proto_645_build_resp_msg((proto_645_header_t *)(pkt_data + data_pos),
revert_mac, IOT_MAC_ADDR_LEN, 0, PROTO_645_2007_FN_READ_ADDR);
if (source == FROM_UART) {
iot_proto_send_to_mainboard(pkt);
} else {
iot_pack_dl645_to_ge(NULL, pkt_data, &dl645_len, req_mac, false);
iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST, 0,
PROTO_UNICAST_RETRY_DEFAULT_INTVL, 1,
prototask_contxt.local_dev.mac, req_mac);
iot_proto_remote_cmd_send_to_plctxrx(pkt_data, pkt_len, &txinfo);
iot_pkt_free(pkt);
}
out:
iot_cus_printf("%s ret:%d\n", __FUNCTION__, ret);
}
/**
* @brief iot_proto_dl645_uart_set() - handle the uart set cmd from uart or plc
* @param dl645_data: point to the dl645 data field
* @param source: from uart or plc
* @param req_mac: the address represents where the cmd came from and the
* response data will be sent to
*/
static void iot_proto_dl645_uart_set(proto_645_set_uart_param_t *dl645_data,
uint8_t source, uint8_t *req_mac)
{
uint8_t ret = 0;
uint8_t reason = 0;
uint32_t baud_val[] = PROTO_GE_UART_BAUD_VALUE;
ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo;
if ((source != FROM_PLC) && (source != FROM_UART)) {
ret = 1;
goto out;
}
if ((source == FROM_PLC) && (req_mac == NULL)) {
ret = 2;
goto out;
}
if ((iot_proto_uart_param_check(dl645_data->baudrate, dl645_data->parity,
dl645_data->data_bit, dl645_data->stop_bit) == false) ||
(p_flash->public.pub.baudidx >= PROTO_GE_UART_BAUD_IDX_MAX)) {
ret = 3;
reason = DL645_ERR_PARAMETER_ERROR;
}
if (reason == 0) {
if ((baud_val[p_flash->public.pub.baudidx] != dl645_data->baudrate) ||
(p_flash->public.pub.parity != dl645_data->parity) ||
(p_flash->public.pub.data != dl645_data->data_bit) ||
(p_flash->public.pub.stop != dl645_data->stop_bit)) {
/* save uart param to flash */
p_flash->public.pub.baudidx =
uart_baud_find_index(dl645_data->baudrate);
p_flash->public.pub.parity = dl645_data->parity;
p_flash->public.pub.data = dl645_data->data_bit;
p_flash->public.pub.stop = dl645_data->stop_bit;
iot_proto_flashsave(p_flash);
}
}
if (iot_proto_send_dl645_ack(PROTO_645_2007_FN_WRITE_DATA, reason,
source, req_mac)) {
ret = 4;
}
out:
iot_cus_printf("%s ret:%d reason:%d\n", __FUNCTION__, ret, reason);
}
/**
* @brief iot_proto_dl645_resp_uart_param() - response uart param to plc
* @param di: dl645 DI
* @param source: from uart or plc
* @param req_mac: the address represents where the cmd came from and the
* response data will be sent to
*/
static void iot_proto_dl645_resp_uart_param(uint32_t di, uint8_t source,
uint8_t *req_mac)
{
uint8_t ret = 0;
uint16_t pkt_len;
uint8_t ge_data_pos = sizeof(ge_frame_data_send_set_subfn160_t);
uint16_t dl645_len = DL645_PARSE_FRM_MIN_LEN +
sizeof(proto_645_resp_uart_param_t);
uint8_t *pkt_data;
proto_645_header_t *dl645_frm;
iot_pkt_t *pkt;
protpkt_tx_info_t txinfo = { 0 };
uint32_t baud_val[] = PROTO_GE_UART_BAUD_VALUE;
ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo;
proto_645_resp_uart_param_t uart_param;
if ((source != FROM_PLC) || (NULL == req_mac)) {
ret = 1;
goto out;
}
pkt_len = dl645_len + sizeof(ge_frm_tail_t) +
sizeof(ge_frame_data_send_set_subfn160_t);
pkt = iot_pkt_alloc(pkt_len, IOT_GREE_APP_MID);
if (!pkt) {
ret = 2;
goto out;
}
uart_param.di = di;
uart_param.baudrate = baud_val[p_flash->public.pub.baudidx];
uart_param.parity = p_flash->public.pub.parity;
uart_param.data_bit = p_flash->public.pub.data;
uart_param.stop_bit = p_flash->public.pub.stop;
pkt_data = iot_pkt_put(pkt, pkt_len);
dl645_frm = (proto_645_header_t *)(pkt_data+ge_data_pos);
iot_proto_645_build_resp_msg(dl645_frm, (uint8_t *)&uart_param,
sizeof(uart_param), 0, PROTO_645_2007_FN_READ_DATA);
iot_pack_dl645_to_ge(NULL, pkt_data, &dl645_len, req_mac, 0);
iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST, 0,
PROTO_UNICAST_RETRY_DEFAULT_INTVL, 1,
prototask_contxt.local_dev.mac, req_mac);
iot_proto_remote_cmd_send_to_plctxrx(pkt_data, pkt_len, &txinfo);
iot_pkt_free(pkt);
out:
iot_cus_printf("%s ret:%d\n", __FUNCTION__, ret);
}
/**
* @brief iot_proto_dl645_write_vout() - handle the power ctrl set cmd from plc
* @param dl645_data: point to the dl645 data field
* @param source: from uart or plc
* @param req_mac: the address represents where the cmd came from and the
* response data will be sent to
*/
static void iot_proto_dl645_write_vout(proto_645_write_vout_param_t *dl645_data,
uint8_t source, uint8_t *req_mac)
{
uint8_t ret = 0;
uint8_t reason = 0;
if ((source != FROM_PLC) || (req_mac == NULL)) {
ret = 1;
goto out;
}
if (((dl645_data->v3p3_on_off == 0) && (dl645_data->v12_on_off == 0)) ||
((dl645_data->v3p3_on_off != HPLC_3P0_JY_VOUT_ON) &&
(dl645_data->v3p3_on_off != HPLC_3P0_JY_VOUT_OFF)) ||
((dl645_data->v12_on_off != HPLC_3P0_JY_VOUT_ON) &&
(dl645_data->v12_on_off != HPLC_3P0_JY_VOUT_OFF))) {
ret = 2;
reason = DL645_ERR_PARAMETER_ERROR;
}
if (!reason) {
if(dl645_data->v3p3_on_off == HPLC_3P0_JY_VOUT_ON) {
iot_gpio_value_set(HPLC_3P0_JY_EN_OUT3V3_PIN , 1);
iot_cus_printf("enable 3.3v output\n");
} else if (dl645_data->v3p3_on_off == HPLC_3P0_JY_VOUT_OFF) {
iot_gpio_value_set(HPLC_3P0_JY_EN_OUT3V3_PIN , 0);
iot_cus_printf("disable 3.3v output\n");
}
if (dl645_data->v12_on_off == HPLC_3P0_JY_VOUT_ON) {
iot_gpio_value_set(HPLC_3P0_JY_EN_OUT12V_PIN , 1);
iot_cus_printf("enable 12v output\n");
} else if (dl645_data->v12_on_off == HPLC_3P0_JY_VOUT_OFF) {
iot_gpio_value_set(HPLC_3P0_JY_EN_OUT12V_PIN , 0);
iot_cus_printf("disable 12v output\n");
}
}
if (iot_proto_send_dl645_ack(PROTO_645_2007_FN_WRITE_DATA, reason,
source, req_mac)) {
ret = 3;
}
out:
iot_cus_printf("%s ret:%d reason:%d\n", __FUNCTION__, ret, reason);
}
/**
* @brief iot_proto_dl645_resp_vout() - response power ctrl status to plc
* @param di: dl645 DI
* @param source: from uart or plc
* @param req_mac: the address represents where the cmd came from and the
* response data will be sent to
*/
static void iot_proto_dl645_resp_vout(uint32_t di, uint8_t source,
uint8_t *req_mac)
{
uint8_t ret = 0, err_3v3 = 0, err_12v = 0;
uint16_t pkt_len;
uint8_t ge_data_pos = sizeof(ge_frame_data_send_set_subfn160_t);
uint16_t dl645_len = DL645_PARSE_FRM_MIN_LEN +
sizeof(proto_645_resp_vol_info_t);
uint8_t *pkt_data;
proto_645_header_t *dl645_frm;
iot_pkt_t *pkt;
int v3p3_level = 0, v12_level = 0;
protpkt_tx_info_t txinfo = { 0 };
proto_645_resp_vol_info_t vol_info;
int32_t v3 = 0;
int32_t v12 = 0;
if ((source != FROM_PLC) || (NULL == req_mac)) {
ret = 1;
goto out;
}
pkt_len = dl645_len + sizeof(ge_frm_tail_t) +
sizeof(ge_frame_data_send_set_subfn160_t);
pkt = iot_pkt_alloc(pkt_len, IOT_GREE_APP_MID);
if (!pkt) {
ret = 2;
goto out;
}
vol_info.di = di;
iot_gpio_output_value_get(HPLC_3P0_JY_EN_OUT3V3_PIN, &v3p3_level);
vol_info.v3p3_on_off =
(v3p3_level == 0) ? HPLC_3P0_JY_VOUT_OFF : HPLC_3P0_JY_VOUT_ON;
v3 = iot_adc_poll_done(ADC_CHANNEL0, ADC_ACC16, ADC_GAIN_3V, &err_3v3);
iot_gpio_output_value_get(HPLC_3P0_JY_EN_OUT12V_PIN, &v12_level);
vol_info.v12_on_off =
(v12_level == 0) ? HPLC_3P0_JY_VOUT_OFF : HPLC_3P0_JY_VOUT_ON;
v12 = iot_adc_poll_done(ADC_CHANNEL4, ADC_ACC16, ADC_GAIN_3V, &err_12v);
iot_cus_printf("adc 3v3[%d %d] 12v[%d %d]\n", err_3v3, v3, err_12v, v12);
if (err_3v3 == 0) {
/* calc volt to 100mv */
v3 = v3 * HPLC_3P0_JY_VOUT3V3_RATE * 32 / 511;
/* for half adjusting */
vol_info.v3p3_vol = (uint8_t)(v3 + 0.5);
} else {
vol_info.v3p3_vol = HPLC_3P0_JY_INVALID_VOL;
}
if (err_12v == 0) {
/* calc volt to 100mv */
v12 = v12 * HPLC_3P0_JY_VOUT12V_RATE * 32 / 511;
/* for half adjusting */
vol_info.v12_vol = (uint8_t)(v12 + 0.5);
} else {
vol_info.v12_vol = HPLC_3P0_JY_INVALID_VOL;
}
iot_cus_printf("calc 3v3[%d %d %d] 12v[%d %d %d]\n", err_3v3, v3,
vol_info.v3p3_vol, err_12v, v12, vol_info.v12_vol);
pkt_data = iot_pkt_put(pkt, pkt_len);
dl645_frm = (proto_645_header_t *)(pkt_data+ge_data_pos);
iot_proto_645_build_resp_msg(dl645_frm, (uint8_t *)&vol_info,
sizeof(vol_info), 0, PROTO_645_2007_FN_READ_DATA);
iot_pack_dl645_to_ge(NULL, pkt_data, &dl645_len, req_mac, 0);
iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST, 0,
PROTO_UNICAST_RETRY_DEFAULT_INTVL, 1,
prototask_contxt.local_dev.mac, req_mac);
iot_proto_remote_cmd_send_to_plctxrx(pkt_data, pkt_len, &txinfo);
iot_pkt_free(pkt);
out:
iot_cus_printf("%s ret:%x\n", __FUNCTION__, ret);
}
/**
* @brief iot_proto_dl645_resp_boot_info() - response boot info to plc
* @param di: dl645 DI
* @param source: from uart or plc
* @param req_mac: the address represents where the cmd came from and the
* response data will be sent to
*/
static void iot_proto_dl645_resp_boot_info(uint32_t di, uint8_t source,
uint8_t *req_mac)
{
uint8_t ret = 0;
uint16_t pkt_len;
uint8_t ge_data_pos = sizeof(ge_frame_data_send_set_subfn160_t);
uint16_t dl645_len = DL645_PARSE_FRM_MIN_LEN +
sizeof(proto_645_resp_boot_info_t);
uint8_t *pkt_data;
proto_645_header_t *dl645_frm;
iot_pkt_t *pkt;
protpkt_tx_info_t txinfo = { 0 };
proto_645_resp_boot_info_t boot_info = { 0 };
if ((source != FROM_PLC) || (NULL == req_mac)) {
ret = 1;
goto out;
}
pkt_len = dl645_len + sizeof(ge_frm_tail_t) +
sizeof(ge_frame_data_send_set_subfn160_t);
pkt = iot_pkt_alloc(pkt_len, IOT_GREE_APP_MID);
if (!pkt) {
ret = 2;
goto out;
}
boot_info.di = di;
iot_board_get_boot_reason(&boot_info.last_reboot_reason);
boot_info.total_boot_cnt = iot_board_get_reset_count(SYSTEM_RESET_PWR) +
iot_board_get_reset_count(SYSTEM_RESET_WDT) +
iot_board_get_reset_count(SYSTEM_RESET_SOFT);
pkt_data = iot_pkt_put(pkt, pkt_len);
dl645_frm = (proto_645_header_t *)(pkt_data+ge_data_pos);
iot_proto_645_build_resp_msg(dl645_frm, (uint8_t *)&boot_info,
sizeof(boot_info), 0, PROTO_645_2007_FN_READ_DATA);
iot_pack_dl645_to_ge(NULL, pkt_data, &dl645_len, req_mac, 0);
iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST, 0,
PROTO_UNICAST_RETRY_DEFAULT_INTVL, 1,
prototask_contxt.local_dev.mac, req_mac);
iot_proto_remote_cmd_send_to_plctxrx(pkt_data, pkt_len, &txinfo);
iot_pkt_free(pkt);
out:
iot_cus_printf("%s ret:%x\n", __FUNCTION__, ret);
}
/**
* @brief iot_proto_dl645_resp_monitor_signal() - response monitor_signal to plc
* @param di: dl645 DI
* @param source: from uart or plc
* @param req_mac: the address represents where the cmd came from and the
* response data will be sent to
*/
static void iot_proto_dl645_resp_monitor_signal(uint32_t di, uint8_t source,
uint8_t *req_mac)
{
uint8_t ret = 0, level = 0;
uint16_t pkt_len;
uint8_t ge_data_pos = sizeof(ge_frame_data_send_set_subfn160_t);
uint16_t dl645_len = DL645_PARSE_FRM_MIN_LEN +
sizeof(proto_645_resp_monitor_signal_t);
uint8_t *pkt_data;
proto_645_header_t *dl645_frm;
iot_pkt_t *pkt;
protpkt_tx_info_t txinfo = { 0 };
proto_645_resp_monitor_signal_t monitor = { 0 };
if ((source != FROM_PLC) || (NULL == req_mac)) {
ret = 1;
goto out;
}
pkt_len = dl645_len + sizeof(ge_frm_tail_t) +
sizeof(ge_frame_data_send_set_subfn160_t);
pkt = iot_pkt_alloc(pkt_len, IOT_GREE_APP_MID);
if (!pkt) {
ret = 2;
goto out;
}
monitor.di = di;
level = iot_gpio_value_get(HPLC_3P0_JY_MONITOR_PIN);
monitor.signal =
(level == 0) ? HPLC_3P0_JY_MONITOR_CLOSE : HPLC_3P0_JY_MONITOR_OPEN;
pkt_data = iot_pkt_put(pkt, pkt_len);
dl645_frm = (proto_645_header_t *)(pkt_data+ge_data_pos);
iot_proto_645_build_resp_msg(dl645_frm, (uint8_t *)&monitor,sizeof(monitor),
0, PROTO_645_2007_FN_READ_DATA);
iot_pack_dl645_to_ge(NULL, pkt_data, &dl645_len, req_mac, 0);
iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST, 0,
PROTO_UNICAST_RETRY_DEFAULT_INTVL, 1,
prototask_contxt.local_dev.mac, req_mac);
iot_proto_remote_cmd_send_to_plctxrx(pkt_data, pkt_len, &txinfo);
iot_pkt_free(pkt);
out:
iot_cus_printf("%s ret:%d\n", __FUNCTION__, ret);
}
/**
* @brief iot_proto_dl645_close_hw_wdg() - disable hardware watchdog
* @param dl645_data: pointer of dlt645 data field
* @param source: from uart or plc
* @param req_mac: the address represents where the cmd came from and the
* response data will be sent to
*/
static void iot_proto_dl645_close_hw_wdg(proto_645_close_hw_wdg_t *dl645_data,
uint8_t source, uint8_t *req_mac)
{
uint8_t ret = 0;
uint8_t reason = 0;
if ((source != FROM_PLC) || (NULL == req_mac)) {
ret = 1;
goto out;
}
if (dl645_data->close_wdg != HPLC_3P0_JY_CLOSE_HW_WDG) {
reason = DL645_ERR_PARAMETER_ERROR;
} else {
prototask_contxt.hw_watchdog_en = 0;
}
if (iot_proto_send_dl645_ack(PROTO_645_2007_FN_WRITE_DATA, reason,
source, req_mac)) {
ret = 2;
}
out:
iot_cus_printf("%s ret:%d reason:%d\n", __FUNCTION__, ret, reason);
}
/**
* @brief iot_proto_dl645_set_edge_cmd_time() - dl645 set edge cmd inverval time
* and total time
* @param dl645_data: point to the 645 frame
* @param source: from uart or plc
* @param req_mac: the address represents where the cmd came from and the
* response data will be sent to
*/
static void iot_proto_dl645_set_edge_cmd_time(
proto_645_set_edge_time_t *dl645_data, uint8_t source, uint8_t *req_mac)
{
uint8_t ret = 0;
uint8_t reason = 0;
edge_delay_time_info_t time_info;
if ((source != FROM_PLC) || (NULL == req_mac)) {
ret = 1;
goto out;
}
if ((dl645_data->cmd_inverval >= EDGE_CMD_INTERVE_MIN) &&
(dl645_data->cmd_inverval <= EDGE_CMD_INTERVE_MAX) &&
(dl645_data->cmd_tol_tm >= UART_RX_MAX_TIMEOUT_MIN) &&
(dl645_data->cmd_tol_tm <= UART_RX_MAX_TIMEOUT_MAX)) {
time_info.cmd_inverval = dl645_data->cmd_inverval;
time_info.cmd_tol_tm = dl645_data->cmd_tol_tm;
} else {
ret = 2;
reason = DL645_ERR_PARAMETER_ERROR;
}
if (iot_proto_send_dl645_ack(PROTO_645_2007_FN_WRITE_DATA, reason,
source, req_mac)) {
ret = 3;
}
if (!reason) {
proto_post_data_to_edge_msg_handle(EDGE_INPUT_SET_DELAY_TIME_ID,
&time_info, sizeof(edge_delay_time_info_t));
}
out:
iot_cus_printf("%s ret:%d reason:%d\n", __FUNCTION__, ret, reason);
}
/**
* @brief iot_proto_dl645_set_edge_cmd_time_inner() - dl645 set edge start time、
* starting_stopping time and each rx timeout
* @param dl645_data: point to the 645 frame
* @param source: from uart or plc
* @param req_mac: the address represents where the cmd came from and the
* response data will be sent to
*/
static void iot_proto_dl645_set_edge_cmd_time_inner(
proto_645_set_edge_time_inner_t *dl645_data, uint8_t source,
uint8_t *req_mac)
{
uint8_t ret = 0, reason = 0;
edge_delay_time_info_inner_t time_info;
ge_app_pib_info_t *p_flash = &prototask_contxt.flashinfo;
if ((source != FROM_PLC) || (NULL == req_mac)) {
ret = 1;
goto out;
}
if ((dl645_data->time_info.edge_start_tm >= UART_MONITOR_START_MIN) &&
(dl645_data->time_info.edge_start_tm <= UART_MONITOR_START_MAX) &&
(dl645_data->time_info.cmd_starting_stopping_tm >=
EDGE_STARTING_STOPPING_MIN) &&
(dl645_data->time_info.cmd_starting_stopping_tm <=
EDGE_STARTING_STOPPING_MAX) &&
(dl645_data->time_info.cmd_each_tm >= UART_RX_TIMEOUT_MIN) &&
(dl645_data->time_info.cmd_each_tm <= UART_RX_TIMEOUT_MAX)) {
p_flash->public.pub.edge_start_tm =
dl645_data->time_info.edge_start_tm;
time_info.cmd_starting_stopping_tm =
dl645_data->time_info.cmd_starting_stopping_tm;
time_info.cmd_each_tm = dl645_data->time_info.cmd_each_tm;
} else {
ret = 2;
reason = DL645_ERR_PARAMETER_ERROR;
}
if (iot_proto_send_dl645_ack(PROTO_645_2007_FN_WRITE_DATA, reason,
source, req_mac)) {
ret = 3;
}
if (!reason) {
/* cmd_starting_stopping_tm and cmd_each_tm are send to edge,
edge_start_tm is saved in proto parameter list */
proto_post_data_to_edge_msg_handle(EDGE_INPUT_SET_DELAY_TIME_INNER_ID,
&time_info, sizeof(edge_delay_time_info_inner_t));
/* save edge_start_tm to pib */
iot_proto_flashsave(p_flash);
}
out:
iot_cus_printf("%s ret:%d reason:%d\n", __FUNCTION__, ret, reason);
}
/**
* @brief iot_proto_dl645_query_edge_cmd_time() - dl645 query edge cmd inverval
* time and total time
* @param source: from uart or plc
*/
static void iot_proto_dl645_query_edge_cmd_time(uint8_t source)
{
uint8_t ret = 0;
if (source != FROM_PLC) {
ret = 1;
goto out;
}
proto_post_data_to_edge_msg_handle(EDGE_INPUT_QUERY_DELAY_TIME_ID, NULL, 0);
out:
iot_cus_printf("query_edge_cmd_time ret:%x\n", ret);
}
/**
* @brief iot_proto_dl645_query_edge_cmd_time_inner() - dl645 query edge cmd
start time、starting stopping time
and each overtime
* @param source: from uart or plc
*/
static void iot_proto_dl645_query_edge_cmd_time_inner(uint8_t source)
{
uint8_t ret = 0;
if (source != FROM_PLC) {
ret = 1;
goto out;
}
proto_post_data_to_edge_msg_handle(EDGE_INPUT_QUERY_DELAY_TIME_INNER_ID, NULL, 0);
out:
iot_cus_printf("query_edge_cmd_time_inner ret:%x\n", ret);
}
static void iot_proto_dl645_query_edge_cmd_cnt(uint8_t source)
{
uint8_t ret = 0;
if (source != FROM_PLC) {
ret = 1;
goto out;
}
proto_post_data_to_edge_msg_handle(EDGE_INPUT_QUERY_CACHE_CNT_ID, NULL, 0);
out:
iot_cus_printf("query_edge_cmd_cnt ret:%x\n", ret);
}
/**
* @brief iot_proto_dl645_query_edge_cmd_baud() - dl645 query edge cmd baud
* @param source: from uart or plc
*/
static void iot_proto_dl645_query_edge_cmd_baud(uint8_t source)
{
uint8_t ret = 0;
if (source != FROM_PLC) {
/* only handle plc query command */
ret = 1;
goto out;
}
proto_post_data_to_edge_msg_handle(EDGE_INPUT_QUERY_BAUD_ID, NULL, 0);
out:
iot_cus_printf("query_edge_baud ret:%d\n", ret);
}
static void iot_proto_dl645_set_edge_cmd(proto_645_edge_dev_cmd_t *dl645_data,
uint16_t frm_len, uint32_t di, uint8_t source, uint8_t *req_mac)
{
uint8_t ret = 0, idx = 0;
uint8_t reason = 0;
uint16_t pkt_len, data_len;
int16_t cmd_len;
iot_pkt_t *cmd_pkt = NULL;
edge_cache_cmd_info_t *cmd_data;
if ((source != FROM_PLC) || (NULL == req_mac)) {
ret = 1;
goto out;
}
if ((di >= DL645_07_DI_EDGE_645_MIN_CMD) &&
(di <= DL645_07_DI_EDGE_645_MAX_CMD)) {
idx = di - DL645_07_DI_EDGE_645_MIN_CMD;
} else if ((di >= DL645_07_DI_EDGE_MODBUS_MIN_CMD) &&
(di <= DL645_07_DI_EDGE_MODBUS_MAX_CMD)) {
idx = di - DL645_07_DI_EDGE_MODBUS_MIN_CMD;
}
data_len = frm_len - DL645_PARSE_FRM_MIN_LEN;
cmd_len = data_len - sizeof(proto_645_edge_dev_cmd_t);
if (cmd_len < 0) {
reason = DL645_ERR_PARAMETER_ERROR;
} else if (cmd_len == 0) {
/* delete edge command */
proto_post_data_to_edge_msg_handle(EDGE_INPUT_DEL_CACHE_ID,
NULL, 0);
} else {
/* add edge command */
if (iot_proto_645_frm_format_check(&dl645_data->data[0], cmd_len, NULL) &&
iot_proto_modbus_frm_format_check(&dl645_data->data[0], cmd_len)) {
/* modbus or dl645 format error */
ret = 2;
reason = DL645_ERR_PARAMETER_ERROR;
} else {
pkt_len = cmd_len + sizeof(edge_cache_cmd_info_t);
cmd_pkt = iot_pkt_alloc(pkt_len, IOT_GREE_APP_MID);
if (!cmd_pkt) {
ret = 3;
goto out;
}
cmd_data = (edge_cache_cmd_info_t *)iot_pkt_put(cmd_pkt, pkt_len);
cmd_data->idx = idx;
os_mem_cpy(cmd_data->data, &dl645_data->data[0], cmd_len);
proto_post_data_to_edge_msg_handle(EDGE_INPUT_ADD_CACHE_ID,
cmd_data, pkt_len);
iot_pkt_free(cmd_pkt);
}
}
if (iot_proto_send_dl645_ack(PROTO_645_2007_FN_WRITE_DATA,
reason, source, req_mac)) {
ret = 4;
}
out:
iot_cus_printf("%s ret:%d reason:%d\n", __FUNCTION__, ret, reason);
}
static void iot_proto_dl645_query_edge_cmd(uint32_t di, uint8_t source)
{
uint8_t ret = 0;
edge_cache_cmd_info_t cmd_data;
if (source != FROM_PLC) {
ret = 1;
goto out;
}
if ((di >= DL645_07_DI_EDGE_645_MIN_CMD) &&
(di <= DL645_07_DI_EDGE_645_MAX_CMD)) {
cmd_data.cmd_type = EDGE_QUERY_EDGE_CMD_645;
cmd_data.idx = di - DL645_07_DI_EDGE_645_MIN_CMD;
} else if ((di >= DL645_07_DI_EDGE_MODBUS_MIN_CMD) &&
(di <= DL645_07_DI_EDGE_MODBUS_MAX_CMD)) {
cmd_data.cmd_type = EDGE_QUERY_EDGE_CMD_MODBUS;
cmd_data.idx = di - DL645_07_DI_EDGE_MODBUS_MIN_CMD;
}
proto_post_data_to_edge_msg_handle(EDGE_INPUT_QUERY_CACHE_INFO_ID,
&cmd_data, sizeof(edge_cache_cmd_info_t));
out:
iot_cus_printf("%s ret:%d\n", __FUNCTION__, ret);
}
/**
* @brief iot_proto_dl645_set_edge_cmd_baud() - dl645 set edge cmd baud
* @param dl645_data: point to the 645 frame
* @param source: from uart or plc
* @param req_mac: the address represents where the cmd came from and the
* response data will be sent to
*/
static void iot_proto_dl645_set_edge_cmd_baud(
proto_645_edge_dev_cmd_t *dl645_data, uint16_t cmd_len,
uint8_t source, uint8_t *req_mac)
{
uint8_t i;
uint8_t cnt;
uint8_t ret = 0;
uint8_t reason = 0;
edge_baud_cmd_t *edge_cmd;
cnt = (uint8_t)(*dl645_data->data);
if ((source != FROM_PLC) || (NULL == req_mac)) {
ret = 1;
goto out;
}
cmd_len -= sizeof(proto_645_edge_dev_cmd_t);
if (cnt == 0 || cnt > EDGECOM_MAX_CMD) {
reason = DL645_ERR_PARAMETER_ERROR;
goto err;
}
if (cmd_len != cnt * sizeof(edge_baud_cmd_t) + sizeof(uint8_t)) {
iot_cus_printf("%s length error cnt:%d\n", __FUNCTION__, cnt);
reason = DL645_ERR_PARAMETER_ERROR;
goto err;
}
edge_cmd = (edge_baud_cmd_t*)(dl645_data->data + sizeof(uint8_t));
/* check param */
for (i = 0; i < cnt; i++) {
if (edge_cmd->index == 0 || edge_cmd->index > EDGECOM_MAX_CMD) {
/* check cmd index */
reason = DL645_ERR_PARAMETER_ERROR;
break;
}
if (edge_cmd->baud_info.baud_idx >= EDGE_BAUD_IDX_CNT) {
/* check cmd baud */
reason = DL645_ERR_PARAMETER_ERROR;
break;
}
if (edge_cmd->baud_info.parity > IOT_UART_PARITY_SPACE) {
/* check cmd parity */
reason = DL645_ERR_PARAMETER_ERROR;
break;
}
edge_cmd++;
}
err:
if (iot_proto_send_dl645_ack(PROTO_645_2007_FN_WRITE_DATA,
reason, source, req_mac)) {
ret = 2;
}
if (!reason) {
proto_post_data_to_edge_msg_handle(EDGE_INPUT_SET_BAUD_ID,
dl645_data->data, cmd_len);
}
out:
iot_cus_printf("%s ret:%d reason:%d\n", __FUNCTION__, ret, reason);
}
static uint8_t iot_proto_645_local_mode_cache(proto_645_header_t *data_645)
{
uint32_t di;
uint8_t revert_mac[IOT_MAC_ADDR_LEN];
uint8_t pos;
uint16_t dl645_len;
iot_mac_addr_cpy(revert_mac, data_645->addr);
iot_mac_addr_reverse(revert_mac);
proto_645_2007_byte_to_di(data_645->data, di);
dl645_len = data_645->len + DL645_PARSE_FRM_MIN_LEN;
/* tail +1 to get memory before storage the input data */
g_local_dl645_cache.tail++;
if (g_local_dl645_cache.tail >= DL645_LOCALMODE_CACHE_MAX_NUM) {
g_local_dl645_cache.tail = 0;
}
/* when tail equal to head means the cache is full, head +1 to free the
earliest data*/
if (g_local_dl645_cache.tail == g_local_dl645_cache.head) {
g_local_dl645_cache.head++;
if (g_local_dl645_cache.head >= DL645_LOCALMODE_CACHE_MAX_NUM) {
g_local_dl645_cache.head = 0;
}
}
/* cache the 645 data on tail */
pos = g_local_dl645_cache.tail;
iot_cus_printf("meter data save to pos[%d], di=%08X, "
"mac=[%02x%02x%02x%02x%02x%02x]\n", pos, di, revert_mac[0],
revert_mac[1], revert_mac[2], revert_mac[3], revert_mac[4],
revert_mac[5]);
g_local_dl645_cache.meter_data[pos].di = di;
iot_mac_addr_cpy(g_local_dl645_cache.meter_data[pos].mac, revert_mac);
iot_proto_645_ext_add33_handle(data_645->data, data_645->len);
os_mem_cpy(g_local_dl645_cache.meter_data[pos].data, data_645, dl645_len);
return ERR_OK;
}
static uint8_t* iot_proto_645_local_mode_lookup(uint32_t di, uint8_t *mac)
{
uint8_t i;
uint8_t cache_size;
uint8_t pos;
iot_cus_printf("look for meter data: di=%08X, "
"mac=[%02x%02x%02x%02x%02x%02x]\n", di, mac[0], mac[1], mac[2], mac[3],
mac[4], mac[5]);
/* to get the size of used cache, the array is regard as a circular fifo */
if (g_local_dl645_cache.tail >= g_local_dl645_cache.head) {
cache_size = g_local_dl645_cache.tail - g_local_dl645_cache.head;
} else {
cache_size = g_local_dl645_cache.tail + DL645_LOCALMODE_CACHE_MAX_NUM -
g_local_dl645_cache.head;
}
/* we should look up the cache from head to tail */
for (i = 0; i < (cache_size + 1); i++) {
pos = g_local_dl645_cache.head + i;
if (pos >= DL645_LOCALMODE_CACHE_MAX_NUM) {
pos -= DL645_LOCALMODE_CACHE_MAX_NUM;
}
if (di == g_local_dl645_cache.meter_data[pos].di &&
iot_mac_addr_cmp(mac, g_local_dl645_cache.meter_data[pos].mac)) {
iot_cus_printf("meter data found in pos[%d]\n", pos);
return (uint8_t *)g_local_dl645_cache.meter_data[pos].data;;
}
}
iot_cus_printf("local meter data not found\n");
return NULL;
}
/**
* @brief iot_proto_645_local_mode_cmd_start() - handle the local read mode
entry cmd
*/
static void iot_proto_645_local_mode_cmd_start(void)
{
g_dl645_local_mode_state = DL645_LOCAL_MODE_STARTED;
iot_cus_printf("dl645_local_read_mode[%d]\n",
g_dl645_local_mode_state);
os_start_timer(prototask_contxt.dl645_localmode_tmr,
PROTO_TMR_645_LOCAL_READ_MODE_INTVL);
}
/**
* @brief iot_proto_645_ckq_req_handle() - handle the meter read cmd where
* came frome ckq in local read mode
* @param hdr: pointer to the integral 645 frame
*/
static void iot_proto_645_ckq_req_handle(proto_645_header_t *hdr)
{
proto_645_header_t *ext_645_hdr = hdr;
proto_645_header_t *cmd_645_hdr = NULL;
proto_645_header_t *local_645 = NULL;
proto_645_header_t *ind_645 = NULL;
uint16_t frm_645_len = 0;
uint8_t dst_mac[IOT_MAC_ADDR_LEN];
uint32_t cmd_di = 0;
uint8_t cmd_mac[IOT_MAC_ADDR_LEN];
iot_pkt_t *pkt = NULL;
uint16_t pkt_len = 0;
uint8_t *pkt_data = NULL;
protpkt_tx_info_t txinfo = { 0 };
if (ext_645_hdr->len < (DL645_PARSE_FRM_MIN_LEN + DL645_DI_LEN)) {
iot_cus_printf("%s length of cmd err!\n", __FUNCTION__);
return;
}
iot_mac_addr_cpy(dst_mac, ext_645_hdr->addr);
iot_mac_addr_reverse(dst_mac);
cmd_645_hdr = (proto_645_header_t *)(ext_645_hdr->data + DL645_DI_LEN);
iot_mac_addr_cpy(cmd_mac, cmd_645_hdr->addr);
iot_mac_addr_reverse(cmd_mac);
iot_proto_645_ext_sub33_handle(cmd_645_hdr->data, cmd_645_hdr->len);
proto_645_2007_byte_to_di(cmd_645_hdr->data, cmd_di);
if (iot_sta_check_local_dl645_cmd((uint8_t *)cmd_645_hdr, &cmd_di,
cmd_mac)) {
/* handle the local dl645 cmd from ckq */
iot_cus_printf("handle local cmd from ckq[%02x:%02x:%02x:%02x:%02x:"
"%02x]\n", cmd_mac[0], cmd_mac[1], cmd_mac[2], cmd_mac[3],
cmd_mac[4], cmd_mac[5]);
iot_sta_handle_local_dl645_cmd((uint8_t *)cmd_645_hdr,
ext_645_hdr->len - DL645_DI_LEN, cmd_645_hdr->control.fn, cmd_di,
FROM_PLC, dst_mac);
return;
}
/* handle all the dl645 cmd except local dl645 cmd from ckq */
local_645 = (proto_645_header_t *)iot_proto_645_local_mode_lookup(cmd_di,
cmd_mac);
if (local_645 != NULL) {
frm_645_len = local_645->len + DL645_PARSE_FRM_MIN_LEN;
pkt_len = frm_645_len + sizeof(ge_frm_tail_t) +
sizeof(ge_frame_data_send_set_subfn160_t);
if (pkt_len > GE_FRM_MAX_LEN) {
iot_cus_printf("%s out of max length of ge frame!\n", __FUNCTION__);
return;
}
pkt = iot_pkt_alloc(pkt_len, IOT_GREE_APP_MID);
if (pkt == NULL) {
iot_cus_printf("%s pkt alloc err!\n", __FUNCTION__);
return;
}
pkt_data = iot_pkt_put(pkt, pkt_len);
iot_pack_dl645_to_ge((uint8_t *)local_645, pkt_data, &frm_645_len,
dst_mac, true);
} else {
frm_645_len = DL645_NACK_FRM_LEN;
pkt_len = frm_645_len + sizeof(ge_frm_tail_t) +
sizeof(ge_frame_data_send_set_subfn160_t);
pkt = iot_pkt_alloc(pkt_len, IOT_GREE_APP_MID);
if (pkt == NULL) {
iot_cus_printf("%s pkt alloc err!\n", __FUNCTION__);
return;
}
pkt_data = iot_pkt_put(pkt, pkt_len);
ind_645 = (proto_645_header_t *)(pkt_data +
sizeof(ge_frame_data_send_set_subfn160_t));
iot_proto_645_build_resp_msg(ind_645, NULL, 0 ,DL645_ERR_NO_REQ_DATA,
PROTO_645_2007_FN_READ_DATA);
iot_pack_dl645_to_ge(NULL, pkt_data, &frm_645_len, dst_mac, true);
}
if (pkt) {
iot_proto_fill_txinfo(&txinfo, true, PLCTXRX_UNICAST,
PROTO_UNICAST_RETRY_DEFAULT_CNT,
PROTO_UNICAST_RETRY_DEFAULT_INTVL, 1,
prototask_contxt.local_dev.mac, dst_mac);
txinfo.force_tx_connless = true;
iot_proto_remote_cmd_send_to_plctxrx(pkt_data, pkt_len, &txinfo);
iot_pkt_free(pkt);
}
}
/**
* @brief iot_sta_check_local_dl645_cmd() - check it is a local cmd or not
* @param data_input: point to the dl645 data
* @param di: point to the dl645 di and get it out if it exist
* @param mac: point to the mac of dl645 cmd
* @retval: local or not
*/
static uint8_t iot_sta_check_local_dl645_cmd(uint8_t *data_input,
uint32_t *di, uint8_t *mac)
{
uint8_t ret = false;
proto_645_header_t *hdr_645 = ( proto_645_header_t *)data_input;
iot_cus_printf("local hdr_645->control.fn = %x\n", hdr_645->control.fn);
switch (hdr_645->control.fn) {
case PROTO_645_2007_FN_READ_DATA:
{
proto_645_2007_byte_to_di(hdr_645->data, *di);
iot_cus_printf("local check di = %x\n", *di);
if ((iot_sta_check_local_645_di(*di) &&
iot_mac_addr_cmp(mac, prototask_contxt.local_dev.mac)) ||
iot_sta_check_local_mode_645_di(*di)) {
ret = true;
}
break;
}
case PROTO_645_2007_FN_READ_ADDR:
{
if (iot_mac_addr_cmp(mac, proto_645_any_addr) ||
iot_mac_addr_cmp(mac, prototask_contxt.local_dev.mac)) {
ret = true;
}
if (hdr_645->control.dir == PROTO_645_DIR_SLAVE &&
!prototask_contxt.macaddr_set) {
/* set module mac after recv response mac */
ret = true;
}
break;
}
case PROTO_645_2007_FN_WRITE_DATA:
{
proto_645_2007_byte_to_di(hdr_645->data, *di);
iot_cus_printf("local write data di = %x\n", *di);
if (iot_sta_check_local_645_di(*di) &&
iot_mac_addr_cmp(mac, prototask_contxt.local_dev.mac)) {
ret = true;
}
break;
}
default:
/* TO DO */
break;
}
return ret;
}
/**
* @brief iot_sta_handle_local_dl645_cmd() - handle the local sta cmd
* @param data_input: point to the dl645 data
* @param data_len: length of the dl645 frame
* @param fn: control.fn of dl645 cmd
* @param di: the dl645 di if it exist
* @param source: from uart or plc
* @param req_mac: the address represents where the cmd came from and the
* response data will be sent to
*/
static void iot_sta_handle_local_dl645_cmd(uint8_t *data_input,
uint16_t data_len, uint8_t fn, uint32_t di, uint8_t source, uint8_t *req_mac)
{
proto_645_header_t *hdr_645;
uint8_t *dst_mac = req_mac;
if ((FROM_UART == source) && (NULL != dst_mac) ){
dst_mac = NULL;
}
if (NULL != dst_mac) {
iot_cus_printf("Response DI[0x%08X] fn[0x%02x] will be sent "
"to[%02x:%02x:%02x:%02x:%02x:%02x]\n", di, fn, req_mac[0],
req_mac[1], req_mac[2], req_mac[3], req_mac[4], req_mac[5]);
}
switch (fn) {
case PROTO_645_2007_FN_READ_DATA:
{
hdr_645 = (proto_645_header_t *)data_input;
if (di == DL645_07_DI_CKQ_MODE_READ) {
iot_proto_645_ckq_req_handle(hdr_645);
} else if (DL645_07_DI_UART_PARAM == di) {
iot_proto_dl645_resp_uart_param(di, source, dst_mac);
} else if (DL645_07_DI_QUERY_BOOT_INFO == di) {
iot_proto_dl645_resp_boot_info(di, source, dst_mac);
}
if (CUS_BOARD_ID_LEDC_V3_0 == iot_board_get_board_id() &&
iot_hwver_is_ledc_v3_0_jy()) {
if (DL645_07_DI_CTRL_VOUT == di) {
iot_proto_dl645_resp_vout(di, source, dst_mac);
} else if (DL645_07_DI_READ_MONITOR_SIGNAL == di) {
iot_proto_dl645_resp_monitor_signal(di, source, dst_mac);
} else if (DL645_07_DI_EDGE_TIME_PARAM == di) {
iot_proto_dl645_query_edge_cmd_time(source);
} else if (DL645_07_DI_QUERY_EDGE_CMD_CNT == di) {
iot_proto_dl645_query_edge_cmd_cnt(source);
} else if (((di >= DL645_07_DI_EDGE_645_MIN_CMD) &&
(di <= DL645_07_DI_EDGE_645_MAX_CMD)) ||
((di >= DL645_07_DI_EDGE_MODBUS_MIN_CMD) &&
(di <= DL645_07_DI_EDGE_MODBUS_MAX_CMD))) {
iot_proto_dl645_query_edge_cmd(di, source);
} else if (DL645_07_DI_EDGE_TIME_PARAM_INNER == di) {
iot_proto_dl645_query_edge_cmd_time_inner(source);
} else if (DL645_07_DI_EDGE_CMD_BAUD == di) {
iot_proto_dl645_query_edge_cmd_baud(source);
}
}
break;
}
case PROTO_645_2007_FN_READ_ADDR:
{
hdr_645 = (proto_645_header_t *)data_input;
if (hdr_645->control.dir == PROTO_645_DIR_MASTER) {
iot_resp_uart_mac_query(source, dst_mac);
} else {
if (!prototask_contxt.macaddr_set) {
/* moudle has already got the meter's addres by this frame
set moudle address same as meter's */
iot_mac_addr_reverse(hdr_645->addr);
iot_proto_set_mac(hdr_645->addr, 0, false);
iot_proto_boot_ready_ind(hdr_645->addr);
}
}
break;
}
case PROTO_645_2007_FN_WRITE_DATA:
{
hdr_645 = (proto_645_header_t *)data_input;
if (di == DL645_07_DI_UART_PARAM) {
iot_proto_dl645_uart_set((proto_645_set_uart_param_t *)hdr_645->data,
source, dst_mac);
}
if (CUS_BOARD_ID_LEDC_V3_0 == iot_board_get_board_id() &&
iot_hwver_is_ledc_v3_0_jy()) {
if (DL645_07_DI_CTRL_VOUT == di) {
iot_proto_dl645_write_vout((proto_645_write_vout_param_t *)
hdr_645->data, source, dst_mac);
} else if (DL645_07_DI_CLOSE_HW_WATCHDOG == di) {
iot_proto_dl645_close_hw_wdg((proto_645_close_hw_wdg_t *)
hdr_645->data, source, dst_mac);
} else if (DL645_07_DI_EDGE_TIME_PARAM == di) {
iot_proto_dl645_set_edge_cmd_time((proto_645_set_edge_time_t *)
hdr_645->data, source, dst_mac);
} else if (((di >= DL645_07_DI_EDGE_645_MIN_CMD) &&
(di <= DL645_07_DI_EDGE_645_MAX_CMD)) ||
((di >= DL645_07_DI_EDGE_MODBUS_MIN_CMD) &&
(di <= DL645_07_DI_EDGE_MODBUS_MAX_CMD))) {
iot_proto_dl645_set_edge_cmd((proto_645_edge_dev_cmd_t *)
hdr_645->data, data_len, di, source, dst_mac);
} else if (DL645_07_DI_EDGE_TIME_PARAM_INNER == di) {
iot_proto_dl645_set_edge_cmd_time_inner(
(proto_645_set_edge_time_inner_t *)hdr_645->data,
source, dst_mac);
} else if (DL645_07_DI_EDGE_CMD_BAUD == di) {
iot_proto_dl645_set_edge_cmd_baud(
(proto_645_edge_dev_cmd_t *)hdr_645->data, hdr_645->len,
source, dst_mac);
}
}
break;
}
default:
/* TO DO */
break;
}
}
uint8_t iot_handle_ge_to_dl645(uint8_t *data_input, uint8_t *data_output)
{
ge_frame_data_send_set_subfn160_t *data_hdr =
(ge_frame_data_send_set_subfn160_t *)data_input;
proto_645_header_t *hdr_645 = (proto_645_header_t *)data_hdr->data;
/* the start position of dl645 data in the ge frame */
uint8_t dl645_data_pos = sizeof(ge_frame_data_send_set_subfn160_t) +
sizeof(proto_645_header_t) + DL645_DI_LEN;
/* length of ge data */
uint8_t ge_data_len = data_hdr->hdr.hdr.data_len - IOT_MAC_ADDR_LEN;
/* length of dl645 data */
uint8_t dl645_data_len = hdr_645->len - DL645_DI_LEN;
uint32_t di = 0;
uint8_t revert_mac[IOT_MAC_ADDR_LEN];
uint8_t *dst = prototask_contxt.cco_dev.mac;
if (hdr_645->control.dir == PROTO_645_DIR_SLAVE) {
dl645_data_len = 0;
iot_cus_printf("the dir of cmd is error, the cmd wont be handled\n");
goto out;
}
iot_mac_addr_cpy(revert_mac, hdr_645->addr);
iot_mac_addr_reverse(revert_mac);
iot_proto_645_ext_sub33_handle(hdr_645->data, hdr_645->len);
if (iot_sta_check_local_dl645_cmd((uint8_t *)hdr_645, &di, revert_mac)) {
iot_sta_handle_local_dl645_cmd((uint8_t *)hdr_645, ge_data_len,
hdr_645->control.fn, di, FROM_PLC, dst);
dl645_data_len = 0;
} else if ((iot_mac_addr_cmp(revert_mac, prototask_contxt.local_dev.mac)) &&
((hdr_645->control.fn == PROTO_645_2007_FN_READ_DATA)) &&
iot_sta_check_extend_645_di(di)) {
os_mem_cpy(data_output, &data_input[dl645_data_pos],
dl645_data_len);
} else if ((hdr_645->control.fn == PROTO_645_2007_FN_READ_DATA) &&
di == DL645_07_DI_CKQ_READ_MODE_EN) {
os_mem_cpy(data_output, &data_input[dl645_data_pos],
dl645_data_len);
iot_proto_645_local_mode_cmd_start();
} else {
iot_proto_645_ext_add33_handle(hdr_645->data, hdr_645->len);
os_mem_cpy(data_output, data_hdr->data, ge_data_len);
dl645_data_len = ge_data_len;
}
out:
return dl645_data_len;
}
uint8_t iot_sta_pack_extend_dl645_to_ge(uint8_t *data_input,
uint8_t *ge_data, uint16_t *data_len, uint8_t protcotype)
{
uint8_t dl645_frame_len;
uint8_t dl645_crc;
uint8_t addr_reverse[IOT_MAC_ADDR_LEN];
uint16_t ge_crc;
proto_645_header_t *dl645_frm =
(proto_645_header_t *)&ge_data[GE_FEA0_HEAD_LEN];
ge_frame_data_send_set_subfn160_t *ge_frm;
ge_frm_tail_t *tail_frm;
iot_mac_addr_cpy(addr_reverse, prototask_contxt.local_dev.mac);
iot_mac_addr_reverse(addr_reverse);
dl645_frm->start_char_1 = PROTO_645_START_CHAR;
dl645_frm->start_char_2 = PROTO_645_START_CHAR;
iot_mac_addr_cpy(dl645_frm->addr, addr_reverse);
dl645_frm->control.fn = PROTO_645_2007_FN_READ_DATA;
dl645_frm->control.dir = PROTO_645_DIR_SLAVE;
dl645_frm->len = *data_len + DL645_DI_LEN;
dl645_frame_len = dl645_frm->len + DL645_PARSE_FRM_MIN_LEN;
if (protcotype == MODBUS_TYPE) {
proto_645_2007_di_to_byte(DL645_07_DI_MODBUS_TYPE, dl645_frm->data);
} else if (protcotype == DL645_TYPE) {
proto_645_2007_di_to_byte(DL645_07_DI_DL645_TYPE, dl645_frm->data);
} else {
iot_cus_printf("%s:the protcotype is not support:\n", __FUNCTION__);
return 1;
}
os_mem_cpy(dl645_frm->data + DL645_DI_LEN, data_input, *data_len);
iot_proto_645_ext_add33_handle(dl645_frm->data, dl645_frm->len);
dl645_crc = iot_proto_645_calc_cs(dl645_frm);
dl645_frm->data[dl645_frm->len] = dl645_crc;
dl645_frm->data[dl645_frm->len + 1] = PROTO_645_END_CHAR;
ge_frm = (ge_frame_data_send_set_subfn160_t *)ge_data;
ge_frm->hdr.hdr.preamble = GE_FRM_PREAMBLE_CODE;
ge_frm->hdr.hdr.data_len = dl645_frame_len + IOT_MAC_ADDR_LEN;
ge_frm->hdr.hdr.fn = PROTO_GE_PLC_SET_CMD;
ge_frm->hdr.subfn = PROTO_GE_DATA_CMD;
ge_frm->force_tx_connless = 0;
ge_frm->force_noaggr = 0;
ge_frm->recv_connless = 0;
ge_frm->resv = DL645_07_RESV0_RESV;
iot_mac_addr_cpy(&ge_frm->dest_mac[0], prototask_contxt.cco_dev.mac);
ge_crc = ge_frm_checksum_calc(ge_data, dl645_frame_len +
sizeof(ge_frame_data_send_set_subfn160_t));
tail_frm = (ge_frm_tail_t*)&ge_frm->data[dl645_frame_len];
tail_frm->check_sum = ge_crc;
tail_frm->tail = GE_FRM_TAIL_CODE;
*data_len = dl645_frame_len + sizeof(ge_frame_data_send_set_subfn160_t) +
sizeof(ge_frm_tail_t);
iot_cus_printf("iot_sta_pack_extend_dl645_to_ge:\n");
iot_common_bin_dump(ge_data, dl645_frame_len +
sizeof(ge_frame_data_send_set_subfn160_t) + sizeof(ge_frm_tail_t));
return 0;
}
#else
uint8_t iot_handle_cco_delay_tm_pack_ge_to_dl645(uint8_t *data_input,
uint8_t *data_output)
{
ge_frame_delay_time_subfn166_t *frame =
(ge_frame_delay_time_subfn166_t *)data_input;
proto_645_header_t * dl645_frm = (proto_645_header_t *)data_output;
uint8_t revert_mac[IOT_MAC_ADDR_LEN], dl645_frm_len;
ge_delay_tm_test_t tm_test;
if (data_input == NULL || data_output == NULL) {
iot_cus_printf("[err]%s data ptr is null\n", "delay tm");
return 0;
}
iot_mac_addr_cpy(revert_mac, frame->dest_mac);
iot_mac_addr_reverse(revert_mac);
tm_test = frame->tm_test;
dl645_frm->len = sizeof(ge_delay_tm_test_t) + DL645_DI_LEN;
dl645_frm_len = dl645_frm->len + sizeof(proto_645_header_t) +
sizeof(proto_645_tailer_t);
proto_645_2007_di_to_byte(DL645_07_DI_DELAYTIME, dl645_frm->data);
os_mem_cpy(dl645_frm->data + DL645_DI_LEN, (uint8_t *)&tm_test,
sizeof(ge_delay_tm_test_t));
iot_proto_645_header_init((proto_645_header_t *)dl645_frm, revert_mac,
PROTO_645_2007_FN_READ_DATA, PROTO_645_DIR_SLAVE, PROTO_645_2007_ERR_OK,
DL645_FOLLOW_INVALID);
iot_proto_645_ext_add33_handle(dl645_frm->data, dl645_frm->len);
iot_proto_645_tail_init(dl645_frm);
return dl645_frm_len;
}
void iot_proto_edge_msg_output_msg_handler(uint8_t msg_id, void *arg)
{
(void)msg_id;
if (arg != NULL) {
iot_pkt_free(arg);
}
}
/**
* @brief dl645_resp_cmd_ack() - dl645 query err、set cmd ack
* @param ctrl: read or write cmd
* @param err: error number,see DL645_ERR_XXX
*/
void dl645_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;
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 ;
}
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);
}
#endif /* PLC_SUPPORT_STA_ROLE */
uint8_t iot_proto_645_format_check(mcu_data_handle_t *recv_data,
uint8_t *pdata, uint16_t *ret_size, uint16_t *ge_len_out)
{
uint8_t test_crc;
uint8_t err_code;
uint8_t frame_check_result = GET_NO_FRAME;
uint8_t *data = &recv_data->data[recv_data->data_pos];
uint16_t ge_len = 0;
uint16_t dl645_len;
uint16_t len = recv_data->total_len - recv_data->data_pos;
proto_645_header_t *hdr_645 = NULL;
proto_645_tailer_t *tail_645 = NULL;
uint8_t revert_mac[IOT_MAC_ADDR_LEN];
uint32_t di = 0;
err_code = 0;
if (data[0] != PROTO_645_START_CHAR) {
err_code = 1;
goto out;
}
if (recv_data->data_pos == recv_data->total_len - 1) {
err_code = 2;
goto out;
}
if (len < PROTO_645_SECOND_HEAD_POS + 1) {
err_code = 3;
frame_check_result = GET_HALF_FRAME;
goto out;
}
hdr_645 = (proto_645_header_t*)data;
if (hdr_645->start_char_2 != PROTO_645_START_CHAR) {
err_code = 4;
goto out;
}
dl645_len = hdr_645->len + DL645_PARSE_FRM_MIN_LEN;
if (len < dl645_len) {
err_code = 5;
frame_check_result = GET_HALF_FRAME;
goto out;
}
tail_645 = (proto_645_tailer_t*)(data + sizeof(proto_645_header_t) +
hdr_645->len);
if (tail_645->end_char != PROTO_645_END_CHAR) {
err_code = 6;
goto out;
}
test_crc = iot_proto_645_calc_cs(hdr_645);
if (tail_645->cs != test_crc) {
iot_cus_printf("[glpr DL645] crc:%x", test_crc);
err_code = 7;
goto out;
}
/* here, the frame is ok */
ge_len = dl645_len;
iot_mac_addr_cpy(revert_mac, hdr_645->addr);
iot_mac_addr_reverse(revert_mac);
iot_proto_645_ext_sub33_handle(hdr_645->data, hdr_645->len);
#if PLC_SUPPORT_STA_ROLE
if (iot_sta_check_local_dl645_cmd((uint8_t *)hdr_645, &di, revert_mac)) {
iot_sta_handle_local_dl645_cmd((uint8_t *)hdr_645, dl645_len,
hdr_645->control.fn, di, FROM_UART, NULL);
ge_len = 0;
} else if (g_dl645_local_mode_state == DL645_LOCAL_MODE_STARTED) {
iot_proto_645_local_mode_cache(hdr_645);
ge_len = 0;
} else {
if (!iot_ge_buf_overflow_test(*ret_size, dl645_len +
sizeof(ge_frame_data_send_set_subfn160_t) +
sizeof(ge_frm_tail_t) + DL645_PARSE_FRM_MIN_LEN + DL645_DI_LEN)) {
frame_check_result = GET_OVERFLOW;
goto out;
}
if (!is_edge_running() &&
iot_mac_addr_cmp(revert_mac, prototask_contxt.local_dev.mac)) {
iot_proto_645_ext_add33_handle(hdr_645->data, hdr_645->len);
iot_pack_dl645_to_ge((uint8_t *)hdr_645, &pdata[*ret_size],
&ge_len, prototask_contxt.cco_dev.mac, false);
} else {
iot_proto_645_ext_add33_handle(hdr_645->data, hdr_645->len);
iot_sta_pack_extend_dl645_to_ge((uint8_t *)hdr_645,
&pdata[*ret_size], &ge_len, DL645_TYPE);
}
}
#else
(void)di;
if (iot_mac_addr_cmp(revert_mac, prototask_contxt.local_dev.mac)) {
// post msg to task handle
iot_proto_post_dl645_cmd_msg(data, dl645_len);
ge_len = 0;
} else {
proto_645_2007_byte_to_di(hdr_645->data, di);
if ((di == DL645_07_DI_DELAYTIME) &&
(hdr_645->control.fn == PROTO_645_2007_FN_READ_DATA)) {
iot_proto_post_dl645_cmd_msg(data, dl645_len);
ge_len = 0;
} else if (iot_ge_buf_overflow_test(*ret_size, dl645_len +
sizeof(ge_frame_data_send_set_subfn160_t) +
sizeof(ge_frm_tail_t))) {
iot_proto_645_ext_add33_handle(hdr_645->data, hdr_645->len);
iot_pack_dl645_to_ge((uint8_t *)hdr_645, &pdata[*ret_size],
&ge_len, revert_mac, false);
} else {
frame_check_result = GET_OVERFLOW;
goto out;
}
}
#endif /* PLC_SUPPORT_STA_ROLE */
*ret_size += ge_len;
*ge_len_out = dl645_len;
frame_check_result = GET_ONE_FRAME;
out:
if (err_code > 0) {
iot_cus_printf("err_code:%x\n", err_code);
}
if (frame_check_result == GET_OVERFLOW) {
iot_cus_printf("ge_buf is overflow, dl645, di = %d\n mac:\n", di);
iot_common_bin_dump(revert_mac, IOT_MAC_ADDR_LEN);
}
return frame_check_result;
}
#if PLC_SUPPORT_STA_ROLE
void iot_proto_645_local_mode_timer_handler(void)
{
g_dl645_local_mode_state = DL645_LOCAL_MODE_INIT;
iot_cus_printf("dl645_local_read_mode[%d]\n", g_dl645_local_mode_state);
/* clear the 645 cache */
os_mem_set(&g_local_dl645_cache, 0, sizeof(g_local_dl645_cache));
}
#endif /* PLC_SUPPORT_STA_ROLE */