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