cron.go 8.6 KB

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