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

739 lines
23 KiB
C

/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
/* os_ship header files */
#include "os_timer_api.h"
#include "os_utils_api.h"
/* iot common header files */
#include "iot_io_api.h"
#include "iot_module_api.h"
#include "iot_errno_api.h"
#include "iot_task_api.h"
#include "iot_pkt_api.h"
#include "iot_ipc_api.h"
#include "iot_sg_ext_api.h"
#include "iot_board_api.h"
#include "iot_oem_api.h"
#include "iot_plc_api.h"
#include "iot_mem_pool_api.h"
#include "iot_pkt_api.h"
#include "iot_proto_common.h"
#include "iot_proto_ge.h"
#include "iot_modbus_task.h"
#include "iot_modbus_ext.h"
#include "iot_gpio_api.h"
#define IOT_MODBUS_EXT_DATA_DUMP 1
#define IOT_MB_EXT_RESP_TIMER_PERIOD (2000) /* units:ms */
extern iot_mb_task_t mb_task;
mb_ext_cmd_current_t current_handle_cmd;
uint8_t mb_ext_gpio_config_flag = 0;
void iot_mb_ext_data_dump(uint8_t * buf, uint32_t len, uint32_t line)
{
#if IOT_MODBUS_EXT_DATA_DUMP
uint32_t i;
iot_printf("[mb_task]DUMP(%03d)@line:%d", len, line);
for (i = 0; i < len; i++) {
iot_printf(" %02X", buf[i]);
}
iot_printf("\n");
#endif
}
mb_extend_fn_hdr_t * iot_mb_ext_get_current_cmd_head()
{
return &(current_handle_cmd.hdr);
}
static uint8_t iot_mb_ext_resp_transmit(uint8_t * data, uint32_t len, mb_transmit_direction_e dir)
{
iot_pkt_t *p_pkt = NULL;
iot_mb_ext_data_dump(data, len, __LINE__);
/* response */
if (dir == MODBUS_CMD_FROM_UART) {
p_pkt = iot_pkt_alloc(len, IOT_MODBUS_MID);
if (NULL == p_pkt) {
iot_printf("[mb_ext][err]no mem@line %d\n", __LINE__);
IOT_ASSERT(0);
return false;
}
os_mem_cpy(iot_pkt_put(p_pkt, len), data, len);
iot_mb_task_msg_post_to_uart(mb_task.uart_h, p_pkt);
} else if (dir == MODBUS_CMD_FROM_PLC) {
p_pkt = iot_modbus_fn160_appdata_pack(data, len, 0, 1);
if (NULL == p_pkt) {
iot_printf("[mb_ext][err]no mem@line %d\n", __LINE__);
IOT_ASSERT(0);
return ERR_FAIL;
}
/* parser ge command and post to task */
iot_proto_data_parse_and_post(iot_pkt_data(p_pkt), iot_pkt_data_len(p_pkt),
iot_mb_task_post_uart_cmd, 0);
iot_pkt_free(p_pkt);
}
os_mem_set(&current_handle_cmd, 0, sizeof(current_handle_cmd));
if (os_is_timer_active(mb_task.mb_ext_resp_timer)) {
os_stop_timer(mb_task.mb_ext_resp_timer);
}
return ERR_OK;
}
uint8_t modbus_ext_set_resp_handler(iot_pkt_t *p_pkt_frame)
{
uint8_t ret = ERR_FAIL;
uint16_t crc16 = 0;
uint32_t data_len = 0;
ge_frame_cmd_cfm_set_subfn20_t *cfm = (ge_frame_cmd_cfm_set_subfn20_t *)
iot_pkt_data(p_pkt_frame);
mb_ext_frame_set_resp_t *mb_resp_frm = NULL;
iot_pkt_t *mb_resp_pkt = NULL;
if (mb_ext_gpio_config_flag) {
mb_ext_gpio_config_flag = 0;
goto out;
}
mb_extend_fn_hdr_t * cur_cmd = iot_mb_ext_get_current_cmd_head();
if ((cfm->result == ERR_OK) && ((cur_cmd->fn == MODBUS_EXT_SET_SINGLE_REG_FN)
|| (cur_cmd->fn == MODBUS_EXT_SET_MULTI_REG_FN))) {
data_len = sizeof(mb_ext_frame_set_resp_t);
mb_resp_pkt = iot_pkt_alloc(data_len, IOT_GREE_APP_MID);
IOT_ASSERT(mb_resp_pkt);
mb_resp_frm = (mb_ext_frame_set_resp_t*)iot_pkt_put(mb_resp_pkt,
sizeof(mb_ext_frame_set_resp_t));
os_mem_cpy(&(mb_resp_frm->hdr), &(current_handle_cmd.hdr),
sizeof(mb_extend_fn_hdr_t));
mb_resp_frm->data = current_handle_cmd.data;
crc16 = iot_modbus_rtu_crc16((uint8_t*)mb_resp_frm, data_len - 2);
mb_resp_frm->tail.check_sum = crc16;
iot_mb_ext_resp_transmit((uint8_t*)mb_resp_frm, data_len,
current_handle_cmd.dir);
iot_pkt_free(mb_resp_pkt);
ret = ERR_OK;
}
return ret;
out:
return ERR_OK;
}
uint8_t modbus_ext_aid_query_resp_handler(iot_pkt_t *p_pkt_frame)
{
uint8_t ret = ERR_FAIL;
uint16_t crc16 = 0;
uint32_t data_len = 0;
ge_frame_nid_resp_subfn16_t *resp_cmd = (ge_frame_nid_resp_subfn16_t *)
iot_pkt_data(p_pkt_frame);
iot_pkt_t *mb_resp_pkt = NULL;
mb_ext_frame_aid_query_resp_t* mb_resp_frm = NULL;
mb_extend_fn_hdr_t * cur_cmd = iot_mb_ext_get_current_cmd_head();
if ((cur_cmd->fn == MODBUS_EXT_QUERY_FN) &&
(big_little_swap16(cur_cmd->reg_addr) == AID_QUERY_RA)) {
data_len = sizeof(mb_ext_frame_aid_query_resp_t);
mb_resp_pkt = iot_pkt_alloc(data_len, IOT_GREE_APP_MID);
IOT_ASSERT(mb_resp_pkt);
mb_resp_frm = (mb_ext_frame_aid_query_resp_t*)iot_pkt_put(mb_resp_pkt,
sizeof(mb_ext_frame_aid_query_resp_t));
mb_resp_frm->adapt_id = big_little_swap16(resp_cmd->nid);
mb_resp_frm->sa = current_handle_cmd.hdr.sa;
mb_resp_frm->fn = current_handle_cmd.hdr.fn;
mb_resp_frm->data_len = sizeof(*mb_resp_frm) - 5;
crc16 = iot_modbus_rtu_crc16((uint8_t*)mb_resp_frm, data_len - 2);
mb_resp_frm->tail.check_sum = crc16;
iot_mb_ext_resp_transmit((uint8_t*)mb_resp_frm, data_len,
current_handle_cmd.dir);
iot_pkt_free(mb_resp_pkt);
ret = ERR_OK;
}
return ret;
}
uint8_t modbus_ext_gpio_query_resp_handler(iot_pkt_t *p_pkt_frame)
{
uint8_t ret = ERR_FAIL;
uint16_t crc16 = 0;
uint32_t data_len = 0;
ge_frame_query_gpio_resp_subfn27_t *resp_cmd =
(ge_frame_query_gpio_resp_subfn27_t *)iot_pkt_data(p_pkt_frame);
mb_ext_frame_gpio_query_resp_t* mb_resp_frm = NULL;
data_len = sizeof(mb_ext_frame_gpio_query_resp_t);
mb_extend_fn_hdr_t * cur_cmd = iot_mb_ext_get_current_cmd_head();
if ((cur_cmd->fn == MODBUS_EXT_QUERY_FN) &&
(big_little_swap16(cur_cmd->reg_addr) >= GPIO_QUERY_BASE_RA)) {
iot_pkt_t *mb_resp_pkt = NULL;
mb_resp_pkt = iot_pkt_alloc(data_len, IOT_GREE_APP_MID);
IOT_ASSERT(mb_resp_pkt);
mb_resp_frm = (mb_ext_frame_gpio_query_resp_t*)iot_pkt_put(mb_resp_pkt,
sizeof(mb_ext_frame_gpio_query_resp_t));
mb_resp_frm->gpio_value = big_little_swap16(resp_cmd->value);
mb_resp_frm->sa = current_handle_cmd.hdr.sa;
mb_resp_frm->fn = current_handle_cmd.hdr.fn;
mb_resp_frm->data_len = sizeof(*mb_resp_frm) - 5;
crc16 = iot_modbus_rtu_crc16((uint8_t*)mb_resp_frm, data_len - 2);
mb_resp_frm->tail.check_sum = crc16;
iot_mb_ext_resp_transmit((uint8_t*)mb_resp_frm, data_len,
current_handle_cmd.dir);
iot_pkt_free(mb_resp_pkt);
ret = ERR_OK;
}
return ret;
}
uint8_t iot_mb_ext_handle_resp_from_ge(iot_pkt_t *p_pkt_frame)
{
ge_extend_fn_hdr_t *hdr = (ge_extend_fn_hdr_t *)iot_pkt_data(p_pkt_frame);
if ((hdr->hdr.fn == PROTO_GE_PLC_SET_CMD) &&
(hdr->subfn == PROTO_CMD_CFM_CMD)) {
if (ERR_OK == modbus_ext_set_resp_handler(p_pkt_frame)) {
goto out;
}
} else if ((hdr->hdr.fn == PROTO_GE_PLC_RESP_CMD) &&
(hdr->subfn == PROTO_NID_QUERY_CMD)) {
if (ERR_OK == modbus_ext_aid_query_resp_handler(p_pkt_frame)) {
goto out;
}
} else if ((hdr->hdr.fn == PROTO_GE_PLC_RESP_CMD) &&
(hdr->subfn == PROTO_GE_GPIO_QUERY_CMD)) {
if (ERR_OK == modbus_ext_gpio_query_resp_handler(p_pkt_frame)) {
goto out;
}
}
return ERR_FAIL;
out:
return ERR_OK;
}
void iot_mb_ext_resp_cmd_timeout_or_failed()
{
if (os_is_timer_active(mb_task.mb_ext_resp_timer)) {
os_stop_timer(mb_task.mb_ext_resp_timer);
}
os_mem_set(&current_handle_cmd, 0, sizeof(current_handle_cmd));
return;
}
static uint8_t modbus_ext_gpio_config(uint8_t gpio_num, uint8_t dir_mode,
uint8_t pull_mode, uint8_t default_value)
{
ge_frame_gpio_config_subfn164_t *pack_frm = NULL;
uint32_t pack_frm_len = sizeof(ge_frame_gpio_config_subfn164_t);
iot_pkt_t *p_pkt = NULL;
uint16_t crc16 = 0;
p_pkt = iot_pkt_alloc(pack_frm_len, IOT_MODBUS_MID);
if (NULL == p_pkt) {
iot_printf("[mb_ext][err]no mem@line %d\n", __LINE__);
IOT_ASSERT(0);
return false;
}
/* pack ge frame. */
pack_frm = (ge_frame_gpio_config_subfn164_t *)iot_pkt_put(p_pkt, pack_frm_len);
pack_frm->hdr.hdr.preamble = 0xAAAA;
pack_frm->hdr.hdr.data_len = 0x11;
pack_frm->hdr.hdr.fn = PROTO_GE_PLC_SET_CMD;
pack_frm->hdr.subfn = PROTO_GE_GPIO_CONFIG_CMD;
pack_frm->seq = 0;
iot_mac_addr_cpy(pack_frm->dest_mac, mb_task.local_mac);
iot_mac_addr_cpy(pack_frm->src_mac, mb_task.local_mac);
pack_frm->gpio_num = gpio_num;
pack_frm->dir_mode = dir_mode;
pack_frm->pull_mode = pull_mode;
pack_frm->output_value = default_value;
crc16 = ge_frm_checksum_calc((uint8_t *)pack_frm, pack_frm_len - 3);
pack_frm->tail.check_sum = crc16;
pack_frm->tail.tail = GE_FRM_TAIL_CODE;
/* post ge command to ge task */
iot_proto_data_parse_and_post(iot_pkt_data(p_pkt), iot_pkt_data_len(p_pkt),
iot_mb_task_post_uart_cmd, 0);
iot_pkt_free(p_pkt);
return ERR_OK;
}
bool_t modbus_ext_aid_query_handler(uint8_t *data, uint8_t len,
mb_transmit_direction_e dir)
{
ge_frame_nid_query_subfn16_t *pack_frm = NULL;
uint32_t pack_frm_len = sizeof(ge_frame_nid_query_subfn16_t);
iot_pkt_t *p_pkt = NULL;
mb_ext_frame_aid_query_t *frm = (mb_ext_frame_aid_query_t *)data;
uint16_t crc16 = 0;
p_pkt = iot_pkt_alloc(pack_frm_len, IOT_MODBUS_MID);
if (NULL == p_pkt) {
iot_printf("[%s][err]no mem@line %d\n", __FUNCTION__, __LINE__);
IOT_ASSERT(0);
return false;
}
os_mem_cpy(&(current_handle_cmd.hdr), &(frm->hdr), sizeof(mb_extend_fn_hdr_t));
current_handle_cmd.data = frm->reg_count;
current_handle_cmd.dir = dir;
/* pack ge frame. */
pack_frm = (ge_frame_nid_query_subfn16_t *)iot_pkt_put(p_pkt, pack_frm_len);
pack_frm->hdr.hdr.preamble = 0xAAAA;
pack_frm->hdr.hdr.data_len = 0x01;
pack_frm->hdr.hdr.fn = PROTO_GE_PLC_QUERY_CMD;
pack_frm->hdr.subfn = PROTO_NID_QUERY_CMD;
pack_frm->seq = 0;
crc16 = ge_frm_checksum_calc((uint8_t *)pack_frm, pack_frm_len - 3);
pack_frm->tail.check_sum = crc16;
pack_frm->tail.tail = GE_FRM_TAIL_CODE;
/* post ge command to ge task */
iot_proto_data_parse_and_post(iot_pkt_data(p_pkt), iot_pkt_data_len(p_pkt),
iot_mb_task_post_uart_cmd, 0);
iot_pkt_free(p_pkt);
os_start_timer(mb_task.mb_ext_resp_timer, IOT_MB_EXT_RESP_TIMER_PERIOD);
return true;
}
static bool_t modbus_ext_sa_query_handler(uint8_t *data, uint8_t len,
mb_transmit_direction_e dir)
{
iot_pkt_t *p_pkt = NULL;
mb_ext_frame_sa_query_resp_t *resp_frm = NULL;
uint32_t resp_frm_len = sizeof(mb_ext_frame_sa_query_resp_t);
uint16_t crc16 = 0;
mb_ext_frame_sa_query_t *frm = (mb_ext_frame_sa_query_t *)data;
p_pkt = iot_pkt_alloc(resp_frm_len, IOT_MODBUS_MID);
if (NULL == p_pkt) {
iot_printf("[%s][err]no mem@line %d\n", __FUNCTION__, __LINE__);
IOT_ASSERT(0);
return false;
}
resp_frm = (mb_ext_frame_sa_query_resp_t *)iot_pkt_put(p_pkt, resp_frm_len);
resp_frm->sa = frm->hdr.sa;
resp_frm->fn = frm->hdr.fn;
resp_frm->data_len = 2;
resp_frm->slaver_addr = big_little_swap16(mb_task.slave_addr);
crc16 = iot_modbus_rtu_crc16((uint8_t*)resp_frm, resp_frm_len - 2);
resp_frm->tail.check_sum = crc16;
iot_mb_ext_resp_transmit((uint8_t*)resp_frm, resp_frm_len, dir);
iot_pkt_free(p_pkt);
return true;
}
bool_t modbus_ext_wl_item_count_query_handler(uint8_t *data,
uint8_t len, mb_transmit_direction_e dir)
{
(void)data;
(void)len;
(void)dir;
return true;
}
bool_t modbus_ext_wl_item_query_handler(uint8_t *data, uint8_t len,
mb_transmit_direction_e dir)
{
(void)data;
(void)len;
(void)dir;
return true;
}
static bool_t modbus_ext_gpio_query_handler(uint8_t *data, uint8_t len,
mb_transmit_direction_e dir)
{
ge_frame_gpio_query_subfn27_t *pack_frm = NULL;
uint32_t pack_frm_len = sizeof(ge_frame_gpio_query_subfn27_t);
iot_pkt_t *p_pkt = NULL;
mb_ext_frame_gpio_query_t *frm = (mb_ext_frame_gpio_query_t *)data;
uint16_t crc16 = 0, reg_addr = 0;
uint8_t gpio_num = 0xff;
reg_addr = big_little_swap16(frm->hdr.reg_addr);
if ((reg_addr - GPIO_QUERY_BASE_RA) % 8 != 0) {
goto param_err;
} else {
gpio_num = (reg_addr - GPIO_QUERY_BASE_RA) / 8;
//if (gpio_num >= GPIO_PIN_COUNT) {
// goto param_err;
//}
}
p_pkt = iot_pkt_alloc(pack_frm_len, IOT_MODBUS_MID);
if (NULL == p_pkt) {
iot_printf("[%s][err]no mem@line %d\n", __FUNCTION__, __LINE__);
IOT_ASSERT(0);
return false;
}
os_mem_cpy(&(current_handle_cmd.hdr), &(frm->hdr), sizeof(mb_extend_fn_hdr_t));
current_handle_cmd.data = frm->reg_count;
current_handle_cmd.dir = dir;
mb_ext_gpio_config_flag = 1;
modbus_ext_gpio_config(gpio_num, IOT_GE_GPIO_DIR_INPUT, IOT_GE_GPIO_PULL_NONE, 0);
/* pack ge frame. */
pack_frm = (ge_frame_gpio_query_subfn27_t *)iot_pkt_put(p_pkt, pack_frm_len);
pack_frm->hdr.hdr.preamble = 0xAAAA;
pack_frm->hdr.hdr.data_len = 0x0E;
pack_frm->hdr.hdr.fn = PROTO_GE_PLC_QUERY_CMD;
pack_frm->hdr.subfn = PROTO_GE_GPIO_QUERY_CMD;
pack_frm->seq = 0;
iot_mac_addr_cpy(pack_frm->dest_mac, mb_task.local_mac);
iot_mac_addr_cpy(pack_frm->src_mac, mb_task.local_mac);
pack_frm->gpio_num = gpio_num;
crc16 = ge_frm_checksum_calc((uint8_t *)pack_frm, pack_frm_len - 3);
pack_frm->tail.check_sum = crc16;
pack_frm->tail.tail = GE_FRM_TAIL_CODE;
/* post ge command to ge task */
iot_proto_data_parse_and_post(iot_pkt_data(p_pkt), iot_pkt_data_len(p_pkt),
iot_mb_task_post_uart_cmd, 0);
iot_pkt_free(p_pkt);
os_start_timer(mb_task.mb_ext_resp_timer, IOT_MB_EXT_RESP_TIMER_PERIOD);
return true;
param_err:
iot_printf("[%s][err]param err @line %d\n", __FUNCTION__, __LINE__);
return false;
}
static mb_fnhdl_tbl_t modbus_query_ra_tbl[] = {
#if PLC_SUPPORT_CCO_ROLE
{AID_QUERY_RA, modbus_ext_aid_query_handler, 0},
{WL_ITEM_COUNT_QUERY_RA, modbus_ext_wl_item_count_query_handler, 0},
{WL_ITEM_QUERY_BASE_RA, modbus_ext_wl_item_query_handler, 0},
#endif
{SA_QUERY_RA, modbus_ext_sa_query_handler, 0},
{GPIO_QUERY_BASE_RA, modbus_ext_gpio_query_handler, 0},
};
static bool_t iot_mb_ext_cmd_query_fn_handler(uint8_t *data,
uint8_t len, mb_transmit_direction_e dir)
{
uint8_t i, ret = ERR_FAIL;
uint16_t reg_addr = 0;
mb_extend_fn_hdr_t *mb_head = (mb_extend_fn_hdr_t *)data;
uint8_t fncode_hdlr_cnt =
sizeof(modbus_query_ra_tbl)/sizeof(mb_fnhdl_tbl_t);
MODBUS_FN_HANDLE handler = NULL;
reg_addr = big_little_swap16(mb_head->reg_addr);
for (i = 0; i < fncode_hdlr_cnt; i++) {
if (modbus_query_ra_tbl[i].cmdid == reg_addr) {
handler = modbus_query_ra_tbl[i].cmd_handle_fn;
break;
}
}
#if PLC_SUPPORT_CCO_ROLE
if (reg_addr > WL_ITEM_QUERY_BASE_RA) {
handler = modbus_ext_wl_item_query_handler;
}
#endif
if (reg_addr > GPIO_QUERY_BASE_RA) {
handler = modbus_ext_gpio_query_handler;
}
if (handler) {
ret = handler(data, len, dir);
ret = (ret == true)? ERR_OK: ERR_FAIL;
}
return ret;
}
bool_t modbus_ext_aid_set_handler(uint8_t *data, uint8_t len,
mb_transmit_direction_e dir)
{
ge_frame_cco_nid_set_subfn17_t *pack_frm = NULL;
uint32_t pack_frm_len = sizeof(ge_frame_cco_nid_set_subfn17_t);
iot_pkt_t *p_pkt = NULL;
mb_ext_frame_aid_set_t *frm = (mb_ext_frame_aid_set_t *)data;
uint16_t crc16 = 0;
p_pkt = iot_pkt_alloc(pack_frm_len, IOT_MODBUS_MID);
if (NULL == p_pkt) {
iot_printf("[mb_ext][err]no mem@line %d\n", __LINE__);
IOT_ASSERT(0);
return false;
}
os_mem_cpy(&(current_handle_cmd.hdr), &(frm->hdr), sizeof(mb_extend_fn_hdr_t));
current_handle_cmd.data = frm->adapt_id;
current_handle_cmd.dir = dir;
/* pack ge frame. */
pack_frm = (ge_frame_cco_nid_set_subfn17_t *)iot_pkt_put(p_pkt, pack_frm_len);
pack_frm->hdr.hdr.preamble = 0xAAAA;
pack_frm->hdr.hdr.data_len = 0X07;
pack_frm->hdr.hdr.fn = PROTO_GE_PLC_SET_CMD;
pack_frm->hdr.subfn = PROTO_CCO_NID_SET_CMD;
pack_frm->nid = (frm->adapt_id) >> 8;
pack_frm->seq = 0;
iot_mac_addr_cpy(pack_frm->mac, mb_task.local_mac);
crc16 = ge_frm_checksum_calc((uint8_t *)pack_frm, pack_frm_len - 3);
pack_frm->tail.check_sum = crc16;
pack_frm->tail.tail = GE_FRM_TAIL_CODE;
/* post ge command to ge task */
iot_proto_data_parse_and_post(iot_pkt_data(p_pkt), iot_pkt_data_len(p_pkt),
iot_mb_task_post_uart_cmd, 0);
iot_pkt_free(p_pkt);
os_start_timer(mb_task.mb_ext_resp_timer, IOT_MB_EXT_RESP_TIMER_PERIOD);
return true;
}
static bool_t modbus_ext_sa_set_handler(uint8_t *data, uint8_t len,
mb_transmit_direction_e dir)
{
mb_ext_frame_sa_set_t *frm = (mb_ext_frame_sa_set_t *)data;
uint8_t new_sa = (frm->slaver_addr) >> 8;
if (mb_task.slave_addr != new_sa) {
mb_task.slave_addr = new_sa;
}
iot_mb_ext_resp_transmit(data, len, dir);
return true;
}
bool_t modbus_ext_wl_set_handler(uint8_t *data, uint8_t len,
mb_transmit_direction_e dir)
{
(void)data;
(void)len;
(void)dir;
return true;
}
static bool_t modbus_ext_gpio_set_handler(uint8_t *data, uint8_t len,
mb_transmit_direction_e dir)
{
ge_frame_gpio_set_subfn165_t *pack_frm = NULL;
uint32_t pack_frm_len = sizeof(ge_frame_gpio_set_subfn165_t);
iot_pkt_t *p_pkt = NULL;
mb_ext_frame_gpio_set_t *frm = (mb_ext_frame_gpio_set_t *)data;
uint16_t crc16 = 0, reg_addr = 0;
uint8_t gpio_num = 0xff;
reg_addr = big_little_swap16(frm->hdr.reg_addr);
if ((reg_addr - GPIO_SET_BASE_RA) % 8 != 0) {
goto param_err;
} else {
gpio_num = (reg_addr - GPIO_SET_BASE_RA) / 8;
//if (gpio_num >= GPIO_PIN_COUNT) {
// goto param_err;
//}
}
p_pkt = iot_pkt_alloc(pack_frm_len, IOT_MODBUS_MID);
if (NULL == p_pkt) {
iot_printf("[%s][err]no mem@line %d\n", __FUNCTION__, __LINE__);
IOT_ASSERT(0);
return false;
}
os_mem_cpy(&(current_handle_cmd.hdr), &(frm->hdr), sizeof(mb_extend_fn_hdr_t));
current_handle_cmd.data = frm->gpio_value;
current_handle_cmd.dir = dir;
mb_ext_gpio_config_flag = 1;
modbus_ext_gpio_config(gpio_num, IOT_GE_GPIO_DIR_OUTPUT, IOT_GE_GPIO_PULL_NONE, 0);
/* pack ge frame. */
pack_frm = (ge_frame_gpio_set_subfn165_t *)iot_pkt_put(p_pkt, pack_frm_len);
pack_frm->hdr.hdr.preamble = 0xAAAA;
pack_frm->hdr.hdr.data_len = 0x0F;
pack_frm->hdr.hdr.fn = PROTO_GE_PLC_SET_CMD;
pack_frm->hdr.subfn = PROTO_GE_GPIO_SET_CMD;
pack_frm->seq = 0;
iot_mac_addr_cpy(pack_frm->dest_mac, mb_task.local_mac);
iot_mac_addr_cpy(pack_frm->src_mac, mb_task.local_mac);
pack_frm->gpio_num = gpio_num;
pack_frm->value = (frm->gpio_value) >> 8;
crc16 = ge_frm_checksum_calc((uint8_t *)pack_frm, pack_frm_len - 3);
pack_frm->tail.check_sum = crc16;
pack_frm->tail.tail = GE_FRM_TAIL_CODE;
/* post ge command to ge task */
iot_proto_data_parse_and_post(iot_pkt_data(p_pkt), iot_pkt_data_len(p_pkt),
iot_mb_task_post_uart_cmd, 0);
iot_pkt_free(p_pkt);
os_start_timer(mb_task.mb_ext_resp_timer, IOT_MB_EXT_RESP_TIMER_PERIOD);
return true;
param_err:
iot_printf("[%s][err]param err @line %d\n", __FUNCTION__, __LINE__);
return false;
}
bool_t modbus_ext_wl_add_item_handler(uint8_t *data, uint8_t len,
mb_transmit_direction_e dir)
{
(void)data;
(void)len;
(void)dir;
return true;
}
bool_t modbus_ext_wl_remove_item_handler(uint8_t *data, uint8_t len,
mb_transmit_direction_e dir)
{
(void)data;
(void)len;
(void)dir;
return true;
}
static mb_fnhdl_tbl_t modbus_set_ra_tbl[] = {
#if PLC_SUPPORT_CCO_ROLE
{AID_SET_RA, modbus_ext_aid_set_handler, 0},
{WL_SET_RA, modbus_ext_wl_set_handler,0},
{WL_ADD_ITEM_SET_RA, modbus_ext_wl_add_item_handler, 0},
{WL_RM_ITEM_SET_RA, modbus_ext_wl_remove_item_handler, 0},
#endif
{SA_SET_RA, modbus_ext_sa_set_handler,0},
{GPIO_SET_BASE_RA, modbus_ext_gpio_set_handler, 0},
};
static bool_t iot_mb_ext_cmd_set_handler(uint8_t *data,
uint8_t len, mb_transmit_direction_e dir)
{
uint8_t i, ret = ERR_FAIL;
mb_extend_fn_hdr_t *mb_head = (mb_extend_fn_hdr_t *)data;;
uint8_t fncode_hdlr_cnt =
sizeof(modbus_set_ra_tbl)/sizeof(mb_fnhdl_tbl_t);
MODBUS_FN_HANDLE handler = NULL;
uint16_t reg_addr = big_little_swap16(mb_head->reg_addr);
for (i = 0; i < fncode_hdlr_cnt; i++) {
if (modbus_set_ra_tbl[i].cmdid == reg_addr) {
handler = modbus_set_ra_tbl[i].cmd_handle_fn;
break;
}
}
if (reg_addr > GPIO_SET_BASE_RA) {
handler = modbus_ext_gpio_set_handler;
}
if (handler) {
ret = handler(data, len, dir);
ret = (ret == true)? ERR_OK: ERR_FAIL;
}
return ret;
}
/* fncode handler table */
static mb_fnhdl_tbl_t mb_fn_hdl_tbl[] = {
{MODBUS_EXT_QUERY_FN, iot_mb_ext_cmd_query_fn_handler, 0 },
{MODBUS_EXT_SET_SINGLE_REG_FN, iot_mb_ext_cmd_set_handler, 0 },
{MODBUS_EXT_SET_MULTI_REG_FN, iot_mb_ext_cmd_set_handler, 0 },
};
uint8_t iot_mb_ext_cmd_handler(uint8_t * data, uint16_t len,
mb_transmit_direction_e dir)
{
uint8_t i, ret = ERR_FAIL;
mb_extend_fn_hdr_t *mb_head = NULL;
uint8_t fncode_hdlr_cnt =
sizeof(mb_fn_hdl_tbl)/sizeof(mb_fnhdl_tbl_t);
if ((data == NULL) || (len == 0)) {
iot_printf("[%s][err] invalid data, data:%p, len:%d\n", __FUNCTION__, data, len);
goto out;
}
iot_mb_ext_data_dump(data, len, __LINE__);
mb_head = (mb_extend_fn_hdr_t *)data;
/* look for fncode handler to handle modbus cmd frame */
for (i = 0; i < fncode_hdlr_cnt; i++) {
if (mb_head->fn == mb_fn_hdl_tbl[i].cmdid) {
/* increase each fn counter */
mb_fn_hdl_tbl[i].cmd_num++;
mb_fn_hdl_tbl[i].cmd_handle_fn(data, len, dir);
break;
}
}
ret = ERR_OK;
out:
return ret;
}