zhangqian
2024-04-25 2d6875c93b25d0b7336c7fa11e066d213259fe2e
pkg/plc/modbusx/modbus.go
@@ -1,59 +1,65 @@
package modbusx
import (
   "encoding/json"
   "sync/atomic"
   "encoding/binary"
)
func Read(ipAddr string, address uint16, quantity uint16) (data []byte, err error) {
   address--
   cli := getModbusConnection(ipAddr)
   data, err = cli.ReadHoldingRegisters(address, quantity)
   dealErr(err, ipAddr)
   if err != nil {
      cli = getModbusConnection(ipAddr)
      data, err = cli.ReadHoldingRegisters(address, quantity)
      dealErr(err, ipAddr)
   }
   return
}
func Write(ipAddr string, address uint16, value interface{}) (err error) {
   bytesVal, err := json.Marshal(value)
   if err != nil {
      return err
   }
func Write(ipAddr string, address uint16, value int, endian string, length int) (err error) {
   address--
   var bytesVal []byte
   bytesVal = intToBytes(value, endian, length)
   cli := getModbusConnection(ipAddr)
   _, err = cli.WriteMultipleRegisters(address, uint16(len(bytesVal)), bytesVal)
   dealErr(err, ipAddr)
   return err
}
func intToBytes(value int, endian string, length int) (data []byte) {
   if endian == "mix" {
      data = make([]byte, 0, 4)
      highVal := value / (1 << 16)
      highBts := make([]byte, 2)
      binary.BigEndian.PutUint16(highBts, uint16(highVal))
      lowValue := value % (1 << 16)
      lowBts := make([]byte, 2)
      binary.BigEndian.PutUint16(lowBts, uint16(lowValue))
      data = append(data, lowBts...)
      data = append(data, highBts...)
   } else {
      if length == 1 {
         data = make([]byte, 2)
         if endian == "big" {
            binary.BigEndian.PutUint16(data, uint16(value))
         } else {
            binary.LittleEndian.PutUint16(data, uint16(value))
         }
      } else {
         data = make([]byte, 4)
         if endian == "big" {
            binary.BigEndian.PutUint32(data, uint32(value))
         } else {
            binary.LittleEndian.PutUint32(data, uint32(value))
         }
      }
   }
   return
}
func dealErr(err error, ipAddr string) {
   if err != nil {
      unsetModbusConnection(ipAddr)       //失败则删除缓存的连接
      FailureRemainingOpportunitiesDecr() //减少失败剩余机会
   } else {
      FailureRemainingOpportunitiesReset() //重置失败剩余机会
      unsetModbusConnection(ipAddr) //失败则删除缓存的连接
   }
}
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() {
   failureRemainingOpportunities.Store(defaultFailureRemainingOpportunities)
   connectionStatus.Store(true)
   return
}