From df9dbb0926838663e2173f30672f392af3586e54 Mon Sep 17 00:00:00 2001 From: mapleafgo Date: Thu, 12 Dec 2024 10:30:21 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=A7=E7=94=B5=E5=99=A8=E3=80=81=E8=AF=BB?= =?UTF-8?q?=E5=8D=A1=E5=99=A8=EF=BC=8C=E9=83=BD=E7=94=A8=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E7=9A=84modbus=E5=8D=8F=E8=AE=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.yml | 6 +-- config/game/push_card.go | 2 +- config/game/wait_card.go | 2 +- demo/modbus2/main.go | 2 +- demo/relay/main.go | 31 +++++++++++++ go.mod | 5 +-- go.sum | 14 +++--- internal/middleware/relay.go | 6 +-- internal/routes/play/push_card.go | 8 ++-- internal/routes/play/wait_card.go | 4 +- internal/routes/wait.go | 8 ++-- internal/server.go | 13 +++--- pkg/card_reader/reader.go | 68 ++++++++++++++--------------- pkg/relay/portlist.go | 28 ------------ pkg/relay/relay.go | 72 +++++++++++++++++++------------ 15 files changed, 142 insertions(+), 127 deletions(-) create mode 100644 demo/relay/main.go delete mode 100644 pkg/relay/portlist.go diff --git a/config.yml b/config.yml index 816634b..84770c7 100755 --- a/config.yml +++ b/config.yml @@ -1,6 +1,6 @@ location: wushan point: 5 -relay: COM7 +relay: /dev/ttyUSB0 maxTimeout: 60 # 单位 s,必须大于 0 log: level: debug @@ -19,7 +19,7 @@ aliyun: timeout: 10 # 单位 s voice: zhifeng_emo game: - url: rtu:///dev/ttyUSB0 # 点位 5 的串口地址 + addr: /dev/ttyUSB0 # 点位 5 的串口地址 # pushGroups: # 点位 4 的发卡器配置 # - name: gpiochip0 # outOK: 6 @@ -29,4 +29,4 @@ game: # push: 11 # reset: 22 # pull: 27 - # readUrl: rtu:///dev/ttyUSB0 # 点位 4 的读卡器配置 \ No newline at end of file + # readAddr: /dev/ttyUSB0 # 点位 4 的读卡器配置 \ No newline at end of file diff --git a/config/game/push_card.go b/config/game/push_card.go index b08e5ff..169fd7a 100644 --- a/config/game/push_card.go +++ b/config/game/push_card.go @@ -4,5 +4,5 @@ import "game-driver/internal/routes/play/card_pusher" type ConfigPush struct { PushGroups []*card_pusher.LineGroup - ReadURL string + ReadAddr string } diff --git a/config/game/wait_card.go b/config/game/wait_card.go index 086a878..9fd449d 100644 --- a/config/game/wait_card.go +++ b/config/game/wait_card.go @@ -1,5 +1,5 @@ package game type ConfigWait struct { - URL string + Addr string } diff --git a/demo/modbus2/main.go b/demo/modbus2/main.go index 0a96409..21ac104 100644 --- a/demo/modbus2/main.go +++ b/demo/modbus2/main.go @@ -15,7 +15,7 @@ func main() { logger.DefaultLogger() defer logger.Sync() - reader, err := card_reader.NewReader("rtu:///dev/ttyUSB0") + reader, err := card_reader.NewReader("/dev/ttyUSB0") if err != nil { zap.S().Panicln(err) } diff --git a/demo/relay/main.go b/demo/relay/main.go new file mode 100644 index 0000000..fbba104 --- /dev/null +++ b/demo/relay/main.go @@ -0,0 +1,31 @@ +package main + +import ( + "game-driver/logger" + "game-driver/pkg/relay" + "go.uber.org/zap" + "os" + "os/signal" + "syscall" +) + +func main() { + logger.DefaultLogger() + defer logger.Sync() + + r, err := relay.New("/dev/ttyUSB0") + if err != nil { + zap.S().Panicln(err) + } + defer r.Close() + + r.On(0) + defer r.Off(0) + + sig := make(chan os.Signal, 1) + signal.Notify(sig, os.Interrupt, syscall.SIGTERM) + + <-sig + zap.S().Infoln("接收到关闭命令 - 正在关闭程序") + zap.S().Infoln("关闭完成") +} diff --git a/go.mod b/go.mod index 2d2fc6c..4e9e33c 100644 --- a/go.mod +++ b/go.mod @@ -6,22 +6,21 @@ require ( github.com/aliyun/alibabacloud-nls-go-sdk v1.1.1 github.com/eclipse/paho.golang v0.22.0 github.com/gopxl/beep/v2 v2.1.0 - github.com/munnik/modbus v1.6.6 + github.com/grid-x/modbus v0.0.0-20241004123532-f6c6fb5201b3 github.com/spf13/cobra v1.8.1 github.com/spf13/viper v1.19.0 github.com/warthog618/go-gpiocdev v0.9.1 - go.bug.st/serial v1.6.2 go.uber.org/zap v1.27.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 ) require ( github.com/aliyun/alibaba-cloud-sdk-go v1.63.53 // indirect - github.com/creack/goselect v0.1.2 // indirect github.com/ebitengine/oto/v3 v3.3.1 // indirect github.com/ebitengine/purego v0.8.1 // indirect github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect + github.com/grid-x/serial v0.0.0-20211107191517-583c7356b3aa // indirect github.com/hajimehoshi/go-mp3 v0.3.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect diff --git a/go.sum b/go.sum index 918d37b..56bc9df 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,6 @@ github.com/aliyun/alibaba-cloud-sdk-go v1.63.53/go.mod h1:SOSDHfe1kX91v3W5QiBsWS github.com/aliyun/alibabacloud-nls-go-sdk v1.1.1 h1:LjItoNZuu5xHlsByFo+kr3nGa4LRIESCGWhfurayxBg= github.com/aliyun/alibabacloud-nls-go-sdk v1.1.1/go.mod h1:4BDMUKpEaP/Ct79w0ozR0nbnEj49g1k3mrgX/IKG5I4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0= -github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -39,6 +37,10 @@ github.com/gopxl/beep/v2 v2.1.0/go.mod h1:sQvj2oSsu8fmmDWH3t0DzIe0OZzTW6/TJEHW4K github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grid-x/modbus v0.0.0-20241004123532-f6c6fb5201b3 h1:TfBJ561lUg0i0GLsxKeRaWoBGN8nyCLNt0OMGRx7R2M= +github.com/grid-x/modbus v0.0.0-20241004123532-f6c6fb5201b3/go.mod h1:WpbUAyptAAi0VAriSRopZa6uhiJOJCTz7KFvgGtNRXc= +github.com/grid-x/serial v0.0.0-20211107191517-583c7356b3aa h1:Rsn6ARgNkXrsXJIzhkE4vQr5Gbx2LvtEMv4BJOK4LyU= +github.com/grid-x/serial v0.0.0-20211107191517-583c7356b3aa/go.mod h1:kdOd86/VGFWRrtkNwf1MPk0u1gIjc4Y7R2j7nhwc7Rk= github.com/hajimehoshi/go-mp3 v0.3.4 h1:NUP7pBYH8OguP4diaTZ9wJbUbk3tC0KlfzsEpWmYj68= github.com/hajimehoshi/go-mp3 v0.3.4/go.mod h1:fRtZraRFcWb0pu7ok0LqyFhCUrPeMsGRSVop0eemFmo= github.com/hajimehoshi/oto/v2 v2.3.1/go.mod h1:seWLbgHH7AyUMYKfKYT9pg7PhUu9/SisyJvNTT+ASQo= @@ -73,8 +75,6 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/munnik/modbus v1.6.6 h1:QRAR+04bivKSzPN5qi5g9Wyzh+e3oQVFMUOhv35ya5Q= -github.com/munnik/modbus v1.6.6/go.mod h1:p8PIBjiZgsY82MiZPrkAGkrDomL1tBNGGQIwyAm4Vp0= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= @@ -126,8 +126,6 @@ github.com/warthog618/go-gpiocdev v0.9.1 h1:pwHPaqjJfhCipIQl78V+O3l9OKHivdRDdmgX github.com/warthog618/go-gpiocdev v0.9.1/go.mod h1:dN3e3t/S2aSNC+hgigGE/dBW8jE1ONk9bDSEYfoPyl8= github.com/warthog618/go-gpiosim v0.1.1 h1:MRAEv+T+itmw+3GeIGpQJBfanUVyg0l3JCTwHtwdre4= github.com/warthog618/go-gpiosim v0.1.1/go.mod h1:YXsnB+I9jdCMY4YAlMSRrlts25ltjmuIsrnoUrBLdqU= -go.bug.st/serial v1.6.2 h1:kn9LRX3sdm+WxWKufMlIRndwGfPWsH1/9lCWXQCasq8= -go.bug.st/serial v1.6.2/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -160,8 +158,6 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -195,4 +191,6 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= +pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/internal/middleware/relay.go b/internal/middleware/relay.go index ffee498..3c0436f 100644 --- a/internal/middleware/relay.go +++ b/internal/middleware/relay.go @@ -8,12 +8,12 @@ import ( ) // RelayMaster 继电器中间件 -func RelayMaster(r *relay.Device) leaf.HandlerFunc { +func RelayMaster(r relay.Relay) leaf.HandlerFunc { return func(c *leaf.Context) { pm := leaf.Value[*schema.PlayModal](c, PayloadJSONKey) if r != nil && pm.Power { - r.On(1) - defer r.Off(1) + r.On(0) + defer r.Off(0) zap.S().Infoln("开启电源") defer zap.S().Infoln("关闭电源") diff --git a/internal/routes/play/push_card.go b/internal/routes/play/push_card.go index 87696ee..e02e61a 100644 --- a/internal/routes/play/push_card.go +++ b/internal/routes/play/push_card.go @@ -31,10 +31,10 @@ func PushCard(ctx context.Context) leaf.HandlerFunc { g := (game.G).(game.ConfigPush) // 开始初始化读卡器 - reader, err := card_reader.NewReader(g.ReadURL) + reader, err := card_reader.NewReader(g.ReadAddr) if err != nil { if errors.Is(err, fs.ErrNotExist) { - zap.S().Errorf("读卡器串口文件不存在: %s", g.ReadURL) + zap.S().Errorf("读卡器串口文件不存在: %s", g.ReadAddr) os.Exit(1) } zap.S().Panicf("读卡器串口连接失败 [%T]: %q", err, err) @@ -48,7 +48,7 @@ func PushCard(ctx context.Context) leaf.HandlerFunc { devices := make([]*card_pusher.Device, 0) for i, group := range g.PushGroups { // 对读卡器初始化配置 - reader.SetUnitID(uint8(i + 1)) + reader.SetSlave(uint8(i + 1)) err = reader.Init() if err != nil { zap.S().Panicln("读卡器初始配置失败", err) @@ -114,7 +114,7 @@ func PushCard(ctx context.Context) leaf.HandlerFunc { if body.num != 0 { // 若卡片就位,读取卡片信息 if devices[body.num-1].GetOutOk() == 1 { - reader.SetUnitID(uint8(body.num)) + reader.SetSlave(uint8(body.num)) if info := reader.GetCardInfo(); info != nil { body.CardId = info.ID } diff --git a/internal/routes/play/wait_card.go b/internal/routes/play/wait_card.go index 69df178..8d5ce41 100644 --- a/internal/routes/play/wait_card.go +++ b/internal/routes/play/wait_card.go @@ -20,10 +20,10 @@ import ( func WaitCard(ctx context.Context) leaf.HandlerFunc { g := (game.G).(game.ConfigWait) - reader, err := card_reader.NewReader(g.URL) + reader, err := card_reader.NewReader(g.Addr) if err != nil { if errors.Is(err, fs.ErrNotExist) { - zap.S().Errorf("读卡器串口文件不存在: %s", g.URL) + zap.S().Errorf("读卡器串口文件不存在: %s", g.Addr) os.Exit(1) } zap.S().Panicf("读卡器串口连接失败 [%T]: %q", err, err) diff --git a/internal/routes/wait.go b/internal/routes/wait.go index 2646a14..0e55710 100644 --- a/internal/routes/wait.go +++ b/internal/routes/wait.go @@ -177,12 +177,12 @@ func relayAction(c *leaf.Context, item schema.WaitItemModel, root schema.TimeMod defer cancel() } - device, err := relay.New(item.Data, nil) + r, err := relay.New(item.Data) if err != nil { zap.S().Errorln("继电器初始化异常: ", err) return } - defer device.Close() + defer r.Close() select { case <-c.Done(): @@ -191,9 +191,9 @@ func relayAction(c *leaf.Context, item schema.WaitItemModel, root schema.TimeMod zap.S().Infoln("待机继电器供电") defer zap.S().Infoln("待机继电器断电") - device.On(1) + r.On(0) <-c.Done() - device.Off(1) + r.Off(0) } } } diff --git a/internal/server.go b/internal/server.go index 01e42b8..edec86d 100644 --- a/internal/server.go +++ b/internal/server.go @@ -10,6 +10,7 @@ import ( "game-driver/internal/schema" "game-driver/leaf" "game-driver/logger" + "game-driver/pkg/relay" "game-driver/pkg/tts" "game-driver/pkg/utils" "github.com/eclipse/paho.golang/autopaho" @@ -108,13 +109,11 @@ func Run() { tts.DefaultTTS = tts.New(ctx, config.C.Aliyun) // 构建继电器对象 - //r, err := relay.New(config.C.Relay, func(msg string) { - // zap.S().Infoln("串口返回: ", msg) - //}) - //if err != nil { - // zap.S().Panicln("串口连接异常: ", err) - //} - //defer r.Close() + r, err := relay.New(config.C.Relay) + if err != nil { + zap.S().Panicln("串口连接异常: ", err) + } + defer r.Close() // 构建全局设备变量 device := common.DefaultDevice(ctx, publishTopic) diff --git a/pkg/card_reader/reader.go b/pkg/card_reader/reader.go index 4b543be..b9d4053 100644 --- a/pkg/card_reader/reader.go +++ b/pkg/card_reader/reader.go @@ -3,7 +3,7 @@ package card_reader import ( "context" "fmt" - "github.com/munnik/modbus" + "github.com/grid-x/modbus" "go.uber.org/zap" "io" "math" @@ -13,7 +13,7 @@ import ( type Reader interface { io.Closer - SetUnitID(uint8) + SetSlave(uint8) // WriteUnitId 写入读卡器的 UnitID WriteUnitId(uint16) error // Init 初始化读卡器配置 @@ -24,40 +24,42 @@ type Reader interface { } type CardInfo struct { - Type uint16 + Type []byte ID string } type reader struct { - c *modbus.Client + h modbus.ClientHandler + c modbus.Client } // WriteUnitId 写入读卡器的 UnitID func (r *reader) WriteUnitId(id uint16) error { v := id<<8 + 1 zap.S().Infof("WriteRegister 40007 %#x", v) - return r.c.WriteRegister(6, v) + _, err := r.c.WriteSingleRegister(6, v) + return err } // Init 初始化读卡器配置 func (r *reader) Init() error { // 配置读卡间隔时间为 50 毫秒 - err := r.c.WriteRegister(8, 0x0511) + _, err := r.c.WriteSingleRegister(8, 0x0511) if err != nil { return err } // 由低到高输出 500 毫秒 - err = r.c.WriteRegister(9, 0xF20A) + _, err = r.c.WriteSingleRegister(9, 0xF20A) if err != nil { return err } // 读取后自动清空,高字节:00 不清空 01 清空 - err = r.c.WriteRegister(10, 0x0103) + _, err = r.c.WriteSingleRegister(10, 0x0103) if err != nil { return err } // 自动读卡号,高字节高4位:0 读一次 1 连续读 - err = r.c.WriteRegister(11, 0x0301) + _, err = r.c.WriteSingleRegister(11, 0x0301) if err != nil { return err } @@ -67,31 +69,31 @@ func (r *reader) Init() error { // GetCardInfo 获取卡号信息 func (r *reader) GetCardInfo() *CardInfo { // 读取状态寄存器确认是否信息已经准备好 - status, err := r.c.ReadRegister(29, modbus.HoldingRegister) + status, err := r.c.ReadHoldingRegisters(29, 1) if err != nil { zap.S().Errorln("ReadRegister 40030 error:", err) return nil - } else if status == 0x0000 { + } else if len(status) != 2 || status[1] == 0 { return nil } // 读取卡号长度 - cardLength, err := r.c.ReadRegister(30, modbus.HoldingRegister) + cardLength, err := r.c.ReadHoldingRegisters(30, 1) if err != nil { zap.S().Errorln("ReadRegister 40031 error:", err) return nil } - dataLength := cardLength >> 8 + dataLength := cardLength[0] // 读取卡类型 - cardType, err := r.c.ReadRegister(31, modbus.HoldingRegister) + cardType, err := r.c.ReadHoldingRegisters(31, 1) if err != nil { zap.S().Errorln("ReadRegister 40032 error:", err) return nil } // 读取卡号数据 - cardData, err := r.c.ReadRegisters(32, uint16(math.Round(float64(dataLength)/2)), modbus.HoldingRegister) + cardData, err := r.c.ReadHoldingRegisters(32, uint16(math.Round(float64(dataLength)/2))) if err != nil { zap.S().Errorln("ReadRegister 40033~ error:", err) return nil @@ -99,11 +101,7 @@ func (r *reader) GetCardInfo() *CardInfo { s := make([]string, dataLength) for i := 0; i < int(dataLength); i++ { - if i%2 == 0 { - s[i] = fmt.Sprintf("%02X", cardData[i/2]>>8) - } else { - s[i] = fmt.Sprintf("%02X", cardData[i/2]&0xFF) - } + s[i] = fmt.Sprintf("%02X", cardData[i]) } return &CardInfo{ @@ -127,30 +125,30 @@ func (r *reader) OnCardInfo(ctx context.Context, f func(info *CardInfo)) { } } -func (r *reader) SetUnitID(unitID uint8) { - _ = r.c.SetUnitID(unitID) +func (r *reader) SetSlave(unitID byte) { + r.h.SetSlave(unitID) } func (r *reader) Close() error { - return r.c.Close() + return r.h.Close() } // NewReader 创建一个新的读卡器 -func NewReader(URL string) (Reader, error) { +func NewReader(address string) (Reader, error) { // 配置串口客户端 - c, _ := modbus.NewClient(&modbus.Configuration{ - URL: URL, - Speed: 9600, - DataBits: 8, - Timeout: 2 * time.Second, - Logger: zap.NewStdLog(zap.L()), - }) + h := modbus.NewRTUClientHandler(address) + h.SlaveID = 1 + h.BaudRate = 9600 + h.DataBits = 8 + h.Parity = "N" + h.StopBits = 1 - // 打开串口连接 - err := c.Open() - if err != nil { + // 连接串口 + if err := h.Connect(); err != nil { return nil, err } + // 创建 modbus 客户端 + c := modbus.NewClient(h) - return &reader{c}, nil + return &reader{h, c}, nil } diff --git a/pkg/relay/portlist.go b/pkg/relay/portlist.go deleted file mode 100644 index 1a9d510..0000000 --- a/pkg/relay/portlist.go +++ /dev/null @@ -1,28 +0,0 @@ -package relay - -import ( - "fmt" - "log" - - "go.bug.st/serial/enumerator" -) - -func PrintPorts() { - ports, err := enumerator.GetDetailedPortsList() - if err != nil { - log.Fatal(err) - } - if len(ports) == 0 { - return - } - for _, port := range ports { - fmt.Printf("Port: %s\n", port.Name) - if port.Product != "" { - fmt.Printf(" Product Name: %s\n", port.Product) - } - if port.IsUSB { - fmt.Printf(" USB ID : %s:%s\n", port.VID, port.PID) - fmt.Printf(" USB serial : %s\n", port.SerialNumber) - } - } -} diff --git a/pkg/relay/relay.go b/pkg/relay/relay.go index 452f0d4..a29c751 100644 --- a/pkg/relay/relay.go +++ b/pkg/relay/relay.go @@ -1,46 +1,64 @@ package relay import ( - "bufio" - "fmt" - "go.bug.st/serial" + "github.com/grid-x/modbus" "io" ) -type Device struct { - port serial.Port +type Relay interface { + io.Closer + SetSlave(slaveID byte) + On(num int) error + Off(num int) error + OnAll() error + OffAll() error } -func (r *Device) Close() error { - return r.port.Close() +type device struct { + h modbus.ClientHandler + c modbus.Client } -func (r *Device) On(num int) error { - _, err := io.WriteString(r.port, fmt.Sprintf("AT+OUT%v+1=ON\r\n", num)) +func (r *device) SetSlave(slaveID byte) { + r.h.SetSlave(slaveID) +} + +func (r *device) Close() error { + return r.h.Close() +} + +func (r *device) OnAll() error { + _, err := r.c.WriteMultipleCoils(uint16(0), 16, []byte{0xFF, 0xFF}) return err } -func (r *Device) Off(num int) error { - _, err := io.WriteString(r.port, fmt.Sprintf("AT+OUT%v+1=OFF\r\n", num)) +func (r *device) OffAll() error { + _, err := r.c.WriteMultipleCoils(uint16(0), 16, []byte{0x00, 0x00}) return err } -func New(portName string, reader func(msg string)) (*Device, error) { - port, err := serial.Open(portName, &serial.Mode{ - BaudRate: 9600, - DataBits: 8, - }) - if err != nil { +func (r *device) On(num int) error { + _, err := r.c.WriteSingleCoil(uint16(num), 0xFF00) + return err +} + +func (r *device) Off(num int) error { + _, err := r.c.WriteSingleCoil(uint16(num), 0x0000) + return err +} + +func New(address string) (Relay, error) { + h := modbus.NewRTUClientHandler(address) + h.SlaveID = 1 + h.BaudRate = 9600 + h.DataBits = 8 + h.Parity = "N" + h.StopBits = 1 + + if err := h.Connect(); err != nil { return nil, err } - go func() { - for { - r := bufio.NewReader(port) - line, _, _ := r.ReadLine() - if reader != nil { - reader(string(line)) - } - } - }() - return &Device{port: port}, nil + c := modbus.NewClient(h) + + return &device{h, c}, nil }