deviceMgr.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. package tcp
  2. import (
  3. "encoding/hex"
  4. "errors"
  5. "fmt"
  6. "go.uber.org/zap"
  7. "gorm.io/gorm"
  8. "net"
  9. Dev "server/dao/devices"
  10. deviceDao "server/dao/devices"
  11. promodel "server/model/common/devices"
  12. "server/model/common/request"
  13. "server/protocol"
  14. "server/utils/logger"
  15. "strings"
  16. "time"
  17. )
  18. var (
  19. devices = make(map[string]Device) // 存储连接的全局 map
  20. )
  21. type Device struct {
  22. info deviceDao.Screens
  23. conn net.Conn
  24. lastTime time.Time
  25. stopChan chan struct{} // 添加停止通道
  26. }
  27. func (s *Device) Start(conn net.Conn) {
  28. s.conn = conn
  29. s.stopChan = make(chan struct{})
  30. go s.Process()
  31. go s.Handle()
  32. }
  33. func (s *Device) Process() {
  34. // 函数执行完之后关闭连接
  35. defer s.conn.Close()
  36. for {
  37. buf := make([]byte, 256)
  38. // 将tcp连接读取到的数据读取到byte数组中, 返回读取到的byte的数目
  39. n, err := s.conn.Read(buf)
  40. if err != nil {
  41. // 从客户端读取数据的过程中发生错误 这里如果没读到可以视为设备离线了
  42. logger.Logger.Errorf("read from client failed [离线了], err:%v", err)
  43. break
  44. }
  45. data := hex.EncodeToString(buf[:n])
  46. if !strings.Contains(strings.ToLower(data), "fe5c4b89") {
  47. continue
  48. }
  49. switch data[16:18] {
  50. case "61":
  51. // fe5c4b89 2a000000 62 00000000 17000000 31 23 32303233(年) 3035(月) 3135(日) 3031(星期) 3038(时) 3334(分) 3135(秒) 23 303630(心跳包时间) 23 ffff
  52. buffer := protocol.AuthDataPack{}.AuthLogin()
  53. // 通过sn 查设备是否存在 不存在return 存在就保存con 和 info
  54. screens, err := deviceDao.QueryScreenBySn(data[34:50])
  55. if errors.Is(err, gorm.ErrRecordNotFound) {
  56. logger.Logger.Errorf("Process[case '61'] SN not found \n")
  57. break
  58. }
  59. err = Dev.UpdateScreensStatusAndOnline(screens.ScreensCode, request.DeviceStatus{
  60. Status: 1,
  61. PlayStatus: 1,
  62. DisplayStatus: 1,
  63. SourceStatus: 1,
  64. })
  65. if err != nil {
  66. logger.Logger.Error("[Handle] UpdateScreensStatus err", zap.Error(err))
  67. continue
  68. }
  69. s.info = screens
  70. devices[s.info.Sn] = *s
  71. s.conn.Write(buffer.Bytes())
  72. logger.Logger.Debugf("设备 [%v] 登录", s.info.ScreensName)
  73. case "91":
  74. //判断内存devices中是否存储了设备(连接)信息
  75. if _, exists := devices[data[34:50]]; !exists {
  76. //不存在
  77. screens, err := deviceDao.QueryScreenBySn(data[34:50])
  78. if errors.Is(err, gorm.ErrRecordNotFound) {
  79. logger.Logger.Errorf("Process[case '91'] SN not found \n")
  80. break
  81. }
  82. s.info = screens
  83. devices[s.info.Sn] = *s
  84. //如果是未登录状态,则登录并更新在线时间
  85. if screens.IsLogin == 0 {
  86. _ = Dev.UpdateScreensStatusAndOnline(screens.ScreensCode, request.DeviceStatus{
  87. Status: s.info.Status,
  88. PlayStatus: s.info.PlayStatus,
  89. DisplayStatus: s.info.DisplayStatus,
  90. SourceStatus: s.info.SourceStatus,
  91. })
  92. }
  93. }
  94. logger.Logger.Debugf("设备 [%v] 心跳", s.info.ScreensName)
  95. if data[34:50] != s.info.Sn {
  96. continue
  97. }
  98. s.UpdateInfo(data[82:84], data[86:88], data[90:92])
  99. default:
  100. fmt.Println("读取:", data)
  101. }
  102. }
  103. }
  104. func (s *Device) Handle() {
  105. defer s.conn.Close()
  106. t2 := time.NewTicker(6 * time.Minute) //在线监测
  107. defer t2.Stop()
  108. for {
  109. select {
  110. case <-t2.C:
  111. state := request.DeviceStatus{
  112. Status: 1,
  113. PlayStatus: s.info.PlayStatus,
  114. DisplayStatus: s.info.DisplayStatus,
  115. SourceStatus: s.info.SourceStatus,
  116. }
  117. if time.Now().Add(-5*time.Minute).After(s.lastTime) || s.lastTime.IsZero() {
  118. //离线
  119. state.Status = 0
  120. err := Dev.UpdateScreensStatusAndOffline(s.info.ScreensCode, state)
  121. if err != nil {
  122. logger.Logger.Error("[Handle] UpdateScreensStatus err", zap.Error(err))
  123. continue
  124. }
  125. s.conn.Close()
  126. close(s.stopChan) // 通知协程停止
  127. delete(devices, s.info.Sn) //从内存中移除连接
  128. logger.Logger.Debugf("设备 [%v] 离线了...", s.info.ScreensName)
  129. return // 结束 Handle 协程
  130. } else {
  131. logger.Logger.Debugf("设备 [%s] 在线", s.info.ScreensCode)
  132. }
  133. //修改数据库状态
  134. err := Dev.UpdateScreensStatus(s.info.ScreensCode, state)
  135. if err != nil {
  136. logger.Logger.Error("[Handle] UpdateScreensStatus err", zap.Error(err))
  137. continue
  138. }
  139. break
  140. default:
  141. continue
  142. }
  143. }
  144. }
  145. func (s *Device) UpdateInfo(playStatus, displayStatus, sourceStatus string) {
  146. play, display, source := 0, 0, 0
  147. if playStatus == "31" {
  148. play = 1
  149. }
  150. if displayStatus == "30" {
  151. display = 1
  152. }
  153. if sourceStatus == "30" {
  154. source = 1
  155. }
  156. s.info.Status = 1
  157. s.info.PlayStatus = play
  158. s.info.DisplayStatus = display
  159. s.info.SourceStatus = source
  160. s.lastTime = time.Now()
  161. }
  162. func (s *Device) SwitchScreen(onOff int) error {
  163. if s.conn == nil {
  164. return errors.New("connection is nil")
  165. }
  166. pack := protocol.SwitchDataPack{Type: 0x52} //熄屏
  167. if onOff == 1 {
  168. pack = protocol.SwitchDataPack{Type: 0x51} //亮屏
  169. }
  170. buf := pack.SwitchScreens() //获取开关屏指令
  171. _, err := s.conn.Write(buf.Bytes())
  172. if err != nil {
  173. logger.Logger.Errorf("SwitchScreen write failed, err:%v", err)
  174. return err
  175. }
  176. return nil
  177. }
  178. func (s *Device) SendInternalCode(content []promodel.InternalCodeContent) error {
  179. if s.conn == nil {
  180. return errors.New("connection is nil")
  181. }
  182. pack := protocol.InternalCodeDataPack{}
  183. //获取要写入连接的字节数组
  184. buf := pack.SendInternalCode(content)
  185. _, err := s.conn.Write(buf.Bytes())
  186. if err != nil {
  187. logger.Logger.Errorf("SendInternalCode write failed, err:%v", err)
  188. return err
  189. }
  190. return nil
  191. }
  192. func (s *Device) VoiceBroad(broad string) error {
  193. if s.conn == nil {
  194. return errors.New("connection is nil")
  195. }
  196. pack := protocol.VoiceBroadDataPack{}
  197. buf := pack.VoiceBroad(broad)
  198. _, err := s.conn.Write(buf.Bytes())
  199. if err != nil {
  200. logger.Logger.Errorf("VoiceBroad write failed, err:%v", err)
  201. return err
  202. }
  203. return nil
  204. }
  205. func (s *Device) SetBrightness(bright byte) error {
  206. if s.conn == nil {
  207. return errors.New("connection is nil")
  208. }
  209. pack := protocol.SetBrightnessDataPack{}
  210. buf := pack.SetBrightness(bright)
  211. _, err := s.conn.Write(buf.Bytes())
  212. if err != nil {
  213. logger.Logger.Errorf("SetBrightness write failed, err:%v", err)
  214. return err
  215. }
  216. return nil
  217. }
  218. func SwitchScreen(sn string, onOff int) error {
  219. device := devices[sn]
  220. err := device.SwitchScreen(onOff)
  221. if err != nil {
  222. return err
  223. }
  224. return nil
  225. }
  226. func SendInternalCode(sn string, content []promodel.InternalCodeContent) error {
  227. device := devices[sn]
  228. err := device.SendInternalCode(content)
  229. if err != nil {
  230. return err
  231. }
  232. return nil
  233. }
  234. func VoiceBroad(sn string, broad string) error {
  235. device := devices[sn]
  236. err := device.VoiceBroad(broad)
  237. if err != nil {
  238. return err
  239. }
  240. return nil
  241. }
  242. func SetBrightness(sn string, bright int) error {
  243. device := devices[sn]
  244. err := device.SetBrightness(brightnessMap[bright])
  245. if err != nil {
  246. return err
  247. }
  248. return nil
  249. }
  250. var brightnessMap = map[int]byte{
  251. 0: 0x19,
  252. 10: 0x18,
  253. 20: 0x16,
  254. 30: 0x14,
  255. 40: 0x12,
  256. 50: 0x10,
  257. 60: 0x08,
  258. 70: 0x06,
  259. 80: 0x04,
  260. 90: 0x02,
  261. 100: 0x00,
  262. }