cron.go 8.9 KB

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