Browse Source

优化架构和封装

longan 11 months ago
parent
commit
2e05a5f340
11 changed files with 228 additions and 210 deletions
  1. 47 0
      README.md
  2. 15 15
      bx/BxArea.go
  3. 4 3
      bx/BxAreaDynamic.go
  4. 8 29
      cmd.go
  5. 0 47
      demo/main.go
  6. 22 8
      lc/IDevice.go
  7. 9 1
      lc/loudspeaker.go
  8. 81 35
      lc/screen.go
  9. 19 61
      lc/server.go
  10. 0 0
      lc/store.json
  11. 23 11
      main.go

+ 47 - 0
README.md

@@ -0,0 +1,47 @@
+#### version:1.0 2023-12-09
+#### 应用层功能
+- [x] 海康通知-输出设备响应 系统架构
+- [x] 事件服务
+- [x] 输出设备响应
+- [x] 发送文字
+  - [x] 静态文件
+  - [x] 动态实时显示信息
+- [x] 删除文件
+- [x] 删除动态区域
+- [x] 切换节目(锁定/解锁节目)
+- [ ] 发送自制位图节目 *
+- [x] 查询当前状态
+- [ ] 定时开关机
+- [ ] 语音响应设备
+#### bx6k1屏 控制卡协议
+- [x] ACK
+- [x] NACK
+- [ ] 发送节目文件
+  - [x] 开始写文件
+  - [x] 写文件
+  - [ ] 写多文件命令
+  - [ ] 结束写多文件命令
+  - [ ] 写客户信息
+  - [ ] 读取文件信息命令
+  - [ ] 返回文件信息命令
+  - [ ] 读取文件内容命令
+  - [ ] 返回文件内容命令
+- [x] 发送实时显示信息
+- [ ] 多分区
+- [x] 查询控制器状态
+- [x] 删除文件
+- [x] 系统时间校正命令
+- [x] 强制开关屏
+- [x] 定时开关屏
+- [x] 取消定时开关机 *
+- [x] 锁定/解锁节目
+- [x] CRC校验算法
+
+#### Note:
+
+- 服务器模式没调通,接收不到控制卡的连接请求,所以使用客户端模式.可能原因:要更换控制卡IP
+- 因为bx6k1不支持查所有节目信息,程序未做持久化保存节目信息,只保存了节目数量.
+- 应将名为P000节目设为默认节目,并永久锁定.节目内容应为类似"减速慢行"等默认黄色提示信息.
+- 应将P001节目设为红色警示节目,状态变更后锁定这个节目.
+- 自定义位图节目发送协议已对接,发送后响应无错误,但是未生效.
+- 定时开关屏可以设置三个,取消定时开关机测试时未取消成功.该功能不能用的话只能设置定时器手动开关屏

+ 15 - 15
bx/BxArea.go

@@ -5,17 +5,17 @@ type BxArea interface {
 	Length() int16
 	Length() int16
 }
 }
 
 
-type bxArea struct {
+type BaseArea struct {
 	BxArea
 	BxArea
 	typ byte
 	typ byte
-	x   int16
-	y   int16
-	w   int16
-	h   int16
+	x   uint16
+	y   uint16
+	w   uint16
+	h   uint16
 }
 }
 
 
