From f2d80dbaa80a1283bf1c0fe9ae1d280832652d7f Mon Sep 17 00:00:00 2001
From: zhangqian <zhangqian@123.com>
Date: 星期四, 02 十一月 2023 18:14:22 +0800
Subject: [PATCH] 增加问题诊断定时任务和查询接口,增加按channel查询工序开始和结束时间
---
api/v1/plc.go | 3
constvar/const.go | 16 ++
api/v1/system.go | 25 +++
service/plc_address/address_map.go | 7 +
service/cache_store.go | 55 ++++++-
service/problem/check.go | 184 ++++++++++++++++++++++++++
service/system.go | 5
model/response/common.go | 8
crontask/cron_task.go | 6
service/problem/observer.go | 82 +++++++++++
api/v1/task.go | 6
11 files changed, 385 insertions(+), 12 deletions(-)
diff --git a/api/v1/plc.go b/api/v1/plc.go
index 14750bc..a02e6f8 100644
--- a/api/v1/plc.go
+++ b/api/v1/plc.go
@@ -46,6 +46,9 @@
}
resp.PlcStatus = plcStatus
+ resp.RealStartTime = service.TaskStartTimeGet(params.Channel)
+ resp.RealEndTime = service.TaskEndTimeGet(params.Channel)
+
ctx.OkWithDetailed(resp)
}
diff --git a/api/v1/system.go b/api/v1/system.go
new file mode 100644
index 0000000..5931a9b
--- /dev/null
+++ b/api/v1/system.go
@@ -0,0 +1,25 @@
+package v1
+
+import (
+ _ "apsClient/model/response"
+ "apsClient/pkg/contextx"
+ "apsClient/service/problem"
+ "github.com/gin-gonic/gin"
+)
+
+type SystemApi struct{}
+
+// ProblemList
+// @Tags 绯荤粺
+// @Summary 闂璇婃柇/闂鍒楄〃
+// @Produce application/json
+// @Success 200 {object} contextx.Response{data=[]problem.CheckResult} "鎴愬姛"
+// @Router /v1/system/problemList [get]
+func (slf *SystemApi) ProblemList(c *gin.Context) {
+ ctx, ok := contextx.NewContext(c, nil)
+ if !ok {
+ return
+ }
+ list := problem.Get()
+ ctx.OkWithDetailed(list)
+}
diff --git a/api/v1/task.go b/api/v1/task.go
index 26cfb2d..0b1c769 100644
--- a/api/v1/task.go
+++ b/api/v1/task.go
@@ -235,7 +235,7 @@
}
service.TaskFlagUnset(procedure.Channel)
-
+ service.TaskEndTimeSet(procedure.Channel, time.Now().Unix()) //璁剧疆宸ュ簭杩愯缁撴潫鏃堕棿
ctx.Ok()
}
@@ -322,7 +322,9 @@
return
}
- service.TaskFlagSet(procedure.Channel)
+ service.TaskFlagSet(procedure.Channel, int(procedure.ID))
+ service.TaskStartTimeSet(procedure.Channel, time.Now().Unix()) //璁剧疆宸ュ簭杩愯寮�濮嬫椂闂�
+ service.TaskEndTimeSet(procedure.Channel, 0) //璁剧疆宸ュ簭杩愯缁撴潫鏃堕棿
ctx.Ok()
}
diff --git a/constvar/const.go b/constvar/const.go
index bb73e7e..3f6fc2b 100644
--- a/constvar/const.go
+++ b/constvar/const.go
@@ -97,3 +97,19 @@
SerfClusterStatusMaster = "master" //闆嗙兢master
SerfClusterStatusSlave = "slave" //闆嗙兢slave
)
+
+type ProblemCode string
+
+const (
+ ProblemCodeService ProblemCode = "service" //鏈嶅姟涓嶅彲鐢�
+ ProblemCodeNetwork ProblemCode = "network" //缃戠粶閿欒
+ ProblemCodeDB ProblemCode = "db" //鏁版嵁搴撹繛鎺ラ敊璇�
+ ProblemCodeSerf ProblemCode = "serf" //鏈姞鍏erf闆嗙兢
+ ProblemCodeNsq ProblemCode = "nsq" //鏈繛鎺ユ秷鎭槦鍒�
+ ProblemCodeDevice ProblemCode = "device" //鏈粦瀹氳澶�
+ ProblemCodeProcessModel ProblemCode = "process_model" //宸ヨ壓鍙傛暟缂哄け
+ ProblemCodePlcConfig ProblemCode = "plc_config" //plc閰嶇疆缂哄け
+ ProblemCodePlcAddressList ProblemCode = "plc_address_list" //plc鍦板潃琛ㄧ己澶�
+ ProblemCodePlcProcessModelAddressList ProblemCode = "plc_process_model_address_list" //plc鍦板潃琛ㄧ己澶�
+ ProblemCodePlcConnect ProblemCode = "plc_connect" //plc杩炴帴澶辫触
+)
diff --git a/crontask/cron_task.go b/crontask/cron_task.go
index 66ddf9b..42dc94b 100644
--- a/crontask/cron_task.go
+++ b/crontask/cron_task.go
@@ -9,6 +9,7 @@
"apsClient/pkg/logx"
"apsClient/serf"
"apsClient/service"
+ "apsClient/service/problem"
"fmt"
"github.com/go-co-op/gocron"
"github.com/spf13/cast"
@@ -82,6 +83,7 @@
}
s.Every(10).Seconds().Do(QueryClusterStatus) //鏌ヨ闆嗙兢鑺傜偣鏁伴噺
+ s.Every(30).Seconds().Do(ProblemCheck) //闂璇婃柇
s.StartAsync()
return nil
@@ -162,3 +164,7 @@
conf.Conf.SerfClusterStatus = clusterStatus
conf.Conf.ClusterNodeQuantity = nodeQuantity
}
+
+func ProblemCheck() {
+ problem.Check()
+}
diff --git a/model/response/common.go b/model/response/common.go
index 9e36958..699292f 100644
--- a/model/response/common.go
+++ b/model/response/common.go
@@ -54,9 +54,11 @@
}
type ProductProgress struct {
- FinishNumber int `json:"finishNumber"`
- TotalNumber int `json:"totalNumber"`
- PlcStatus int `json:"plcStatus"`
+ FinishNumber int `json:"finishNumber"`
+ TotalNumber int `json:"totalNumber"`
+ PlcStatus int `json:"plcStatus"`
+ RealStartTime int64 `json:"RealStartTime"`
+ RealEndTime int64 `json:"RealEndTime"`
}
type TaskCountdown struct {
diff --git a/service/cache_store.go b/service/cache_store.go
index 1d9b7d1..2ac4594 100644
--- a/service/cache_store.go
+++ b/service/cache_store.go
@@ -52,6 +52,8 @@
CurrentTaskCacheKey = "current_task:%v" //current_task:channel
CurrentProgressCacheKey = "current_progress:%v" //current_progress:channel
PlcCacheKeyUpdateTime = "finish_number_update_time:%v" //finish_number_update_time:channel
+ TaskStartTimeCache = "task_start_time:%v" //task_start_time:channel
+ TaskEndTimeCache = "task_end_time:%v" //task_end_time:channel
)
func PlcCacheGet(channel int32, key string) (interface{}, bool) {
@@ -76,28 +78,67 @@
return 0
}
+func TaskStartTimeSet(channel int32, ts int64) {
+ defaultCacheStore.Add(fmt.Sprintf(TaskStartTimeCache, channel), ts)
+}
+
+func TaskStartTimeGet(channel int32) int64 {
+ if v, ok := defaultCacheStore.Get(fmt.Sprintf(TaskStartTimeCache, channel)); ok {
+ return v.(int64)
+ }
+ procedure, err := model.NewProceduresSearch(nil).SetDeviceId(conf.Conf.CurrentDeviceID).SetStatus(model.ProcedureStatusProcessing).SetChannels([]int32{channel}).First() //杩涜涓换鍔�
+ if err == gorm.ErrRecordNotFound {
+ procedure, err = model.NewProceduresSearch(nil).SetDeviceId(conf.Conf.CurrentDeviceID).
+ SetStatus(model.ProcedureStatusFinished).SetChannels([]int32{channel}).SetOrder("real_end_time desc").First() //涓婁竴涓粨鏉熺殑浠诲姟
+ if err == gorm.ErrRecordNotFound { //杩涜涓拰缁撴潫鐨勯兘娌℃湁锛屽紑濮嬫椂闂村拰缁撴潫鏃堕棿閮借缃�0
+ TaskStartTimeSet(channel, int64(0))
+ TaskEndTimeSet(channel, int64(0))
+ return 0
+ } else {
+ TaskStartTimeSet(channel, procedure.RealStartTime)
+ TaskStartTimeSet(channel, procedure.RealEndTime)
+ return 0
+ }
+ } else {
+ TaskStartTimeSet(channel, procedure.RealStartTime)
+ TaskStartTimeSet(channel, int64(0))
+ return procedure.RealStartTime
+ }
+}
+
+func TaskEndTimeSet(channel int32, ts int64) {
+ defaultCacheStore.Add(fmt.Sprintf(TaskEndTimeCache, channel), ts)
+}
+
+func TaskEndTimeGet(channel int32) int64 {
+ if v, ok := defaultCacheStore.Get(fmt.Sprintf(TaskEndTimeCache, channel)); ok {
+ return v.(int64)
+ }
+ return 0
+}
+
func FinishUpdateTimeSet(channel int32, value interface{}) {
defaultCacheStore.Add(fmt.Sprintf(PlcCacheKeyUpdateTime, channel), value)
}
-func TaskFlagSet(channel int32) {
- defaultCacheStore.Add(fmt.Sprintf(CurrentTaskCacheKey, channel), true)
+func TaskFlagSet(channel int32, taskId int) {
+ defaultCacheStore.Add(fmt.Sprintf(CurrentTaskCacheKey, channel), taskId)
}
func TaskFlagUnset(channel int32) {
- defaultCacheStore.Add(fmt.Sprintf(CurrentTaskCacheKey, channel), false)
+ defaultCacheStore.Add(fmt.Sprintf(CurrentTaskCacheKey, channel), 0)
}
func TaskFlagGet(channel int32) bool {
if v, ok := defaultCacheStore.Get(fmt.Sprintf(CurrentTaskCacheKey, channel)); ok {
- return v.(bool)
+ return v.(int) > 0
}
- _, err := model.NewProceduresSearch(nil).SetDeviceId(conf.Conf.CurrentDeviceID).SetStatus(model.ProcedureStatusProcessing).SetChannels([]int32{channel}).First()
+ procedure, err := model.NewProceduresSearch(nil).SetDeviceId(conf.Conf.CurrentDeviceID).SetStatus(model.ProcedureStatusProcessing).SetChannels([]int32{channel}).First()
if err == gorm.ErrRecordNotFound {
- defaultCacheStore.Add(fmt.Sprintf(CurrentTaskCacheKey, channel), false)
+ defaultCacheStore.Add(fmt.Sprintf(CurrentTaskCacheKey, channel), 0)
return false
} else {
- defaultCacheStore.Add(fmt.Sprintf(CurrentTaskCacheKey, channel), true)
+ defaultCacheStore.Add(fmt.Sprintf(CurrentTaskCacheKey, channel), int(procedure.ID))
return true
}
}
diff --git a/service/plc_address/address_map.go b/service/plc_address/address_map.go
index 609bf22..0bf753b 100644
--- a/service/plc_address/address_map.go
+++ b/service/plc_address/address_map.go
@@ -36,6 +36,12 @@
return 0, false
}
+var LoadOk bool
+
+func IsLoad() bool {
+ return LoadOk
+}
+
func LoadAddressFromFile() (loadOk bool) {
keyFileName := fmt.Sprintf("%s%s", constvar.PlcAddressDataPath, constvar.PlcAddressDataKeyFileName)
addressFileName := fmt.Sprintf("%s%s", constvar.PlcAddressDataPath, constvar.PlcAddressDataValueFileName)
@@ -65,5 +71,6 @@
address := cast.ToInt(strings.ReplaceAll(addresses[i], "\r", ""))
Set(key, address)
}
+ LoadOk = true
return true
}
diff --git a/service/problem/check.go b/service/problem/check.go
new file mode 100644
index 0000000..a7110d6
--- /dev/null
+++ b/service/problem/check.go
@@ -0,0 +1,184 @@
+package problem
+
+import (
+ "apsClient/conf"
+ "apsClient/constvar"
+ "apsClient/pkg/sqlitex"
+ "apsClient/service"
+ "apsClient/service/plc_address"
+ "sync"
+)
+
+var checkItems = []constvar.ProblemCode{
+ constvar.ProblemCodeService,
+ constvar.ProblemCodeNetwork,
+ constvar.ProblemCodeDB,
+ constvar.ProblemCodeSerf,
+ constvar.ProblemCodeNsq,
+ constvar.ProblemCodeDevice,
+ constvar.ProblemCodeProcessModel,
+ constvar.ProblemCodePlcConfig,
+ constvar.ProblemCodePlcAddressList,
+ constvar.ProblemCodePlcProcessModelAddressList,
+ constvar.ProblemCodePlcConnect,
+}
+var itemNameMap = map[constvar.ProblemCode]string{
+ constvar.ProblemCodeService: "鏈嶅姟",
+ constvar.ProblemCodeNetwork: "缃戠粶杩炴帴",
+ constvar.ProblemCodeDB: "鏁版嵁搴�",
+ constvar.ProblemCodeSerf: "serf闆嗙兢",
+ constvar.ProblemCodeNsq: "娑堟伅闃熷垪",
+ constvar.ProblemCodeDevice: "鐢熶骇璁惧缁戝畾",
+ constvar.ProblemCodeProcessModel: "宸ヨ壓鍙傛暟",
+ constvar.ProblemCodePlcConfig: "plc閰嶇疆",
+ constvar.ProblemCodePlcAddressList: "plc鍦板潃琛�",
+ constvar.ProblemCodePlcProcessModelAddressList: "plc宸ヨ壓鍙傛暟鍦板潃琛�",
+ constvar.ProblemCodePlcConnect: "plc杩炴帴",
+}
+
+type CheckResult struct {
+ ItemCode constvar.ProblemCode
+ ItemName string
+ CheckResult bool
+}
+
+var checkResultList []*CheckResult
+var mutex sync.RWMutex
+
+func Check() {
+ checkResultListTemp := make([]*CheckResult, 0)
+ var checkObj check
+ for _, item := range checkItems {
+ switch item {
+ case constvar.ProblemCodeService:
+ checkObj = &Default{}
+ case constvar.ProblemCodeNetwork:
+ checkObj = &Network{}
+ case constvar.ProblemCodeDB:
+ checkObj = &DB{}
+ case constvar.ProblemCodeSerf:
+ checkObj = &Serf{}
+ case constvar.ProblemCodeNsq:
+ checkObj = &Nsq{}
+ case constvar.ProblemCodeDevice:
+ checkObj = &Device{}
+ case constvar.ProblemCodePlcConfig:
+ checkObj = &PlcConfig{}
+ case constvar.ProblemCodePlcAddressList:
+ checkObj = &PlcAddressList{}
+ case constvar.ProblemCodePlcProcessModelAddressList:
+ checkObj = &PlcProcessModelAddressList{}
+ case constvar.ProblemCodePlcConnect:
+ checkObj = &PlcConnect{}
+ }
+ checkResultList = append(checkResultList, &CheckResult{
+ ItemCode: item,
+ ItemName: itemNameMap[item],
+ CheckResult: checkObj.Check(),
+ })
+ }
+ mutex.Lock()
+ checkResultList = checkResultListTemp
+ mutex.Unlock()
+}
+
+func Get() []*CheckResult {
+ mutex.RLock()
+ defer mutex.RUnlock()
+ return checkResultList
+
+}
+
+type check interface {
+ Check() bool
+}
+
+type Default struct{}
+
+func (slf *Default) Check() bool {
+ return true
+}
+
+type Network struct{}
+
+func (slf *Network) Check() bool {
+ return false
+}
+
+type DB struct{}
+
+func (slf *DB) Check() bool {
+ err := sqlitex.GetDB().DB().Ping()
+ if err != nil {
+ return false
+ }
+ return true
+}
+
+type Serf struct{}
+
+func (slf *Serf) Check() bool {
+ return conf.Conf.SerfClusterStatus != ""
+}
+
+type Nsq struct{}
+
+func (slf *Nsq) Check() bool {
+ return false
+}
+
+type Device struct{}
+
+func (slf *Device) Check() bool {
+ list, err := service.GetDeviceIDList()
+ if err != nil {
+ return false
+ }
+ return len(list) > 0
+}
+
+type ProcessModel struct {
+}
+
+func (slf *ProcessModel) Check() bool {
+ return false
+}
+
+type PlcConfig struct{}
+
+func (slf *PlcConfig) Check() bool {
+ plcConfig, _ := service.NewDevicePlcService().GetDevicePlc()
+ if plcConfig.Method == "" {
+ return false
+ }
+ if plcConfig.Method == constvar.PlcMethodModbusTCP && (plcConfig.Address == "" || plcConfig.Port == 0) {
+ return false
+ }
+ if plcConfig.Method == constvar.PlcMethodSerial && (plcConfig.BaudRate == 0 || plcConfig.SerialName == "") {
+ return false
+ }
+
+ if plcConfig.Method == constvar.PlcMethodModbusRTU && (plcConfig.DataBit == 0 || plcConfig.StopBit == 0 || plcConfig.Parity == 0) {
+ return false
+ }
+ return true
+}
+
+type PlcAddressList struct{}
+
+func (slf *PlcAddressList) Check() bool {
+ plcConfig, _ := service.NewDevicePlcService().GetDevicePlc()
+ return len(plcConfig.Details) > 0
+}
+
+type PlcProcessModelAddressList struct{}
+
+func (slf *PlcProcessModelAddressList) Check() bool {
+ return plc_address.IsLoad()
+}
+
+type PlcConnect struct{}
+
+func (slf *PlcConnect) Check() bool {
+ return service.PlcIsConnect()
+}
diff --git a/service/problem/observer.go b/service/problem/observer.go
new file mode 100644
index 0000000..7a3638a
--- /dev/null
+++ b/service/problem/observer.go
@@ -0,0 +1,82 @@
+package problem
+
+import "fmt"
+
+// Subject 涓婚鎺ュ彛
+type Subject interface {
+ Register(observer Observer)
+ Deregister(observer Observer)
+ Notify(data interface{})
+}
+
+// Observer 瑙傚療鑰呮帴鍙�
+type Observer interface {
+ Update(data interface{})
+}
+
+// BaseSubject 涓婚鍩虹被瀹炵幇
+type BaseSubject struct {
+ observers []Observer
+}
+
+func (s *BaseSubject) Register(observer Observer) {
+ s.observers = append(s.observers, observer)
+}
+
+func (s *BaseSubject) Deregister(observer Observer) {
+ for i, obs := range s.observers {
+ if obs == observer {
+ s.observers = append(s.observers[:i], s.observers[i+1:]...)
+ return
+ }
+ }
+}
+
+func (s *BaseSubject) Notify(data interface{}) {
+ for _, obs := range s.observers {
+ obs.Update(data)
+ }
+}
+
+//// 涓婚瀹炵幇
+//type ConcreteSubject struct {
+// BaseSubject
+//}
+//
+//// 瑙傚療鑰呭疄鐜�
+//type ConcreteObserver struct {
+// name string
+//}
+//
+//func (o *ConcreteObserver) Update(data interface{}) {
+// fmt.Printf("%s 鏀跺埌閫氱煡锛�%v\n", o.name, data)
+//}
+//
+//func main() {
+// subject := &ConcreteSubject{}
+//
+// observer1 := &ConcreteObserver{name: "瑙傚療鑰�1"}
+// observer2 := &ConcreteObserver{name: "瑙傚療鑰�2"}
+//
+// subject.Register(observer1)
+// subject.Register(observer2)
+//
+// subject.Notify("鏂版暟鎹�1")
+// subject.Deregister(observer1)
+//
+// subject.Notify("鏂版暟鎹�2")
+//}
+
+// 涓婚瀹炵幇
+type EventSubject struct {
+ BaseSubject
+}
+
+// 瑙傚療鑰呭疄鐜�
+type EventObserver struct {
+ name string
+}
+
+func (o *EventObserver) Update(data interface{}) {
+ fmt.Printf("%s 鏀跺埌閫氱煡锛�%v\n", o.name, data)
+}
diff --git a/service/system.go b/service/system.go
new file mode 100644
index 0000000..bde2c9e
--- /dev/null
+++ b/service/system.go
@@ -0,0 +1,5 @@
+package service
+
+func GetProblemList() {
+
+}
--
Gitblit v1.8.0