123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- package tcp
- import (
- "encoding/hex"
- "errors"
- "fmt"
- "go.uber.org/zap"
- "gorm.io/gorm"
- "net"
- Dev "server/dao/devices"
- deviceDao "server/dao/devices"
- promodel "server/model/common/devices"
- "server/model/common/request"
- "server/protocol"
- "server/utils/logger"
- "strings"
- "time"
- )
- var (
- devices = make(map[string]Device) // 存储连接的全局 map
- )
- type Device struct {
- info deviceDao.Screens
- conn net.Conn
- lastTime time.Time
- stopChan chan struct{} // 添加停止通道
- }
- func (s *Device) Start(conn net.Conn) {
- s.conn = conn
- s.stopChan = make(chan struct{})
- go s.Process()
- go s.Handle()
- }
- func (s *Device) Process() {
- // 函数执行完之后关闭连接
- defer s.conn.Close()
- for {
- buf := make([]byte, 256)
- // 将tcp连接读取到的数据读取到byte数组中, 返回读取到的byte的数目
- n, err := s.conn.Read(buf)
- if err != nil {
- // 从客户端读取数据的过程中发生错误
- logger.Logger.Errorf("read from client failed, err:%v", err)
- break
- }
- data := hex.EncodeToString(buf[:n])
- if !strings.Contains(strings.ToLower(data), "fe5c4b89") {
- continue
- }
- switch data[16:18] {
- case "61":
- logger.Logger.Debug("登录")
- // fe5c4b89 2a000000 62 00000000 17000000 31 23 32303233(年) 3035(月) 3135(日) 3031(星期) 3038(时) 3334(分) 3135(秒) 23 303630(心跳包时间) 23 ffff
- buffer := protocol.AuthDataPack{}.AuthLogin()
- // 通过sn 查设备是否存在 不存在return 存在就保存con 和 info
- screens, err := deviceDao.QueryScreenBySn(data[34:50])
- if errors.Is(err, gorm.ErrRecordNotFound) {
- logger.Logger.Errorf("Process SN not found \n")
- break
- }
- s.info = screens
- devices[s.info.Sn] = *s
- s.conn.Write(buffer.Bytes())
- case "91":
- logger.Logger.Debug("心跳")
- if data[34:50] != s.info.Sn {
- continue
- }
- s.UpdateInfo(data[82:84], data[86:88], data[90:92])
- default:
- fmt.Println("读取:", data)
- }
- }
- }
- func (s *Device) Handle() {
- defer s.conn.Close()
- t2 := time.NewTicker(3 * time.Minute) //在线监测
- defer t2.Stop()
- for {
- select {
- case <-t2.C:
- state := request.DeviceStatus{
- Status: 1,
- PlayStatus: 1,
- DisplayStatus: 1,
- SourceStatus: 1,
- }
- if time.Now().Add(-2*time.Minute).After(s.lastTime) && !s.lastTime.IsZero() {
- //离线
- state.Status = 0
- state.PlayStatus = 0
- state.DisplayStatus = 0
- state.SourceStatus = 0
- err := Dev.UpdateScreensStatus(s.info.ScreensCode, state)
- if err != nil {
- logger.Logger.Error("UpdateScreensStatus err", zap.Error(err))
- continue
- }
- s.conn.Close()
- close(s.stopChan) // 通知协程停止
- return // 结束 Handle 协程
- } else {
- logger.Logger.Debugf("%s在线", s.info.ScreensCode)
- }
- //修改数据库状态
- err := Dev.UpdateScreensStatus(s.info.ScreensCode, state)
- if err != nil {
- logger.Logger.Error("UpdateScreensStatus err", zap.Error(err))
- continue
- }
- break
- default:
- continue
- }
- }
- }
- func (s *Device) UpdateInfo(playStatus, displayStatus, sourceStatus string) {
- play, display, source := 0, 0, 0
- if playStatus == "31" {
- play = 1
- }
- if displayStatus == "30" {
- display = 1
- }
- if sourceStatus == "30" {
- source = 1
- }
- s.info.Status = 1
- s.info.PlayStatus = play
- s.info.DisplayStatus = display
- s.info.SourceStatus = source
- s.lastTime = time.Now()
- }
- func (s *Device) SwitchScreen(onOff int) error {
- pack := protocol.SwitchDataPack{Type: 0x52} //熄屏
- if onOff == 1 {
- pack = protocol.SwitchDataPack{Type: 0x51} //亮屏
- }
- buf := pack.SwitchScreens() //获取开关屏指令
- _, err := s.conn.Write(buf.Bytes())
- if err != nil {
- logger.Logger.Errorf("SwitchScreen write failed, err:%v", err)
- return err
- }
- return nil
- }
- func (s *Device) SendInternalCode(content []promodel.InternalCodeContent) error {
- pack := protocol.InternalCodeDataPack{}
- //获取要写入连接的字节数组
- buf := pack.SendInternalCode(content)
- _, err := s.conn.Write(buf.Bytes())
- if err != nil {
- logger.Logger.Errorf("SendInternalCode write failed, err:%v", err)
- return err
- }
- return nil
- }
- func (s *Device) VoiceBroad(broad string) error {
- pack := protocol.VoiceBroadDataPack{}
- buf := pack.VoiceBroad(broad)
- _, err := s.conn.Write(buf.Bytes())
- if err != nil {
- logger.Logger.Errorf("VoiceBroad write failed, err:%v", err)
- return err
- }
- return nil
- }
- // 向外暴露的开关操作
- func SwitchScreen(sn string, onOff int) error {
- device := devices[sn]
- err := device.SwitchScreen(onOff)
- if err != nil {
- return err
- }
- return nil
- }
- // 向外暴露的发送内码文字操作
- func SendInternalCode(sn string, content []promodel.InternalCodeContent) error {
- device := devices[sn]
- err := device.SendInternalCode(content)
- if err != nil {
- return err
- }
- return nil
- }
- // 向外暴露的远程喊话操作
- func VoiceBroad(sn string, broad string) error {
- device := devices[sn]
- err := device.VoiceBroad(broad)
- if err != nil {
- return err
- }
- return nil
- }
|