feat: train record session.
This commit is contained in:
@@ -7,10 +7,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"gorm.io/gorm/clause"
|
"gorm.io/gorm/clause"
|
||||||
|
"gorm.io/gorm/schema"
|
||||||
"hr_receiver/config"
|
"hr_receiver/config"
|
||||||
"hr_receiver/models"
|
"hr_receiver/models"
|
||||||
"math"
|
"math"
|
||||||
@@ -97,6 +102,122 @@ func (tc *TrainingController) CreateTrainingRecord(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type trainingSessionRequest struct {
|
||||||
|
Tid int `json:"tid"`
|
||||||
|
Time int64 `json:"time"`
|
||||||
|
TestTime int64 `json:"testTime"`
|
||||||
|
EndTime int64 `json:"endTime"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
RunType string `json:"runType"`
|
||||||
|
Gender string `json:"gender"`
|
||||||
|
Age int `json:"age"`
|
||||||
|
MaxHeartRate int `json:"maxHeartRate"`
|
||||||
|
Duration int `json:"duration"`
|
||||||
|
PeopleNum int `json:"peopleNum"`
|
||||||
|
Evaluation string `json:"evaluation"`
|
||||||
|
AiResult string `json:"aiResult"`
|
||||||
|
IsStart bool `json:"isStart"`
|
||||||
|
RegionID uint32 `json:"regionId"`
|
||||||
|
AppName string `json:"appName"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tc *TrainingController) UploadTrainingSession(c *gin.Context) {
|
||||||
|
var req trainingSessionRequest
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
writeError(c, http.StatusBadRequest, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
trainID := fmt.Sprintf("%d", req.Time)
|
||||||
|
now := time.Now().UnixMilli()
|
||||||
|
flavorType := "heartrate"
|
||||||
|
|
||||||
|
identifier := schema.NamingStrategy{}.IndexName(
|
||||||
|
"mqtt_training_session",
|
||||||
|
fmt.Sprintf("%s_%d_%s", flavorType, req.RegionID, trainID),
|
||||||
|
)
|
||||||
|
|
||||||
|
rawPayload, _ := json.Marshal(req)
|
||||||
|
|
||||||
|
if req.IsStart {
|
||||||
|
record := &models.MqttTrainingSessionRecord{
|
||||||
|
Identifier: identifier,
|
||||||
|
TestID: trainID,
|
||||||
|
EventType: "start_test",
|
||||||
|
RegionID: req.RegionID,
|
||||||
|
FlavorType: flavorType,
|
||||||
|
RawFlavor: "hr",
|
||||||
|
AppName: req.AppName,
|
||||||
|
TrainId: trainID,
|
||||||
|
PeopleNum: req.PeopleNum,
|
||||||
|
StartedAt: &req.Time,
|
||||||
|
PublishedAt: now,
|
||||||
|
ReceivedAt: now,
|
||||||
|
RawPayload: string(rawPayload),
|
||||||
|
}
|
||||||
|
err := tc.DB.Clauses(clause.OnConflict{
|
||||||
|
Columns: []clause.Column{{Name: "identifier"}},
|
||||||
|
DoUpdates: clause.Assignments(map[string]interface{}{"started_at": *record.StartedAt, "train_id": record.TrainId, "updated_at": time.Now()}),
|
||||||
|
}).Create(record).Error
|
||||||
|
if err != nil {
|
||||||
|
writeError(c, http.StatusInternalServerError, "failed to save session")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
writeSuccess(c, http.StatusOK, "session start registered", nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var existing models.MqttTrainingSessionRecord
|
||||||
|
err := tc.DB.Where("train_id = ?", trainID).First(&existing).Error
|
||||||
|
if err != nil {
|
||||||
|
record := &models.MqttTrainingSessionRecord{
|
||||||
|
Identifier: identifier,
|
||||||
|
TestID: trainID,
|
||||||
|
EventType: "stop_test",
|
||||||
|
RegionID: req.RegionID,
|
||||||
|
FlavorType: flavorType,
|
||||||
|
RawFlavor: "hr",
|
||||||
|
AppName: req.AppName,
|
||||||
|
TrainId: trainID,
|
||||||
|
PeopleNum: req.PeopleNum,
|
||||||
|
StartedAt: &req.Time,
|
||||||
|
EndedAt: &req.EndTime,
|
||||||
|
PublishedAt: now,
|
||||||
|
ReceivedAt: now,
|
||||||
|
RawPayload: string(rawPayload),
|
||||||
|
}
|
||||||
|
err = tc.DB.Clauses(clause.OnConflict{
|
||||||
|
Columns: []clause.Column{{Name: "identifier"}},
|
||||||
|
DoUpdates: clause.Assignments(map[string]interface{}{
|
||||||
|
"ended_at": *record.EndedAt,
|
||||||
|
"people_num": record.PeopleNum,
|
||||||
|
"event_type": record.EventType,
|
||||||
|
"updated_at": time.Now(),
|
||||||
|
}),
|
||||||
|
}).Create(record).Error
|
||||||
|
if err != nil {
|
||||||
|
writeError(c, http.StatusInternalServerError, "failed to create session")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
writeSuccess(c, http.StatusOK, "session created", nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
updates := map[string]interface{}{
|
||||||
|
"event_type": "stop_test",
|
||||||
|
"ended_at": req.EndTime,
|
||||||
|
"people_num": req.PeopleNum,
|
||||||
|
"received_at": now,
|
||||||
|
"raw_payload": string(rawPayload),
|
||||||
|
"updated_at": time.Now(),
|
||||||
|
}
|
||||||
|
if err := tc.DB.Model(&existing).Updates(updates).Error; err != nil {
|
||||||
|
writeError(c, http.StatusInternalServerError, "failed to update session")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
writeSuccess(c, http.StatusOK, "session updated", nil)
|
||||||
|
}
|
||||||
|
|
||||||
// analysis_response.go
|
// analysis_response.go
|
||||||
type AnalysisResponse struct {
|
type AnalysisResponse struct {
|
||||||
Status string `json:"status"` // 状态码
|
Status string `json:"status"` // 状态码
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ type MqttTrainingSessionRecord struct {
|
|||||||
FlavorType string `gorm:"size:64;index" json:"flavorType"`
|
FlavorType string `gorm:"size:64;index" json:"flavorType"`
|
||||||
RawFlavor string `gorm:"size:64" json:"rawFlavor"`
|
RawFlavor string `gorm:"size:64" json:"rawFlavor"`
|
||||||
AppName string `gorm:"size:255" json:"appName"`
|
AppName string `gorm:"size:255" json:"appName"`
|
||||||
|
TrainId string `gorm:"size:255;index" json:"trainId"`
|
||||||
|
PeopleNum int `gorm:"type:int" json:"peopleNum"`
|
||||||
StartedAt *int64 `gorm:"type:bigint;index" json:"startedAt"`
|
StartedAt *int64 `gorm:"type:bigint;index" json:"startedAt"`
|
||||||
EndedAt *int64 `gorm:"type:bigint;index" json:"endedAt"`
|
EndedAt *int64 `gorm:"type:bigint;index" json:"endedAt"`
|
||||||
PublishedAt int64 `gorm:"type:bigint;index" json:"publishedAt"`
|
PublishedAt int64 `gorm:"type:bigint;index" json:"publishedAt"`
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ type trainingSessionPayload struct {
|
|||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
EventType string `json:"eventType"`
|
EventType string `json:"eventType"`
|
||||||
TestID string `json:"testId"`
|
TestID string `json:"testId"`
|
||||||
|
TrainId string `json:"trainId"`
|
||||||
RegionID string `json:"regionId"`
|
RegionID string `json:"regionId"`
|
||||||
Flavor string `json:"flavor"`
|
Flavor string `json:"flavor"`
|
||||||
AppName string `json:"appName"`
|
AppName string `json:"appName"`
|
||||||
@@ -400,6 +401,7 @@ func buildTrainingSessionRecord(topic string, payload []byte, now int64) (*model
|
|||||||
FlavorType: flavorType,
|
FlavorType: flavorType,
|
||||||
RawFlavor: event.Flavor,
|
RawFlavor: event.Flavor,
|
||||||
AppName: event.AppName,
|
AppName: event.AppName,
|
||||||
|
TrainId: event.TrainId,
|
||||||
PublishedAt: publishedAt,
|
PublishedAt: publishedAt,
|
||||||
ReceivedAt: now,
|
ReceivedAt: now,
|
||||||
RawPayload: string(payload),
|
RawPayload: string(payload),
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ func SetupRouter() *gin.Engine {
|
|||||||
records := v1.Group("/train-records") //.Use(middleware.AuthMiddleware())
|
records := v1.Group("/train-records") //.Use(middleware.AuthMiddleware())
|
||||||
{
|
{
|
||||||
records.POST("", trainingController.CreateTrainingRecord)
|
records.POST("", trainingController.CreateTrainingRecord)
|
||||||
|
records.POST("/session", trainingController.UploadTrainingSession)
|
||||||
records.GET("/analysis", trainingController.HandleCurveAnalysis)
|
records.GET("/analysis", trainingController.HandleCurveAnalysis)
|
||||||
records.POST("/analysis-by-ai", trainingController.AnalyzeByAI)
|
records.POST("/analysis-by-ai", trainingController.AnalyzeByAI)
|
||||||
// 可扩展其他路由:GET, PUT, DELETE等
|
// 可扩展其他路由:GET, PUT, DELETE等
|
||||||
|
|||||||
Reference in New Issue
Block a user