|
@@ -10,7 +10,6 @@ import (
|
|
|
Dev "server/dao/devices"
|
|
|
deviceDao "server/dao/devices"
|
|
|
promodel "server/model/common/devices"
|
|
|
- "server/model/common/request"
|
|
|
"server/protocol"
|
|
|
"server/utils/logger"
|
|
|
"strings"
|
|
@@ -18,30 +17,40 @@ import (
|
|
|
)
|
|
|
|
|
|
var (
|
|
|
- devices = make(map[string]Device) // 存储连接的全局 map
|
|
|
+ Devices = make(map[string]*Device) // 存储连接的全局 map
|
|
|
)
|
|
|
|
|
|
type Device struct {
|
|
|
- info deviceDao.Screens
|
|
|
- conn net.Conn
|
|
|
- lastTime time.Time
|
|
|
- stopChan chan struct{} // 添加停止通道
|
|
|
+ Info deviceDao.Screens
|
|
|
+ Conn net.Conn
|
|
|
+ LastTime time.Time
|
|
|
+}
|
|
|
+
|
|
|
+// 实例所有设备
|
|
|
+func InitDevices() {
|
|
|
+ // 将数据库中的设备全部离线
|
|
|
+ devs, _ := deviceDao.QueryAllScreens()
|
|
|
+ for _, screen := range devs {
|
|
|
+ if screen.Status != 0 {
|
|
|
+ screen.Status = 0
|
|
|
+ screen.LastOfflineTime = time.Now()
|
|
|
+ }
|
|
|
+ Devices[screen.Sn] = &Device{Info: screen}
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
func (s *Device) Start(conn net.Conn) {
|
|
|
- s.conn = conn
|
|
|
- s.stopChan = make(chan struct{})
|
|
|
+ s.Conn = conn
|
|
|
go s.Process()
|
|
|
- go s.Handle()
|
|
|
}
|
|
|
|
|
|
func (s *Device) Process() {
|
|
|
// 函数执行完之后关闭连接
|
|
|
- defer s.conn.Close()
|
|
|
+ defer s.Conn.Close()
|
|
|
for {
|
|
|
buf := make([]byte, 256)
|
|
|
// 将tcp连接读取到的数据读取到byte数组中, 返回读取到的byte的数目
|
|
|
- n, err := s.conn.Read(buf)
|
|
|
+ n, err := s.Conn.Read(buf)
|
|
|
if err != nil {
|
|
|
// 从客户端读取数据的过程中发生错误 这里如果没读到可以视为设备离线了
|
|
|
logger.Logger.Errorf("read from client failed [离线了], err:%v", err)
|
|
@@ -61,119 +70,60 @@ func (s *Device) Process() {
|
|
|
logger.Logger.Errorf("Process[case '61'] SN not found \n")
|
|
|
break
|
|
|
}
|
|
|
-
|
|
|
- err = Dev.UpdateScreensStatusAndOnline(screens.ScreensCode, request.DeviceStatus{
|
|
|
- Status: 1,
|
|
|
- PlayStatus: 1,
|
|
|
- DisplayStatus: 1,
|
|
|
- SourceStatus: 1,
|
|
|
- })
|
|
|
- if err != nil {
|
|
|
- logger.Logger.Error("[Handle] UpdateScreensStatus err", zap.Error(err))
|
|
|
- continue
|
|
|
- }
|
|
|
-
|
|
|
- s.info = screens
|
|
|
- devices[s.info.Sn] = *s
|
|
|
- s.conn.Write(buffer.Bytes())
|
|
|
- logger.Logger.Debugf("设备 [%v] 登录", s.info.ScreensName)
|
|
|
+ s.Info = screens
|
|
|
+ Devices[s.Info.Sn] = s
|
|
|
+ s.Conn.Write(buffer.Bytes())
|
|
|
+ logger.Logger.Debugf("设备 [%v] 登录", s.Info.ScreensName)
|
|
|
case "91":
|
|
|
- //判断内存devices中是否存储了设备(连接)信息
|
|
|
- if _, exists := devices[data[34:50]]; !exists {
|
|
|
- //不存在
|
|
|
- screens, err := deviceDao.QueryScreenBySn(data[34:50])
|
|
|
- if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
|
- logger.Logger.Errorf("Process[case '91'] SN not found \n")
|
|
|
- break
|
|
|
- }
|
|
|
- s.info = screens
|
|
|
- devices[s.info.Sn] = *s
|
|
|
-
|
|
|
- //如果是未登录状态,则登录并更新在线时间
|
|
|
- if screens.IsLogin == 0 {
|
|
|
- _ = Dev.UpdateScreensStatusAndOnline(screens.ScreensCode, request.DeviceStatus{
|
|
|
- Status: s.info.Status,
|
|
|
- PlayStatus: s.info.PlayStatus,
|
|
|
- DisplayStatus: s.info.DisplayStatus,
|
|
|
- SourceStatus: s.info.SourceStatus,
|
|
|
- })
|
|
|
+ dev := Devices[data[34:50]]
|
|
|
+ if dev.Info.Status == 0 {
|
|
|
+ state := 1
|
|
|
+ //上线 则修改数据库上线时间
|
|
|
+ err := Dev.UpdateScreensStatusAndOnline(dev.Info.ScreensCode, state)
|
|
|
+ if err != nil {
|
|
|
+ logger.Logger.Error("Process[case '91'] UpdateScreensStatusAndOnline err", zap.Error(err))
|
|
|
+ continue
|
|
|
}
|
|
|
+ dev.Info.Status = 1
|
|
|
+ dev.Info.LastOnlineTime = time.Now()
|
|
|
+ logger.Logger.Debugf("设备 [%v] 上线", dev.Info.ScreensName)
|
|
|
}
|
|
|
- logger.Logger.Debugf("设备 [%v] 心跳", s.info.ScreensName)
|
|
|
- if data[34:50] != s.info.Sn {
|
|
|
- continue
|
|
|
- }
|
|
|
- s.UpdateInfo(data[82:84], data[86:88], data[90:92])
|
|
|
+ dev.Conn = s.Conn
|
|
|
+ dev.LastTime = time.Now()
|
|
|
+ logger.Logger.Debugf("设备 [%v] 心跳", dev.Info.ScreensName)
|
|
|
default:
|
|
|
fmt.Println("读取:", data)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func (s *Device) Handle() {
|
|
|
- defer s.conn.Close()
|
|
|
- t2 := time.NewTicker(6 * time.Minute) //在线监测
|
|
|
- defer t2.Stop()
|
|
|
-
|
|
|
+func IsOnline() {
|
|
|
+ t := time.NewTicker(1 * time.Minute) //每分钟
|
|
|
for {
|
|
|
select {
|
|
|
- case <-t2.C:
|
|
|
- state := request.DeviceStatus{
|
|
|
- Status: 1,
|
|
|
- PlayStatus: s.info.PlayStatus,
|
|
|
- DisplayStatus: s.info.DisplayStatus,
|
|
|
- SourceStatus: s.info.SourceStatus,
|
|
|
- }
|
|
|
- if time.Now().Add(-5*time.Minute).After(s.lastTime) || s.lastTime.IsZero() {
|
|
|
- //离线
|
|
|
- state.Status = 0
|
|
|
- err := Dev.UpdateScreensStatusAndOffline(s.info.ScreensCode, state)
|
|
|
- if err != nil {
|
|
|
- logger.Logger.Error("[Handle] UpdateScreensStatus err", zap.Error(err))
|
|
|
- continue
|
|
|
+ case <-t.C:
|
|
|
+ for _, device := range Devices {
|
|
|
+ //符合条件
|
|
|
+ if (time.Now().Add(-5*time.Minute).After(device.LastTime) || device.LastTime.IsZero()) && device.Info.Status != 0 {
|
|
|
+ //修改数据库和内存
|
|
|
+ //离线
|
|
|
+ state := 0
|
|
|
+ err := Dev.UpdateScreensStatusAndOffline(device.Info.ScreensCode, state)
|
|
|
+ if err != nil {
|
|
|
+ logger.Logger.Error("[Handle] UpdateScreensStatus err", zap.Error(err))
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ device.Info.Status = 0
|
|
|
+ device.Info.LastOfflineTime = time.Now()
|
|
|
+ logger.Logger.Debugf("设备 [%v] 离线了...", device.Info.ScreensName)
|
|
|
}
|
|
|
-
|
|
|
- s.conn.Close()
|
|
|
- close(s.stopChan) // 通知协程停止
|
|
|
- delete(devices, s.info.Sn) //从内存中移除连接
|
|
|
- logger.Logger.Debugf("设备 [%v] 离线了...", s.info.ScreensName)
|
|
|
- return // 结束 Handle 协程
|
|
|
- } else {
|
|
|
- logger.Logger.Debugf("设备 [%s] 在线", s.info.ScreensCode)
|
|
|
}
|
|
|
- //修改数据库状态
|
|
|
- err := Dev.UpdateScreensStatus(s.info.ScreensCode, state)
|
|
|
- if err != nil {
|
|
|
- logger.Logger.Error("[Handle] 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 {
|
|
|
- if s.conn == nil {
|
|
|
+ if s.Conn == nil {
|
|
|
return errors.New("connection is nil")
|
|
|
}
|
|
|
pack := protocol.SwitchDataPack{Type: 0x52} //熄屏
|
|
@@ -181,7 +131,7 @@ func (s *Device) SwitchScreen(onOff int) error {
|
|
|
pack = protocol.SwitchDataPack{Type: 0x51} //亮屏
|
|
|
}
|
|
|
buf := pack.SwitchScreens() //获取开关屏指令
|
|
|
- _, err := s.conn.Write(buf.Bytes())
|
|
|
+ _, err := s.Conn.Write(buf.Bytes())
|
|
|
if err != nil {
|
|
|
logger.Logger.Errorf("SwitchScreen write failed, err:%v", err)
|
|
|
return err
|
|
@@ -190,13 +140,13 @@ func (s *Device) SwitchScreen(onOff int) error {
|
|
|
}
|
|
|
|
|
|
func (s *Device) SendInternalCode(content []promodel.InternalCodeContent) error {
|
|
|
- if s.conn == nil {
|
|
|
+ if s.Conn == nil {
|
|
|
return errors.New("connection is nil")
|
|
|
}
|
|
|
pack := protocol.InternalCodeDataPack{}
|
|
|
//获取要写入连接的字节数组
|
|
|
buf := pack.SendInternalCode(content)
|
|
|
- _, err := s.conn.Write(buf.Bytes())
|
|
|
+ _, err := s.Conn.Write(buf.Bytes())
|
|
|
if err != nil {
|
|
|
logger.Logger.Errorf("SendInternalCode write failed, err:%v", err)
|
|
|
return err
|
|
@@ -206,12 +156,12 @@ func (s *Device) SendInternalCode(content []promodel.InternalCodeContent) error
|
|
|
}
|
|
|
|
|
|
func (s *Device) VoiceBroad(broad string) error {
|
|
|
- if s.conn == nil {
|
|
|
+ if s.Conn == nil {
|
|
|
return errors.New("connection is nil")
|
|
|
}
|
|
|
pack := protocol.VoiceBroadDataPack{}
|
|
|
buf := pack.VoiceBroad(broad)
|
|
|
- _, err := s.conn.Write(buf.Bytes())
|
|
|
+ _, err := s.Conn.Write(buf.Bytes())
|
|
|
if err != nil {
|
|
|
logger.Logger.Errorf("VoiceBroad write failed, err:%v", err)
|
|
|
return err
|
|
@@ -220,12 +170,12 @@ func (s *Device) VoiceBroad(broad string) error {
|
|
|
}
|
|
|
|
|
|
func (s *Device) SetBrightness(bright byte) error {
|
|
|
- if s.conn == nil {
|
|
|
+ if s.Conn == nil {
|
|
|
return errors.New("connection is nil")
|
|
|
}
|
|
|
pack := protocol.SetBrightnessDataPack{}
|
|
|
buf := pack.SetBrightness(bright)
|
|
|
- _, err := s.conn.Write(buf.Bytes())
|
|
|
+ _, err := s.Conn.Write(buf.Bytes())
|
|
|
if err != nil {
|
|
|
logger.Logger.Errorf("SetBrightness write failed, err:%v", err)
|
|
|
return err
|
|
@@ -234,7 +184,7 @@ func (s *Device) SetBrightness(bright byte) error {
|
|
|
}
|
|
|
|
|
|
func SwitchScreen(sn string, onOff int) error {
|
|
|
- device := devices[sn]
|
|
|
+ device := Devices[sn]
|
|
|
err := device.SwitchScreen(onOff)
|
|
|
if err != nil {
|
|
|
return err
|
|
@@ -243,7 +193,7 @@ func SwitchScreen(sn string, onOff int) error {
|
|
|
}
|
|
|
|
|
|
func SendInternalCode(sn string, content []promodel.InternalCodeContent) error {
|
|
|
- device := devices[sn]
|
|
|
+ device := Devices[sn]
|
|
|
err := device.SendInternalCode(content)
|
|
|
if err != nil {
|
|
|
return err
|
|
@@ -252,7 +202,7 @@ func SendInternalCode(sn string, content []promodel.InternalCodeContent) error {
|
|
|
}
|
|
|
|
|
|
func VoiceBroad(sn string, broad string) error {
|
|
|
- device := devices[sn]
|
|
|
+ device := Devices[sn]
|
|
|
err := device.VoiceBroad(broad)
|
|
|
if err != nil {
|
|
|
return err
|
|
@@ -261,7 +211,7 @@ func VoiceBroad(sn string, broad string) error {
|
|
|
}
|
|
|
|
|
|
func SetBrightness(sn string, bright int) error {
|
|
|
- device := devices[sn]
|
|
|
+ device := Devices[sn]
|
|
|
err := device.SetBrightness(brightnessMap[bright])
|
|
|
if err != nil {
|
|
|
return err
|