-func NewBxArea(typ byte, x int16, y int16, w int16, h int16) bxArea {
-	return bxArea{
+func NewBxArea(typ byte, x uint16, y uint16, w uint16, h uint16) BaseArea {
+	return BaseArea{
 		typ: typ,
 		typ: typ,
 		x:   x,
 		x:   x,
 		y:   y,
 		y:   y,
@@ -24,34 +24,34 @@ func NewBxArea(typ byte, x int16, y int16, w int16, h int16) bxArea {
 	}
 	}
 }
 }
 
 
-func (a *bxArea) GetX() int16 {
+func (a *BaseArea) GetX() uint16 {
 	return a.x
 	return a.x
 }
 }
 
 
-func (a *bxArea) SetX(x int16) {
+func (a *BaseArea) SetX(x uint16) {
 	a.x = x
 	a.x = x
 }
 }
 
 
-func (a *bxArea) GetY() int16 {
+func (a *BaseArea) GetY() uint16 {
 	return a.y
 	return a.y
 }
 }
 
 
-func (a *bxArea) SetY(y int16) {
+func (a *BaseArea) SetY(y uint16) {
 	a.y = y
 	a.y = y
 }
 }
 
 
-func (a *bxArea) GetW() int16 {
+func (a *BaseArea) GetW() uint16 {
 	return a.w
 	return a.w
 }
 }
 
 
-func (a *bxArea) SetW(w int16) {
+func (a *BaseArea) SetW(w uint16) {
 	a.w = w
 	a.w = w
 }
 }
 
 
-func (a *bxArea) GetH() int16 {
+func (a *BaseArea) GetH() uint16 {
 	return a.h
 	return a.h
 }
 }
 
 
-func (a *bxArea) SetH(h int16) {
+func (a *BaseArea) SetH(h uint16) {
 	a.h = h
 	a.h = h
 }
 }

+ 4 - 3
bx/BxAreaDynamic.go

@@ -6,7 +6,7 @@ import (
 )
 )
 
 
 type BxAreaDynamic struct {
 type BxAreaDynamic struct {
-	bxArea
+	BaseArea
 	is5K bool
 	is5K bool
 	//
 	//
 	// id
 	// id
@@ -73,13 +73,14 @@ type BxAreaDynamic struct {
 	data     []byte
 	data     []byte
 }
 }
 
 
-func NewBxAreaDynamic(id, dispMode byte, x int16, y int16, w int16, h int16, data []byte, is5K bool) *BxAreaDynamic {
+func NewBxAreaDynamic(id, runMode, dispMode byte, x uint16, y uint16, w uint16, h uint16, data []byte, is5K bool) *BxAreaDynamic {
 	return &BxAreaDynamic{
 	return &BxAreaDynamic{
-		bxArea:      NewBxArea(0, x, y, w, h),
+		BaseArea:    NewBxArea(0, x, y, w, h),
 		id:          id,
 		id:          id,
 		data:        data,
 		data:        data,
 		is5K:        is5K,
 		is5K:        is5K,
 		timeout:     5,
 		timeout:     5,
+		runMode:     runMode,
 		soundVolume: 0x05,
 		soundVolume: 0x05,
 		soundSpeed:  0x05,
 		soundSpeed:  0x05,
 		singleLine:  0x02,
 		singleLine:  0x02,

+ 8 - 29
cmd.go

@@ -3,23 +3,22 @@ package main
 import (
 import (
 	"fmt"
 	"fmt"
 	"github.com/chzyer/readline"
 	"github.com/chzyer/readline"
-	"os"
 	"strings"
 	"strings"
 )
 )
 
 
+// 开发指令在控制台操作屏
+
 func lcCmdServer() {
 func lcCmdServer() {
-	//rl, err := readline.New("> ")
-	rl := readline.NewCancelableStdin(os.Stdin)
-	readline.NewFillableStdin(os.Stdin)
-	//if err != nil {
-	//	fmt.Println("start cmd server Error:", err)
-	//	return
-	//}
+	rl, err := readline.New("> ")
+	if err != nil {
+		fmt.Println("start cmd server Error:", err)
+		return
+	}
 	defer rl.Close()
 	defer rl.Close()
 
 
 	for {
 	for {
 		var line []byte
 		var line []byte
-		_, err := rl.Read(line)
+		_, err := rl.Readline()
 		if err != nil {
 		if err != nil {
 			fmt.Println("read line Error:", err)
 			fmt.Println("read line Error:", err)
 			break
 			break
@@ -45,26 +44,6 @@ func lcCmdServer() {
 			fmt.Println("Invalid command")
 			fmt.Println("Invalid command")
 		}
 		}
 	}
 	}
-
-	//inputReader := bufio.NewReader(os.Stdin)
-	//fmt.Printf("Please enter your name:")
-	//input, err := inputReader.ReadString('\n')
-	//if err != nil {
-	//	fmt.Println("There were errors reading, exiting program.")
-	//	return
-	//}
-	//fmt.Printf("Your name is %s", input)
-	//switch input {
-	//case "yinzhengjie\n":
-	//	fmt.Println("Welcome yinzhengjie!")
-	//case "bingan\n":
-	//	fmt.Println("Welcome bingan!")
-	//case "liufei\n":
-	//	fmt.Println("Welcome liufei")
-	//default:
-	//	fmt.Println("You are not welcome here! Goodbye!")
-	//}
-
 }
 }
 
 
 func handleRmCommand(args []string) {
 func handleRmCommand(args []string) {

+ 0 - 47
demo/main.go

@@ -1,47 +0,0 @@
-package main
-
-import (
-	"fmt"
-	"time"
-)
-
-func main() {
-	s := "2023-12-30"
-	//4BC6 [4,11,12,6]
-	t, err := time.Parse("2006-01-02", s)
-	if err != nil {
-		fmt.Println(err)
-		return
-	}
-	y := Uint2BCD(uint64(t.Year()), true)
-	fmt.Println("year:", y)
-	m := Uint2BCD(uint64(t.Month()), true)
-	fmt.Println("mouth:", m)
-	d := Uint2BCD(uint64(t.Day()), true)
-	fmt.Println("day:", d)
-}
-
-func Uint2BCD(n uint64, isBigEndian bool) []byte {
-	var b []byte
-	//if n < 256 {
-	//	b = []byte{0}
-	//}
-	for i := 0; ; i++ {
-		h := (n / 10) % 10
-		l := n % 10
-		b = append(b, byte(h<<4|l))
-		n = n / 100
-		if n == 0 {
-			break
-		}
-	}
-	if !isBigEndian {
-		return b
-	}
-	l := len(b)
-	var r = make([]byte, l)
-	for i, v := range b {
-		r[l-1-i] = v
-	}
-	return r
-}

+ 22 - 8
lc/IDevice.go

@@ -5,12 +5,16 @@ import (
 	"github.com/sirupsen/logrus"
 	"github.com/sirupsen/logrus"
 	"lc-smartX/util"
 	"lc-smartX/util"
 	"net"
 	"net"
+	"time"
 )
 )
 
 
 // IDevice 抽象设备,包含屏和喇叭
 // IDevice 抽象设备,包含屏和喇叭
 type IDevice interface {
 type IDevice interface {
+	// Call 通知输出设备,输出信息
 	Call()
 	Call()
 	ReConnect()
 	ReConnect()
+	// Correct time 校时
+	Correct()
 }
 }
 
 
 type IntersectionDevice struct {
 type IntersectionDevice struct {
@@ -25,13 +29,23 @@ func (id *IntersectionDevice) Call() {
 }
 }
 
 
 func (id *IntersectionDevice) ReConnect() {
 func (id *IntersectionDevice) ReConnect() {
-	conn, err := net.Dial("tcp", id.Info.ScreenIp+":5000")
-	if err != nil {
-		logrus.Error("连接", id.Info.ScreenIp, "失败!error:", err)
-		return
+	//重连屏
+	if !id.S.IsLive {
+		conn, err := net.DialTimeout("tcp", id.Info.ScreenIp+":5000", 5*time.Second)
+		if err != nil {
+			logrus.Error("连接", id.Info.ScreenIp, "失败!error:", err)
+			return
+		}
+		logrus.Info("连接", id.Info.ScreenIp, "成功!")
+		fmt.Println("连接", id.Info.ScreenIp, "成功!")
+		id.S.Conn = conn
+		id.S.IsLive = true
 	}
 	}
-	logrus.Info("连接", id.Info.ScreenIp, "成功!")
-	fmt.Println("连接", id.Info.ScreenIp, "成功!")
-	id.S.Conn = conn
-	id.S.IsLive = true
+	//todo 重连loudspeaker
+}
+
+func (id *IntersectionDevice) Correct() {
+	t := time.Now()
+	id.S.CorrectTime(t)
+	id.L.CorrectTime(t)
 }
 }

+ 9 - 1
lc/loudspeaker.go

@@ -1,9 +1,13 @@
 package lc
 package lc
 
 
-import "fmt"
+import (
+	"fmt"
+	"time"
+)
 
 
 type Loudspeaker interface {
 type Loudspeaker interface {
 	Speak()
 	Speak()
+	CorrectTime(time.Time)
 }
 }
 
 
 type IpCast struct {
 type IpCast struct {
@@ -12,3 +16,7 @@ type IpCast struct {
 func (ip IpCast) Speak() {
 func (ip IpCast) Speak() {
 	fmt.Println("语音")
 	fmt.Println("语音")
 }
 }
+
+func (ip IpCast) CorrectTime(t time.Time) {
+
+}

+ 81 - 35
lc/screen.go

@@ -12,15 +12,11 @@ import (
 
 
 type Screener interface {
 type Screener interface {
 	Display()
 	Display()
+	CorrectTime(time.Time)
 }
 }
 
 
 type Screen struct {
 type Screen struct {
-	Id        byte
-	Sn        string //B006K12311020021
 	Name      string
 	Name      string
-	Type      byte
-	FileNum   byte
-	Files     []string
 	Conn      net.Conn
 	Conn      net.Conn
 	IsLive    bool
 	IsLive    bool
 	StateInfo *bx.StateInfo //状态信息
 	StateInfo *bx.StateInfo //状态信息
@@ -48,29 +44,23 @@ func (s *Screen) Display() {
 
 
 func (s *Screen) send(data []byte) {
 func (s *Screen) send(data []byte) {
 	if !s.IsLive {
 	if !s.IsLive {
-		fmt.Println("连接已断开!")
 		return
 		return
 	}
 	}
 	_, err := s.Conn.Write(data)
 	_, err := s.Conn.Write(data)
 	if err != nil {
 	if err != nil {
-		logrus.Error("tcp write error:", err)
+		logrus.WithFields(map[string]interface{}{"设备名": s.Name}).Error("tcp write error:", err)
 		s.IsLive = false
 		s.IsLive = false
 	}
 	}
 }
 }
 
 
 // CorrectTime 校正时间
 // CorrectTime 校正时间
-func (s *Screen) CorrectTime() (ok bool) {
+func (s *Screen) CorrectTime(now time.Time) {
 	if !s.IsLive {
 	if !s.IsLive {
-		return false
+		return
 	}
 	}
-	cmd := bx.NewBxCmdSystemClockCorrect(time.Now())
+	cmd := bx.NewBxCmdSystemClockCorrect(now)
 	data := bx.NewBxDataPackCmd(cmd)
 	data := bx.NewBxDataPackCmd(cmd)
-	_, err := s.Conn.Write(data.Pack())
-	if err != nil {
-		logrus.WithFields(map[string]interface{}{"Id": s.Id, "Name": s.Name}).Errorf("Conn写数据失败:%v", err)
-		return false
-	}
-	return true
+	s.send(data.Pack())
 }
 }
 
 
 type Color byte
 type Color byte
@@ -87,14 +77,14 @@ const (
 	None
 	None
 )
 )
 
 
-// TextRam
+// TextRam dispMode显示方式
 // 0x01——静止显示
 // 0x01——静止显示
 // 0x02——快速打出
 // 0x02——快速打出
 // 0x03——向左移动
 // 0x03——向左移动
 // 0x04——向右移动
 // 0x04——向右移动
 // 0x05——向上移动
 // 0x05——向上移动
 // 0x06——向下移动
 // 0x06——向下移动
-func (s *Screen) TextRam(str string, color Color, playMode byte) {
+func (s *Screen) TextRam(ft FlashFile) {
 	if !s.IsLive {
 	if !s.IsLive {
 		return
 		return
 	}
 	}
@@ -103,19 +93,17 @@ func (s *Screen) TextRam(str string, color Color, playMode byte) {
 	//var x, y int16
 	//var x, y int16
 	//var w, h int16 = 64, 16
 	//var w, h int16 = 64, 16
 	encoder := simplifiedchinese.GB18030.NewEncoder()
 	encoder := simplifiedchinese.GB18030.NewEncoder()
-	bytes, err := encoder.Bytes([]byte("\\C" + strconv.Itoa(int(color)) + str))
+	bytes, err := encoder.Bytes([]byte("\\C" + strconv.Itoa(int(ft.color)) + ft.msg))
 	if err != nil {
 	if err != nil {
 		logrus.Error("编码转换失败:", err)
 		logrus.Error("编码转换失败:", err)
 		return
 		return
 	}
 	}
-	x := 0x8000
-	w := 0x8040
-	area := bx.NewBxAreaDynamic(s.StateInfo.DynaAreaNum, playMode, int16(x), 0, int16(w), 16, bytes, false)
+	area := bx.NewBxAreaDynamic(s.StateInfo.DynaAreaNum, 0, byte(ft.dispMode), ft.originX, ft.originY, ft.width, ft.height, bytes, false)
 	areas = append(areas, area)
 	areas = append(areas, area)
 	//
 	//
 	cmd := bx.NewBxCmdSendDynamicArea(areas)
 	cmd := bx.NewBxCmdSendDynamicArea(areas)
 	pack := bx.NewBxDataPackCmd(cmd)
 	pack := bx.NewBxDataPackCmd(cmd)
-	pack.SetDispType(2) //动态显示模式
+	pack.SetDispType(1) //动态显示模式
 	d := pack.Pack()
 	d := pack.Pack()
 	s.send(d)
 	s.send(d)
 	s.ReadResp()
 	s.ReadResp()
@@ -138,30 +126,90 @@ func (s *Screen) DelRamText(numbers ...byte) {
 	}
 	}
 }
 }
 
 
-func (s *Screen) TextFlash(msg string, color Color) {
+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 isPixel=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) {
 	if !s.IsLive {
 	if !s.IsLive {
 		return
 		return
 	}
 	}
 	encoder := simplifiedchinese.GB18030.NewEncoder()
 	encoder := simplifiedchinese.GB18030.NewEncoder()
 	var bytes []byte
 	var bytes []byte
 	//
 	//
-	if color == None {
-		bytes = []byte(msg)
+	if ft.color == None {
+		bytes = []byte(ft.msg)
 	} else {
 	} else {
-		bytes, _ = encoder.Bytes([]byte("\\C" + strconv.Itoa(int(color)) + msg))
+		bytes, _ = encoder.Bytes([]byte("\\C" + strconv.Itoa(int(ft.color)) + ft.msg))
 	}
 	}
-	x := 0x8000
-	w := 0x8040
-	area := bx.NewBxAreaDynamic(0xff, 2, int16(x), 0, int16(w), 16, 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
 	//if s.FileNum
 	name := fmt.Sprintf("P%03d", s.StateInfo.ProgramNum)
 	name := fmt.Sprintf("P%03d", s.StateInfo.ProgramNum)
-	fmt.Println("文件名:", name)
 	file := bx.NewBxFile(name, "", []bx.BxArea{area})
 	file := bx.NewBxFile(name, "", []bx.BxArea{area})
 	cmd := file.NewCmdWriteFile()
 	cmd := file.NewCmdWriteFile()
 	pack := bx.NewBxDataPackCmd(cmd)
 	pack := bx.NewBxDataPackCmd(cmd)
 	data := pack.Pack()
 	data := pack.Pack()
-	fmt.Println("数据长度:", len(data))
-	fmt.Printf("数据:% 02x\n", data)
 	s.send(data)
 	s.send(data)
 	resp := s.ReadResp()
 	resp := s.ReadResp()
 	if !resp.IsAck() {
 	if !resp.IsAck() {
@@ -170,9 +218,7 @@ func (s *Screen) TextFlash(msg string, color Color) {
 	}
 	}
 	pack1 := bx.NewBxDataPackCmd(cmd)
 	pack1 := bx.NewBxDataPackCmd(cmd)
 	data1 := pack1.Pack()
 	data1 := pack1.Pack()
-	fmt.Println("数据长度:", len(data))
 	s.send(data1)
 	s.send(data1)
-	fmt.Printf("数据1:% 02x\n", data1)
 	resp1 := s.ReadResp()
 	resp1 := s.ReadResp()
 	if resp1.NoError() {
 	if resp1.NoError() {
 		s.StateInfo.ProgramNum++
 		s.StateInfo.ProgramNum++

+ 19 - 61
lc/server.go

@@ -5,19 +5,15 @@ import (
 	"github.com/sirupsen/logrus"
 	"github.com/sirupsen/logrus"
 	"lc-smartX/util"
 	"lc-smartX/util"
 	"lc-smartX/util/gopool"
 	"lc-smartX/util/gopool"
-	"net"
-	"strings"
 	"time"
 	"time"
 )
 )
 
 
-type Controller interface {
-	StartServer()
+type SmartXServer interface {
+	Serve()
 }
 }
 
 
-var Ctl = IntersectionCtl{
-	Main:     time.NewTicker(5 * time.Second),
-	Sub:      time.NewTicker(5 * time.Second),
-	ReTicker: time.NewTicker(18 * time.Second),
+func StartSmartXServer(s SmartXServer) {
+	s.Serve()
 }
 }
 
 
 type IntersectionCtl struct {
 type IntersectionCtl struct {
@@ -30,14 +26,14 @@ type IntersectionCtl struct {
 	Sub         *time.Ticker
 	Sub         *time.Ticker
 }
 }
 
 
-type MainNotifier struct{}
+type MainNotifier struct{ ctl *IntersectionCtl }
 
 
 // Notify 主路来车,通知支路设备
 // Notify 主路来车,通知支路设备
 func (m MainNotifier) Notify() {
 func (m MainNotifier) Notify() {
-	Ctl.Main.Reset(5 * time.Second)
-	if Ctl.MainState != 1 {
-		Ctl.MainState = 1
-		for _, v := range Ctl.SubDevices {
+	m.ctl.Main.Reset(5 * time.Second)
+	if m.ctl.MainState != 1 {
+		m.ctl.MainState = 1
+		for _, v := range m.ctl.SubDevices {
 			if v.S.IsLive {
 			if v.S.IsLive {
 				gopool.Go(v.Call)
 				gopool.Go(v.Call)
 			}
 			}
@@ -45,14 +41,14 @@ func (m MainNotifier) Notify() {
 	}
 	}
 }
 }
 
 
-type SubNotifier struct{}
+type SubNotifier struct{ ctl *IntersectionCtl }
 
 
 // Notify 支路来车,通知主路设备
 // Notify 支路来车,通知主路设备
 func (s SubNotifier) Notify() {
 func (s SubNotifier) Notify() {
-	Ctl.Sub.Reset(5 * time.Second)
-	if Ctl.SubState != 1 {
-		Ctl.SubState = 1
-		for _, v := range Ctl.MainDevices {
+	s.ctl.Sub.Reset(5 * time.Second)
+	if s.ctl.SubState != 1 {
+		s.ctl.SubState = 1
+		for _, v := range s.ctl.MainDevices {
 			if v.S.IsLive {
 			if v.S.IsLive {
 				gopool.Go(v.Call)
 				gopool.Go(v.Call)
 			}
 			}
@@ -60,9 +56,9 @@ func (s SubNotifier) Notify() {
 	}
 	}
 }
 }
 
 
-func (ctl *IntersectionCtl) StartServer() {
-	RegisterCallback(1, &SubNotifier{})
-	RegisterCallback(0, &MainNotifier{})
+func (ctl *IntersectionCtl) Serve() {
+	RegisterCallback(1, &SubNotifier{ctl})
+	RegisterCallback(0, &MainNotifier{ctl})
 	//先创建响应设备
 	//先创建响应设备
 	for _, v := range util.Config.OutputDevices {
 	for _, v := range util.Config.OutputDevices {
 		iDevice := IntersectionDevice{
 		iDevice := IntersectionDevice{
@@ -82,24 +78,22 @@ func (ctl *IntersectionCtl) StartServer() {
 	for {
 	for {
 		select {
 		select {
 		case <-ctl.Main.C: //检查主路状态->支路输出设备作出响应
 		case <-ctl.Main.C: //检查主路状态->支路输出设备作出响应
-			for _, v := range Ctl.SubDevices {
+			for _, v := range ctl.SubDevices {
 				if v.S.IsLive && ctl.MainState == 1 {
 				if v.S.IsLive && ctl.MainState == 1 {
 					back := func() {
 					back := func() {
 						v.S.Lock(1, "P000")
 						v.S.Lock(1, "P000")
 					}
 					}
 					gopool.Go(back)
 					gopool.Go(back)
-					//go v.S.Lock(1, "P000")
 				}
 				}
 			}
 			}
 			ctl.MainState = 0
 			ctl.MainState = 0
 		case <-ctl.Sub.C: //检查支路状态->主路输出设备作出响应
 		case <-ctl.Sub.C: //检查支路状态->主路输出设备作出响应
-			for _, v := range Ctl.MainDevices {
+			for _, v := range ctl.MainDevices {
 				if v.S.IsLive && ctl.SubState == 1 {
 				if v.S.IsLive && ctl.SubState == 1 {
 					back := func() {
 					back := func() {
 						v.S.Lock(1, "P000")
 						v.S.Lock(1, "P000")
 					}
 					}
 					gopool.Go(back)
 					gopool.Go(back)
-					//go v.S.Lock(1, "P000")
 				}
 				}
 			}
 			}
 			ctl.SubState = 0
 			ctl.SubState = 0
@@ -133,39 +127,3 @@ func (ctl *IntersectionCtl) StartServer() {
 // ===
 // ===
 // ===
 // ===
 // === todo 服务器模式没测通,屏没有连接服务器
 // === todo 服务器模式没测通,屏没有连接服务器
-var LServer LedServer
-
-type LedServer struct {
-}
-
-func (ls LedServer) Start() {
-	listener, err := net.Listen("tcp", "192.168.110.69"+util.Config.LedServerAddr)
-	if err != nil {
-		fmt.Println("服务启动失败:", err)
-		return
-	}
-	fmt.Println("led屏服务启动成功!addr:", listener.Addr())
-	for {
-		conn, err := listener.Accept()
-		if err != nil {
-			continue
-		}
-		go func(c net.Conn) {
-			ip := strings.Split(c.RemoteAddr().String(), ":")[0]
-			for i, v := range Ctl.MainDevices {
-				if v.Info.ScreenIp == ip {
-					fmt.Println("主路屏幕注册,ip:", ip)
-					screen := NewScreen(v.Info.Name, c)
-					Ctl.MainDevices[i].S = screen
-				}
-			}
-			for i, v := range Ctl.SubDevices {
-				if v.Info.ScreenIp == ip {
-					fmt.Println("支路屏幕注册,ip:", ip)
-					screen := NewScreen(v.Info.Name, c)
-					Ctl.SubDevices[i].S = screen
-				}
-			}
-		}(conn)
-	}
-}

+ 0 - 0
lc/store.json


+ 23 - 11
main.go

@@ -8,12 +8,15 @@ import (
 
 
 func main() {
 func main() {
 	gopool.SetCap(64)
 	gopool.SetCap(64)
-	//gopool.Go(lcCmdServer)
-	time.Sleep(10 * time.Second)
 	gopool.Go(lc.StartEventServer)
 	gopool.Go(lc.StartEventServer)
 	//等事件服务先启动
 	//等事件服务先启动
 	time.Sleep(1 * time.Second)
 	time.Sleep(1 * time.Second)
-	lc.Ctl.StartServer()
+	ctl := &lc.IntersectionCtl{
+		Main:     time.NewTicker(5 * time.Second),
+		Sub:      time.NewTicker(5 * time.Second),
+		ReTicker: time.NewTicker(18 * time.Second),
+	}
+	lc.StartSmartXServer(ctl)
 
 
 	//conn, err := net.Dial("tcp", "192.168.110.200:5000")
 	//conn, err := net.Dial("tcp", "192.168.110.200:5000")
 	//if err != nil {
 	//if err != nil {
@@ -30,9 +33,13 @@ func main() {
 	//删除指定文件
 	//删除指定文件
 	//client.DelFile("P002")
 	//client.DelFile("P002")
 
 
-	//发送文件节目
-	//client.TextFlash("减速慢行", lc.Yellow)
-	//client.TextFlash("支路来车", lc.Red)
+	//发送flash文件节目
+	//file := lc.FlashFile{}
+	//file.SetMsg("龙弛智慧", lc.Green)
+	//file.SetMode(lc.DefaultRunMode, lc.DefaultDispMode)
+	//file.SetOrigin(0, true, 0)
+	//file.SetArea(64, true, 16)
+	//client.TextFlash(file)
 
 
 	//发送位图文件-不报错,不成功
 	//发送位图文件-不报错,不成功
 	//file, err := os.ReadFile("./lc/bitmap/T000.bcm")
 	//file, err := os.ReadFile("./lc/bitmap/T000.bcm")
@@ -43,8 +50,13 @@ func main() {
 	//client.Bitmap("T000", file)
 	//client.Bitmap("T000", file)
 
 
 	//发送动态区
 	//发送动态区
-	//0,1红,2绿,3黄,4蓝,5浅蓝,6浅紫,7白
-	//client.TextRam("支路来车", lc.Red, 1)
+	//file1 := lc.FlashFile{}
+	//file1.SetMsg("动态", lc.Blue)
+	//file1.SetMode(lc.DefaultRunMode, lc.DefaultDispMode)
+	//file1.SetOrigin(32, true, 0)
+	//file1.SetArea(32, true, 16)
+	//client.TextFlash(file1)
+	//client.TextRam(file1)
 
 
 	//锁定/解锁节目
 	//锁定/解锁节目
 	//client.Lock(1, "P000")
 	//client.Lock(1, "P000")
@@ -54,9 +66,9 @@ func main() {
 
 
 	//client.Lock(1, "P000")
 	//client.Lock(1, "P000")
 	//time.Sleep(time.Second * 1)
 	//time.Sleep(time.Second * 1)
-	//查询当前状态
+	////查询当前状态
 	//client.State()
 	//client.State()
-
+	//time.Sleep(time.Second * 1)
 	//client.Info()
 	//client.Info()
-	time.Sleep(time.Second * 15)
+	//time.Sleep(time.Second * 2)
 }
 }