package service import ( "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 { //if d.State == 0 { // continue //} tmp, isExist := relayMap[d.Sn] 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.Sn] = tmp } } } for key, value := range relayMap { reg, dev, err := utils.GetDataByDeviceId(key) if err != nil { logger.Get().Errorf("GetDataByDeviceId err = %s\n", err.Error()) } for i, i2 := range value { data := modbus.DeviceLoopSwitch(i, i2) if model.ConnectionMap[key] == nil { logger.Get().Errorf("设备连接丢失") } err := utils.WriteDevice(dev.Sn, data, model.ConnectionMap[key]) time.Sleep(100 * time.Millisecond) if err != nil { logger.Get().Errorf("WriteDevice err = %s\n", err.Error()) } for j, loop := range dev.DeviceLoops { if loop.ID == i { dev.DeviceLoops[j].State = i2 } } } 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()) } } } func (c Cron) RelayOnOffTimeTaskSn(sn string) { _, dev, err := utils.GetDataByDeviceId(sn) if err != nil { logger.Get().Errorf("LoadData err = %s", err.Error()) return } relays := dev.DeviceLoops rcTime, rlTime, err := utils.SunriseSunsetForChina(28.23, 113.05) tmp := make(map[int]int) for _, relay := range relays { //日出日落时间 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, _ := ss(relay.TimeCondition1OnTime, relay.TimeCondition1OffTime, relay.TimeCondition2OnTime, relay.TimeCondition2OffTime) tmp[relay.ID] = state } for loop1, state := range tmp { reg, dev, err := utils.GetDataByDeviceId(sn) if err != nil { logger.Get().Errorf("GetDataByDeviceId err = %s\n", err.Error()) } data := modbus.DeviceLoopSwitch(loop1, state) if model.ConnectionMap[sn] == nil { logger.Get().Errorf("设备连接丢失") } err = utils.WriteDevice(dev.Sn, data, model.ConnectionMap[sn]) time.Sleep(100 * time.Millisecond) if err != nil { logger.Get().Errorf("WriteDevice err = %s\n", err.Error()) } for j, loop := range dev.DeviceLoops { if loop.ID == loop1 { dev.DeviceLoops[j].State = state } } for i, device := range reg.Devices { if device.Sn == dev.Sn { reg.Devices[i] = dev } } data1, err := utils.SaveRegionOnData(reg) if err != nil { logger.Get().Errorf("SaveRegionOnData err = %s\n", err.Error()) } err = SaveData(data1) if err != nil { logger.Get().Errorf("SaveData err = %s\n", err.Error()) } } } 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) if period.start.After(period.end) { if now.After(period.start) || now.Before(period.end) { return period.state } } else { if now.After(period.start) && now.Before(period.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)}) } //for _, control := range timeControls { // fmt.Printf("%s : %s : %d\n", control.start, control.end, control.state) //} // 在恢复时检查状态 state := getDeviceState(timeControls, deviceRecoveryTime) return state, nil }