|
|
@@ -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)
|
|
|
+ }
|
|
|
}
|