From fbae58e8f6e6159325ef41b85917ddb468d1b98a Mon Sep 17 00:00:00 2001
From: zhangqian <zhangqian@123.com>
Date: 星期六, 16 九月 2023 18:17:23 +0800
Subject: [PATCH] 读写plc连续失败20次认为失去心跳
---
api/v1/plc.go | 14 +-----
service/plc.go | 18 +--------
pkg/plc/modbusx/modbus.go | 50 ++++++++++++++++++------
crontask/cron_task.go | 6 ++-
pkg/plc/modbusx/connection_manager.go | 16 ++++++--
5 files changed, 58 insertions(+), 46 deletions(-)
diff --git a/api/v1/plc.go b/api/v1/plc.go
index 782e28c..d244314 100644
--- a/api/v1/plc.go
+++ b/api/v1/plc.go
@@ -6,10 +6,8 @@
"apsClient/model/response"
_ "apsClient/model/response"
"apsClient/pkg/contextx"
- "apsClient/pkg/ecode"
- "apsClient/pkg/plc"
+ "apsClient/pkg/plc/modbusx"
"apsClient/service"
- "fmt"
"github.com/gin-gonic/gin"
"github.com/spf13/cast"
)
@@ -35,15 +33,9 @@
resp.FinishNumber = cast.ToInt(finishNumber)
resp.TotalNumber = cast.ToInt(totalNumber)
- plcConfig, code := service.NewDevicePlcService().GetDevicePlc()
- if code != ecode.OK {
- return
- }
plcStatus := 1 //鏂紑杩炴帴
- ipAddr := fmt.Sprintf("%s:%v", plcConfig.Address, plcConfig.Port)
-
- _, err := plc.GetModbusConnection(ipAddr)
- if err == nil {
+ isConnect := modbusx.IsConnect()
+ if isConnect {
if resp.FinishNumber > 0 { //鐢熶骇
plcStatus = 2
} else { //寰呮満
diff --git a/crontask/cron_task.go b/crontask/cron_task.go
index 968abfc..45072b2 100644
--- a/crontask/cron_task.go
+++ b/crontask/cron_task.go
@@ -33,6 +33,7 @@
if addressItem.FieldName == constvar.PlcStartAddressTypeFinishNumber {
value, err := service.PlcReadDirect(plcConfig, addressItem.StartAddress, addressItem.Length, addressItem.Type)
if err != nil {
+ logx.Infof("plc read finish number err: %v", err)
continue
}
finishNumber := cast.ToInt64(value)
@@ -40,7 +41,7 @@
service.PlcCacheSet(addressItem.Position, constvar.PlcCacheKeyFinishNumber, finishNumber)
_ = service.NewProgressService().UpdateProgress(addressItem.Position, cast.ToInt64(finishNumber))
}
- logx.Infof("plc read finish number:%v, err:%v", finishNumber, err)
+ logx.Infof("plc read finish number: %v", finishNumber)
}
}
@@ -58,6 +59,7 @@
if addressItem.FieldName == constvar.PlcStartAddressTypeTotalNumber {
value, err := service.PlcReadDirect(plcConfig, addressItem.StartAddress, addressItem.Length, addressItem.Type)
if err != nil {
+ logx.Infof("plc read total number err: %v", err)
continue
}
totalNumber := cast.ToInt64(value)
@@ -65,7 +67,7 @@
service.PlcCacheSet(addressItem.Position, constvar.PlcCacheKeyTotalNumber, totalNumber)
_ = service.NewProgressService().UpdateProgress(addressItem.Position, cast.ToInt64(totalNumber))
}
- logx.Infof("plc read total number:%v, err:%v", totalNumber, err)
+ logx.Infof("plc read total number: %v", totalNumber)
}
}
diff --git a/pkg/plc/modbusx/connection_manager.go b/pkg/plc/modbusx/connection_manager.go
index 898968f..3757d34 100644
--- a/pkg/plc/modbusx/connection_manager.go
+++ b/pkg/plc/modbusx/connection_manager.go
@@ -3,7 +3,6 @@
import (
"github.com/goburrow/modbus"
"sync"
- "time"
)
type ConnectionManager struct {
@@ -37,10 +36,11 @@
cm.connections[address] = connection
}
-func (cm *ConnectionManager) CheckConnect(conn modbus.Client, timeout time.Duration) (bool, error) {
- return true, nil
+func (cm *ConnectionManager) RemoveConnection(address string) {
+ cm.mu.Lock()
+ defer cm.mu.Unlock()
+ delete(cm.connections, address)
}
-
func getModbusConnection(ipAddr string) modbus.Client {
if conn, ok := connectionManager.GetConnection(ipAddr); ok {
return conn
@@ -50,6 +50,14 @@
return conn
}
+func unsetModbusConnection(ipAddr string) {
+ _, ok := connectionManager.GetConnection(ipAddr)
+ if !ok {
+ return
+ }
+ connectionManager.RemoveConnection(ipAddr)
+}
+
func newGetModbusConnection(ipAddr string) modbus.Client {
return modbus.TCPClient(ipAddr)
}
diff --git a/pkg/plc/modbusx/modbus.go b/pkg/plc/modbusx/modbus.go
index a2941a6..796aa17 100644
--- a/pkg/plc/modbusx/modbus.go
+++ b/pkg/plc/modbusx/modbus.go
@@ -2,11 +2,13 @@
import (
"encoding/json"
+ "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
}
@@ -17,19 +19,41 @@
}
cli := getModbusConnection(ipAddr)
_, err = cli.WriteMultipleRegisters(address, uint16(len(bytesVal)), bytesVal)
+ dealErr(err, ipAddr)
+ return err
+}
+
+func dealErr(err error, ipAddr string) {
if err != nil {
- return err
+ unsetModbusConnection(ipAddr) //澶辫触鍒欏垹闄ょ紦瀛樼殑杩炴帴
+ FailureRemainingOpportunitiesDecr() //鍑忓皯澶辫触鍓╀綑鏈轰細
+ } else {
+ FailureRemainingOpportunitiesReset() //閲嶇疆澶辫触鍓╀綑鏈轰細
}
- //time.Sleep(time.Second)
- //// 鏍¢獙鍐欏叆鐨勬暟鎹�
- //result, err := cli.ReadHoldingRegisters(address, uint16(len(bytesVal)))
- //if err != nil {
- // return err
- //}
- //resultVal := int(binary.BigEndian.Uint16(result))
- //valueInt := cast.ToInt(value)
- //if resultVal != valueInt {
- // return errors.New("write result not equal read result")
- //}
- return nil
+}
+
+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
}
diff --git a/service/plc.go b/service/plc.go
index aaa58f2..8b00c7d 100644
--- a/service/plc.go
+++ b/service/plc.go
@@ -116,12 +116,6 @@
var (
ipAddr string
)
-
- if plcConfig.CurrentTryTimes > plcConfig.MaxTryTimes {
- logx.Errorf("plc write try time beyond max try times, err: %v", plcConfig.CurrentErr)
- return plcConfig.CurrentErr
- }
- plcConfig.CurrentTryTimes++
if plcConfig.Method == constvar.PlcMethodModbusTCP {
ipAddr = fmt.Sprintf("%s:%v", plcConfig.Address, plcConfig.Port)
//conn, err := plc.GetModbusConnection(ipAddr)
@@ -135,8 +129,7 @@
err = modbusx.Write(ipAddr, uint16(address), value)
if err != nil {
logx.Errorf("plc write failed, address: %v, value: %v, err: %v", address, value, err.Error())
- plcConfig.CurrentErr = err
- return PlcWriteDirect(plcConfig, address, value)
+ return err
}
logx.Infof("plc write ok, address: %v, value: %v", address, value)
} else if plcConfig.Method == constvar.PlcMethodSerial {
@@ -154,12 +147,6 @@
var (
ipAddr string
)
-
- if plcConfig.CurrentTryTimes > plcConfig.MaxTryTimes {
- logx.Errorf("plc read try time beyond max try times, err: %v", plcConfig.CurrentErr)
- return nil, plcConfig.CurrentErr
- }
- plcConfig.CurrentTryTimes++
if plcConfig.Method == constvar.PlcMethodModbusTCP {
ipAddr = fmt.Sprintf("%s:%v", plcConfig.Address, plcConfig.Port)
//conn, err := plc.GetModbusConnection(ipAddr)
@@ -170,8 +157,7 @@
//value, err := plc.ReadHoldingRegister(conn, address, dataLength)
value, err := modbusx.Read(ipAddr, uint16(address), uint16(dataLength))
if err != nil {
- plcConfig.CurrentErr = err
- return PlcReadDirect(plcConfig, address, dataLength, valueType)
+ return nil, err
}
switch valueType {
case constvar.PlcStartAddressValueTypeString:
--
Gitblit v1.8.0