瀏覽代碼

整体的优化修改代码

niujiuru 2 周之前
父節點
當前提交
ad3d99b695

二進制
docs/拍照性诱智能监测设备MCU与RTU通信协议.docx


+ 80 - 2
mcu_ctrl_board/bridge.go

@@ -12,7 +12,9 @@ import "C"
 import (
 	"encoding/json"
 	"fmt"
+	"sync"
 	"time"
+	"unsafe"
 
 	"hnyfkj.com.cn/rtu/linux/baseapp"
 	"hnyfkj.com.cn/rtu/linux/netmgrd"
@@ -37,6 +39,18 @@ func mcuCtrlBoard_ComExit() error {
 	return nil
 }
 
+// 主动的发送指令给MCU控制板
+func mcuCtrlBoard_SendCmd(cmd string) error {
+	cstr := C.CString(cmd)
+	defer C.free(unsafe.Pointer(cstr))
+
+	ret := int(C.MCBComSendCmd(cstr))
+	if ret != 0 {
+		return fmt.Errorf("an error occurred while calling the C.MCBComSendCmd function(%d)", ret)
+	}
+	return nil
+}
+
 // 判断输入字符串是请求/应答
 func detectJsonRole(jsonStr string) string {
 	var obj map[string]json.RawMessage
@@ -69,7 +83,10 @@ func RTU_JsonMsgProcCb(jsonStr *C.char) *C.char {
 	}
 
 	if role == "response" {
-		Board.handleResponse(s)
+		err := Board.handleResponse(s)
+		if err != nil {
+			baseapp.Logger.Errorf("[%s] 解析数据板发送的命令应答时发生错误: %v", MODULE_NAME, err)
+		}
 		return nil
 	}
 
@@ -192,6 +209,67 @@ func (board *MCUCtrlBoard) powerDown(r *jsonrpc2.Request) (*jsonrpc2.Response, e
 	return jsonrpc2.BuildResult(r, wjson)
 }
 
+var pendingRequests sync.Map // 存储所有待处理的请求ID和对应的应答通道
+
+// 发送请求, 并等待应答
+func (board *MCUCtrlBoard) SendRequest(req *jsonrpc2.Request, timeout int /*单位: ms*/) (*jsonrpc2.Response, error) {
+	if req == nil || req.ID == nil {
+		return nil, fmt.Errorf("invalid request or request ID")
+	}
+
+	id := *req.ID
+	ch := make(chan *jsonrpc2.Response, 1)
+	pendingRequests.Store(id, ch)
+	defer pendingRequests.Delete(id)
+
+	jsonStr, err := req.String()
+	if err != nil {
+		return nil, err
+	}
+
+	err = mcuCtrlBoard_SendCmd(jsonStr)
+	if err != nil {
+		return nil, err
+	}
+
+	timer := time.NewTimer(time.Duration(timeout) * time.Millisecond)
+	defer timer.Stop()
+
+	select {
+	case resp := <-ch:
+		return resp, nil
+	case <-timer.C:
+		return nil, fmt.Errorf("request %v timed out after %d ms", id, timeout)
+	}
+}
+
 // 处理控制板返回的请求
-func (board *MCUCtrlBoard) handleResponse(jsonStr string) {
+func (board *MCUCtrlBoard) handleResponse(jsonStr string) error {
+	w, err := jsonrpc2.ParseResponse(jsonStr)
+	if err != nil {
+		return fmt.Errorf("an error occurred while parsing JSON-RPC response: %v", err)
+	}
+
+	if w.ID == nil {
+		return nil
+	}
+
+	id := *w.ID
+
+	v, ok := pendingRequests.Load(id)
+	if !ok {
+		return fmt.Errorf("orphan response id=%d, no pending request", id)
+	}
+
+	ch, ok := v.(chan *jsonrpc2.Response)
+	if !ok {
+		return fmt.Errorf("invalid response channel for id=%d", id)
+	}
+
+	select {
+	case ch <- w:
+		return nil
+	default:
+		return fmt.Errorf("response dropped for id=%d, channel not receiving", id)
+	}
 }

+ 11 - 1
mcu_ctrl_board/mcu_ctrl_board.c

@@ -46,7 +46,7 @@ static int comio_data_recv_proc(unsigned long wParam/*传递打开的串口句
       int sendBytes = serial_send_data(pSerial, (const unsigned char *)pResponse, nRspBytes);
       if(sendBytes == nRspBytes) sw_log_debug("[%s] %s send a response(%d bytes): %s", MODULE_NAME, log_prefix, nRspBytes, pResponse);
       else sw_log_error("[%s] %s failed to send a response(%d bytes, ret=%d): %s!!", MODULE_NAME, log_prefix, nRspBytes, sendBytes, pResponse);
-      free(pResponse);
+      free(pResponse); // 释放Go侧C.CString()分配的堆内存
     }
     pComIO->jsonStartTick = 0; serial_clear_recv_buffer(pSerial); lwjson_stream_reset(&pComIO->parser);
     break;
@@ -105,3 +105,13 @@ int MCBComExit()
   memset(&s_myCom, 0, sizeof(s_myCom));
   return 0;
 }
+
+// 主动的发送指令给MCU控制板, 返回: 0成功, <0时失败
+int MCBComSendCmd(const char *cmd)
+{
+  if(!s_myCom.h || !cmd) return -1;
+  int nBytes = strlen(cmd);
+  int ret = serial_send_data(s_myCom.h, (const unsigned char *)cmd, nBytes);
+  if(ret == nBytes) return 0;
+  return -2;
+}

+ 3 - 0
mcu_ctrl_board/mcu_ctrl_board.h

@@ -17,6 +17,9 @@ int MCBComInit();
 // 关闭与MCU控制板的串口通讯, 返回: 0成功, <0时失败
 int MCBComExit();
 
+// 主动的发送指令给MCU控制板, 返回: 0成功, <0时失败
+int MCBComSendCmd(const char *cmd);
+
 #ifdef __cplusplus
 }
 #endif