logs.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package tools
  2. import (
  3. "context"
  4. "sort"
  5. "strconv"
  6. "strings"
  7. "time"
  8. "github.com/mark3labs/mcp-go/mcp"
  9. "fwh-toolbox-server/agentmcp/kit"
  10. "fwh-toolbox-server/domain"
  11. "fwh-toolbox-server/repositories"
  12. )
  13. // ---- mqtt_log_search ----
  14. type mqttLogSearchArgs struct {
  15. SN string `json:"sn" jsonschema:"站点 SN(aGate 序列号)"`
  16. CmdType string `json:"cmdType" jsonschema:"MQTT 命令类型,如 0(连接中断)、101(登录)、105(心跳)、107(参数更新)、201、211 等"`
  17. From string `json:"from" jsonschema:"开始时间,yyyy-MM-dd HH:mm:ss"`
  18. To string `json:"to" jsonschema:"结束时间,同上;与开始时间相差不超过 7 天"`
  19. Limit int `json:"limit,omitempty" jsonschema:"最多返回条数,1~300,默认 50"`
  20. }
  21. // MqttRow mqtt_log_search 的精简行
  22. type MqttRow struct {
  23. LogTime string `json:"logTime"` // 设备时间
  24. Time string `json:"time,omitempty"` // UTC 时间
  25. Cmd string `json:"cmd,omitempty"`
  26. Data string `json:"data,omitempty"` // 原始报文,超过 1500 字截断
  27. }
  28. var MqttLogSearch = kit.Def[mqttLogSearchArgs]{
  29. Name: "mqtt_log_search",
  30. Title: "查询站点 MQTT 日志",
  31. Description: "查询单个站点在一段时间内某类 MQTT 命令的日志(FWH 平台),按时间倒序。" +
  32. "返回字段:logTime(设备时间)、time(UTC)、cmd、data(原始报文 JSON,超过 1500 字截断)。报文较大,建议缩小时间范围、减少 limit。",
  33. ReadOnly: true,
  34. Handler: func(ctx context.Context, a mqttLogSearchArgs) (*mcp.CallToolResult, error) {
  35. sn, err := kit.Required("sn", a.SN)
  36. if err != nil {
  37. return kit.Fail(err), nil
  38. }
  39. cmd, err := kit.Required("cmdType", a.CmdType)
  40. if err != nil {
  41. return kit.Fail(err), nil
  42. }
  43. from, to, err := kit.ParseRange(a.From, a.To, 7*24*time.Hour)
  44. if err != nil {
  45. return kit.Fail(err), nil
  46. }
  47. items, err := repositories.QueryMqttLogListOnTimeRange(sn, domain.MqttCmdType(cmd), from, to)
  48. if err != nil {
  49. return kit.Upstream("FWH 平台 MQTT 日志接口", err), nil
  50. }
  51. rows := make([]MqttRow, 0, len(items))
  52. for _, it := range items {
  53. rows = append(rows, MqttRow{
  54. LogTime: it.LogTime,
  55. Time: it.Time,
  56. Cmd: strings.TrimSpace(it.CmdType + " " + it.CmdName),
  57. Data: clip(it.LogData, 1500),
  58. })
  59. }
  60. sort.SliceStable(rows, func(i, j int) bool { return rows[i].LogTime > rows[j].LogTime })
  61. return kit.List(rows, -1, kit.Limit(a.Limit, 50, 300), "结果已截断,请缩短时间范围"), nil
  62. },
  63. }
  64. // ---- ems_log_records ----
  65. type emsLogRecordsArgs struct {
  66. SN string `json:"sn" jsonschema:"站点 SN(aGate 序列号)"`
  67. Date string `json:"date,omitempty" jsonschema:"日志日期 yyyy-MM-dd,不填查询全部"`
  68. LogType int `json:"logType,omitempty" jsonschema:"日志类型,默认 0(全部),取值以 FWH 平台定义为准"`
  69. }
  70. var EmsLogRecords = kit.Def[emsLogRecordsArgs]{
  71. Name: "ems_log_records",
  72. Title: "查询 EMS 日志召唤记录",
  73. Description: "查询站点最近的 EMS 日志召唤记录(FWH 平台)。返回字段:id、fileName、callTime(召唤时间)、completeTime、status(1 成功、0 召唤中、-1 失败)、fileUrl、linkId(SN)。" +
  74. "没有召唤记录时返回提示。",
  75. ReadOnly: true,
  76. Handler: func(ctx context.Context, a emsLogRecordsArgs) (*mcp.CallToolResult, error) {
  77. sn, err := kit.Required("sn", a.SN)
  78. if err != nil {
  79. return kit.Fail(err), nil
  80. }
  81. date := ""
  82. if d, err := kit.ParseDate("date", a.Date, true); err != nil {
  83. return kit.Fail(err), nil
  84. } else if d != nil {
  85. date = d.Format(kit.DateLayout)
  86. }
  87. rec, err := repositories.QueryEmsLogCallRecord(sn, date, a.LogType)
  88. if err != nil {
  89. // 上游在"没有召唤日志"时也返回 error,这里按无数据处理并带上原因
  90. return kit.Empty("未找到 EMS 日志召唤记录:" + err.Error()), nil
  91. }
  92. return kit.Object(rec), nil
  93. },
  94. }
  95. // ---- update_log_system ----
  96. type updateLogSystemArgs struct {
  97. SN string `json:"sn" jsonschema:"站点 SN(aGate 序列号)"`
  98. OrderID string `json:"orderId,omitempty" jsonschema:"升级单 ID(列表中的 id),填写时返回该升级单在本站点的明细"`
  99. Limit int `json:"limit,omitempty" jsonschema:"最多返回条数,1~200,默认 50"`
  100. }
  101. var UpdateLogSystem = kit.Def[updateLogSystemArgs]{
  102. Name: "update_log_system",
  103. Title: "查询系统升级记录",
  104. Description: "查询站点的系统(固件)升级记录(FWH 平台)。不填 orderId 时返回升级单列表:id、orderNo(升级单号)、name、upgradeType、upgradeTime(UTC)、upgradeNum 等;" +
  105. "填 orderId 时返回该升级单在本站点各设备的升级明细(版本、状态、时间等,以实际返回为准)。",
  106. ReadOnly: true,
  107. Handler: func(ctx context.Context, a updateLogSystemArgs) (*mcp.CallToolResult, error) {
  108. sn, err := kit.Required("sn", a.SN)
  109. if err != nil {
  110. return kit.Fail(err), nil
  111. }
  112. limit := kit.Limit(a.Limit, 50, 200)
  113. if id := strings.TrimSpace(a.OrderID); id != "" {
  114. orderID, err := strconv.ParseInt(id, 10, 64)
  115. if err != nil {
  116. return kit.Failf("参数 orderId 必须是数字:%s", id), nil
  117. }
  118. items, err := repositories.QuerySystemUpdateLogDetail(orderID, sn)
  119. if err != nil {
  120. return kit.Upstream("FWH 平台升级记录接口", err), nil
  121. }
  122. return kit.List(items, -1, limit, ""), nil
  123. }
  124. items, err := repositories.QuerySystemUpdateLog(sn)
  125. if err != nil {
  126. return kit.Upstream("FWH 平台升级记录接口", err), nil
  127. }
  128. return kit.List(items, -1, limit, ""), nil
  129. },
  130. }
  131. // ---- update_log_ahub ----
  132. type updateLogAhubArgs struct {
  133. SN string `json:"sn" jsonschema:"站点 SN(aGate 序列号)"`
  134. Limit int `json:"limit,omitempty" jsonschema:"最多返回条数,1~200,默认 50"`
  135. }
  136. var UpdateLogAhub = kit.Def[updateLogAhubArgs]{
  137. Name: "update_log_ahub",
  138. Title: "查询 aHub 升级记录",
  139. Description: "查询站点下 aHub(PowerLink)的升级记录(FWH 平台),返回升级时间、版本、状态等(以实际返回为准)。",
  140. ReadOnly: true,
  141. Handler: func(ctx context.Context, a updateLogAhubArgs) (*mcp.CallToolResult, error) {
  142. sn, err := kit.Required("sn", a.SN)
  143. if err != nil {
  144. return kit.Fail(err), nil
  145. }
  146. items, err := repositories.QueryAHubUpdateLog(sn)
  147. if err != nil {
  148. return kit.Upstream("FWH 平台 aHub 升级记录接口", err), nil
  149. }
  150. return kit.List(items, -1, kit.Limit(a.Limit, 50, 200), ""), nil
  151. },
  152. }