|
@@ -2,12 +2,9 @@ package lc
|
|
|
|
|
|
import (
|
|
import (
|
|
"fmt"
|
|
"fmt"
|
|
- "github.com/sirupsen/logrus"
|
|
|
|
- "golang.org/x/text/encoding/simplifiedchinese"
|
|
|
|
"lc-smartX/bx"
|
|
"lc-smartX/bx"
|
|
|
|
+ "lc-smartX/util/mqtt"
|
|
"net"
|
|
"net"
|
|
- "strconv"
|
|
|
|
- "time"
|
|
|
|
)
|
|
)
|
|
|
|
|
|
// Screener 屏接口
|
|
// Screener 屏接口
|
|
@@ -36,396 +33,17 @@ func NewScreen(name string, ip, port string) *Screen {
|
|
}
|
|
}
|
|
|
|
|
|
func (s *Screen) Display(id int) {
|
|
func (s *Screen) Display(id int) {
|
|
- if !s.getLiveState() {
|
|
|
|
- return
|
|
|
|
|
|
+ msg := "来车new-55"
|
|
|
|
+ if id == 0 {
|
|
|
|
+ msg = "路口new-54"
|
|
}
|
|
}
|
|
- s.SendRam(id)
|
|
|
|
|
|
+ GetMQTTMgr().Publish("000000/cltled/LED20230408/down/switch", []byte(msg), mqtt.AtMostOnce, ToCloud)
|
|
}
|
|
}
|
|
|
|
|
|
// Correct 校正时间
|
|
// Correct 校正时间
|
|
func (s *Screen) Correct() {
|
|
func (s *Screen) Correct() {
|
|
- if !s.getLiveState() {
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- now := time.Now()
|
|
|
|
- cmd := bx.NewBxCmdSystemClockCorrect(now)
|
|
|
|
- data := bx.NewBxDataPackCmd(cmd)
|
|
|
|
- s.Send(data.Pack())
|
|
|
|
}
|
|
}
|
|
|
|
|
|
// Reconnect 重连
|
|
// Reconnect 重连
|
|
func (s *Screen) Reconnect() {
|
|
func (s *Screen) Reconnect() {
|
|
- if s.getLiveState() {
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- conn, err := net.DialTimeout("tcp", s.Addr, 5*time.Second)
|
|
|
|
- if err != nil {
|
|
|
|
- logrus.Error(s.Name, "-", s.Addr, "[屏]重连接失败! error:", err)
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- logrus.Info(s.Name, "-", s.Addr, "[屏]连接成功!")
|
|
|
|
- s.setConn(conn)
|
|
|
|
- //读取屏信息
|
|
|
|
- state := s.State()
|
|
|
|
- s.StateInfo.Parse(state.Data)
|
|
|
|
- params := s.Param()
|
|
|
|
- s.Params.Parse(params.Data)
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (s *Screen) getLiveState() bool {
|
|
|
|
- return s.liveState
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (s *Screen) setConn(conn net.Conn) {
|
|
|
|
- s.conn = conn
|
|
|
|
- s.liveState = true
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// 给屏发送数据
|
|
|
|
-func (s *Screen) Send(data []byte) {
|
|
|
|
- if !s.getLiveState() {
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- _, err := s.conn.Write(data)
|
|
|
|
- if err != nil {
|
|
|
|
- logrus.WithFields(map[string]interface{}{"设备名": s.Name}).Error("tcp write error:", err)
|
|
|
|
- s.liveState = false
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//以下对协议进行封装
|
|
|
|
-//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
|
|
|
|
-
|
|
|
|
-type Color byte
|
|
|
|
-
|
|
|
|
-const (
|
|
|
|
- Default Color = iota
|
|
|
|
- Red
|
|
|
|
- Green
|
|
|
|
- Yellow
|
|
|
|
- Blue
|
|
|
|
- LightBlue
|
|
|
|
- LightPurple
|
|
|
|
- White
|
|
|
|
-)
|
|
|
|
-
|
|
|
|
-const (
|
|
|
|
- Normal = 0
|
|
|
|
- Warn = 1
|
|
|
|
-)
|
|
|
|
-
|
|
|
|
-// 发送动态区节目 0正常页面 1红色提醒页面
|
|
|
|
-func (s *Screen) SendRam(id int) {
|
|
|
|
- file := FlashFile{}
|
|
|
|
- if id == 0 {
|
|
|
|
- file.SetMsg("减速慢行", Yellow)
|
|
|
|
- file.SetMode(DefaultRunMode, DefaultDisplayMode)
|
|
|
|
- file.SetOrigin(0, true, 0)
|
|
|
|
- file.SetArea(64, true, 16)
|
|
|
|
- s.TextRam(file, false)
|
|
|
|
- } else {
|
|
|
|
- file.SetMsg("支路来车", Red)
|
|
|
|
- file.SetSoundData("支路来车,请减速")
|
|
|
|
- file.SetMode(DefaultRunMode, DefaultDisplayMode)
|
|
|
|
- file.SetOrigin(0, true, 0)
|
|
|
|
- file.SetArea(64, true, 16)
|
|
|
|
- s.TextRam(file, true)
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// TextRam 发送动态区节目实现
|
|
|
|
-func (s *Screen) TextRam(ff FlashFile, needSpeak bool) {
|
|
|
|
- if !s.getLiveState() {
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- var areas []bx.BxArea
|
|
|
|
- encoder := simplifiedchinese.GB18030.NewEncoder()
|
|
|
|
- var bytes []byte
|
|
|
|
- if ff.color == Default {
|
|
|
|
- bytes, _ = encoder.Bytes([]byte(ff.msg))
|
|
|
|
- } else {
|
|
|
|
- bytes, _ = encoder.Bytes([]byte("\\C" + strconv.Itoa(int(ff.color)) + ff.msg))
|
|
|
|
- }
|
|
|
|
- if needSpeak {
|
|
|
|
- soundData, _ := encoder.Bytes([]byte(ff.soundData))
|
|
|
|
- area := bx.NewBxAreaDynamic(0, 1, byte(ff.dispMode), ff.originX, ff.originY, ff.width,
|
|
|
|
- ff.height, bytes, soundData, false)
|
|
|
|
- areas = append(areas, area)
|
|
|
|
- } else {
|
|
|
|
- area := bx.NewBxAreaProgram(0, 1, byte(ff.dispMode), ff.originX, ff.originY, ff.width,
|
|
|
|
- ff.height, bytes, false)
|
|
|
|
- areas = append(areas, area)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //
|
|
|
|
- cmd := bx.NewBxCmdSendDynamicArea(areas)
|
|
|
|
- pack := bx.NewBxDataPackCmd(cmd)
|
|
|
|
- pack.SetDisplayType(1) //动态显示模式
|
|
|
|
- d := pack.Pack()
|
|
|
|
- s.Send(d)
|
|
|
|
- resp := s.ReadResp()
|
|
|
|
- if !resp.IsAck() {
|
|
|
|
- println("设备拒绝写文件! error:", resp.Error().Description)
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- //s.StateInfo.DynaAreaNum++
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// DelRamText 删除动态区,不传删除所有
|
|
|
|
-func (s *Screen) DelRamText(numbers ...byte) {
|
|
|
|
- if !s.getLiveState() {
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- cmd := bx.NewCmdDelDynamicArea(numbers)
|
|
|
|
- pack := bx.NewBxDataPackCmd(cmd)
|
|
|
|
- s.Send(pack.Pack())
|
|
|
|
- s.ReadResp()
|
|
|
|
- if len(numbers) == 0 {
|
|
|
|
- s.StateInfo.DynaAreaNum = 0
|
|
|
|
- } else {
|
|
|
|
- s.StateInfo.DynaAreaNum--
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-type RunMode byte
|
|
|
|
-
|
|
|
|
-const (
|
|
|
|
- Loop RunMode = iota //循环
|
|
|
|
- LoopAndStayAtEnd //循环直到最后,停留在最后一个动态区
|
|
|
|
- LoopAndTimeoutOff //循环直到超时,超时后未更新不在显示
|
|
|
|
- LoopAndStayAtLogo //循环完后,停留显示LOGO
|
|
|
|
- LoopAndOff //循环完后不在显示
|
|
|
|
- LoopAndCountOff //循环设定次数后不在显示
|
|
|
|
- DefaultRunMode RunMode = Loop //默认
|
|
|
|
-)
|
|
|
|
-
|
|
|
|
-type DisplayMode byte
|
|
|
|
-
|
|
|
|
-const (
|
|
|
|
- _ DisplayMode = iota
|
|
|
|
- Static //0x01——静止显示
|
|
|
|
- QuickPunch //0x02——快速打出
|
|
|
|
- MoveLeft //0x03——向左移动
|
|
|
|
- MoveRight //0x04——向右移动
|
|
|
|
- MoveUp //0x05——向上移动
|
|
|
|
- MoveDown //0x06——向下移动
|
|
|
|
- Flicker //0x07——闪烁
|
|
|
|
- DefaultDisplayMode DisplayMode = Static
|
|
|
|
-)
|
|
|
|
-
|
|
|
|
-type FlashFile struct {
|
|
|
|
- msg string
|
|
|
|
- soundData string
|
|
|
|
- color Color
|
|
|
|
- runMode RunMode
|
|
|
|
- dispMode DisplayMode
|
|
|
|
- originX uint16
|
|
|
|
- originY uint16
|
|
|
|
- width uint16
|
|
|
|
- height uint16
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (ft *FlashFile) SetMsg(msg string, color Color) {
|
|
|
|
- ft.msg = msg
|
|
|
|
- ft.color = color
|
|
|
|
-}
|
|
|
|
-func (ft *FlashFile) SetMode(runMode RunMode, displayMode DisplayMode) {
|
|
|
|
- ft.runMode = runMode
|
|
|
|
- ft.dispMode = displayMode
|
|
|
|
-}
|
|
|
|
-func (ft *FlashFile) SetSoundData(soundData string) {
|
|
|
|
- ft.soundData = soundData
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// SetOrigin xIsPixel=true表示x坐标为像素单位, =false表示以字节(8像素)为单位;y只有像素单位
|
|
|
|
-func (ft *FlashFile) SetOrigin(x uint16, xIsPixel bool, y uint16) {
|
|
|
|
- ft.originY = y
|
|
|
|
- if xIsPixel {
|
|
|
|
- ft.originX = 0x8000 | x
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- ft.originX = x
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// SetArea yIsPixel=true表示像素单位, =false表示以字节(8像素)为单位
|
|
|
|
-func (ft *FlashFile) SetArea(w uint16, yIsPixel bool, h uint16) {
|
|
|
|
- ft.height = h
|
|
|
|
- if yIsPixel {
|
|
|
|
- ft.width = 0x8000 | w
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- ft.width = w
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// TextFlash 发送静态文件节目,掉电保存,文件名格式"P000","P001"
|
|
|
|
-func (s *Screen) TextFlash(ft []FlashFile, name string, isLogo bool) {
|
|
|
|
- if !s.getLiveState() {
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- encoder := simplifiedchinese.GB18030.NewEncoder()
|
|
|
|
- if isLogo {
|
|
|
|
- name = "LOGO"
|
|
|
|
- }
|
|
|
|
- var areas []bx.BxArea
|
|
|
|
- for _, i := range ft {
|
|
|
|
- var bytes []byte
|
|
|
|
- if i.color == Default {
|
|
|
|
- bytes, _ = encoder.Bytes([]byte(i.msg))
|
|
|
|
- } else {
|
|
|
|
- bytes, _ = encoder.Bytes([]byte("\\C" + strconv.Itoa(int(i.color)) + i.msg))
|
|
|
|
- }
|
|
|
|
- area := bx.NewBxAreaProgram(0xff, byte(i.runMode), byte(i.dispMode), i.originX, i.originY, i.width, i.height, bytes, false)
|
|
|
|
- areas = append(areas, area)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- file := bx.NewBxFile(name, "", areas)
|
|
|
|
- cmd := file.NewCmdWriteFile()
|
|
|
|
- pack := bx.NewBxDataPackCmd(cmd)
|
|
|
|
- data := pack.Pack()
|
|
|
|
- s.Send(data)
|
|
|
|
- resp := s.ReadResp()
|
|
|
|
- if !resp.IsAck() {
|
|
|
|
- logrus.Error("设备拒绝写文件! error:", resp.Error().Description)
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- pack1 := bx.NewBxDataPackCmd(cmd)
|
|
|
|
- data1 := pack1.Pack()
|
|
|
|
- s.Send(data1)
|
|
|
|
- resp1 := s.ReadResp()
|
|
|
|
- if resp1.NoError() {
|
|
|
|
- s.StateInfo.ProgramNum++
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// Bitmap 发送自定义位图节目
|
|
|
|
-func (s *Screen) Bitmap(name string, bitmap []byte) {
|
|
|
|
- file := bx.NewBitmapFile(name, bitmap)
|
|
|
|
- cmd := file.NewCmd()
|
|
|
|
- pack := bx.NewBxDataPackCmd(cmd)
|
|
|
|
- data := pack.Pack()
|
|
|
|
- s.Send(data)
|
|
|
|
- resp := s.ReadResp()
|
|
|
|
- if !resp.IsAck() {
|
|
|
|
- logrus.Error("设备拒绝写文件! error:", resp.Error().Description)
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- pack1 := bx.NewBxDataPackCmd(cmd)
|
|
|
|
- data1 := pack1.Pack()
|
|
|
|
- s.Send(data1)
|
|
|
|
- fmt.Printf("写图文件数据:% 02x\n", data1)
|
|
|
|
- s.ReadResp()
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// Lock 锁定状态:0x00——解锁状态,0x01——锁定状态
|
|
|
|
-func (s *Screen) Lock(flag byte, name string) {
|
|
|
|
- cmd := bx.NewCmdLock(flag, name)
|
|
|
|
- pack := bx.NewBxDataPackCmd(&cmd)
|
|
|
|
- s.Send(pack.Pack())
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// DelFile 删除静态文件节目
|
|
|
|
-func (s *Screen) DelFile(delFiles ...string) {
|
|
|
|
- cmd := bx.NewCmdDeleteFile(delFiles)
|
|
|
|
- pack := bx.NewBxDataPackCmd(cmd)
|
|
|
|
- s.Send(pack.Pack())
|
|
|
|
- s.ReadResp()
|
|
|
|
- if len(delFiles) == 0 {
|
|
|
|
- s.StateInfo.ProgramNum = 0
|
|
|
|
- } else {
|
|
|
|
- s.StateInfo.ProgramNum--
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// DelText 删除动态区域节目
|
|
|
|
-func (s *Screen) DelText(delIds []byte) {
|
|
|
|
- cmd := bx.NewBxCmdSendDynamicArea(nil)
|
|
|
|
- cmd.SetDelAreaIds(delIds)
|
|
|
|
- pack := bx.NewBxDataPackCmd(cmd)
|
|
|
|
- s.Send(pack.Pack())
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (s *Screen) TurnOnOff(onOff bool) {
|
|
|
|
- if !s.getLiveState() {
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- cmd := bx.NewBxCmdTurnOnOff(onOff)
|
|
|
|
- pack := bx.NewBxDataPackCmd(cmd)
|
|
|
|
- s.Send(pack.Pack())
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// TimingSwitch 定时开关屏
|
|
|
|
-// 13:49 开, 13:55 关,最多设置3组
|
|
|
|
-//
|
|
|
|
-// onOffSet := [][2]uint64{
|
|
|
|
-// {1349, 1355},
|
|
|
|
-// }
|
|
|
|
-func (s *Screen) TimingSwitch(onOffSet [][2]uint64) {
|
|
|
|
- if !s.getLiveState() {
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- cmd := bx.NewCmdTimingSwitch(onOffSet)
|
|
|
|
- pack := bx.NewBxDataPackCmd(cmd)
|
|
|
|
- s.Send(pack.Pack())
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (s *Screen) CancelTimingSwitch() {
|
|
|
|
- if !s.getLiveState() {
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- cmd := bx.NewCmdCancelTimingSwitch()
|
|
|
|
- pack := bx.NewBxDataPackCmd(cmd)
|
|
|
|
- s.Send(pack.Pack())
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (s *Screen) State() *bx.BxResp {
|
|
|
|
- if !s.getLiveState() {
|
|
|
|
- return nil
|
|
|
|
- }
|
|
|
|
- cmd := bx.NewCmdState()
|
|
|
|
- pack := bx.NewBxDataPackCmd(cmd)
|
|
|
|
- s.Send(pack.Pack())
|
|
|
|
- r := s.ReadResp()
|
|
|
|
- return &r
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (s *Screen) Param() *bx.BxResp {
|
|
|
|
- if !s.getLiveState() {
|
|
|
|
- return nil
|
|
|
|
- }
|
|
|
|
- cmd := bx.NewCmdReadParams()
|
|
|
|
- pack := bx.NewBxDataPackCmd(cmd)
|
|
|
|
- s.Send(pack.Pack())
|
|
|
|
- r := s.ReadResp()
|
|
|
|
- return &r
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (s *Screen) Info() {
|
|
|
|
- s.StateInfo.Print(s.Name)
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// ReadResp 读取响应
|
|
|
|
-func (s *Screen) ReadResp() bx.BxResp {
|
|
|
|
- var resp = make([]byte, 1024)
|
|
|
|
- read, err := s.conn.Read(resp)
|
|
|
|
- if err != nil {
|
|
|
|
- logrus.Error("读数据错误:", err)
|
|
|
|
- s.liveState = false
|
|
|
|
- return bx.BxResp{}
|
|
|
|
- }
|
|
|
|
- var bxResp = bx.BxResp{}
|
|
|
|
- parse := bxResp.Parse(resp, read)
|
|
|
|
- //if parse.IsAck() {
|
|
|
|
- // fmt.Println("response ACK")
|
|
|
|
- // fmt.Printf("原始响应数据:% 0x\n", resp[:read])
|
|
|
|
- // fmt.Println("解析响应数据:", parse)
|
|
|
|
- //} else if parse.IsInfo() {
|
|
|
|
- // fmt.Println("state ACK")
|
|
|
|
- // fmt.Printf("原始响应数据:% 0x\n", resp[:read])
|
|
|
|
- // fmt.Println("解析响应数据:", parse)
|
|
|
|
- //} else {
|
|
|
|
- // fmt.Println("response")
|
|
|
|
- // fmt.Printf("原始响应数据:% 0x\n", resp[:read])
|
|
|
|
- // fmt.Println("解析响应数据:", parse)
|
|
|
|
- //}
|
|
|
|
- return *parse
|
|
|
|
}
|
|
}
|