package service import ( "net" "server/logger" "server/modbus" "server/model" "server/utils" "sort" "time" ) type Cron struct { } // RelayOnOffTimeTask 定时开关 前提是 设备在线 否则失效 func (c Cron) RelayOnOffTimeTask() { current := time.Now().Format("15:04") devices, err := utils.GetOnlineDevices() if err != nil { logger.Get().Errorf("LoadData err = %s", err.Error()) return } relayMap := make(map[string]map[int]int) for _, d := range devices { tmp, isExist := relayMap[d.Ip] if !isExist { // 回路id 回路状态 tmp = make(map[int]int) } relays := d.DeviceLoops rcTime, rlTime, err := utils.SunriseSunsetForChina(28.23, 113.05) if err != nil { logger.Get().Errorf("SunriseSunsetForChina err = %s", err.Error()) rcTime = "06:00" rlTime = "18:00" } for _, r := range relays { //日出日落时间 if r.TimeCondition1OnTime == "日出" { r.TimeCondition1OnTime = rcTime } else if r.TimeCondition1OnTime == "日落" { r.TimeCondition1OnTime = rlTime } if r.TimeCondition1OffTime == "日出" { r.TimeCondition1OffTime = rcTime } else if r.TimeCondition1OffTime == "日落" { r.TimeCondition1OffTime = rlTime } if r.TimeCondition2OnTime == "日出" { r.TimeCondition2OnTime = rcTime } else if r.TimeCondition2OnTime == "日落" { r.TimeCondition2OnTime = rlTime } if r.TimeCondition2OffTime == "日出" { r.TimeCondition2OffTime = rcTime } else if r.TimeCondition2OffTime == "日落" { r.TimeCondition2OffTime = rlTime } isTiming := 0 // 用来判断该设备的回路 是否定时 //控制回路 时间判断 是否关闭 当前时间是否等与规定时间 规定时间到规定时间+10分钟 //因为1分钟执行一次,所以会多次执行,则新加判断 如果数据库中状态和回路状态相同则不执行下去 layout := "15:04" rTimeCondition1OnTime, _ := time.Parse(layout, r.TimeCondition1OnTime) rTimeCondition1OffTime, _ := time.Parse(layout, r.TimeCondition1OffTime) rTimeCondition2OnTime, _ := time.Parse(layout, r.TimeCondition2OnTime) rTimeCondition2OffTime, _ := time.Parse(layout, r.TimeCondition2OffTime) rCurrent, _ := time.Parse(layout, current) if r.TimeCondition1OnTime != "关闭" && (r.TimeCondition1OnTime == current || (rCurrent.Before(rTimeCondition1OnTime.Add(11*time.Minute)) && rCurrent.After(rTimeCondition1OnTime))) { tmp[r.ID] = 1 isTiming = 1 } if r.TimeCondition1OffTime != "关闭" && (r.TimeCondition1OffTime == current || (rCurrent.Before(rTimeCondition1OffTime.Add(11*time.Minute)) && rCurrent.After(rTimeCondition1OffTime))) { tmp[r.ID] = 0 isTiming = 1 } if r.TimeCondition2OnTime != "关闭" && (r.TimeCondition2OnTime == current || (rCurrent.Before(rTimeCondition2OnTime.Add(11*time.Minute)) && rCurrent.After(rTimeCondition2OnTime))) { tmp[r.ID] = 1 isTiming = 1 } if r.TimeCondition2OffTime != "关闭" && (r.TimeCondition2OffTime == current || (rCurrent.Before(rTimeCondition2OffTime.Add(11*time.Minute)) && rCurrent.After(rTimeCondition2OffTime))) { tmp[r.ID] = 0 isTiming = 1 } if isTiming == 1 { relayMap[d.Ip] = tmp } } } for key, value := range relayMap { reg, dev, err := utils.GetDataByDeviceIP(key) if err != nil { logger.Get().Errorf("GetDataByDeviceId err = %s\n", err.Error()) } for i, i2 := range value { data := modbus.DeviceLoopSwitch(i, i2) if conn1, ok := model.ConnectionMap1.Load(key); ok { // 成功找到连接 netConn := conn1.(net.Conn) err := utils.WriteDevice(data, netConn) if err != nil { logger.Get().Errorf("定时控制 写命令错误: %s -- conn: %v", err, netConn.RemoteAddr().String()) return } time.Sleep(1 * time.Second) for j, loop := range dev.DeviceLoops { if loop.ID == i { dev.DeviceLoops[j].State = i2 } } } else { // 没有找到对应的连接 logger.Get().Printf("定时Connection for key %s not found", key) } } for i, device := range reg.Devices { if device.Sn == dev.Sn { reg.Devices[i] = dev } } data, err := utils.SaveRegionOnData(reg) if err != nil { logger.Get().Errorf("SaveRegionOnData err = %s\n", err.Error()) } err = SaveData(data) if err != nil { logger.Get().Errorf("SaveData err = %s\n", err.Error()) } } } // DeviceAdjustment 设备调正 func DeviceAdjustment(ip string) { reg, dev, _ := utils.GetDataByDeviceIP(ip) rcTime, rlTime, err := utils.SunriseSunsetForChina(28.23, 113.05) tmp := make(map[int]int) for _, relay := range dev.DeviceLoops { //日出日落时间 if relay.TimeCondition1OnTime == "日出" { relay.TimeCondition1OnTime = rcTime } else if relay.TimeCondition1OnTime == "日落" { relay.TimeCondition1OnTime = rlTime } if relay.TimeCondition1OffTime == "日出" { relay.TimeCondition1OffTime = rcTime } else if relay.TimeCondition1OffTime == "日落" { relay.TimeCondition1OffTime = rlTime } if relay.TimeCondition2OnTime == "日出" { relay.TimeCondition2OnTime = rcTime } else if relay.TimeCondition2OnTime == "日落" { relay.TimeCondition2OnTime = rlTime } if relay.TimeCondition2OffTime == "日出" { relay.TimeCondition2OffTime = rcTime } else if relay.TimeCondition2OffTime == "日落" { relay.TimeCondition2OffTime = rlTime } if relay.TimeCondition1OffTime == "关闭" && relay.TimeCondition1OnTime == "关闭" && relay.TimeCondition2OffTime == "关闭" && relay.TimeCondition2OnTime == "关闭" { continue } state, err := ss(relay.TimeCondition1OnTime, relay.TimeCondition1OffTime, relay.TimeCondition2OnTime, relay.TimeCondition2OffTime) if err != nil { return } tmp[relay.ID] = state } logger.Get().Printf("[DEBUG] %v", tmp) for i, i2 := range tmp { data := modbus.DeviceLoopSwitch(i, i2) if conn1, ok := model.ConnectionMap1.Load(ip); ok { // 成功找到连接 netConn := conn1.(net.Conn) err := utils.WriteDevice(data, netConn) if err != nil { logger.Get().Errorf("定时控制 写命令错误: %s -- conn: %v", err, netConn.RemoteAddr().String()) return } time.Sleep(2 * time.Second) for j, loop := range dev.DeviceLoops { if loop.ID == i { dev.DeviceLoops[j].State = i2 } } } else { // 没有找到对应的连接 logger.Get().Printf("重连Connection for key %s not found", ip) } } for i, device := range reg.Devices { if device.Sn == dev.Sn { reg.Devices[i] = dev } } data, err := utils.SaveRegionOnData(reg) if err != nil { logger.Get().Errorf("重连SaveRegionOnData err = %s\n", err.Error()) } err = SaveData(data) if err != nil { logger.Get().Errorf("SaveData err = %s\n", err.Error()) } return } const ( Off = iota On ) type TimeControl struct { start time.Time end time.Time state int } func getDeviceState(schedules []TimeControl, currentTime time.Time) int { for _, period := range schedules { now := time.Date(0, time.January, 1, currentTime.Hour(), currentTime.Minute(), currentTime.Second(), currentTime.Nanosecond(), time.UTC) start := time.Date(0, time.January, 1, period.start.Hour(), period.start.Minute(), period.start.Second(), period.start.Nanosecond(), time.UTC) end := time.Date(0, time.January, 1, period.end.Hour(), period.end.Minute(), period.end.Second(), period.end.Nanosecond(), time.UTC) if start.After(end) { // 跨越午夜 if now.After(start) || now.Before(end) { return period.state } } else { // 不跨越午夜 if now.After(start) && now.Before(end) { return period.state } } } return Off } func stateTransition(str string) int { if str == "on1" || str == "on2" { return On } else { return Off } } func ss(on1, off1, on2, off2 string) (int, error) { deviceRecoveryTime := time.Now() // 定义时间映射 deviceTime := map[string]string{ "on1": on1, "off1": off1, "on2": on2, "off2": off2, } // 创建一个切片存储时间 var times []struct { key string value time.Time } // 将时间字符串解析为 time.Time 对象,并存入切片 for key, value := range deviceTime { if value == "关闭" { continue } t, err := time.Parse("15:04", value) if err != nil { logger.Get().Error("时间转换失败!" + err.Error()) return 0, err } times = append(times, struct { key string value time.Time }{key, t}) } // 对时间进行排序 sort.Slice(times, func(i, j int) bool { return times[i].value.Before(times[j].value) }) var timeControls []TimeControl for i, _ := range times { if len(times) == i+1 { timeControls = append(timeControls, TimeControl{start: times[i].value, end: times[0].value.Add(24 * time.Hour), state: stateTransition(times[i].key)}) continue } timeControls = append(timeControls, TimeControl{start: times[i].value, end: times[i+1].value, state: stateTransition(times[i].key)}) } // 在恢复时检查状态 state := getDeviceState(timeControls, deviceRecoveryTime) return state, nil }