Files
hr_data_analyzer/controllers/system_debug.go
T
2026-07-08 15:31:58 +08:00

334 lines
9.8 KiB
Go

package controllers
import (
"errors"
"hr_receiver/config"
"hr_receiver/models"
"hr_receiver/mqtt"
"hr_receiver/util"
"net/http"
"strings"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
)
type SystemDebugController struct{}
type mqttDebugStartRequest struct {
PersistToDatabase bool `json:"persistToDatabase"`
}
type mqttReplayStartRequest struct {
Addr string `json:"addr"`
EndTime int64 `json:"endTime"`
RegionID uint32 `json:"regionId"`
StartTime int64 `json:"startTime"`
}
var debugUpgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
func NewSystemDebugController() *SystemDebugController {
return &SystemDebugController{}
}
// @Summary 获取MQTT调试状态
// @Description 获取MQTT调试服务的当前运行状态
// @Tags 系统调试
// @Produce json
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Router /admin/system-debug/mqtt/status [get]
func (sc *SystemDebugController) MqttStatus(c *gin.Context) {
service := mqtt.GetDebugService()
if service == nil {
writeError(c, http.StatusServiceUnavailable, "mqtt debug service unavailable")
return
}
writeSuccess(c, http.StatusOK, "query success", service.Status())
}
// @Summary 启动MQTT调试
// @Description 启动MQTT调试服务
// @Tags 系统调试
// @Accept json
// @Produce json
// @Param persist body mqttDebugStartRequest false "是否持久化到数据库"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "启动成功"
// @Router /admin/system-debug/mqtt/start [post]
func (sc *SystemDebugController) StartMqtt(c *gin.Context) {
service := mqtt.GetDebugService()
if service == nil {
writeError(c, http.StatusServiceUnavailable, "mqtt debug service unavailable")
return
}
var payload mqttDebugStartRequest
if err := c.ShouldBindJSON(&payload); err != nil && !errors.Is(err, http.ErrBodyNotAllowed) {
writeError(c, http.StatusBadRequest, err.Error())
return
}
if err := service.Start(payload.PersistToDatabase); err != nil {
writeError(c, http.StatusInternalServerError, err.Error())
return
}
writeSuccess(c, http.StatusOK, "start success", service.Status())
}
// @Summary 停止MQTT调试
// @Description 停止MQTT调试服务
// @Tags 系统调试
// @Produce json
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "停止成功"
// @Router /admin/system-debug/mqtt/stop [post]
func (sc *SystemDebugController) StopMqtt(c *gin.Context) {
service := mqtt.GetDebugService()
if service == nil {
writeError(c, http.StatusServiceUnavailable, "mqtt debug service unavailable")
return
}
service.Stop()
writeSuccess(c, http.StatusOK, "stop success", service.Status())
}
// @Summary 获取MQTT V3调试状态
// @Description 获取MQTT V3调试服务的当前运行状态
// @Tags 系统调试
// @Produce json
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Router /admin/system-debug/mqtt-v3/status [get]
func (sc *SystemDebugController) MqttV3Status(c *gin.Context) {
service := mqtt.GetDebugV3Service()
if service == nil {
writeError(c, http.StatusServiceUnavailable, "mqtt v3 debug service unavailable")
return
}
writeSuccess(c, http.StatusOK, "query success", service.Status())
}
// @Summary 启动MQTT V3调试
// @Description 启动MQTT V3调试服务
// @Tags 系统调试
// @Accept json
// @Produce json
// @Param persist body mqttDebugStartRequest false "是否持久化到数据库"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "启动成功"
// @Router /admin/system-debug/mqtt-v3/start [post]
func (sc *SystemDebugController) StartMqttV3(c *gin.Context) {
service := mqtt.GetDebugV3Service()
if service == nil {
writeError(c, http.StatusServiceUnavailable, "mqtt v3 debug service unavailable")
return
}
var payload mqttDebugStartRequest
if err := c.ShouldBindJSON(&payload); err != nil && !errors.Is(err, http.ErrBodyNotAllowed) {
writeError(c, http.StatusBadRequest, err.Error())
return
}
if err := service.Start(payload.PersistToDatabase); err != nil {
writeError(c, http.StatusInternalServerError, err.Error())
return
}
writeSuccess(c, http.StatusOK, "start success", service.Status())
}
// @Summary 停止MQTT V3调试
// @Description 停止MQTT V3调试服务
// @Tags 系统调试
// @Produce json
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "停止成功"
// @Router /admin/system-debug/mqtt-v3/stop [post]
func (sc *SystemDebugController) StopMqttV3(c *gin.Context) {
service := mqtt.GetDebugV3Service()
if service == nil {
writeError(c, http.StatusServiceUnavailable, "mqtt v3 debug service unavailable")
return
}
service.Stop()
writeSuccess(c, http.StatusOK, "stop success", service.Status())
}
// @Summary 获取MQTT重放状态
// @Description 获取心率历史数据 MQTT 重放状态
// @Tags 系统调试
// @Produce json
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Router /admin/system-debug/mqtt/replay/status [get]
func (sc *SystemDebugController) MqttReplayStatus(c *gin.Context) {
service := mqtt.GetReplayService()
if service == nil {
writeError(c, http.StatusServiceUnavailable, "mqtt replay service unavailable")
return
}
writeSuccess(c, http.StatusOK, "query success", service.Status())
}
// @Summary 启动MQTT历史数据重放
// @Description 按指定时间范围重放历史心率数据到 MQTT
// @Tags 系统调试
// @Accept json
// @Produce json
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "启动成功"
// @Router /admin/system-debug/mqtt/replay/start [post]
func (sc *SystemDebugController) StartMqttReplay(c *gin.Context) {
service := mqtt.GetReplayService()
if service == nil {
writeError(c, http.StatusServiceUnavailable, "mqtt replay service unavailable")
return
}
var payload mqttReplayStartRequest
if err := c.ShouldBindJSON(&payload); err != nil {
writeError(c, http.StatusBadRequest, err.Error())
return
}
status, err := service.Start(mqtt.ReplayStartRequest{
Addr: payload.Addr,
EndTime: payload.EndTime,
RegionID: payload.RegionID,
StartTime: payload.StartTime,
})
if err != nil {
writeError(c, http.StatusBadRequest, err.Error())
return
}
writeSuccess(c, http.StatusOK, "start success", status)
}
// @Summary 停止MQTT历史数据重放
// @Description 停止当前正在执行的心率历史数据 MQTT 重放
// @Tags 系统调试
// @Produce json
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "停止成功"
// @Router /admin/system-debug/mqtt/replay/stop [post]
func (sc *SystemDebugController) StopMqttReplay(c *gin.Context) {
service := mqtt.GetReplayService()
if service == nil {
writeError(c, http.StatusServiceUnavailable, "mqtt replay service unavailable")
return
}
writeSuccess(c, http.StatusOK, "stop success", service.Stop())
}
// @Summary MQTT WebSocket连接
// @Description 通过WebSocket实时监听MQTT消息(需要SuperAdmin权限)
// @Tags 系统调试
// @Param token query string true "JWT Token"
// @Success 101 "切换为WebSocket协议"
// @Router /admin/system-debug/mqtt/ws [get]
func (sc *SystemDebugController) MqttWebSocket(c *gin.Context) {
service := mqtt.GetDebugService()
if service == nil {
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "mqtt debug service unavailable"})
return
}
token := strings.TrimSpace(c.Query("token"))
if token == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "missing token"})
return
}
claims, err := util.ParseToken(token)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid token"})
return
}
var user models.User
if err := config.DB.First(&user, claims.UserID).Error; err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "user not found"})
return
}
if !user.IsActive {
c.JSON(http.StatusForbidden, gin.H{"error": "user is disabled"})
return
}
if util.IsTokenRevoked(&user, claims) {
c.JSON(http.StatusUnauthorized, gin.H{"error": "token has been revoked"})
return
}
if user.Role != models.UserRoleSuperAdmin {
c.JSON(http.StatusForbidden, gin.H{"error": "super admin required"})
return
}
conn, err := debugUpgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
return
}
service.AddSubscriber(conn)
defer service.RemoveSubscriber(conn)
for {
if _, _, err := conn.ReadMessage(); err != nil {
break
}
}
}
// @Summary MQTT V3 WebSocket连接
// @Description 通过WebSocket实时监听MQTT V3消息(需要SuperAdmin权限)
// @Tags 系统调试
// @Param token query string true "JWT Token"
// @Success 101 "切换为WebSocket协议"
// @Router /admin/system-debug/mqtt-v3/ws [get]
func (sc *SystemDebugController) MqttV3WebSocket(c *gin.Context) {
service := mqtt.GetDebugV3Service()
if service == nil {
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "mqtt v3 debug service unavailable"})
return
}
token := strings.TrimSpace(c.Query("token"))
if token == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "missing token"})
return
}
claims, err := util.ParseToken(token)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid token"})
return
}
var user models.User
if err := config.DB.First(&user, claims.UserID).Error; err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "user not found"})
return
}
if !user.IsActive {
c.JSON(http.StatusForbidden, gin.H{"error": "user is disabled"})
return
}
if util.IsTokenRevoked(&user, claims) {
c.JSON(http.StatusUnauthorized, gin.H{"error": "token has been revoked"})
return
}
if user.Role != models.UserRoleSuperAdmin {
c.JSON(http.StatusForbidden, gin.H{"error": "super admin required"})
return
}
conn, err := debugUpgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
return
}
service.AddSubscriber(conn)
defer service.RemoveSubscriber(conn)
for {
if _, _, err := conn.ReadMessage(); err != nil {
break
}
}
}