2024 lines
		
	
	
		
			70 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			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 */
 |