You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

141 lines
4.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package m9z
import (
"encoding/binary"
"fmt"
"github.com/gogf/gf/v2/errors/gerror"
"tgk-touch/internal/global"
)
// 定义任务指令结构
type TaskInstruction struct {
Type uint32 `json:"type"` // 指令类型 (ISA_CMP, ISA_GOTO, etc.)
Param uint32 `json:"param"`
Value uint32 `json:"value"` // 指令参数
}
// 定义任务结构
type TaskProgram struct {
Index uint8 `json:"index"` // 任务索引 (0~2)
Size uint8 `json:"size"` // 指令数量
Instructions []TaskInstruction `json:"instructions"` // 指令列表
}
// StartTaskRead 读取开始任务 (优化指令 CMD=0x13)
func StartTaskRead(deviceId string, idx uint8) (*TaskProgram, error) {
return taskRead(deviceId, startTask, idx, "读取开始任务")
}
// MiddleTaskRead 读取中间任务 (优化指令 CMD=0x14)
func MiddleTaskRead(deviceId string, idx uint8) (*TaskProgram, error) {
// 实现与StartTaskRead相同仅CMD不同
return taskRead(deviceId, middleTask, idx, "读取中间任务")
}
// StopTaskRead 读取结束任务 (优化指令 CMD=0x15)
func StopTaskRead(deviceId string, idx uint8) (*TaskProgram, error) {
// 实现与StartTaskRead相同仅CMD不同
return taskRead(deviceId, stopTask, idx, "读取结束任务")
}
// 通用任务读取函数
func taskRead(deviceId string, cmd M9zCtrl, idx uint8, detail string) (*TaskProgram, error) {
readResp, err := ReadCmd(deviceId, cmd, detail, uint(idx))
if err != nil {
return nil, err
}
data := readResp.Data
// 解析逻辑与StartTaskRead相同
if idx < 0 || idx > 2 {
idx = 0
}
task := &TaskProgram{Index: idx}
if len(data) < 1 {
return nil, fmt.Errorf("invalid task data length")
}
task.Size = data[0]
task.Instructions = make([]TaskInstruction, 0, task.Size)
for i := 1; i+3 < len(data) && len(task.Instructions) < int(task.Size); i += 4 {
instruction := binary.LittleEndian.Uint32(data[i : i+4])
g.Log().Debugf("% X", instruction)
insType := uint32(instruction >> 28)
ins := TaskInstruction{Type: insType}
// 根据指令类型解析参数
switch insType {
case 0x01: // ISA_CMP
// 参数: 源类型 + 比较值
ins.Param = (instruction >> 24) & 0x0F
ins.Value = instruction & 0x0000FFFF
case 0x02: // ISA_GOTO
// 参数: 跳转类型 + 跳转地址 + 最大次数 + 索引值
ins.Param = (instruction >> 24) & 0x0F
ins.Value = ((instruction >> 16) & 0xFF) | ((instruction >> 8) & 0xFF) | (instruction & 0xFF)
case 0x03: // ISA_DLY
// 参数: 延迟单位 + 延迟值
ins.Param = (instruction >> 24) & 0x0F
ins.Value = instruction & 0x00FFFFFF
case 0x04: // ISA_OUTPUT
// 参数: 输出类型 + 输出值
ins.Param = (instruction >> 24) & 0x0F
ins.Value = instruction & 0x00FFFFFF // 输出值
default:
// 未知指令类型
ins.Param = instruction
}
task.Instructions = append(task.Instructions, ins)
}
return task, nil
}
// StartTaskWrite 写入开始任务 (优化指令 CMD=0x13)
func StartTaskWrite(deviceId string, task *TaskProgram) error {
return taskWrite(deviceId, startTask, task, "写入开始任务")
}
// MiddleTaskWrite 写入中间任务 (优化指令 CMD=0x14)
func MiddleTaskWrite(deviceId string, task *TaskProgram) error {
return taskWrite(deviceId, middleTask, task, "写入中间任务")
}
// StopTaskWrite 写入结束任务 (优化指令 CMD=0x15)
func StopTaskWrite(deviceId string, task *TaskProgram) error {
return taskWrite(deviceId, stopTask, task, "写入结束任务")
}
// 通用任务写入函数
func taskWrite(deviceId string, cmd M9zCtrl, task *TaskProgram, detail string) error {
if task.Size > 23 {
return fmt.Errorf("任务数量 %+v 太多,超过了上限,请删除一些后重试}", task.Size)
}
// 构造数据缓冲区 (1字节大小 + 每个指令4字节)
buf := make([]byte, 1+4*len(task.Instructions))
buf[0] = byte(len(task.Instructions))
offset := 1
for _, ins := range task.Instructions {
// 组合指令 (类型在高4位)
instruction := ins.Type | ins.Param | ins.Value
// 写入小端序
binary.LittleEndian.PutUint32(buf[offset:offset+4], instruction)
offset += 4
}
writeResp, err := WriteCmd(deviceId, M9zCtrl(cmd), buf, detail, task.Index)
if err != nil {
return err
}
if !writeResp.Success {
return gerror.New("设置失败")
}
// 发送写入命令
return nil
}