package modbusx
|
|
import (
|
"encoding/binary"
|
"sync/atomic"
|
)
|
|
func Read(ipAddr string, address uint16, quantity uint16) (data []byte, err error) {
|
cli := getModbusConnection(ipAddr)
|
data, err = cli.ReadHoldingRegisters(address, quantity)
|
dealErr(err, ipAddr)
|
return
|
}
|
|
func Write(ipAddr string, address uint16, value int) (err error) {
|
var bytesVal []byte
|
if value <= 1<<16 {
|
uint16ToBytes(uint16(value))
|
} else {
|
bytesVal = intToBytes(value)
|
}
|
cli := getModbusConnection(ipAddr)
|
_, err = cli.WriteMultipleRegisters(address, uint16(len(bytesVal)), bytesVal)
|
dealErr(err, ipAddr)
|
return err
|
}
|
|
func uint16ToBytes(value uint16) []byte {
|
// 创建一个长度为2的字节切片
|
bytes := make([]byte, 2)
|
|
// 将 uint16 的值写入字节切片,可以选择使用大端或小端字节序
|
bytes[0] = byte(value >> 8) // 获取高8位
|
bytes[1] = byte(value) // 获取低8位
|
|
return bytes
|
}
|
|
func intToBytes(value int) []byte {
|
// 创建一个长度为4的字节切片,用于存储 int 值
|
bytes := make([]byte, 4)
|
|
// 使用 binary 包将 int 值转换为字节切片
|
binary.BigEndian.PutUint32(bytes, uint32(value))
|
|
return bytes
|
}
|
|
func dealErr(err error, ipAddr string) {
|
if err != nil {
|
unsetModbusConnection(ipAddr) //失败则删除缓存的连接
|
FailureRemainingOpportunitiesDecr() //减少失败剩余机会
|
} else {
|
FailureRemainingOpportunitiesReset() //重置失败剩余机会
|
}
|
}
|
|
var connectionStatus atomic.Bool
|
|
var failureRemainingOpportunities atomic.Int64
|
|
const (
|
defaultFailureRemainingOpportunities = 20
|
)
|
|
func IsConnect() bool {
|
return connectionStatus.Load()
|
}
|
|
func FailureRemainingOpportunitiesDecr() {
|
newValue := failureRemainingOpportunities.Add(-1)
|
if newValue <= 0 {
|
connectionStatus.Store(false)
|
}
|
return
|
}
|
|
func FailureRemainingOpportunitiesReset() {
|
if failureRemainingOpportunities.Load() < defaultFailureRemainingOpportunities {
|
failureRemainingOpportunities.Store(defaultFailureRemainingOpportunities)
|
}
|
if connectionStatus.Load() == false {
|
connectionStatus.Store(true)
|
}
|
return
|
}
|