terry 8 bulan lalu
induk
melakukan
d3e4156152
14 mengubah file dengan 202 tambahan dan 105 penghapusan
  1. 3 0
      bx/BxCmdCode.go
  2. 1 1
      bx/BxCmdFileRead.go
  3. 0 3
      bx/BxCmdFileWrite.go
  4. 3 3
      bx/BxDataPack.go
  5. 3 2
      bx/BxResp.go
  6. 2 1
      go.mod
  7. 2 0
      go.sum
  8. 1 1
      lc/IDevice.go
  9. TEMPAT SAMPAH
      lc/bitmap/huang.bcm
  10. 7 0
      lc/model/rtu.go
  11. 32 29
      lc/screen.go
  12. 25 65
      main.go
  13. 84 0
      program_test.go
  14. 39 0
      util/serial.go

+ 3 - 0
bx/BxCmdCode.go

@@ -11,6 +11,8 @@ var (
 	CMD_NACK                 = CmdCode{"nack", 0xa0, 0x01}
 	CMD_DEL_FILE             = CmdCode{"delete file", 0xa1, 0x01}
 	CMD_SYSTEM_STATE         = CmdCode{"system state", 0xa1, 0x02}
+	CMD_SYSTEM_PING          = CmdCode{"ping", 0xa2, 0x00}
+	CMD_SYSTEM_HEARTBEAT     = CmdCode{"system heartbeat", 0xa4, 0x07}
 	CMD_START_WRITE_FILE     = CmdCode{"start write file", 0xa1, 0x05}
 	CMD_WRITE_FILE           = CmdCode{"write file", 0xa1, 0x06}
 	CMD_WRITE_TRANS_START    = CmdCode{"start write trans", 0xa1, 0x07}
@@ -20,6 +22,7 @@ var (
 	CMD_GET_FILE_CONTENT     = CmdCode{"get file content", 0xa1, 0x0b}
 	CMD_SYSTEM_CLOCK_CORRECT = CmdCode{"system clock correct", 0xa2, 0x03}
 	CMD_READ_PARAMS          = CmdCode{"read params", 0xa2, 0x0a}
+	CMD_SOUND                = CmdCode{"add sound", 0xa2, 0x0e}
 	CMD_TURN_ON_OFF          = CmdCode{"turn on/off screen", 0xa3, 0x00}
 	CMD_TIMING_SWITCH        = CmdCode{"auto turn on/off screen", 0xa3, 0x01}
 	CMD_LOCK_UNLOCK          = CmdCode{"lock or unlock program", 0xa3, 0x04}

+ 1 - 1
bx/BxCmdFileRead.go

@@ -9,7 +9,7 @@ type CmdReadFileInfo struct {
 	baseBxCmd
 }
 
-func NewCmdReadFileInfo() CmdReadFileInfo {
+func NewCmdReadFileInfo(FileName string) CmdReadFileInfo {
 	return CmdReadFileInfo{
 		baseBxCmd: newBaseCmd(CMD_GET_FILE_INTO.group, CMD_GET_FILE_INTO.code),
 	}

+ 0 - 3
bx/BxCmdFileWrite.go

@@ -3,7 +3,6 @@ package bx
 import (
 	"bytes"
 	"encoding/binary"
-	"fmt"
 	"github.com/sirupsen/logrus"
 	"time"
 )
@@ -110,7 +109,6 @@ func (cmd *CmdWriteFile) Build() []byte {
 		l := w0.Len() + 27
 		cmd.BlockLen = uint16(l)
 		cmd.file.len = uint32(l)
-		fmt.Println("传输的长度:", l)
 		//Write File
 		w1 := bytes.NewBuffer(make([]byte, 0, 1024))
 		//文件描述数据
@@ -141,7 +139,6 @@ func (cmd *CmdWriteFile) Build() []byte {
 		b2 := w2.Bytes()
 		binary.Write(w1, binary.BigEndian, b2)
 		crc16 := CRC16(b2, 0, w2.Len())
-		fmt.Printf("文件校验:% 02x\n", crc16)
 		binary.Write(w1, binary.LittleEndian, crc16)
 		cmd.temp = w1.Bytes()
 		//Start Write File "开始写文件",写文件前先检查内存是否够用

+ 3 - 3
bx/BxDataPack.go

@@ -42,17 +42,17 @@ func NewBxDataPackCmd(cmd BxCmd) BxDataPack {
 		dataLen:     uint16(len(b)),
 		WRAP_A5_NUM: 8,
 		WRAP_5A_NUM: 1,
-		dstAddr:     0x0002,
+		dstAddr:     0x0001,
 		srcAddr:     0x8000,
 		deviceType:  0xfe,
 		version:     0x02,
 	}
 }
 
-// SetDispType 注:特殊动态区不支持动态模式
+// SetDisplayType 注:特殊动态区不支持动态模式
 // 0x00:普通模式,动态区与节目可同时显示,但各区域不可重叠。
 // 0x01:动态模式,优先显示动态区,无动态区则显示节目,动态区与节目区可重叠。
-func (dp *BxDataPack) SetDispType(typ byte) {
+func (dp *BxDataPack) SetDisplayType(typ byte) {
 	dp.dispMode = typ
 }
 

+ 3 - 2
bx/BxResp.go

@@ -101,7 +101,6 @@ type StateInfo struct {
 	DynaAreaNum     byte
 	DynaAreaIDs     []byte
 	BarCode         string
-	//CustomId        string
 }
 
 func (s *StateInfo) Print(name string) {
@@ -112,6 +111,7 @@ func (s *StateInfo) Print(name string) {
 节目数量: %d
 当前播放: %s
 动态区数: %d
+动态ID: %v
 条码: %s
 ===============
 `
@@ -121,7 +121,8 @@ func (s *StateInfo) Print(name string) {
 	} else {
 		onoff = "关机"
 	}
-	fmt.Printf(info, name, onoff, s.SystemTime, s.ProgramNum, s.CruFileName, s.DynaAreaNum, s.BarCode)
+	fmt.Printf(info, name, onoff, s.SystemTime, s.ProgramNum, s.CruFileName, s.DynaAreaNum, s.DynaAreaIDs,
+		s.BarCode)
 }
 
 func (s *StateInfo) Parse(data []byte) {

+ 2 - 1
go.mod

@@ -1,9 +1,10 @@
 module lc-smartX
 
-go 1.20
+go 1.19
 
 require (
 	github.com/chzyer/readline v1.5.1
+	github.com/jacobsa/go-serial v0.0.0-20180131005756-15cf729a72d4
 	github.com/lestrrat/go-file-rotatelogs v0.0.0-20180223000712-d3151e2a480f
 	github.com/sirupsen/logrus v1.9.3
 	golang.org/x/text v0.14.0

+ 2 - 0
go.sum

@@ -9,6 +9,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 h1:Ghm4eQYC0nEPnSJdVkTrXpu9KtoVCSo1hg7mtI7G9KU=
 github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239/go.mod h1:Gdwt2ce0yfBxPvZrHkprdPPTTS3N5rwmLE8T22KBXlw=
+github.com/jacobsa/go-serial v0.0.0-20180131005756-15cf729a72d4 h1:G2ztCwXov8mRvP0ZfjE6nAlaCX2XbykaeHdbT6KwDz0=
+github.com/jacobsa/go-serial v0.0.0-20180131005756-15cf729a72d4/go.mod h1:2RvX5ZjVtsznNZPEt4xwJXNJrM3VTZoQf7V6gk0ysvs=
 github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 h1:IPJ3dvxmJ4uczJe5YQdrYB16oTJlGSC/OyZDqUk9xX4=
 github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869/go.mod h1:cJ6Cj7dQo+O6GJNiMx+Pa94qKj+TG8ONdKHgMNIyyag=
 github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=

+ 1 - 1
lc/IDevice.go

@@ -47,7 +47,7 @@ func (id *IntersectionDevice) Call() {
 	id.S.Display("P001")
 }
 func (id *IntersectionDevice) Rollback() {
-	id.S.Display("P000")
+	id.S.Display("P002")
 }
 
 func (id *IntersectionDevice) Reconnect() {

TEMPAT SAMPAH
lc/bitmap/huang.bcm


+ 7 - 0
lc/model/rtu.go

@@ -0,0 +1,7 @@
+package model
+
+type RTUInfo struct {
+	Port   string `yaml:"ip"`
+	Name   string `yaml:"name"`
+	Branch byte   `yaml:"branch"`
+}

+ 32 - 29
lc/screen.go

@@ -50,7 +50,7 @@ func (s *Screen) Correct() {
 	now := time.Now()
 	cmd := bx.NewBxCmdSystemClockCorrect(now)
 	data := bx.NewBxDataPackCmd(cmd)
-	s.send(data.Pack())
+	s.Send(data.Pack())
 }
 
 // Reconnect 重连
@@ -82,7 +82,7 @@ func (s *Screen) setConn(conn net.Conn) {
 }
 
 // 给屏发送数据
-func (s *Screen) send(data []byte) {
+func (s *Screen) Send(data []byte) {
 	if !s.getLiveState() {
 		return
 	}
@@ -127,9 +127,9 @@ func (s *Screen) TextRam(ff FlashFile) {
 	//
 	cmd := bx.NewBxCmdSendDynamicArea(areas)
 	pack := bx.NewBxDataPackCmd(cmd)
-	pack.SetDispType(1) //动态显示模式
+	pack.SetDisplayType(1) //动态显示模式
 	d := pack.Pack()
-	s.send(d)
+	s.Send(d)
 	s.ReadResp()
 	s.StateInfo.DynaAreaNum++
 }
@@ -141,7 +141,7 @@ func (s *Screen) DelRamText(numbers ...byte) {
 	}
 	cmd := bx.NewCmdDelDynamicArea(numbers)
 	pack := bx.NewBxDataPackCmd(cmd)
-	s.send(pack.Pack())
+	s.Send(pack.Pack())
 	s.ReadResp()
 	if len(numbers) == 0 {
 		s.StateInfo.DynaAreaNum = 0
@@ -172,6 +172,7 @@ const (
 	MoveRight                      //0x04——向右移动
 	MoveUp                         //0x05——向上移动
 	MoveDown                       //0x06——向下移动
+	Flicker                        //0x07——闪烁
 	DefaultDisplayMode DisplayMode = Static
 )
 
@@ -216,27 +217,32 @@ func (ft *FlashFile) SetArea(w uint16, yIsPixel bool, h uint16) {
 }
 
 // TextFlash 发送静态文件节目,掉电保存,文件名格式"P000","P001"
-func (s *Screen) TextFlash(ft FlashFile, isLogo bool) {
+func (s *Screen) TextFlash(ft []FlashFile, isLogo bool) {
 	if !s.getLiveState() {
 		return
 	}
 	encoder := simplifiedchinese.GB18030.NewEncoder()
-	var bytes []byte
-	if 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)
 	name := fmt.Sprintf("P%03d", s.StateInfo.ProgramNum)
 	if isLogo {
 		name = "LOGO"
 	}
-	file := bx.NewBxFile(name, "", []bx.BxArea{area})
+	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.NewBxAreaDynamic(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)
+	s.Send(data)
 	resp := s.ReadResp()
 	if !resp.IsAck() {
 		logrus.Error("设备拒绝写文件! error:", resp.Error().Description)
@@ -244,7 +250,7 @@ func (s *Screen) TextFlash(ft FlashFile, isLogo bool) {
 	}
 	pack1 := bx.NewBxDataPackCmd(cmd)
 	data1 := pack1.Pack()
-	s.send(data1)
+	s.Send(data1)
 	resp1 := s.ReadResp()
 	if resp1.NoError() {
 		s.StateInfo.ProgramNum++
@@ -257,9 +263,7 @@ func (s *Screen) Bitmap(name string, bitmap []byte) {
 	cmd := file.NewCmd()
 	pack := bx.NewBxDataPackCmd(cmd)
 	data := pack.Pack()
-	fmt.Println("数据长度:", len(data))
-	fmt.Printf("数据:% 02x\n", data)
-	s.send(data)
+	s.Send(data)
 	resp := s.ReadResp()
 	if !resp.IsAck() {
 		logrus.Error("设备拒绝写文件! error:", resp.Error().Description)
@@ -267,8 +271,7 @@ func (s *Screen) Bitmap(name string, bitmap []byte) {
 	}
 	pack1 := bx.NewBxDataPackCmd(cmd)
 	data1 := pack1.Pack()
-	fmt.Println("数据长度1:", len(data1))
-	s.send(data1)
+	s.Send(data1)
 	fmt.Printf("写图文件数据:% 02x\n", data1)
 	s.ReadResp()
 }
@@ -277,14 +280,14 @@ func (s *Screen) Bitmap(name string, bitmap []byte) {
 func (s *Screen) Lock(flag byte, name string) {
 	cmd := bx.NewCmdLock(flag, name)
 	pack := bx.NewBxDataPackCmd(&cmd)
-	s.send(pack.Pack())
+	s.Send(pack.Pack())
 }
 
 // DelFile 删除静态文件节目
 func (s *Screen) DelFile(delFiles ...string) {
 	cmd := bx.NewCmdDeleteFile(delFiles)
 	pack := bx.NewBxDataPackCmd(cmd)
-	s.send(pack.Pack())
+	s.Send(pack.Pack())
 	s.ReadResp()
 	if len(delFiles) == 0 {
 		s.StateInfo.ProgramNum = 0
@@ -298,7 +301,7 @@ func (s *Screen) DelText(delIds []byte) {
 	cmd := bx.NewBxCmdSendDynamicArea(nil)
 	cmd.SetDelAreaIds(delIds)
 	pack := bx.NewBxDataPackCmd(cmd)
-	s.send(pack.Pack())
+	s.Send(pack.Pack())
 }
 
 func (s *Screen) TurnOnOff(onOff bool) {
@@ -307,7 +310,7 @@ func (s *Screen) TurnOnOff(onOff bool) {
 	}
 	cmd := bx.NewBxCmdTurnOnOff(onOff)
 	pack := bx.NewBxDataPackCmd(cmd)
-	s.send(pack.Pack())
+	s.Send(pack.Pack())
 }
 
 // TimingSwitch 定时开关屏
@@ -322,7 +325,7 @@ func (s *Screen) TimingSwitch(onOffSet [][2]uint64) {
 	}
 	cmd := bx.NewCmdTimingSwitch(onOffSet)
 	pack := bx.NewBxDataPackCmd(cmd)
-	s.send(pack.Pack())
+	s.Send(pack.Pack())
 }
 
 func (s *Screen) CancelTimingSwitch() {
@@ -331,7 +334,7 @@ func (s *Screen) CancelTimingSwitch() {
 	}
 	cmd := bx.NewCmdCancelTimingSwitch()
 	pack := bx.NewBxDataPackCmd(cmd)
-	s.send(pack.Pack())
+	s.Send(pack.Pack())
 }
 
 func (s *Screen) State() *bx.BxResp {
@@ -340,7 +343,7 @@ func (s *Screen) State() *bx.BxResp {
 	}
 	cmd := bx.NewCmdState()
 	pack := bx.NewBxDataPackCmd(cmd)
-	s.send(pack.Pack())
+	s.Send(pack.Pack())
 	r := s.ReadResp()
 	return &r
 }
@@ -351,7 +354,7 @@ func (s *Screen) Param() *bx.BxResp {
 	}
 	cmd := bx.NewCmdReadParams()
 	pack := bx.NewBxDataPackCmd(cmd)
-	s.send(pack.Pack())
+	s.Send(pack.Pack())
 	r := s.ReadResp()
 	return &r
 }

+ 25 - 65
main.go

@@ -1,80 +1,40 @@
 package main
 
 import (
+	//"github.com/sirupsen/logrus"
 	"lc-smartX/lc"
-	"lc-smartX/util/gopool"
+	//"lc-smartX/util/gopool"
+	//"net"
+	//"time"
+	//
+	//"lc-smartX/util/gopool"
 	"time"
+	//
+	//"lc-smartX/util/gopool"
+	//"net"
+	//"os"
+	//"time"
 )
 
 func main() {
-	gopool.SetCap(64)
-	gopool.Go(lc.StartEventServer)
-	//等事件服务先启动
-	time.Sleep(1 * time.Second)
-	is := &lc.IntersectionServer{
-		Main:     time.NewTicker(5 * time.Second),  //主路状态回滚
-		Sub:      time.NewTicker(5 * time.Second),  //支路状态回滚
-		ReTicker: time.NewTicker(19 * time.Second), //重连
-	}
-	lc.StartSmartXServer(is)
-
-	//先用以下示例将静态节目发送至屏,P000为初始节目,P001为来车警示节目,LOGO为开机节目
-	//单个屏设备连接不能并发发送数据,未作实现
-	//conn, err := net.Dial("tcp", "192.168.110.200:5000")
-	//if err != nil {
-	//	logrus.Fatalln("建立连接失败:", err)
-	//}
-	//client := lc.NewScreen("支路1屏", conn)
-
-	//开关机
-	//client.TurnOnOff(false)
-
-	//清除所有文件
-	//client.DelFile("")
+	//gopool.SetCap(64)
+	//gopool.Go(lc.StartEventServer)
+	////等事件服务先启动
 	//time.Sleep(1 * time.Second)
-
-	//删除指定文件
-	//client.DelFile("P002")
-	//time.Sleep(1*time.Second)
-
-	//发送flash文件节目
-	//file := lc.FlashFile{}
-	//file.SetMsg("龙弛智慧", lc.Green)
-	//file.SetMode(lc.DefaultRunMode, lc.DefaultDisplayMode)
-	//file.SetOrigin(0, true, 0)
-	//file.SetArea(64, true, 16)
-	//client.TextFlash(file, true)
-	//time.Sleep(1 * time.Second)
-
-	//发送位图文件-不报错,不成功
-	//file, err := os.ReadFile("./lc/bitmap/T000.bcm")
-	//if err != nil {
-	//	logrus.Error("读取图库文件失败:", err)
-	//	return
+	//is := &lc.IntersectionServer{
+	//	Main:     time.NewTicker(5 * time.Second),  //主路状态回滚
+	//	Sub:      time.NewTicker(5 * time.Second),  //支路状态回滚
+	//	ReTicker: time.NewTicker(19 * time.Second), //重连
 	//}
-	//client.Bitmap("T000", file)
-	//time.Sleep(1*time.Second)
+	//lc.StartSmartXServer(is)
 
-	//发送动态区
-	//file1 := lc.FlashFile{}
-	//file1.SetMsg("动态", lc.Blue)
-	//file1.SetMode(lc.DefaultRunMode, lc.DefaultDisplayMode)
-	//file1.SetOrigin(32, true, 0)
-	//file1.SetArea(32, true, 16)
-	//client.TextFlash(file1)
-	//client.TextRam(file1)
-	//time.Sleep(1*time.Second)
+	//先用以下示例将静态节目发送至屏,P000为初始节目,P001为来车警示节目,LOGO为开机节目
+	//单个屏设备连接不能并发发送数据,未作实现
 
-	//锁定/解锁节目
-	//client.Lock(1, "P000")
-	//time.Sleep(1*time.Second)
+	client := lc.NewScreen("支路1屏", "192.168.1.200", "5005")
+	client.Param()
+	time.Sleep(5 * time.Second)
 
-	//删除动态区
-	//client.DelRamText(0)
+	return
 
-	////查询当前状态
-	//client.State()
-	//time.Sleep(time.Second * 1)
-	//client.Info()
-	//time.Sleep(time.Second * 2)
 }

+ 84 - 0
program_test.go

@@ -0,0 +1,84 @@
+package main
+
+import (
+	"lc-smartX/lc"
+	"testing"
+	"time"
+)
+
+func TestProgram(t *testing.T) {
+	//先用以下示例将静态节目发送至屏,P000为初始节目,P001为来车警示节目,LOGO为开机节目
+	//单个屏设备连接不能并发发送数据,未作实现
+	client := lc.NewScreen("支路1屏", "192.168.1.200", "5005")
+	time.Sleep(2 * time.Second)
+
+	////清除所有文件
+	//client.DelFile("P002")
+	//client.DelFile("P001")
+	//time.Sleep(1*time.Second)
+
+	//发送flash文件节目 静态Logo
+	//file := lc.FlashFile{}
+	//file.SetMsg("龙弛智慧", lc.Green)
+	//file.SetMode(lc.DefaultRunMode, lc.DefaultDisplayMode)
+	//file.SetOrigin(0, true, 0)
+	//file.SetArea(64, true, 16)
+	//client.TextFlash([]lc.FlashFile{file}, true)
+	//time.Sleep(1 * time.Second)
+
+	//发送flash文件节目 减速慢行
+	file1 := lc.FlashFile{}
+	file1.SetMsg("减速慢行", lc.Yellow)
+	file1.SetMode(lc.DefaultRunMode, lc.DefaultDisplayMode)
+	file1.SetOrigin(0, true, 0)
+	file1.SetArea(64, true, 16)
+	client.TextFlash([]lc.FlashFile{file1}, false)
+	time.Sleep(1 * time.Second)
+
+	//发送flash文件节目 主路来车
+	//file2 := lc.FlashFile{}
+	//file2.SetMsg("\\T002huang|", lc.Red)
+	//file2.SetMode(lc.DefaultRunMode, lc.Flicker)
+	//file2.SetOrigin(0, true, 0)
+	//file2.SetArea(16, true, 16)
+	//file3 := lc.FlashFile{}
+	//file3.SetMsg("主路来车", lc.Red)
+	//file3.SetMode(lc.DefaultRunMode, lc.DefaultDisplayMode)
+	//file3.SetOrigin(16, true, 0)
+	//file3.SetArea(48, true, 16)
+	//client.TextFlash([]lc.FlashFile{file2,file3}, false)
+	//time.Sleep(1 * time.Second)
+
+	//发送位图文件-不报错,不成功
+	//bit, err := os.ReadFile("./lc/bitmap/huang.bcm")
+	//if err != nil {
+	//	logrus.Error("读取图库文件失败:", err)
+	//	return
+	//}
+	//client.Bitmap("T000", bit)
+	//time.Sleep(1*time.Second)
+
+	//发送动态区
+	//file1 := lc.FlashFile{}
+	//file1.SetMsg("动态", lc.Blue)
+	//file1.SetMode(lc.DefaultRunMode, lc.DefaultDisplayMode)
+	//file1.SetOrigin(32, true, 0)
+	//file1.SetArea(32, true, 16)
+	//client.TextFlash(file1)
+	//client.TextRam(file1)
+	//time.Sleep(1*time.Second)
+
+	//锁定/解锁节目
+	//client.Lock(1, "P000")
+	//time.Sleep(1*time.Second)
+
+	//删除动态区
+	//client.DelRamText(0)
+
+	////查询当前状态
+	client.State()
+	time.Sleep(time.Second * 1)
+	client.Info()
+	time.Sleep(time.Second * 1)
+
+}

+ 39 - 0
util/serial.go

@@ -0,0 +1,39 @@
+package util
+
+import (
+	"fmt"
+	"github.com/jacobsa/go-serial/serial"
+	"log"
+)
+
+func openSerial(portName string) {
+	// 配置串口参数
+	options := serial.OpenOptions{
+		PortName:        portName, // /dev/ttymxc4 6 3
+		BaudRate:        9600,
+		DataBits:        8,
+		StopBits:        1,
+		MinimumReadSize: 4,
+	}
+
+	// 打开串口
+	port, err := serial.Open(options)
+	if err != nil {
+		fmt.Printf("err : %s", err.Error())
+		return
+	}
+
+	// 关闭串口
+	defer port.Close()
+	for {
+		// 读取数据
+		buf := make([]byte, 128)
+		n, err := port.Read(buf)
+		if err != nil {
+			log.Fatal(err)
+		}
+
+		// 输出读取到的数据
+		fmt.Printf("Read %s %d bytes: %s \n", portName, n, string(buf[:n]))
+	}
+}