cabinet_channel.go 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. package service
  2. import (
  3. "dy-admin/internal/pcmserver/bus/cabinet_pkg"
  4. "dy-admin/internal/pcmserver/bus/cabinet_pkg/dataProto"
  5. "dy-admin/internal/pcmserver/bus/model"
  6. "dy-admin/pkg/log"
  7. "go.uber.org/zap"
  8. "strconv"
  9. "sync"
  10. )
  11. var cabinetMapChannel *cabinetsChannel
  12. type cabinetChannel struct {
  13. cabinetConnectChan chan *dataProto.CabinetConnect
  14. gridStatusChan chan *dataProto.GridStatsProto
  15. openStatusChan chan *dataProto.GridLockStatusProto
  16. }
  17. type cabinetsChannel struct {
  18. cabinetMapChannel map[int]*cabinetChannel
  19. mutex *sync.Mutex
  20. }
  21. func newCabinetsChannel() {
  22. if cabinetMapChannel == nil {
  23. cabinetMapChannel = &cabinetsChannel{
  24. cabinetMapChannel: make(map[int]*cabinetChannel),
  25. mutex: &sync.Mutex{},
  26. }
  27. }
  28. }
  29. func (cc *cabinetsChannel) setCabinetChannel(cabinetId int) *cabinetChannel {
  30. cc.mutex.Lock()
  31. defer cc.mutex.Unlock()
  32. channels := &cabinetChannel{
  33. cabinetConnectChan: make(chan *dataProto.CabinetConnect),
  34. gridStatusChan: make(chan *dataProto.GridStatsProto, 1024),
  35. openStatusChan: make(chan *dataProto.GridLockStatusProto, 1024),
  36. }
  37. go watchChannel(cabinetId, channels)
  38. cc.cabinetMapChannel[cabinetId] = channels
  39. return channels
  40. }
  41. func (cc *cabinetsChannel) deleteCabinetChannel(cabinetId int) {
  42. cc.mutex.Lock()
  43. defer cc.mutex.Unlock()
  44. channels, ok := cc.cabinetMapChannel[cabinetId]
  45. if !ok {
  46. return
  47. }
  48. close(channels.cabinetConnectChan)
  49. close(channels.gridStatusChan)
  50. close(channels.openStatusChan)
  51. }
  52. func watchChannel(cabinetId int, channels *cabinetChannel) {
  53. for {
  54. select {
  55. // 推送柜子连接信息
  56. case connectInfo, ok := <-channels.cabinetConnectChan:
  57. if !ok {
  58. return
  59. }
  60. var dbConnected = "断开"
  61. if connectInfo.IsConnected {
  62. dbConnected = "连接"
  63. }
  64. // 数据库更新
  65. err := ServicesGroupApp.CabinetService.ChangeCabinetConnectStatus(cabinetId, dbConnected)
  66. if err != nil {
  67. log.Error("update cabinet connect err", zap.Error(err))
  68. continue
  69. }
  70. // 推送格子状态,关门后触发
  71. case gridStatusInfo, ok := <-channels.gridStatusChan:
  72. if !ok {
  73. return
  74. }
  75. deviceGridId := int(gridStatusInfo.GridNumber)
  76. // 获取格子信息
  77. grid, err := ServicesGroupApp.GridService.GetGridByCabinetIDAndGridID(cabinetId, deviceGridId)
  78. if err != nil {
  79. log.Error("get grid err", zap.Error(err))
  80. continue
  81. }
  82. oldGridStore := grid.StoneState
  83. // 格子的状态
  84. if grid.Staff.ID == 0 {
  85. // 格子未被占用。什么都不记录
  86. log.Info("grid.staff is nil,do nothing", zap.Any("gridStatusInfo", gridStatusInfo))
  87. continue
  88. }
  89. // 格子被占用,将设备推送的格子信息转换为本地格子信息
  90. grid.ChargeState = model.GridRechargeMap[gridStatusInfo.CellStatus]
  91. grid.OpenState = model.GridOpenStateMap[gridStatusInfo.LockStatus]
  92. grid.StoneState = model.GridStoneStateMap[gridStatusInfo.StoreStatus]
  93. grid.RFID = strconv.FormatUint(uint64(gridStatusInfo.RFID), 10)
  94. // 如果之前的就是存物未登记,不重复执行更新格子和记录日志
  95. if grid.StoneState == oldGridStore && oldGridStore == model.GridStoneStateMap[model.GridNoMatchStoneCode] {
  96. log.Info("物品未登记,重复记录", zap.Int("CabinetID", grid.CabinetID), zap.Int("DeviceGridID", grid.DeviceGridID))
  97. continue
  98. }
  99. // 格子最终状态判断和日志记录
  100. processGridStatus(&grid, oldGridStore)
  101. err = ServicesGroupApp.GridService.UpdateGrid(grid)
  102. if err != nil {
  103. log.Error("update gird open status err", zap.Error(err))
  104. continue
  105. }
  106. // 推送柜门状态,开门响应
  107. case openStatus, ok := <-channels.openStatusChan:
  108. if !ok {
  109. return
  110. }
  111. deviceGridId := int(openStatus.GridNumber)
  112. // 获取格子信息
  113. grid, err := ServicesGroupApp.GridService.GetGridByCabinetIDAndGridID(cabinetId, deviceGridId)
  114. if err != nil {
  115. log.Error("get grid err", zap.Error(err))
  116. continue
  117. }
  118. if grid.Staff.ID == 0 {
  119. // 格子未被占用。什么都不记录
  120. log.Info("grid.staff is nil,do nothing", zap.Any("openStatusInfo", openStatus))
  121. continue
  122. }
  123. grid.OpenState = model.GridOpenStateMap[openStatus.LockStatus]
  124. processOpenGridStatus(&grid)
  125. err = createOpenLog(&grid)
  126. if err != nil {
  127. log.Error("createOpenLog err", zap.Error(err))
  128. }
  129. // 更新格子门状态
  130. err = ServicesGroupApp.GridService.UpdateByCabinetIDAndGridID(model.Grid{
  131. CabinetID: cabinetId,
  132. DeviceGridID: deviceGridId,
  133. OpenState: model.GridOpenStateMap[openStatus.LockStatus],
  134. })
  135. if err != nil {
  136. log.Error("update gird open status err", zap.Error(err))
  137. continue
  138. }
  139. }
  140. }
  141. }
  142. // 根据当前推送的信息,判断格子最终状态。并记录日志
  143. func processGridStatus(grid *model.Grid, oldStoneStatus string) {
  144. // 判断是否报警逻辑
  145. cabinet := cabinet_pkg.GetCabinet(grid.CabinetID)
  146. if cabinet == nil {
  147. log.Error("processGridStatus cabinet is nil")
  148. return
  149. }
  150. var iswarn bool
  151. // 如果格子中的人员为请假
  152. if grid.Staff.VacationState == 2 {
  153. // 柜子人员为请假状态
  154. grid.ColorStatus = "黄色"
  155. grid.GridInfo = "请假中"
  156. } else {
  157. if grid.StoneState == model.GridStoneStateMap[model.GridNoStoneStateCode] {
  158. // 格子未存物
  159. if !cabinet.IsAllowOpen {
  160. // 柜子不允许开 并且未存物 -报警
  161. // 报警
  162. iswarn = true
  163. grid.ColorStatus = "红色"
  164. if oldStoneStatus == model.GridStoneStateMap[model.GridNoStoneStateCode] {
  165. // 之前格子就没存入
  166. grid.GridInfo = "未存入"
  167. } else if oldStoneStatus == model.GridStoneStateMap[model.GridStoneStateCode] {
  168. // 之前格子有,现在没了,被视为取出
  169. grid.GridInfo = "非正常取出"
  170. }
  171. } else {
  172. // 柜子允许开 未存物 -正常
  173. grid.ColorStatus = "绿色"
  174. grid.GridInfo = "已取出"
  175. }
  176. } else if grid.StoneState == model.GridStoneStateMap[model.GridStoneStateCode] {
  177. // 格子存物了
  178. grid.ColorStatus = "绿色"
  179. grid.GridInfo = grid.ChargeState
  180. } else if grid.StoneState == model.GridStoneStateMap[model.GridNoMatchStoneCode] {
  181. // 物品未登记
  182. iswarn = true
  183. grid.ColorStatus = "红色"
  184. grid.GridInfo = grid.StoneState
  185. }
  186. }
  187. var err error
  188. if iswarn {
  189. err = createWarnLog(grid)
  190. if err != nil {
  191. log.Error("createWarnLog err", zap.Error(err))
  192. }
  193. go func() {
  194. memInfo := cabinet_pkg.GetCabinet(grid.CabinetID)
  195. err = sendDeptWarnLog(memInfo.DeptID, true, nil)
  196. if err != nil {
  197. log.Error("sendUpdateCabinetOpenStatus", zap.Error(err))
  198. }
  199. }()
  200. }
  201. err = createStoreLog(grid)
  202. if err != nil {
  203. log.Error("createStoreLog err", zap.Error(err))
  204. }
  205. err = createOpenLog(grid)
  206. if err != nil {
  207. log.Error("createOpenLog err", zap.Error(err))
  208. }
  209. }
  210. // 根据开门响应推送的信息,记录是否报警的日志
  211. func processOpenGridStatus(grid *model.Grid) {
  212. // 判断是否报警逻辑
  213. cabinet := cabinet_pkg.GetCabinet(grid.CabinetID)
  214. if cabinet == nil {
  215. log.Error("processGridStatus cabinet is nil")
  216. return
  217. }
  218. if cabinet_pkg.IsHumanization() {
  219. // 人性化管理时,不允许开门时打开门,记录警告日志
  220. if !cabinet.IsAllowOpen {
  221. // 柜子当前是不允许开的,发出警告
  222. grid.ColorStatus = "红色"
  223. grid.GridInfo = "在规定时间以外开门"
  224. err := createWarnLog(grid)
  225. if err != nil {
  226. log.Error("createWarnLog err", zap.Error(err))
  227. }
  228. go func() {
  229. memInfo := cabinet_pkg.GetCabinet(grid.CabinetID)
  230. err = sendDeptWarnLog(memInfo.DeptID, true, nil)
  231. if err != nil {
  232. log.Error("sendUpdateCabinetOpenStatus", zap.Error(err))
  233. }
  234. }()
  235. }
  236. }
  237. // 任何时候,如果出现非指令开锁,报警
  238. if grid.OpenState == model.GridNoCmdState {
  239. grid.ColorStatus = "红色"
  240. grid.GridInfo = model.GridNoCmdState
  241. err := createWarnLog(grid)
  242. if err != nil {
  243. log.Error("createWarnLog err", zap.Error(err))
  244. }
  245. go func() {
  246. memInfo := cabinet_pkg.GetCabinet(grid.CabinetID)
  247. err = sendDeptWarnLog(memInfo.DeptID, true, nil)
  248. if err != nil {
  249. log.Error("sendUpdateCabinetOpenStatus", zap.Error(err))
  250. }
  251. }()
  252. }
  253. }
  254. func createWarnLog(grid *model.Grid) error {
  255. lg := model.GridWarnLog{
  256. DepartmentID: grid.Staff.DepartmentID,
  257. DepartmentName: grid.Staff.Name,
  258. StaffID: grid.Staff.ID,
  259. StaffName: grid.Staff.Name,
  260. CabinetID: grid.CabinetID,
  261. CabinetName: grid.Staff.CabinetName,
  262. GridDeviceID: grid.DeviceGridID,
  263. WarnState: grid.GridInfo,
  264. }
  265. err := ServicesGroupApp.GridWarnLogService.CreateGridWarnLog(lg)
  266. return err
  267. }
  268. func createStoreLog(grid *model.Grid) error {
  269. lg := model.GridStoreLog{
  270. DepartmentID: grid.Staff.DepartmentID,
  271. DepartmentName: grid.Staff.Name,
  272. StaffID: grid.Staff.ID,
  273. StaffName: grid.Staff.Name,
  274. CabinetID: grid.CabinetID,
  275. CabinetName: grid.Staff.CabinetName,
  276. GridDeviceID: grid.DeviceGridID,
  277. StoreState: grid.StoneState,
  278. }
  279. err := ServicesGroupApp.GridStoreLogService.CreateGridStoreLog(lg)
  280. return err
  281. }
  282. func createOpenLog(grid *model.Grid) error {
  283. lg := model.GridOpenLog{
  284. DepartmentID: grid.Staff.DepartmentID,
  285. DepartmentName: grid.Staff.Name,
  286. StaffID: grid.Staff.ID,
  287. StaffName: grid.Staff.Name,
  288. CabinetID: grid.CabinetID,
  289. CabinetName: grid.Staff.CabinetName,
  290. GridDeviceID: grid.DeviceGridID,
  291. OpenState: grid.OpenState,
  292. }
  293. err := ServicesGroupApp.GridOpenLogService.CreateGridOpenLog(lg)
  294. return err
  295. }