123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- package service
- import (
- "fmt"
- "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)})
- }
- for _, control := range timeControls {
- fmt.Printf("%s : %s : %d\n", control.start, control.end, control.state)
- }
- // 在恢复时检查状态
- state := getDeviceState(timeControls, deviceRecoveryTime)
- fmt.Printf("%s %d\n", timeControls, state)
- return state, nil
- }
|