fix
zhangqian
2023-12-01 8324f872ef3a4d0c978a9b1d062800c6a1701c12
pkg/plc/plc4x.go
@@ -1,12 +1,15 @@
package plc
import (
   "apsClient/conf"
   "apsClient/pkg/logx"
   "context"
   "errors"
   "fmt"
   apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
   "github.com/spf13/cast"
   "sync"
   "sync/atomic"
   "time"
   plc4go "github.com/apache/plc4x/plc4go/pkg/api"
@@ -33,15 +36,11 @@
   if !ok {
      return nil, false
   }
   connOK, err := cm.CheckConnect(conn, time.Second*1)
   if err != nil {
      logx.Errorf("ping plc err:%v", err.Error())
      return nil, false
   }
   if connOK {
      return conn, ok
   }
   return nil, false
   //if ok, _ := cm.CheckConnect(conn, time.Second); !ok {
   //   conn.Close()
   //}
   return conn, true
}
var connectionManager = newPlcConnectionManager()
@@ -70,7 +69,6 @@
func GetModbusConnection(ipAddr string) (plc4go.PlcConnection, error) {
   if conn, ok := connectionManager.GetConnection(ipAddr); ok {
      time.Sleep(time.Millisecond * 500)
      return conn, nil
   }
   // 创建一个上下文,并设置 3 秒超时
@@ -82,7 +80,6 @@
      return nil, err
   }
   connectionManager.AddConnection(ipAddr, conn)
   time.Sleep(time.Millisecond * 500)
   return conn, nil
}
@@ -113,7 +110,7 @@
func readHoldingRegisterSingle(connection plc4go.PlcConnection, address int) ([]byte, error) {
   tag := fmt.Sprintf("tag:%v", address)
   tagAddress := fmt.Sprintf("holding-register:%d:UINT", address)
   tagAddress := getTagAddress(address, 1)
   // 读模式
   readRequest, err := connection.ReadRequestBuilder().AddTagAddress(tag, tagAddress).Build()
@@ -143,7 +140,7 @@
func readHoldingRegisterList(connection plc4go.PlcConnection, address, length int) ([]byte, error) {
   tag := fmt.Sprintf("tag:%v:%v", address, length)
   tagAddress := fmt.Sprintf("holding-register:%d:UINT[%d]", address, length)
   tagAddress := getTagAddress(address, length)
   // 读模式
   readRequest, err := connection.ReadRequestBuilder().AddTagAddress(tag, tagAddress).Build()
@@ -155,13 +152,13 @@
   // 执行
   readResult := <-readRequest.Execute()
   if err := readResult.GetErr(); err != nil {
      logx.Errorf("execting read-request:%s\n", err.Error())
      logx.Errorf("plc4x execute read-request:%s\n", err.Error())
      return nil, err
   }
   // 判断响应码是否正确
   if readResult.GetResponse().GetResponseCode(tag) != apiModel.PlcResponseCode_OK {
      logx.Errorf("error an non-ok return code: %s", readResult.GetResponse().GetResponseCode(tag).GetName())
      logx.Errorf("plc4x response error code: %s", readResult.GetResponse().GetResponseCode(tag).GetName())
      return nil, errors.New("error  code: " + readResult.GetResponse().GetResponseCode(tag).GetName())
   }
@@ -184,27 +181,44 @@
   return readHoldingRegisterSingle(connection, address)
}
func getTagAddress(address int, length int) string {
   intType := conf.Conf.PLC.ModbusIntType
   if intType == "" {
      intType = "DINT"
   }
   if length == 1 {
      return fmt.Sprintf("holding-register:%d:%v", address, intType)
   } else {
      return fmt.Sprintf("holding-register:%d:%v[%d]", address, intType, length)
   }
}
func WriteHoldingRegister(connection plc4go.PlcConnection, address int, value any) (string, error) {
   tag := fmt.Sprintf("tag:%v:w", address)
   tagAddress := fmt.Sprintf("holding-register:%d:UINT", address)
   var tagAddress string
   if cast.ToInt32(value) > 2<<16 {
      tagAddress = getTagAddress(address, 2)
   } else {
      tagAddress = getTagAddress(address, 1)
   }
   // 写模式
   writeRequest, err := connection.WriteRequestBuilder().AddTagAddress(tag, tagAddress, value).Build()
   if err != nil {
      logx.Errorf("preparing read-request:%s\n", err.Error())
      logx.Errorf("plc4x preparing read-request:%s\n", err.Error())
      return "", err
   }
   // 执行
   writeResult := <-writeRequest.Execute()
   if err := writeResult.GetErr(); err != nil {
      logx.Errorf("execting read-request:%s\n", err.Error())
      logx.Errorf("plc4x execute write-request:%s\n", err.Error())
      return "", err
   }
   // 判断响应码是否正确
   if writeResult.GetResponse().GetResponseCode(tag) != apiModel.PlcResponseCode_OK {
      logx.Errorf("error an non-ok return code: %s", writeResult.GetResponse().GetResponseCode(tag).GetName())
      logx.Errorf("plc4x  response error code: %s", writeResult.GetResponse().GetResponseCode(tag).GetName())
      return "", errors.New("error  code: " + writeResult.GetResponse().GetResponseCode(tag).GetName())
   }
@@ -212,3 +226,41 @@
   return result, nil
}
func dealErr(err error, ipAddr string) {
   if err != nil {
      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
}