102 lines
1.9 KiB
Go
102 lines
1.9 KiB
Go
package relay
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"github.com/grid-x/modbus"
|
|
"go.uber.org/zap"
|
|
"io"
|
|
"io/fs"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type Relay interface {
|
|
io.Closer
|
|
// SetSlave 设置继电器的 UnitID
|
|
SetSlave(byte)
|
|
// On 打开继电器
|
|
On(int) error
|
|
// Off 关闭继电器
|
|
Off(int) error
|
|
// OnAll 打开所有继电器
|
|
OnAll() error
|
|
// OffAll 关闭所有继电器
|
|
OffAll() error
|
|
}
|
|
|
|
type device struct {
|
|
h modbus.ClientHandler
|
|
c modbus.Client
|
|
}
|
|
|
|
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) OffAll() error {
|
|
_, err := r.c.WriteMultipleCoils(uint16(0), 16, []byte{0x00, 0x00})
|
|
return err
|
|
}
|
|
|
|
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) {
|
|
zap.S().Infoln("连接继电器: ", address)
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
|
defer cancel()
|
|
a := make(chan struct{})
|
|
go func() {
|
|
defer close(a)
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
zap.S().Infoln("等待继电器资源释放超时:", address)
|
|
return
|
|
case <-time.After(3 * time.Second):
|
|
_, err := os.OpenFile(address, os.O_RDWR, 0666)
|
|
var e *fs.PathError
|
|
if errors.As(err, &e) && strings.Contains(e.Error(), "busy") {
|
|
zap.S().Infoln("等待继电器资源释放:", address)
|
|
} else {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
<-a
|
|
|
|
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
|
|
}
|
|
c := modbus.NewClient(h)
|
|
|
|
return &device{h, c}, nil
|
|
}
|