package lc import ( "fmt" "github.com/sirupsen/logrus" "golang.org/x/text/encoding/simplifiedchinese" "lc-smartX/bx" "net" "strconv" "time" ) type Screener interface { Display() } type Screen struct { Name string Conn net.Conn IsLive bool StateInfo *bx.StateInfo //状态信息 Params *bx.Params //屏参 } func NewScreen(name string, conn net.Conn) Screen { s := Screen{ Name: name, Conn: conn, IsLive: true, StateInfo: &bx.StateInfo{}, Params: &bx.Params{}, } state := s.State() s.StateInfo.Parse(state.Data) params := s.Param() s.Params.Parse(params.Data) return s } func (s *Screen) Display() { if !s.IsLive { return } s.Lock(1, "P001") } func (s *Screen) Back() { s.Lock(1, "P000") } // Correct 校正时间 func (s *Screen) Correct() { now := time.Now() if !s.IsLive { return } cmd := bx.NewBxCmdSystemClockCorrect(now) data := bx.NewBxDataPackCmd(cmd) s.send(data.Pack()) } func (s *Screen) send(data []byte) { if !s.IsLive { return } _, err := s.Conn.Write(data) if err != nil { logrus.WithFields(map[string]interface{}{"设备名": s.Name}).Error("tcp write error:", err) s.IsLive = false } } type Color byte const ( Default Color = iota Red Green Yellow Blue LightBlue LightPurple White None ) // TextRam dispMode显示方式 // 0x01——静止显示 // 0x02——快速打出 // 0x03——向左移动 // 0x04——向右移动 // 0x05——向上移动 // 0x06——向下移动 func (s *Screen) TextRam(ff FlashFile) { if !s.IsLive { return } var areas []bx.BxArea encoder := simplifiedchinese.GB18030.NewEncoder() var bytes []byte if ff.color == None || ff.color == Default { bytes, _ = encoder.Bytes([]byte(ff.msg)) } else { bytes, _ = encoder.Bytes([]byte("\\C" + strconv.Itoa(int(ff.color)) + ff.msg)) } area := bx.NewBxAreaDynamic(s.StateInfo.DynaAreaNum, 0, 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.SetDispType(1) //动态显示模式 d := pack.Pack() s.send(d) s.ReadResp() s.StateInfo.DynaAreaNum++ } // DelRamText 删除动态区,不传删除所有 func (s *Screen) DelRamText(numbers ...byte) { if !s.IsLive { 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 DispMode byte const ( _ DispMode = iota Static //0x01——静止显示 QuickPunch //0x02——快速打出 MoveLeft //0x03——向左移动 MoveRight //0x04——向右移动 MoveUp //0x05——向上移动 MoveDown //0x06——向下移动 DefaultDispMode DispMode = Static ) type FlashFile struct { msg string color Color runMode RunMode dispMode DispMode 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, dispMode DispMode) { ft.runMode = runMode ft.dispMode = dispMode } // 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 } func (s *Screen) TextFlash(ft FlashFile, isLogo bool) { if !s.IsLive { return } encoder := simplifiedchinese.GB18030.NewEncoder() var bytes []byte if ft.color == None || ft.color == Default { bytes, _ = encoder.Bytes([]byte(ft.msg)) } else { 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) //if s.FileNum name := fmt.Sprintf("P%03d", s.StateInfo.ProgramNum) if isLogo { name = "LOGO" } file := bx.NewBxFile(name, "", []bx.BxArea{area}) 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++ } } func (s *Screen) Bitmap(name string, bitmap []byte) { file := bx.NewBitmapFile(name, bitmap) cmd := file.NewCmd() pack := bx.NewBxDataPackCmd(cmd) data := pack.Pack() fmt.Println("数据长度:", len(data)) fmt.Printf("数据:% 02x\n", data) s.send(data) resp := s.ReadResp() if !resp.IsAck() { logrus.Error("设备拒绝写文件! error:", resp.Error().Description) return } pack1 := bx.NewBxDataPackCmd(cmd) data1 := pack1.Pack() fmt.Println("数据长度1:", len(data1)) 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()) } func (s *Screen) QueryFile() { } 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-- } } 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.IsLive { 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.IsLive { return } cmd := bx.NewCmdTimingSwitch(onOffSet) pack := bx.NewBxDataPackCmd(cmd) s.send(pack.Pack()) } func (s *Screen) CancelTimingSwitch() { if !s.IsLive { return } cmd := bx.NewCmdCancelTimingSwitch() pack := bx.NewBxDataPackCmd(cmd) s.send(pack.Pack()) } func (s *Screen) State() *bx.BxResp { if !s.IsLive { 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.IsLive { 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) } func (s *Screen) ReadResp() bx.BxResp { var resp = make([]byte, 1024) read, err := s.Conn.Read(resp) if err != nil { logrus.Error("读数据错误:", err) s.IsLive = 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 }