|
|
package m9z // 插件
|
|
|
import (
|
|
|
"encoding/binary"
|
|
|
"fmt"
|
|
|
"github.com/gogf/gf/v2/errors/gerror"
|
|
|
|
|
|
"sort"
|
|
|
"tgk-touch/internal/global"
|
|
|
"time"
|
|
|
)
|
|
|
|
|
|
var (
|
|
|
DefaultStartTask ControlTask = ControlTask{
|
|
|
TimeType: 0,
|
|
|
Loops: []TaskLoop{
|
|
|
{
|
|
|
0, true, 70,
|
|
|
},
|
|
|
{
|
|
|
1, true, 70,
|
|
|
},
|
|
|
{
|
|
|
2, true, 70,
|
|
|
},
|
|
|
{
|
|
|
3, true, 70,
|
|
|
},
|
|
|
{
|
|
|
4, true, 70,
|
|
|
},
|
|
|
{
|
|
|
5, true, 70,
|
|
|
},
|
|
|
{
|
|
|
6, true, 70,
|
|
|
},
|
|
|
{
|
|
|
7, true, 70,
|
|
|
},
|
|
|
{
|
|
|
8, true, 70,
|
|
|
},
|
|
|
{
|
|
|
9, true, 70,
|
|
|
},
|
|
|
},
|
|
|
}
|
|
|
DefaultMiddleTask MiddleControlTask = MiddleControlTask{
|
|
|
[]ControlTask{
|
|
|
ControlTask{
|
|
|
|
|
|
TimeType: 0,
|
|
|
Loops: []TaskLoop{
|
|
|
{
|
|
|
0, true, 70,
|
|
|
},
|
|
|
{
|
|
|
1, true, 70,
|
|
|
},
|
|
|
{
|
|
|
2, true, 70,
|
|
|
},
|
|
|
{
|
|
|
3, true, 70,
|
|
|
},
|
|
|
{
|
|
|
4, true, 70,
|
|
|
},
|
|
|
{
|
|
|
5, true, 70,
|
|
|
},
|
|
|
{
|
|
|
6, true, 70,
|
|
|
},
|
|
|
{
|
|
|
7, true, 70,
|
|
|
},
|
|
|
{
|
|
|
8, true, 70,
|
|
|
},
|
|
|
{
|
|
|
9, true, 70,
|
|
|
},
|
|
|
},
|
|
|
},
|
|
|
},
|
|
|
}
|
|
|
DefaultStopTask ControlTask = ControlTask{
|
|
|
|
|
|
TimeType: 0,
|
|
|
Loops: []TaskLoop{
|
|
|
{
|
|
|
0, false, 70,
|
|
|
},
|
|
|
{
|
|
|
1, false, 70,
|
|
|
},
|
|
|
{
|
|
|
2, false, 70,
|
|
|
},
|
|
|
{
|
|
|
3, false, 70,
|
|
|
},
|
|
|
{
|
|
|
4, false, 70,
|
|
|
},
|
|
|
{
|
|
|
5, false, 70,
|
|
|
},
|
|
|
{
|
|
|
6, false, 70,
|
|
|
},
|
|
|
{
|
|
|
7, false, 70,
|
|
|
},
|
|
|
{
|
|
|
8, false, 70,
|
|
|
},
|
|
|
{
|
|
|
9, false, 70,
|
|
|
},
|
|
|
},
|
|
|
}
|
|
|
)
|
|
|
|
|
|
func init() {
|
|
|
parse, _ := time.ParseInLocation("2006-01-02 15:04:05", "2025-06-05 19:00:00", time.Local)
|
|
|
|
|
|
DefaultStartTask.ExecTime = parse
|
|
|
for i, c := range DefaultMiddleTask.ControlTaskList {
|
|
|
p, _ := time.ParseInLocation("2006-01-02 15:04:05", "2025-06-05 20:00:00", time.Local)
|
|
|
c.ExecTime = p
|
|
|
DefaultMiddleTask.ControlTaskList[i] = c
|
|
|
}
|
|
|
parse, _ = time.ParseInLocation("2006-01-02 15:04:05", "2025-06-05 07:00:00", time.Local)
|
|
|
DefaultStartTask.ExecTime = parse
|
|
|
}
|
|
|
|
|
|
func IsTaskInitRead(deviceId string) (bool, error) {
|
|
|
read, err := ManualRead(deviceId)
|
|
|
if err != nil {
|
|
|
return false, err
|
|
|
}
|
|
|
return read.BackupByte1 == 1, nil
|
|
|
}
|
|
|
func SetIsTaskInitRead(deviceId string, b bool) error {
|
|
|
read, err := ManualRead(deviceId)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
if b {
|
|
|
read.BackupByte1 = 1
|
|
|
} else {
|
|
|
read.BackupByte1 = 0
|
|
|
}
|
|
|
return ManualWrite(deviceId, read)
|
|
|
}
|
|
|
|
|
|
type TaskLoop struct {
|
|
|
Index uint `json:"index"` // 0 D0 回路0
|
|
|
TurnOn bool `json:"turnOn"`
|
|
|
Pwm uint8 `json:"pwm"` // 功率百分比
|
|
|
}
|
|
|
|
|
|
// 控制任务配置
|
|
|
type ControlTask struct {
|
|
|
ExecTime time.Time `json:"execTime"` // "2006-01-02 15:04:05" 格式时间
|
|
|
TimeType int `json:"timeType"` // 0 定时 1经纬
|
|
|
Loops []TaskLoop `json:"loops"`
|
|
|
}
|
|
|
type MiddleControlTask struct {
|
|
|
ControlTaskList []ControlTask `json:"controlTaskList"`
|
|
|
}
|
|
|
|
|
|
func ControlTaskToTaskProgram(task ControlTask, idx uint8) (*TaskProgram, error) {
|
|
|
if uint8(0) > idx || idx > uint8(2) {
|
|
|
idx = 0
|
|
|
}
|
|
|
// 1. 创建任务程序对象
|
|
|
program := &TaskProgram{
|
|
|
Index: idx,
|
|
|
}
|
|
|
|
|
|
// 2. 解析执行时间
|
|
|
eTime := task.ExecTime
|
|
|
g.Log().Debugf("task:%+v\ntask.ExecTime %+v , eTime:%+v,hour:%d,min:%d", task, task.ExecTime, eTime, eTime.Hour(), eTime.Minute())
|
|
|
minValue := uint32(eTime.Hour()*60 + eTime.Minute())
|
|
|
var cmpInstruction TaskInstruction
|
|
|
// 3. 添加时间比较指令
|
|
|
if task.TimeType == 0 {
|
|
|
cmpInstruction = TaskInstruction{
|
|
|
Type: 0x01 << 28, // CMP指令类型
|
|
|
Param: 0x01 << 24,
|
|
|
Value: minValue,
|
|
|
}
|
|
|
} else {
|
|
|
cmpInstruction = TaskInstruction{
|
|
|
Type: 0x01 << 28,
|
|
|
Param: 0x02 << 24,
|
|
|
Value: minValue,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
program.Instructions = append(program.Instructions, cmpInstruction)
|
|
|
|
|
|
// 开灯任务需要两条指令:
|
|
|
// 1. 开启所有回路继电器
|
|
|
var openLoopValue uint32
|
|
|
var closeLoopValue uint32
|
|
|
for _, loop := range task.Loops {
|
|
|
if loop.TurnOn {
|
|
|
openLoopValue |= (0x1 << loop.Index)
|
|
|
} else {
|
|
|
closeLoopValue |= (0x1 << loop.Index)
|
|
|
}
|
|
|
if loop.Pwm > 100 {
|
|
|
loop.Pwm = 100
|
|
|
}
|
|
|
loopIndex := (0x1 << loop.Index)
|
|
|
loopIndex |= (0x1 << loop.Index)
|
|
|
// 修复类型不匹配问题
|
|
|
pwmValue := (uint32(loopIndex) << 12) | uint32(loop.Pwm)
|
|
|
|
|
|
pwmInstruction := TaskInstruction{
|
|
|
Type: 0x4 << 28, // OUTPUT指令
|
|
|
Param: 0x03 << 24,
|
|
|
Value: pwmValue,
|
|
|
}
|
|
|
program.Instructions = append(program.Instructions, pwmInstruction)
|
|
|
}
|
|
|
if openLoopValue != 0 {
|
|
|
openLoopValue = (openLoopValue << 12) | 0x01
|
|
|
}
|
|
|
if closeLoopValue != 0 {
|
|
|
closeLoopValue = (closeLoopValue << 12) | 0x00
|
|
|
}
|
|
|
|
|
|
openLoopIns := TaskInstruction{
|
|
|
Type: 0x04 << 28, // OUTPUT指令
|
|
|
Param: 0x01 << 24,
|
|
|
Value: openLoopValue,
|
|
|
}
|
|
|
closeLoopIns := TaskInstruction{
|
|
|
Type: 0x04 << 28, // OUTPUT指令
|
|
|
Param: 0x01 << 24,
|
|
|
Value: closeLoopValue,
|
|
|
}
|
|
|
|
|
|
program.Instructions = append(program.Instructions, openLoopIns, closeLoopIns)
|
|
|
// 2. 设置PWM亮度
|
|
|
// 5. 设置任务大小(现在有3条指令)
|
|
|
program.Size = uint8(len(program.Instructions))
|
|
|
|
|
|
return program, nil
|
|
|
}
|
|
|
|
|
|
func TaskProgramToControlTask(program *TaskProgram) (*ControlTask, error) {
|
|
|
task := &ControlTask{
|
|
|
TimeType: 0, // 默认定时类型
|
|
|
// 初始化所有10个回路(0-9)
|
|
|
Loops: make([]TaskLoop, 10),
|
|
|
}
|
|
|
|
|
|
// 初始化所有回路为关闭状态
|
|
|
for i := range task.Loops {
|
|
|
task.Loops[i] = TaskLoop{
|
|
|
Index: uint(i),
|
|
|
TurnOn: false,
|
|
|
Pwm: 0,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
foundTimeInstruction := false
|
|
|
|
|
|
// 解析所有指令
|
|
|
for _, ins := range program.Instructions {
|
|
|
g.Log().Debugf("Found instruction: %+v,type %+v isTime %+v", ins, ins.Type, ins.Type == 0x01)
|
|
|
switch ins.Type {
|
|
|
case 0x01: // 时间命令
|
|
|
foundTimeInstruction = true
|
|
|
minutes := ins.Value
|
|
|
hour := minutes / 60
|
|
|
minute := minutes % 60
|
|
|
parse, err := time.ParseInLocation("2006-01-02 15:04:05", fmt.Sprintf("%s %02d:%02d:00", time.Now().Format(time.DateOnly), hour, minute), time.Local)
|
|
|
if err != nil {
|
|
|
return nil, gerror.Wrapf(err, "failed to parse time")
|
|
|
}
|
|
|
task.ExecTime = parse
|
|
|
|
|
|
// 处理时间类型
|
|
|
switch ins.Param {
|
|
|
case 0x01:
|
|
|
task.TimeType = 0 // 定时
|
|
|
case 0x02:
|
|
|
task.TimeType = 1 // 经纬
|
|
|
}
|
|
|
|
|
|
case 0x04: // OUTPUT指令
|
|
|
paramType := ins.Param
|
|
|
switch paramType {
|
|
|
case 0x01: // 继电器状态命令
|
|
|
relayValue := ins.Value
|
|
|
// 判断是开还是关
|
|
|
isOpen := (relayValue & 1) == 1
|
|
|
// 获取开启掩码(高12位)
|
|
|
onMask := (relayValue >> 12) & 0xFFF
|
|
|
|
|
|
// 颠倒位顺序 - 低位对应低索引回路
|
|
|
reversedOnMask := uint32(0)
|
|
|
for i := 0; i < 12; i++ {
|
|
|
originalBit := (onMask >> i) & 0x1
|
|
|
reversedOnMask |= (originalBit << (11 - i))
|
|
|
}
|
|
|
|
|
|
str := fmt.Sprintf("%12b", reversedOnMask)
|
|
|
for i := 0; i < len(str)-2; i++ {
|
|
|
if str[i] == '1' {
|
|
|
if isOpen {
|
|
|
task.Loops[i].TurnOn = true
|
|
|
g.Log().Debugf("isOpen %+v ,loop %+v ,on %q ,t :%+v", isOpen, i, str[i], true)
|
|
|
|
|
|
} else {
|
|
|
task.Loops[i].TurnOn = false
|
|
|
g.Log().Debugf("isOpen %+v ,loop %+v ,on %q ,t :%+v", isOpen, i, str[i], false)
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
case 0x03: // PWM指令
|
|
|
pwmValue := ins.Value
|
|
|
// 高12位:通道掩码,低12位:PWM值
|
|
|
channelMask := (pwmValue >> 12) & 0xFFF
|
|
|
pwmVal := uint8(pwmValue & 0xFF) // 取低8位作为PWM值
|
|
|
|
|
|
// 处理每个回路的PWM值
|
|
|
for i := 0; i < 12; i++ {
|
|
|
if i < len(task.Loops) && (channelMask&(1<<i) != 0) {
|
|
|
task.Loops[i].Pwm = pwmVal
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 如果没有找到时间指令,返回错误
|
|
|
if !foundTimeInstruction {
|
|
|
return nil, fmt.Errorf("missing time instruction in task program %+v", program.Instructions)
|
|
|
}
|
|
|
|
|
|
/* // 过滤掉保持默认关闭状态的回路
|
|
|
activeLoops := make([]TaskLoop, 0, len(task.Loops))
|
|
|
for _, loop := range task.Loops {
|
|
|
if loop.TurnOn || loop.Pwm > 0 {
|
|
|
activeLoops = append(activeLoops, loop)
|
|
|
}
|
|
|
}
|
|
|
task.Loops = activeLoops*/
|
|
|
|
|
|
return task, nil
|
|
|
}
|
|
|
|
|
|
func MiddleControlTaskToTaskProgram(middle MiddleControlTask, idx uint8) (*TaskProgram, error) {
|
|
|
sort.Slice(middle.ControlTaskList, func(i, j int) bool {
|
|
|
t1 := middle.ControlTaskList[i].ExecTime
|
|
|
t2 := middle.ControlTaskList[i].ExecTime
|
|
|
return t1.Before(t2)
|
|
|
})
|
|
|
if idx < 0 || idx > 2 {
|
|
|
idx = 0
|
|
|
}
|
|
|
program := &TaskProgram{
|
|
|
Index: idx,
|
|
|
}
|
|
|
fmt.Printf("middleControlTaskToTaskProgram middle:%+v\n", middle)
|
|
|
|
|
|
for _, task := range middle.ControlTaskList {
|
|
|
|
|
|
// 2. 解析执行时间
|
|
|
eTime := task.ExecTime
|
|
|
fmt.Printf("task:%+v\ntask.ExecTime %+v , eTime:%+v,hour:%d,min:%d\n", task, task.ExecTime, eTime, eTime.Hour(), eTime.Minute())
|
|
|
|
|
|
minValue := uint32(eTime.Hour()*60 + eTime.Minute())
|
|
|
var cmpInstruction TaskInstruction
|
|
|
// 3. 添加时间比较指令
|
|
|
if task.TimeType == 0 {
|
|
|
cmpInstruction = TaskInstruction{
|
|
|
Type: 0x01 << 28, // CMP指令类型
|
|
|
Param: 0x5 << 24,
|
|
|
Value: minValue,
|
|
|
}
|
|
|
} else {
|
|
|
cmpInstruction = TaskInstruction{
|
|
|
Type: 0x01 << 28,
|
|
|
Param: 0x04 << 24,
|
|
|
Value: minValue,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
program.Instructions = append(program.Instructions, cmpInstruction)
|
|
|
|
|
|
// 开灯任务需要两条指令:
|
|
|
// 1. 开启所有回路继电器
|
|
|
var openLoopValue uint32
|
|
|
var closeLoopValue uint32
|
|
|
// 2. PWM指令(针对每个回路)
|
|
|
pwmMap := make(map[uint8][]uint) // 按PWM值分组
|
|
|
for _, loop := range task.Loops {
|
|
|
if loop.Pwm > 0 {
|
|
|
pwmMap[loop.Pwm] = append(pwmMap[loop.Pwm], loop.Index)
|
|
|
}
|
|
|
}
|
|
|
// 为每个PWM值创建指令
|
|
|
for pwmVal, indices := range pwmMap {
|
|
|
channelMask := uint32(0)
|
|
|
for _, idx2 := range indices {
|
|
|
if idx2 < 12 {
|
|
|
channelMask |= (1 << idx2)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
pwmInstruction := TaskInstruction{
|
|
|
Type: 0x4 << 28, // OUTPUT指令
|
|
|
Param: 0x03 << 24, // PWM类型
|
|
|
Value: (channelMask << 12) | uint32(pwmVal),
|
|
|
}
|
|
|
program.Instructions = append(program.Instructions, pwmInstruction)
|
|
|
}
|
|
|
for _, loop := range task.Loops {
|
|
|
if loop.TurnOn {
|
|
|
openLoopValue |= (0x1 << loop.Index)
|
|
|
} else {
|
|
|
closeLoopValue |= (0x1 << loop.Index)
|
|
|
}
|
|
|
}
|
|
|
if openLoopValue != 0 {
|
|
|
openLoopValue = (openLoopValue << 12) | 0x01
|
|
|
}
|
|
|
if closeLoopValue != 0 {
|
|
|
closeLoopValue = (closeLoopValue << 12) | 0x00
|
|
|
}
|
|
|
openLoopIns := TaskInstruction{
|
|
|
Type: 0x04 << 28, // OUTPUT指令
|
|
|
Param: 0x01 << 24,
|
|
|
Value: openLoopValue,
|
|
|
}
|
|
|
if openLoopValue != 0 {
|
|
|
program.Instructions = append(program.Instructions, openLoopIns)
|
|
|
|
|
|
}
|
|
|
closeLoopIns := TaskInstruction{
|
|
|
Type: 0x04 << 28, // OUTPUT指令
|
|
|
Param: 0x01 << 24,
|
|
|
Value: closeLoopValue,
|
|
|
}
|
|
|
|
|
|
if closeLoopValue != 0 {
|
|
|
program.Instructions = append(program.Instructions, closeLoopIns)
|
|
|
}
|
|
|
|
|
|
}
|
|
|
// 中间任务需要循环
|
|
|
loopIns := TaskInstruction{
|
|
|
Type: 0x2 << 28,
|
|
|
Param: ((0x1 /*跳转使能*/) & 0xF) << 24,
|
|
|
Value: (((0 /*跳转到第几步*/) & 0xFF) << 16) | (((0 /*最大次数*/) & 0xFF) << 8),
|
|
|
}
|
|
|
program.Instructions = append(program.Instructions, loopIns)
|
|
|
program.Size = uint8(len(program.Instructions))
|
|
|
return program, nil
|
|
|
}
|
|
|
|
|
|
func TaskProgramToMiddleControlTask(program *TaskProgram) (*MiddleControlTask, error) {
|
|
|
middle := &MiddleControlTask{
|
|
|
ControlTaskList: make([]ControlTask, 0),
|
|
|
}
|
|
|
|
|
|
// 存储当前正在解析的任务
|
|
|
var currentTask *ControlTask
|
|
|
taskIndex := 0
|
|
|
|
|
|
for i, ins := range program.Instructions {
|
|
|
insType := ins.Type
|
|
|
paramType := ins.Param
|
|
|
|
|
|
g.Log().Debugf("解析指令 %d: Type=0x%X, Param=0x%X, Value=0x%08X", i, insType, paramType, ins.Value)
|
|
|
switch insType {
|
|
|
case 0x01: // 时间比较指令
|
|
|
// 完成前一个任务(如果有)
|
|
|
if currentTask != nil {
|
|
|
middle.ControlTaskList = append(middle.ControlTaskList, *currentTask)
|
|
|
taskIndex++
|
|
|
}
|
|
|
|
|
|
// 创建新任务
|
|
|
currentTask = &ControlTask{
|
|
|
Loops: make([]TaskLoop, 10), // 10个回路的默认配置
|
|
|
}
|
|
|
|
|
|
// 初始化所有回路状态
|
|
|
for j := range currentTask.Loops {
|
|
|
currentTask.Loops[j] = TaskLoop{
|
|
|
Index: uint(j),
|
|
|
TurnOn: false,
|
|
|
Pwm: 0,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 解析时间
|
|
|
minutes := ins.Value
|
|
|
hour := minutes / 60
|
|
|
minute := minutes % 60
|
|
|
parse, err := time.ParseInLocation("2006-01-02 15:04", fmt.Sprintf("%s %02d:%02d", time.Now().Format(time.DateOnly), hour, minute), time.Local)
|
|
|
|
|
|
if err != nil {
|
|
|
return nil, gerror.Wrap(err, "parse time error")
|
|
|
}
|
|
|
currentTask.ExecTime = parse
|
|
|
|
|
|
// 解析时间类型
|
|
|
switch paramType {
|
|
|
case 0x5:
|
|
|
currentTask.TimeType = 0 // 定时
|
|
|
case 0x4:
|
|
|
currentTask.TimeType = 1 // 经纬
|
|
|
default:
|
|
|
g.Log().Warnf("未知的时间类型: 0x%X", paramType)
|
|
|
currentTask.TimeType = 0
|
|
|
}
|
|
|
|
|
|
g.Log().Debugf("时间指令: %s, 时间类型: %d ,分钟数:%d", currentTask.ExecTime, currentTask.TimeType, minutes)
|
|
|
case 0x04: // OUTPUT指令
|
|
|
if currentTask == nil {
|
|
|
g.Log().Warnf("在时间指令前发现OUTPUT指令,忽略")
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
switch paramType {
|
|
|
case 0x01: // 继电器状态命令
|
|
|
|
|
|
value := ins.Value
|
|
|
// 判断是开还是关
|
|
|
isOpen := (value & 1) == 1
|
|
|
onMask := (value >> 12) & 0xFFF
|
|
|
|
|
|
// 输出原始掩码值(二进制12位格式)
|
|
|
g.Log().Debugf("开关命令%+v", isOpen)
|
|
|
g.Log().Debugf("原始继电器掩码: %012b (onMask = 0x%03X)", onMask, onMask)
|
|
|
|
|
|
// 颠倒位顺序 - 低位对应低索引回路
|
|
|
reversedOnMask := uint32(0)
|
|
|
for j := 0; j < 12; j++ {
|
|
|
originalBit := (onMask >> j) & 0x1
|
|
|
reversedOnMask |= (originalBit << (11 - j))
|
|
|
}
|
|
|
|
|
|
// 输出反转后的掩码值
|
|
|
str := fmt.Sprintf("%012b", reversedOnMask)
|
|
|
g.Log().Debugf("反转后继电器掩码: %s (reversedOnMask = 0x%03X)", str, reversedOnMask)
|
|
|
|
|
|
// 逐个输出每个回路的位状态
|
|
|
g.Log().Debug("按位解析回路状态:")
|
|
|
for j := 0; j < len(str)-2; j++ {
|
|
|
if j >= len(currentTask.Loops) {
|
|
|
break
|
|
|
}
|
|
|
|
|
|
if str[j] == '1' {
|
|
|
if isOpen {
|
|
|
currentTask.Loops[j].TurnOn = str[j] == '1' && isOpen
|
|
|
g.Log().Debugf("loop %+v ,on %q ,t :%+v", j, str[j], true)
|
|
|
} else {
|
|
|
currentTask.Loops[j].TurnOn = false
|
|
|
g.Log().Debugf("loop %+v ,on %q ,t :%+v", j, str[j], false)
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
case 0x03: // PWM指令
|
|
|
value := ins.Value
|
|
|
channelMask := (value >> 12) & 0xFFF
|
|
|
pwmVal := uint8(value & 0xFF)
|
|
|
|
|
|
// 输出原始掩码值
|
|
|
g.Log().Debugf("原始PWM掩码: %012b (channelMask = 0x%03X), PWM值: %d", channelMask, channelMask, pwmVal)
|
|
|
|
|
|
// 颠倒位顺序 - 低位对应低索引回路
|
|
|
reversedChannelMask := uint32(0)
|
|
|
for j := 0; j < 12; j++ {
|
|
|
originalBit := (channelMask >> j) & 0x1
|
|
|
reversedChannelMask |= (originalBit << (11 - j))
|
|
|
}
|
|
|
|
|
|
// 输出反转后的掩码值
|
|
|
str := fmt.Sprintf("%012b", reversedChannelMask)
|
|
|
g.Log().Debugf("反转后PWM掩码: %s (reversedChannelMask = 0x%03X)", str, reversedChannelMask)
|
|
|
|
|
|
// 设置每个回路的PWM值
|
|
|
for j := 0; j < len(str); j++ {
|
|
|
if j >= len(currentTask.Loops) {
|
|
|
break
|
|
|
}
|
|
|
|
|
|
if str[j] == '1' {
|
|
|
g.Log().Debugf(" 设置回路 %d PWM值: %d%%", j, pwmVal)
|
|
|
currentTask.Loops[j].Pwm = pwmVal
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
case 0x02: // 循环指令
|
|
|
g.Log().Debug("检测到循环指令,跳过")
|
|
|
|
|
|
default:
|
|
|
g.Log().Warnf("未知的指令类型: 0x%X", insType)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 添加最后一个任务(如果有)
|
|
|
if currentTask != nil {
|
|
|
middle.ControlTaskList = append(middle.ControlTaskList, *currentTask)
|
|
|
}
|
|
|
|
|
|
g.Log().Debugf("成功解析 %d 个控制任务", len(middle.ControlTaskList))
|
|
|
|
|
|
return middle, nil
|
|
|
}
|
|
|
|
|
|
// 写入开始任务到设备
|
|
|
func StartTaskWriteByTaskCfg(deviceId string, idx uint8, task ControlTask) error {
|
|
|
// 1. 将控制任务转换为任务程序
|
|
|
tp, err := ControlTaskToTaskProgram(task, idx)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
// 2. 使用CMD 0x13写入开始任务
|
|
|
return StartTaskWrite(deviceId, tp)
|
|
|
}
|
|
|
|
|
|
// 写入任务程序到设备
|
|
|
func StartTaskWrite2(deviceId string, program *TaskProgram) error {
|
|
|
// 1. 构造数据缓冲区 (1字节大小 + 每个指令4字节)
|
|
|
buf := make([]byte, 1+4*len(program.Instructions))
|
|
|
buf[0] = program.Size
|
|
|
|
|
|
offset := 1
|
|
|
for _, ins := range program.Instructions {
|
|
|
// 2. 组合指令 (类型在高4位)
|
|
|
instruction := uint32(ins.Type) << 28
|
|
|
|
|
|
/*// 3. 根据指令类型组合参数
|
|
|
switch len(ins.Params) {
|
|
|
case 1:
|
|
|
instruction |= ins.Param & 0x0FFFFFFF
|
|
|
case 2:
|
|
|
instruction |= (ins.Param & 0x0F) << 24
|
|
|
instruction |= ins.Value & 0x00FFFFFF
|
|
|
case 3:
|
|
|
instruction |= (ins.Param & 0x0F) << 24
|
|
|
instruction |= (ins.Value & 0xFFFF) << 8
|
|
|
instruction |= ins.Params[2] & 0xFF
|
|
|
}*/
|
|
|
|
|
|
// 4. 写入小端序
|
|
|
binary.LittleEndian.PutUint32(buf[offset:offset+4], instruction)
|
|
|
offset += 4
|
|
|
}
|
|
|
|
|
|
// 5. 发送写入命令
|
|
|
|
|
|
return StartTaskWrite(deviceId, program)
|
|
|
}
|