|
@@ -10,66 +10,92 @@ import (
|
|
"time"
|
|
"time"
|
|
)
|
|
)
|
|
|
|
|
|
|
|
+// Screener 屏接口
|
|
type Screener interface {
|
|
type Screener interface {
|
|
- Display()
|
|
|
|
|
|
+ Display(string)
|
|
}
|
|
}
|
|
|
|
|
|
type Screen struct {
|
|
type Screen struct {
|
|
Name string
|
|
Name string
|
|
- Conn net.Conn
|
|
|
|
- IsLive bool
|
|
|
|
|
|
+ Addr string
|
|
|
|
+ conn net.Conn
|
|
|
|
+ liveState bool
|
|
StateInfo *bx.StateInfo //状态信息
|
|
StateInfo *bx.StateInfo //状态信息
|
|
Params *bx.Params //屏参
|
|
Params *bx.Params //屏参
|
|
}
|
|
}
|
|
|
|
|
|
-func NewScreen(name string, conn net.Conn) Screen {
|
|
|
|
- s := Screen{
|
|
|
|
|
|
+func NewScreen(name string, ip, port string) *Screen {
|
|
|
|
+ s := &Screen{
|
|
Name: name,
|
|
Name: name,
|
|
- Conn: conn,
|
|
|
|
- IsLive: true,
|
|
|
|
|
|
+ Addr: fmt.Sprintf("%s:%s", ip, port),
|
|
StateInfo: &bx.StateInfo{},
|
|
StateInfo: &bx.StateInfo{},
|
|
Params: &bx.Params{},
|
|
Params: &bx.Params{},
|
|
}
|
|
}
|
|
- state := s.State()
|
|
|
|
- s.StateInfo.Parse(state.Data)
|
|
|
|
- params := s.Param()
|
|
|
|
- s.Params.Parse(params.Data)
|
|
|
|
|
|
+ s.Reconnect()
|
|
return s
|
|
return s
|
|
}
|
|
}
|
|
|
|
|
|
-func (s *Screen) Display() {
|
|
|
|
- if !s.IsLive {
|
|
|
|
|
|
+func (s *Screen) Display(str string) {
|
|
|
|
+ if !s.getLiveState() {
|
|
return
|
|
return
|
|
}
|
|
}
|
|
- s.Lock(1, "P001")
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (s *Screen) Back() {
|
|
|
|
- s.Lock(1, "P000")
|
|
|
|
|
|
+ s.Lock(1, str)
|
|
}
|
|
}
|
|
|
|
|
|
// Correct 校正时间
|
|
// Correct 校正时间
|
|
func (s *Screen) Correct() {
|
|
func (s *Screen) Correct() {
|
|
- now := time.Now()
|
|
|
|
- if !s.IsLive {
|
|
|
|
|
|
+ if !s.getLiveState() {
|
|
return
|
|
return
|
|
}
|
|
}
|
|
|
|
+ now := time.Now()
|
|
cmd := bx.NewBxCmdSystemClockCorrect(now)
|
|
cmd := bx.NewBxCmdSystemClockCorrect(now)
|
|
data := bx.NewBxDataPackCmd(cmd)
|
|
data := bx.NewBxDataPackCmd(cmd)
|
|
s.send(data.Pack())
|
|
s.send(data.Pack())
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// 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) {
|
|
func (s *Screen) send(data []byte) {
|
|
- if !s.IsLive {
|
|
|
|
|
|
+ if !s.getLiveState() {
|
|
return
|
|
return
|
|
}
|
|
}
|
|
- _, err := s.Conn.Write(data)
|
|
|
|
|
|
+ _, err := s.conn.Write(data)
|
|
if err != nil {
|
|
if err != nil {
|
|
logrus.WithFields(map[string]interface{}{"设备名": s.Name}).Error("tcp write error:", err)
|
|
logrus.WithFields(map[string]interface{}{"设备名": s.Name}).Error("tcp write error:", err)
|
|
- s.IsLive = false
|
|
|
|
|
|
+ s.liveState = false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+//以下对协议进行封装
|
|
|
|
+//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
|
|
|
|
+
|
|
type Color byte
|
|
type Color byte
|
|
|
|
|
|
const (
|
|
const (
|
|
@@ -81,24 +107,17 @@ const (
|
|
LightBlue
|
|
LightBlue
|
|
LightPurple
|
|
LightPurple
|
|
White
|
|
White
|
|
- None
|
|
|
|
)
|
|
)
|
|
|
|
|
|
-// TextRam dispMode显示方式
|
|
|
|
-// 0x01——静止显示
|
|
|
|
-// 0x02——快速打出
|
|
|
|
-// 0x03——向左移动
|
|
|
|
-// 0x04——向右移动
|
|
|
|
-// 0x05——向上移动
|
|
|
|
-// 0x06——向下移动
|
|
|
|
|
|
+// TextRam 发送动态区节目
|
|
func (s *Screen) TextRam(ff FlashFile) {
|
|
func (s *Screen) TextRam(ff FlashFile) {
|
|
- if !s.IsLive {
|
|
|
|
|
|
+ if !s.getLiveState() {
|
|
return
|
|
return
|
|
}
|
|
}
|
|
var areas []bx.BxArea
|
|
var areas []bx.BxArea
|
|
encoder := simplifiedchinese.GB18030.NewEncoder()
|
|
encoder := simplifiedchinese.GB18030.NewEncoder()
|
|
var bytes []byte
|
|
var bytes []byte
|
|
- if ff.color == None || ff.color == Default {
|
|
|
|
|
|
+ if ff.color == Default {
|
|
bytes, _ = encoder.Bytes([]byte(ff.msg))
|
|
bytes, _ = encoder.Bytes([]byte(ff.msg))
|
|
} else {
|
|
} else {
|
|
bytes, _ = encoder.Bytes([]byte("\\C" + strconv.Itoa(int(ff.color)) + ff.msg))
|
|
bytes, _ = encoder.Bytes([]byte("\\C" + strconv.Itoa(int(ff.color)) + ff.msg))
|
|
@@ -117,7 +136,7 @@ func (s *Screen) TextRam(ff FlashFile) {
|
|
|
|
|
|
// DelRamText 删除动态区,不传删除所有
|
|
// DelRamText 删除动态区,不传删除所有
|
|
func (s *Screen) DelRamText(numbers ...byte) {
|
|
func (s *Screen) DelRamText(numbers ...byte) {
|
|
- if !s.IsLive {
|
|
|
|
|
|
+ if !s.getLiveState() {
|
|
return
|
|
return
|
|
}
|
|
}
|
|
cmd := bx.NewCmdDelDynamicArea(numbers)
|
|
cmd := bx.NewCmdDelDynamicArea(numbers)
|
|
@@ -143,24 +162,24 @@ const (
|
|
DefaultRunMode RunMode = Loop //默认
|
|
DefaultRunMode RunMode = Loop //默认
|
|
)
|
|
)
|
|
|
|
|
|
-type DispMode byte
|
|
|
|
|
|
+type DisplayMode byte
|
|
|
|
|
|
const (
|
|
const (
|
|
- _ DispMode = iota
|
|
|
|
- Static //0x01——静止显示
|
|
|
|
- QuickPunch //0x02——快速打出
|
|
|
|
- MoveLeft //0x03——向左移动
|
|
|
|
- MoveRight //0x04——向右移动
|
|
|
|
- MoveUp //0x05——向上移动
|
|
|
|
- MoveDown //0x06——向下移动
|
|
|
|
- DefaultDispMode DispMode = Static
|
|
|
|
|
|
+ _ DisplayMode = iota
|
|
|
|
+ Static //0x01——静止显示
|
|
|
|
+ QuickPunch //0x02——快速打出
|
|
|
|
+ MoveLeft //0x03——向左移动
|
|
|
|
+ MoveRight //0x04——向右移动
|
|
|
|
+ MoveUp //0x05——向上移动
|
|
|
|
+ MoveDown //0x06——向下移动
|
|
|
|
+ DefaultDisplayMode DisplayMode = Static
|
|
)
|
|
)
|
|
|
|
|
|
type FlashFile struct {
|
|
type FlashFile struct {
|
|
msg string
|
|
msg string
|
|
color Color
|
|
color Color
|
|
runMode RunMode
|
|
runMode RunMode
|
|
- dispMode DispMode
|
|
|
|
|
|
+ dispMode DisplayMode
|
|
originX uint16
|
|
originX uint16
|
|
originY uint16
|
|
originY uint16
|
|
width uint16
|
|
width uint16
|
|
@@ -171,9 +190,9 @@ func (ft *FlashFile) SetMsg(msg string, color Color) {
|
|
ft.msg = msg
|
|
ft.msg = msg
|
|
ft.color = color
|
|
ft.color = color
|
|
}
|
|
}
|
|
-func (ft *FlashFile) SetMode(runMode RunMode, dispMode DispMode) {
|
|
|
|
|
|
+func (ft *FlashFile) SetMode(runMode RunMode, displayMode DisplayMode) {
|
|
ft.runMode = runMode
|
|
ft.runMode = runMode
|
|
- ft.dispMode = dispMode
|
|
|
|
|
|
+ ft.dispMode = displayMode
|
|
}
|
|
}
|
|
|
|
|
|
// SetOrigin xIsPixel=true表示x坐标为像素单位, =false表示以字节(8像素)为单位;y只有像素单位
|
|
// SetOrigin xIsPixel=true表示x坐标为像素单位, =false表示以字节(8像素)为单位;y只有像素单位
|
|
@@ -196,19 +215,19 @@ func (ft *FlashFile) SetArea(w uint16, yIsPixel bool, h uint16) {
|
|
ft.width = w
|
|
ft.width = w
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// TextFlash 发送静态文件节目,掉电保存,文件名格式"P000","P001"
|
|
func (s *Screen) TextFlash(ft FlashFile, isLogo bool) {
|
|
func (s *Screen) TextFlash(ft FlashFile, isLogo bool) {
|
|
- if !s.IsLive {
|
|
|
|
|
|
+ if !s.getLiveState() {
|
|
return
|
|
return
|
|
}
|
|
}
|
|
encoder := simplifiedchinese.GB18030.NewEncoder()
|
|
encoder := simplifiedchinese.GB18030.NewEncoder()
|
|
var bytes []byte
|
|
var bytes []byte
|
|
- if ft.color == None || ft.color == Default {
|
|
|
|
|
|
+ if ft.color == Default {
|
|
bytes, _ = encoder.Bytes([]byte(ft.msg))
|
|
bytes, _ = encoder.Bytes([]byte(ft.msg))
|
|
} else {
|
|
} else {
|
|
bytes, _ = encoder.Bytes([]byte("\\C" + strconv.Itoa(int(ft.color)) + ft.msg))
|
|
bytes, _ = encoder.Bytes([]byte("\\C" + strconv.Itoa(int(ft.color)) + ft.msg))
|
|
}
|
|
}
|
|
area := bx.NewBxAreaDynamic(0xff, byte(ft.runMode), byte(ft.dispMode), ft.originX, ft.originY, ft.width, ft.height, bytes, false)
|
|
area := bx.NewBxAreaDynamic(0xff, byte(ft.runMode), byte(ft.dispMode), ft.originX, ft.originY, ft.width, ft.height, bytes, false)
|
|
- //if s.FileNum
|
|
|
|
name := fmt.Sprintf("P%03d", s.StateInfo.ProgramNum)
|
|
name := fmt.Sprintf("P%03d", s.StateInfo.ProgramNum)
|
|
if isLogo {
|
|
if isLogo {
|
|
name = "LOGO"
|
|
name = "LOGO"
|
|
@@ -232,6 +251,7 @@ func (s *Screen) TextFlash(ft FlashFile, isLogo bool) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// Bitmap 发送自定义位图节目
|
|
func (s *Screen) Bitmap(name string, bitmap []byte) {
|
|
func (s *Screen) Bitmap(name string, bitmap []byte) {
|
|
file := bx.NewBitmapFile(name, bitmap)
|
|
file := bx.NewBitmapFile(name, bitmap)
|
|
cmd := file.NewCmd()
|
|
cmd := file.NewCmd()
|
|
@@ -260,10 +280,7 @@ func (s *Screen) Lock(flag byte, name string) {
|
|
s.send(pack.Pack())
|
|
s.send(pack.Pack())
|
|
}
|
|
}
|
|
|
|
|
|
-func (s *Screen) QueryFile() {
|
|
|
|
-
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
|
|
+// DelFile 删除静态文件节目
|
|
func (s *Screen) DelFile(delFiles ...string) {
|
|
func (s *Screen) DelFile(delFiles ...string) {
|
|
cmd := bx.NewCmdDeleteFile(delFiles)
|
|
cmd := bx.NewCmdDeleteFile(delFiles)
|
|
pack := bx.NewBxDataPackCmd(cmd)
|
|
pack := bx.NewBxDataPackCmd(cmd)
|
|
@@ -276,6 +293,7 @@ func (s *Screen) DelFile(delFiles ...string) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// DelText 删除动态区域节目
|
|
func (s *Screen) DelText(delIds []byte) {
|
|
func (s *Screen) DelText(delIds []byte) {
|
|
cmd := bx.NewBxCmdSendDynamicArea(nil)
|
|
cmd := bx.NewBxCmdSendDynamicArea(nil)
|
|
cmd.SetDelAreaIds(delIds)
|
|
cmd.SetDelAreaIds(delIds)
|
|
@@ -284,7 +302,7 @@ func (s *Screen) DelText(delIds []byte) {
|
|
}
|
|
}
|
|
|
|
|
|
func (s *Screen) TurnOnOff(onOff bool) {
|
|
func (s *Screen) TurnOnOff(onOff bool) {
|
|
- if !s.IsLive {
|
|
|
|
|
|
+ if !s.getLiveState() {
|
|
return
|
|
return
|
|
}
|
|
}
|
|
cmd := bx.NewBxCmdTurnOnOff(onOff)
|
|
cmd := bx.NewBxCmdTurnOnOff(onOff)
|
|
@@ -299,7 +317,7 @@ func (s *Screen) TurnOnOff(onOff bool) {
|
|
// {1349, 1355},
|
|
// {1349, 1355},
|
|
// }
|
|
// }
|
|
func (s *Screen) TimingSwitch(onOffSet [][2]uint64) {
|
|
func (s *Screen) TimingSwitch(onOffSet [][2]uint64) {
|
|
- if !s.IsLive {
|
|
|
|
|
|
+ if !s.getLiveState() {
|
|
return
|
|
return
|
|
}
|
|
}
|
|
cmd := bx.NewCmdTimingSwitch(onOffSet)
|
|
cmd := bx.NewCmdTimingSwitch(onOffSet)
|
|
@@ -308,7 +326,7 @@ func (s *Screen) TimingSwitch(onOffSet [][2]uint64) {
|
|
}
|
|
}
|
|
|
|
|
|
func (s *Screen) CancelTimingSwitch() {
|
|
func (s *Screen) CancelTimingSwitch() {
|
|
- if !s.IsLive {
|
|
|
|
|
|
+ if !s.getLiveState() {
|
|
return
|
|
return
|
|
}
|
|
}
|
|
cmd := bx.NewCmdCancelTimingSwitch()
|
|
cmd := bx.NewCmdCancelTimingSwitch()
|
|
@@ -317,7 +335,7 @@ func (s *Screen) CancelTimingSwitch() {
|
|
}
|
|
}
|
|
|
|
|
|
func (s *Screen) State() *bx.BxResp {
|
|
func (s *Screen) State() *bx.BxResp {
|
|
- if !s.IsLive {
|
|
|
|
|
|
+ if !s.getLiveState() {
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
cmd := bx.NewCmdState()
|
|
cmd := bx.NewCmdState()
|
|
@@ -328,7 +346,7 @@ func (s *Screen) State() *bx.BxResp {
|
|
}
|
|
}
|
|
|
|
|
|
func (s *Screen) Param() *bx.BxResp {
|
|
func (s *Screen) Param() *bx.BxResp {
|
|
- if !s.IsLive {
|
|
|
|
|
|
+ if !s.getLiveState() {
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
cmd := bx.NewCmdReadParams()
|
|
cmd := bx.NewCmdReadParams()
|
|
@@ -342,28 +360,29 @@ func (s *Screen) Info() {
|
|
s.StateInfo.Print(s.Name)
|
|
s.StateInfo.Print(s.Name)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// ReadResp 读取响应
|
|
func (s *Screen) ReadResp() bx.BxResp {
|
|
func (s *Screen) ReadResp() bx.BxResp {
|
|
var resp = make([]byte, 1024)
|
|
var resp = make([]byte, 1024)
|
|
- read, err := s.Conn.Read(resp)
|
|
|
|
|
|
+ read, err := s.conn.Read(resp)
|
|
if err != nil {
|
|
if err != nil {
|
|
logrus.Error("读数据错误:", err)
|
|
logrus.Error("读数据错误:", err)
|
|
- s.IsLive = false
|
|
|
|
|
|
+ s.liveState = false
|
|
return bx.BxResp{}
|
|
return bx.BxResp{}
|
|
}
|
|
}
|
|
var bxResp = bx.BxResp{}
|
|
var bxResp = bx.BxResp{}
|
|
parse := bxResp.Parse(resp, read)
|
|
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)
|
|
|
|
- }
|
|
|
|
|
|
+ //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
|
|
return *parse
|
|
}
|
|
}
|