faultRecordMqttDomain.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. package domain
  2. import (
  3. "time"
  4. proto "fwh-toolbox-server/function/FaultRecordProtocol"
  5. "go.mongodb.org/mongo-driver/bson/primitive"
  6. )
  7. // FaultRecordOpKind 故障录波 MQTT 操作类型
  8. type FaultRecordOpKind string
  9. const (
  10. FaultRecordOpDeviceInfo FaultRecordOpKind = "device_info" // cmd=0
  11. FaultRecordOpRecordFetch FaultRecordOpKind = "record_fetch" // cmd=2
  12. FaultRecordOpParamRead FaultRecordOpKind = "param_read" // cmd=3
  13. FaultRecordOpParamWrite FaultRecordOpKind = "param_write" // cmd=1
  14. )
  15. // Cmd 操作对应的业务层 cmd
  16. func (k FaultRecordOpKind) Cmd() int {
  17. switch k {
  18. case FaultRecordOpDeviceInfo:
  19. return proto.CmdRealtime
  20. case FaultRecordOpRecordFetch:
  21. return proto.CmdGetRecord
  22. case FaultRecordOpParamRead:
  23. return proto.CmdQueryParam
  24. case FaultRecordOpParamWrite:
  25. return proto.CmdSetParam
  26. }
  27. return -1
  28. }
  29. // FaultRecordOpStatus 操作状态
  30. type FaultRecordOpStatus string
  31. const (
  32. // 进行中
  33. FaultRecordStatusPending FaultRecordOpStatus = "pending" // 已创建,未发送
  34. FaultRecordStatusSent FaultRecordOpStatus = "sent" // 已发送 377
  35. FaultRecordStatusAccepted FaultRecordOpStatus = "accepted" // 收到 378
  36. FaultRecordStatusReady FaultRecordOpStatus = "ready" // 收到 379(record_fetch 继续等待上传)
  37. FaultRecordStatusUploading FaultRecordOpStatus = "uploading" // 收到 607
  38. FaultRecordStatusUploaded FaultRecordOpStatus = "uploaded" // 收到 609 成功
  39. FaultRecordStatusDownloaded FaultRecordOpStatus = "downloaded" // 文件已存 MinIO
  40. // 终止
  41. FaultRecordStatusDone FaultRecordOpStatus = "done"
  42. FaultRecordStatusItemFailed FaultRecordOpStatus = "item_failed" // 379 中有子项失败
  43. FaultRecordStatusBusy FaultRecordOpStatus = "busy" // 设备正在处理其他命令
  44. FaultRecordStatusRejected FaultRecordOpStatus = "rejected" // 378 失败或 379 错误回复
  45. FaultRecordStatusTimeout FaultRecordOpStatus = "timeout" // 某阶段等待超时,见 TimeoutStage
  46. FaultRecordStatusUploadFailed FaultRecordOpStatus = "upload_failed" // 609 失败
  47. FaultRecordStatusDownloadFailed FaultRecordOpStatus = "download_failed" // 下载或存储失败
  48. FaultRecordStatusParseFailed FaultRecordOpStatus = "parse_failed" // 文件已保存但解析失败
  49. FaultRecordStatusCancelled FaultRecordOpStatus = "cancelled"
  50. FaultRecordStatusInterrupted FaultRecordOpStatus = "interrupted" // 服务重启时处于无法安全恢复的阶段
  51. FaultRecordStatusGatewayLocked FaultRecordOpStatus = "gateway_locked" // 本工具内该网关已有操作进行中
  52. FaultRecordStatusError FaultRecordOpStatus = "error" // 其他错误(MQTT 不可用等)
  53. )
  54. var faultRecordTerminal = map[FaultRecordOpStatus]bool{
  55. FaultRecordStatusDone: true, FaultRecordStatusItemFailed: true, FaultRecordStatusBusy: true,
  56. FaultRecordStatusRejected: true, FaultRecordStatusTimeout: true, FaultRecordStatusUploadFailed: true,
  57. FaultRecordStatusDownloadFailed: true, FaultRecordStatusParseFailed: true, FaultRecordStatusCancelled: true,
  58. FaultRecordStatusInterrupted: true, FaultRecordStatusGatewayLocked: true, FaultRecordStatusError: true,
  59. }
  60. func (s FaultRecordOpStatus) Terminal() bool { return faultRecordTerminal[s] }
  61. // CanRetryDownload 上传已完成(收到 609)但下载失败或超时,且有文件名时,可手动重试下载
  62. func (op *FaultRecordOperation) CanRetryDownload() bool {
  63. if op.Kind != FaultRecordOpRecordFetch || op.FileName == "" {
  64. return false
  65. }
  66. if _, uploaded := op.StageTimes[string(FaultRecordStatusUploaded)]; !uploaded {
  67. return false
  68. }
  69. return op.Status == FaultRecordStatusDownloadFailed || op.Status == FaultRecordStatusTimeout
  70. }
  71. // FaultRecordTerminalStatuses 全部终止状态
  72. func FaultRecordTerminalStatuses() []FaultRecordOpStatus {
  73. list := make([]FaultRecordOpStatus, 0, len(faultRecordTerminal))
  74. for s := range faultRecordTerminal {
  75. list = append(list, s)
  76. }
  77. return list
  78. }
  79. // FaultRecordOpRequest 操作请求参数
  80. type FaultRecordOpRequest struct {
  81. CodeList []int `bson:"codeList,omitempty" json:"codeList,omitempty"` // device_info
  82. RecordIndex int `bson:"recordIndex,omitempty" json:"recordIndex,omitempty"` // record_fetch(旧记录,单条)
  83. RecordIndexes []int `bson:"recordIndexes,omitempty" json:"recordIndexes,omitempty"` // record_fetch,可多条
  84. IdList []int `bson:"idList,omitempty" json:"idList,omitempty"` // param_read
  85. ParaList []proto.ParaItem `bson:"paraList,omitempty" json:"paraList,omitempty"` // param_write
  86. }
  87. // Indexes 本次获取的记录序号(兼容只有 RecordIndex 的旧记录)
  88. func (r FaultRecordOpRequest) Indexes() []int {
  89. if len(r.RecordIndexes) > 0 {
  90. return r.RecordIndexes
  91. }
  92. if r.RecordIndex > 0 {
  93. return []int{r.RecordIndex}
  94. }
  95. return nil
  96. }
  97. // FaultRecordOpMessage 收发的原始报文
  98. type FaultRecordOpMessage struct {
  99. Direction string `bson:"direction" json:"direction"` // send / recv / http(文件下载)/ action(用户操作,如手动重试下载)
  100. Topic string `bson:"topic" json:"topic"`
  101. CmdType uint `bson:"cmdType" json:"cmdType"`
  102. At time.Time `bson:"at" json:"at"`
  103. Raw string `bson:"raw" json:"raw"`
  104. }
  105. // FaultRecordOperation 一次故障录波 MQTT 操作(MongoDB 文档)
  106. type FaultRecordOperation struct {
  107. ID primitive.ObjectID `bson:"_id" json:"id"`
  108. Env string `bson:"env" json:"env"`
  109. GatewaySn string `bson:"gatewaySn" json:"gatewaySn"`
  110. DeviceType string `bson:"deviceType" json:"deviceType"` // pe / aGate
  111. DeviceSn string `bson:"deviceSn" json:"deviceSn"`
  112. Kind FaultRecordOpKind `bson:"kind" json:"kind"`
  113. Cmd int `bson:"cmd" json:"cmd"`
  114. Request FaultRecordOpRequest `bson:"request" json:"request"`
  115. Operator string `bson:"operator" json:"operator"`
  116. Status FaultRecordOpStatus `bson:"status" json:"status"`
  117. TimeoutStage FaultRecordOpStatus `bson:"timeoutStage,omitempty" json:"timeoutStage,omitempty"` // 超时时所等待的阶段
  118. Error string `bson:"error,omitempty" json:"error,omitempty"`
  119. StageTimes map[string]time.Time `bson:"stageTimes" json:"stageTimes"`
  120. CancelReq bool `bson:"cancelRequested" json:"cancelRequested"`
  121. ExitSent bool `bson:"exitSent" json:"exitSent"` // 取消时已向设备发送 cmd=4
  122. Messages []FaultRecordOpMessage `bson:"messages" json:"messages,omitempty"`
  123. Reply *proto.Reply `bson:"reply,omitempty" json:"reply,omitempty"` // 379 原文结构
  124. // record_fetch
  125. FileName string `bson:"fileName,omitempty" json:"fileName,omitempty"` // 609.fileName
  126. FaultRecordID int64 `bson:"faultRecordId,omitempty" json:"faultRecordId,omitempty"`
  127. UploadEquipNo string `bson:"uploadEquipNo,omitempty" json:"-"` // 下载路径中的 equipNo
  128. MinioObject string `bson:"minioObject,omitempty" json:"-"`
  129. FileSize int64 `bson:"fileSize,omitempty" json:"fileSize,omitempty"`
  130. // 手动重试下载:上传已完成(收到 609)但下载失败时,由用户触发重新下载
  131. DownloadRetryAt *time.Time `bson:"downloadRetryAt,omitempty" json:"downloadRetryAt,omitempty"`
  132. DownloadRetryCount int `bson:"downloadRetryCount,omitempty" json:"downloadRetryCount,omitempty"`
  133. CreatedAt time.Time `bson:"createdAt" json:"createdAt"`
  134. UpdatedAt time.Time `bson:"updatedAt" json:"updatedAt"`
  135. }