继电器、读卡器,都用统一的modbus协议

This commit is contained in:
2024-12-12 10:30:21 +08:00
parent 25cb34f6f5
commit df9dbb0926
15 changed files with 142 additions and 127 deletions

View File

@@ -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
}

View File

@@ -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)
}
}
}

View File

@@ -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
}