cron.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. package service
  2. import (
  3. "fmt"
  4. "net"
  5. "server/logger"
  6. "server/modbus"
  7. "server/model"
  8. "server/utils"
  9. "sort"
  10. "time"
  11. )
  12. type Cron struct {
  13. }
  14. // RelayOnOffTimeTask 定时开关 前提是 设备在线 否则失效
  15. func (c Cron) RelayOnOffTimeTask() {
  16. current := time.Now().Format("15:04")
  17. devices, err := utils.GetOnlineDevices()
  18. if err != nil {
  19. logger.Get().Errorf("LoadData err = %s", err.Error())
  20. return
  21. }
  22. relayMap := make(map[string]map[int]int)
  23. for _, d := range devices {
  24. tmp, isExist := relayMap[d.Ip]
  25. if !isExist { // 回路id 回路状态
  26. tmp = make(map[int]int)
  27. }
  28. relays := d.DeviceLoops
  29. rcTime, rlTime, err := utils.SunriseSunsetForChina(28.23, 113.05)
  30. if err != nil {
  31. logger.Get().Errorf("SunriseSunsetForChina err = %s", err.Error())
  32. rcTime = "06:00"
  33. rlTime = "18:00"
  34. }
  35. for _, r := range relays {
  36. //日出日落时间
  37. if r.TimeCondition1OnTime == "日出" {
  38. r.TimeCondition1OnTime = rcTime
  39. } else if r.TimeCondition1OnTime == "日落" {
  40. r.TimeCondition1OnTime = rlTime
  41. }
  42. if r.TimeCondition1OffTime == "日出" {
  43. r.TimeCondition1OffTime = rcTime
  44. } else if r.TimeCondition1OffTime == "日落" {
  45. r.TimeCondition1OffTime = rlTime
  46. }
  47. if r.TimeCondition2OnTime == "日出" {
  48. r.TimeCondition2OnTime = rcTime
  49. } else if r.TimeCondition2OnTime == "日落" {
  50. r.TimeCondition2OnTime = rlTime
  51. }
  52. if r.TimeCondition2OffTime == "日出" {
  53. r.TimeCondition2OffTime = rcTime
  54. } else if r.TimeCondition2OffTime == "日落" {
  55. r.TimeCondition2OffTime = rlTime
  56. }
  57. isTiming := 0 // 用来判断该设备的回路 是否定时
  58. //控制回路 时间判断 是否关闭 当前时间是否等与规定时间 规定时间到规定时间+10分钟
  59. //因为1分钟执行一次,所以会多次执行,则新加判断 如果数据库中状态和回路状态相同则不执行下去
  60. layout := "15:04"
  61. rTimeCondition1OnTime, _ := time.Parse(layout, r.TimeCondition1OnTime)
  62. rTimeCondition1OffTime, _ := time.Parse(layout, r.TimeCondition1OffTime)
  63. rTimeCondition2OnTime, _ := time.Parse(layout, r.TimeCondition2OnTime)
  64. rTimeCondition2OffTime, _ := time.Parse(layout, r.TimeCondition2OffTime)
  65. rCurrent, _ := time.Parse(layout, current)
  66. if r.TimeCondition1OnTime != "关闭" &&
  67. (r.TimeCondition1OnTime == current ||
  68. (rCurrent.Before(rTimeCondition1OnTime.Add(11*time.Minute)) && rCurrent.After(rTimeCondition1OnTime))) {
  69. tmp[r.ID] = 1
  70. isTiming = 1
  71. }
  72. if r.TimeCondition1OffTime != "关闭" && (r.TimeCondition1OffTime == current ||
  73. (rCurrent.Before(rTimeCondition1OffTime.Add(11*time.Minute)) && rCurrent.After(rTimeCondition1OffTime))) {
  74. tmp[r.ID] = 0
  75. isTiming = 1
  76. }
  77. if r.TimeCondition2OnTime != "关闭" && (r.TimeCondition2OnTime == current ||
  78. (rCurrent.Before(rTimeCondition2OnTime.Add(11*time.Minute)) && rCurrent.After(rTimeCondition2OnTime))) {
  79. tmp[r.ID] = 1
  80. isTiming = 1
  81. }
  82. if r.TimeCondition2OffTime != "关闭" && (r.TimeCondition2OffTime == current ||
  83. (rCurrent.Before(rTimeCondition2OffTime.Add(11*time.Minute)) && rCurrent.After(rTimeCondition2OffTime))) {
  84. tmp[r.ID] = 0
  85. isTiming = 1
  86. }
  87. if isTiming == 1 {
  88. relayMap[d.Ip] = tmp
  89. }
  90. }
  91. }
  92. for key, value := range relayMap {
  93. reg, dev, err := utils.GetDataByDeviceIP(key)
  94. if err != nil {
  95. logger.Get().Errorf("GetDataByDeviceId err = %s\n", err.Error())
  96. }
  97. for i, i2 := range value {
  98. data := modbus.DeviceLoopSwitch(i, i2)
  99. if conn1, ok := model.ConnectionMap1.Load(key); ok {
  100. // 成功找到连接
  101. netConn := conn1.(net.Conn)
  102. err := utils.WriteDevice(data, netConn)
  103. if err != nil {
  104. logger.Get().Errorf("定时控制 写命令错误: %s -- conn: %v", err, netConn.RemoteAddr().String())
  105. return
  106. }
  107. time.Sleep(1 * time.Second)
  108. for j, loop := range dev.DeviceLoops {
  109. if loop.ID == i {
  110. dev.DeviceLoops[j].State = i2
  111. }
  112. }
  113. } else {
  114. // 没有找到对应的连接
  115. logger.Get().Printf("定时Connection for key %s not found", key)
  116. }
  117. }
  118. for i, device := range reg.Devices {
  119. if device.Sn == dev.Sn {
  120. reg.Devices[i] = dev
  121. }
  122. }
  123. data, err := utils.SaveRegionOnData(reg)
  124. if err != nil {
  125. logger.Get().Errorf("SaveRegionOnData err = %s\n", err.Error())
  126. }
  127. err = SaveData(data)
  128. if err != nil {
  129. logger.Get().Errorf("SaveData err = %s\n", err.Error())
  130. }
  131. }
  132. }
  133. // DeviceAdjustment 设备调正
  134. func DeviceAdjustment(ip string) {
  135. reg, dev, _ := utils.GetDataByDeviceIP(ip)
  136. rcTime, rlTime, err := utils.SunriseSunsetForChina(28.23, 113.05)
  137. tmp := make(map[int]int)
  138. for _, relay := range dev.DeviceLoops {
  139. //日出日落时间
  140. if relay.TimeCondition1OnTime == "日出" {
  141. relay.TimeCondition1OnTime = rcTime
  142. } else if relay.TimeCondition1OnTime == "日落" {
  143. relay.TimeCondition1OnTime = rlTime
  144. }
  145. if relay.TimeCondition1OffTime == "日出" {
  146. relay.TimeCondition1OffTime = rcTime
  147. } else if relay.TimeCondition1OffTime == "日落" {
  148. relay.TimeCondition1OffTime = rlTime
  149. }
  150. if relay.TimeCondition2OnTime == "日出" {
  151. relay.TimeCondition2OnTime = rcTime
  152. } else if relay.TimeCondition2OnTime == "日落" {
  153. relay.TimeCondition2OnTime = rlTime
  154. }
  155. if relay.TimeCondition2OffTime == "日出" {
  156. relay.TimeCondition2OffTime = rcTime
  157. } else if relay.TimeCondition2OffTime == "日落" {
  158. relay.TimeCondition2OffTime = rlTime
  159. }
  160. if relay.TimeCondition1OffTime == "关闭" && relay.TimeCondition1OnTime == "关闭" && relay.TimeCondition2OffTime == "关闭" && relay.TimeCondition2OnTime == "关闭" {
  161. continue
  162. }
  163. state, err := ss(relay.TimeCondition1OnTime, relay.TimeCondition1OffTime, relay.TimeCondition2OnTime, relay.TimeCondition2OffTime)
  164. if err != nil {
  165. return
  166. }
  167. tmp[relay.ID] = state
  168. }
  169. logger.Get().Printf("[DEBUG] %v", tmp)
  170. for i, i2 := range tmp {
  171. data := modbus.DeviceLoopSwitch(i, i2)
  172. if conn1, ok := model.ConnectionMap1.Load(ip); ok {
  173. // 成功找到连接
  174. netConn := conn1.(net.Conn)
  175. err := utils.WriteDevice(data, netConn)
  176. if err != nil {
  177. logger.Get().Errorf("定时控制 写命令错误: %s -- conn: %v", err, netConn.RemoteAddr().String())
  178. return
  179. }
  180. time.Sleep(2 * time.Second)
  181. for j, loop := range dev.DeviceLoops {
  182. if loop.ID == i {
  183. dev.DeviceLoops[j].State = i2
  184. }
  185. }
  186. } else {
  187. // 没有找到对应的连接
  188. logger.Get().Printf("重连Connection for key %s not found", ip)
  189. }
  190. }
  191. for i, device := range reg.Devices {
  192. if device.Sn == dev.Sn {
  193. reg.Devices[i] = dev
  194. }
  195. }
  196. data, err := utils.SaveRegionOnData(reg)
  197. if err != nil {
  198. logger.Get().Errorf("重连SaveRegionOnData err = %s\n", err.Error())
  199. }
  200. err = SaveData(data)
  201. if err != nil {
  202. logger.Get().Errorf("SaveData err = %s\n", err.Error())
  203. }
  204. return
  205. }
  206. const (
  207. Off = iota
  208. On
  209. )
  210. type TimeControl struct {
  211. start time.Time
  212. end time.Time
  213. state int
  214. }
  215. func getDeviceState(schedules []TimeControl, currentTime time.Time) int {
  216. for _, period := range schedules {
  217. now := time.Date(0, time.January, 1, currentTime.Hour(), currentTime.Minute(), currentTime.Second(), currentTime.Nanosecond(), time.UTC)
  218. start := time.Date(0, time.January, 1, period.start.Hour(), period.start.Minute(), period.start.Second(), period.start.Nanosecond(), time.UTC)
  219. end := time.Date(0, time.January, 1, period.end.Hour(), period.end.Minute(), period.end.Second(), period.end.Nanosecond(), time.UTC)
  220. if start.After(end) { // 跨越午夜
  221. if now.After(start) || now.Before(end) {
  222. return period.state
  223. }
  224. } else { // 不跨越午夜
  225. if now.After(start) && now.Before(end) {
  226. return period.state
  227. }
  228. }
  229. }
  230. return Off
  231. }
  232. func stateTransition(str string) int {
  233. if str == "on1" || str == "on2" {
  234. return On
  235. } else {
  236. return Off
  237. }
  238. }
  239. func ss(on1, off1, on2, off2 string) (int, error) {
  240. deviceRecoveryTime := time.Now()
  241. // 定义时间映射
  242. deviceTime := map[string]string{
  243. "on1": on1,
  244. "off1": off1,
  245. "on2": on2,
  246. "off2": off2,
  247. }
  248. // 创建一个切片存储时间
  249. var times []struct {
  250. key string
  251. value time.Time
  252. }
  253. // 将时间字符串解析为 time.Time 对象,并存入切片
  254. for key, value := range deviceTime {
  255. if value == "关闭" {
  256. continue
  257. }
  258. t, err := time.Parse("15:04", value)
  259. if err != nil {
  260. logger.Get().Error("时间转换失败!" + err.Error())
  261. return 0, err
  262. }
  263. times = append(times, struct {
  264. key string
  265. value time.Time
  266. }{key, t})
  267. }
  268. // 对时间进行排序
  269. sort.Slice(times, func(i, j int) bool {
  270. return times[i].value.Before(times[j].value)
  271. })
  272. var timeControls []TimeControl
  273. for i, _ := range times {
  274. if len(times) == i+1 {
  275. timeControls = append(timeControls, TimeControl{start: times[i].value, end: times[0].value.Add(24 * time.Hour), state: stateTransition(times[i].key)})
  276. continue
  277. }
  278. timeControls = append(timeControls, TimeControl{start: times[i].value, end: times[i+1].value, state: stateTransition(times[i].key)})
  279. }
  280. for _, control := range timeControls {
  281. fmt.Printf("%s : %s : %d\n", control.start, control.end, control.state)
  282. }
  283. // 在恢复时检查状态
  284. state := getDeviceState(timeControls, deviceRecoveryTime)
  285. fmt.Printf("%s %d\n", timeControls, state)
  286. return state, nil
  287. }