diff --git a/internal/module/m9zTtyApi/automatic_mode_demo.go b/internal/module/m9zTtyApi/automatic_mode_demo.go new file mode 100644 index 0000000..3e266af --- /dev/null +++ b/internal/module/m9zTtyApi/automatic_mode_demo.go @@ -0,0 +1,123 @@ +package m9zApi + +import ( + "sync" + "time" + + "tgk-touch/internal/library/m9z" +) + +const automaticModeUseDemoAPI = false + +type automaticModeTaskReq struct { + CommUid string `json:"comm_uid"` + Mode uint8 `json:"mode"` +} + +type automaticModeDemoStore struct { + mu sync.RWMutex + currentMode uint8 + startTasks [3]m9z.ControlTask + stopTasks [3]m9z.ControlTask + middleTasks [3]m9z.MiddleControlTask +} + +var automaticModeDemo = newAutomaticModeDemoStore() + +func newAutomaticModeDemoStore() *automaticModeDemoStore { + store := &automaticModeDemoStore{} + for mode := uint8(0); mode < 3; mode++ { + store.startTasks[mode] = buildAutomaticModeDemoTask(6+int(mode), 30, true, uint8(60+mode*10)) + store.stopTasks[mode] = buildAutomaticModeDemoTask(22, int(mode)*10, false, 0) + store.middleTasks[mode] = m9z.MiddleControlTask{ + ControlTaskList: []m9z.ControlTask{ + buildAutomaticModeDemoTask(12, int(mode)*10, true, uint8(45+mode*5)), + }, + } + } + return store +} + +func buildAutomaticModeDemoTask(hour int, minute int, turnOn bool, pwm uint8) m9z.ControlTask { + loops := make([]m9z.TaskLoop, 10) + for i := range loops { + loops[i] = m9z.TaskLoop{ + Index: uint(i), + TurnOn: turnOn, + Pwm: pwm, + } + } + return m9z.ControlTask{ + ExecTime: time.Date(2025, 6, 7, hour, minute, 0, 0, time.Local), + TimeType: 0, + Loops: loops, + } +} + +func normalizeAutomaticMode(mode uint8) uint8 { + if mode > 2 { + return 0 + } + return mode +} + +func cloneAutomaticControlTask(task m9z.ControlTask) m9z.ControlTask { + task.Loops = append([]m9z.TaskLoop(nil), task.Loops...) + return task +} + +func cloneAutomaticMiddleTask(task m9z.MiddleControlTask) m9z.MiddleControlTask { + task.ControlTaskList = append([]m9z.ControlTask(nil), task.ControlTaskList...) + for i := range task.ControlTaskList { + task.ControlTaskList[i] = cloneAutomaticControlTask(task.ControlTaskList[i]) + } + return task +} + +func (s *automaticModeDemoStore) getMode() uint8 { + s.mu.RLock() + defer s.mu.RUnlock() + return s.currentMode +} + +func (s *automaticModeDemoStore) setMode(mode uint8) { + s.mu.Lock() + defer s.mu.Unlock() + s.currentMode = normalizeAutomaticMode(mode) +} + +func (s *automaticModeDemoStore) getStartTask(mode uint8) m9z.ControlTask { + s.mu.RLock() + defer s.mu.RUnlock() + return cloneAutomaticControlTask(s.startTasks[normalizeAutomaticMode(mode)]) +} + +func (s *automaticModeDemoStore) setStartTask(mode uint8, task m9z.ControlTask) { + s.mu.Lock() + defer s.mu.Unlock() + s.startTasks[normalizeAutomaticMode(mode)] = cloneAutomaticControlTask(task) +} + +func (s *automaticModeDemoStore) getStopTask(mode uint8) m9z.ControlTask { + s.mu.RLock() + defer s.mu.RUnlock() + return cloneAutomaticControlTask(s.stopTasks[normalizeAutomaticMode(mode)]) +} + +func (s *automaticModeDemoStore) setStopTask(mode uint8, task m9z.ControlTask) { + s.mu.Lock() + defer s.mu.Unlock() + s.stopTasks[normalizeAutomaticMode(mode)] = cloneAutomaticControlTask(task) +} + +func (s *automaticModeDemoStore) getMiddleTask(mode uint8) m9z.MiddleControlTask { + s.mu.RLock() + defer s.mu.RUnlock() + return cloneAutomaticMiddleTask(s.middleTasks[normalizeAutomaticMode(mode)]) +} + +func (s *automaticModeDemoStore) setMiddleTask(mode uint8, task m9z.MiddleControlTask) { + s.mu.Lock() + defer s.mu.Unlock() + s.middleTasks[normalizeAutomaticMode(mode)] = cloneAutomaticMiddleTask(task) +} diff --git a/internal/module/m9zTtyApi/automatic_mode_demo_test.go b/internal/module/m9zTtyApi/automatic_mode_demo_test.go new file mode 100644 index 0000000..7a4e1d3 --- /dev/null +++ b/internal/module/m9zTtyApi/automatic_mode_demo_test.go @@ -0,0 +1,39 @@ +package m9zApi + +import "testing" + +func TestAutomaticModeDemoStoreReturnsCopies(t *testing.T) { + store := newAutomaticModeDemoStore() + + start := store.getStartTask(0) + if len(start.Loops) == 0 { + t.Fatal("demo start task should include loops") + } + start.Loops[0].TurnOn = !start.Loops[0].TurnOn + start.Loops[0].Pwm = 1 + + got := store.getStartTask(0) + if got.Loops[0].Pwm == 1 { + t.Fatal("demo start task loop was mutated through returned value") + } + + middle := store.getMiddleTask(0) + if len(middle.ControlTaskList) == 0 || len(middle.ControlTaskList[0].Loops) == 0 { + t.Fatal("demo middle task should include control tasks and loops") + } + middle.ControlTaskList[0].Loops[0].Pwm = 1 + + gotMiddle := store.getMiddleTask(0) + if gotMiddle.ControlTaskList[0].Loops[0].Pwm == 1 { + t.Fatal("demo middle task loop was mutated through returned value") + } +} + +func TestNormalizeAutomaticMode(t *testing.T) { + if got := normalizeAutomaticMode(2); got != 2 { + t.Fatalf("normalizeAutomaticMode(2) = %d, want 2", got) + } + if got := normalizeAutomaticMode(3); got != 0 { + t.Fatalf("normalizeAutomaticMode(3) = %d, want 0", got) + } +} diff --git a/internal/module/m9zTtyApi/read.go b/internal/module/m9zTtyApi/read.go index 6bce7db..0259300 100644 --- a/internal/module/m9zTtyApi/read.go +++ b/internal/module/m9zTtyApi/read.go @@ -39,6 +39,18 @@ func getOutStatus(rpc towgo.JsonRpcConnection) { // todo 有问题 不管写入什么模式返回都是FF 获取设备编程模式 1-3 对应模式01~模式03 编程模式0~2 func getDeviceMode(rpc towgo.JsonRpcConnection) { + if automaticModeUseDemoAPI { + getDeviceModeDemo(rpc) + return + } + getDeviceModeReal(rpc) +} + +func getDeviceModeDemo(rpc towgo.JsonRpcConnection) { + rpc.WriteResult(automaticModeDemo.getMode()) +} + +func getDeviceModeReal(rpc towgo.JsonRpcConnection) { cuid, _ := getDeviceId(rpc) read, err := m9z.ModeRead(cuid) @@ -366,6 +378,20 @@ func getStopTaskRead(rpc towgo.JsonRpcConnection) { rpc.WriteResult(read) } func getStartTask2(rpc towgo.JsonRpcConnection) { + if automaticModeUseDemoAPI { + getStartTask2Demo(rpc) + return + } + getStartTask2Real(rpc) +} + +func getStartTask2Demo(rpc towgo.JsonRpcConnection) { + var p automaticModeTaskReq + rpc.ReadParams(&p) + rpc.WriteResult(automaticModeDemo.getStartTask(p.Mode)) +} + +func getStartTask2Real(rpc towgo.JsonRpcConnection) { var p struct { CommUid string `json:"comm_uid"` Mode uint8 `json:"mode"` // 0x00-0x02 @@ -395,6 +421,20 @@ func getStartTask2(rpc towgo.JsonRpcConnection) { } func getStopTask2(rpc towgo.JsonRpcConnection) { + if automaticModeUseDemoAPI { + getStopTask2Demo(rpc) + return + } + getStopTask2Real(rpc) +} + +func getStopTask2Demo(rpc towgo.JsonRpcConnection) { + var p automaticModeTaskReq + rpc.ReadParams(&p) + rpc.WriteResult(automaticModeDemo.getStopTask(p.Mode)) +} + +func getStopTask2Real(rpc towgo.JsonRpcConnection) { var p struct { CommUid string `json:"comm_uid"` Mode uint8 `json:"mode"` // 0x00-0x02 @@ -424,6 +464,20 @@ func getStopTask2(rpc towgo.JsonRpcConnection) { } func getMiddleTask2(rpc towgo.JsonRpcConnection) { + if automaticModeUseDemoAPI { + getMiddleTask2Demo(rpc) + return + } + getMiddleTask2Real(rpc) +} + +func getMiddleTask2Demo(rpc towgo.JsonRpcConnection) { + var p automaticModeTaskReq + rpc.ReadParams(&p) + rpc.WriteResult(automaticModeDemo.getMiddleTask(p.Mode)) +} + +func getMiddleTask2Real(rpc towgo.JsonRpcConnection) { var p struct { CommUid string `json:"comm_uid"` diff --git a/internal/module/m9zTtyApi/set.go b/internal/module/m9zTtyApi/set.go index 013f582..6df24a2 100644 --- a/internal/module/m9zTtyApi/set.go +++ b/internal/module/m9zTtyApi/set.go @@ -15,6 +15,21 @@ import ( // 写入设备编程模式 func setDeviceMode(rpc towgo.JsonRpcConnection) { + if automaticModeUseDemoAPI { + setDeviceModeDemo(rpc) + return + } + setDeviceModeReal(rpc) +} + +func setDeviceModeDemo(rpc towgo.JsonRpcConnection) { + var p automaticModeTaskReq + rpc.ReadParams(&p) + automaticModeDemo.setMode(p.Mode) + rpc.WriteResult("ok") +} + +func setDeviceModeReal(rpc towgo.JsonRpcConnection) { var p struct { CommUid string `json:"comm_uid"` Mode uint8 `json:"mode"` @@ -292,6 +307,30 @@ func setStopTaskWrite(rpc towgo.JsonRpcConnection) { // 写入开始任务 (优化指令 CMD=0x15) func setStartTask2(rpc towgo.JsonRpcConnection) { + if automaticModeUseDemoAPI { + setStartTask2Demo(rpc) + return + } + setStartTask2Real(rpc) +} + +func setStartTask2Demo(rpc towgo.JsonRpcConnection) { + var p struct { + ExecTime string `json:"execTime"` + Mode uint8 `json:"mode"` + m9z.ControlTask + } + rpc.ReadParams(&p) + parse, err := utility.ParseTime(p.ExecTime) + if err != nil { + panic(err) + } + p.ControlTask.ExecTime = parse + automaticModeDemo.setStartTask(p.Mode, p.ControlTask) + rpc.WriteResult("ok") +} + +func setStartTask2Real(rpc towgo.JsonRpcConnection) { var p struct { ExecTime string `json:"execTime"` CommUid string `json:"comm_uid"` @@ -322,6 +361,30 @@ func setStartTask2(rpc towgo.JsonRpcConnection) { rpc.WriteResult("ok") } func setStopTask2(rpc towgo.JsonRpcConnection) { + if automaticModeUseDemoAPI { + setStopTask2Demo(rpc) + return + } + setStopTask2Real(rpc) +} + +func setStopTask2Demo(rpc towgo.JsonRpcConnection) { + var p struct { + ExecTime string `json:"execTime"` + Mode uint8 `json:"mode"` + m9z.ControlTask + } + rpc.ReadParams(&p) + parse, err := utility.ParseTime(p.ExecTime) + if err != nil { + panic(err) + } + p.ControlTask.ExecTime = parse + automaticModeDemo.setStopTask(p.Mode, p.ControlTask) + rpc.WriteResult("ok") +} + +func setStopTask2Real(rpc towgo.JsonRpcConnection) { var p struct { ExecTime string `json:"execTime"` CommUid string `json:"comm_uid"` @@ -355,6 +418,37 @@ func setStopTask2(rpc towgo.JsonRpcConnection) { } func setMiddleTask2(rpc towgo.JsonRpcConnection) { + if automaticModeUseDemoAPI { + setMiddleTask2Demo(rpc) + return + } + setMiddleTask2Real(rpc) +} + +func setMiddleTask2Demo(rpc towgo.JsonRpcConnection) { + var p struct { + Mode uint8 `json:"mode"` + ControlTaskList []struct { + m9z.ControlTask + ExecTime string `json:"execTime"` + } `json:"controlTaskList"` + } + rpc.ReadParams(&p) + middleTask := m9z.MiddleControlTask{} + middleTask.ControlTaskList = make([]m9z.ControlTask, len(p.ControlTaskList)) + for i, controlTask := range p.ControlTaskList { + parse, err := utility.ParseTime(controlTask.ExecTime) + if err != nil { + panic(gerror.NewCodef(gcode.CodeInvalidParameter, " %s parse control task time error, %s", controlTask.ExecTime, err)) + } + controlTask.ControlTask.ExecTime = parse + middleTask.ControlTaskList[i] = controlTask.ControlTask + } + automaticModeDemo.setMiddleTask(p.Mode, middleTask) + rpc.WriteResult("ok") +} + +func setMiddleTask2Real(rpc towgo.JsonRpcConnection) { var p struct { CommUid string `json:"comm_uid"` Mode uint8 `json:"mode"`