package main import ( "fmt" "net/http" "strconv" "time" "github.com/gin-gonic/gin" ) // JavaAPIResponse 标准化的Java API响应格式 type JavaAPIResponse struct { Code int `json:"code"` Message string `json:"message"` Data interface{} `json:"data"` Success bool `json:"success"` } // CameraListResponse 摄像头列表响应 type CameraListResponse struct { Total int `json:"total"` Cameras []Camera `json:"cameras"` } // StreamListResponse 流列表响应 type StreamListResponse struct { Total int `json:"total"` Streams []Stream `json:"streams"` } // JavaCamera 摄像头信息结构 - 用于Java集成API type JavaCamera struct { ID string `json:"id"` Name string `json:"name"` IP string `json:"ip"` Port int `json:"port"` Username string `json:"username"` Password string `json:"password,omitempty"` // 敏感信息可选返回 RTSPURL string `json:"rtsp_url"` Status string `json:"status"` Enabled bool `json:"enabled"` DeviceType string `json:"device_type"` UnitCode string `json:"unit_code"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` PlayURLs PlayURLs `json:"play_urls"` } // Stream 流信息结构 type Stream struct { ID string `json:"id"` Name string `json:"name"` Channels map[string]string `json:"channels"` PlayURLs PlayURLs `json:"play_urls"` } // PlayURLs 播放地址结构 type PlayURLs struct { HLS string `json:"hls"` WebRTC string `json:"webrtc"` MSE string `json:"mse"` All string `json:"all"` } // HTTPJavaAPICameras Java项目专用的摄像头列表API func HTTPJavaAPICameras(c *gin.Context) { if !Storage.ServerHTTPDemo() { c.JSON(http.StatusForbidden, JavaAPIResponse{ Code: 403, Message: "Demo mode is disabled", Success: false, }) return } // 获取查询参数 unitCode := c.Query("unit_code") status := c.Query("status") page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) size, _ := strconv.Atoi(c.DefaultQuery("size", "20")) var cameras []JavaCamera var total int // 如果数据库启用,从数据库获取 if Storage.Server.DatabaseEnabled { dbCameras, err := Storage.DatabaseGetCameras() if err != nil { c.JSON(http.StatusInternalServerError, JavaAPIResponse{ Code: 500, Message: fmt.Sprintf("Database error: %v", err), Success: false, }) return } // 转换数据库摄像头为API格式 for _, dbCamera := range dbCameras { camera := JavaCamera{ ID: fmt.Sprintf("%d", dbCamera.CameraID), Name: getStringValue(dbCamera.CameraName), IP: dbCamera.IP, Port: dbCamera.Port, Username: getStringValue(dbCamera.Username), RTSPURL: dbCamera.URL, Status: "online", // 默认状态 Enabled: dbCamera.DelFlag == "0", // 删除标志为0表示启用 DeviceType: getStringValue(dbCamera.DeviceType), UnitCode: getStringValue(dbCamera.UnitCode), CreatedAt: getTimeValue(dbCamera.CreateTime), UpdatedAt: getTimeValue(dbCamera.UpdateTime), PlayURLs: generatePlayURLs(fmt.Sprintf("%d", dbCamera.CameraID)), } // 过滤条件 if unitCode != "" && camera.UnitCode != unitCode { continue } if status != "" && camera.Status != status { continue } cameras = append(cameras, camera) } } else { // 从流配置获取 streamsList := Storage.Streams for streamID := range streamsList { camera := JavaCamera{ ID: streamID, Name: fmt.Sprintf("Stream %s", streamID), Status: "online", Enabled: true, PlayURLs: generatePlayURLs(streamID), } cameras = append(cameras, camera) } } total = len(cameras) // 分页处理 start := (page - 1) * size end := start + size if start > total { cameras = []JavaCamera{} } else if end > total { cameras = cameras[start:] } else { cameras = cameras[start:end] } response := JavaAPIResponse{ Code: 200, Message: "Success", Success: true, Data: map[string]interface{}{ "total": total, "cameras": cameras, }, } c.JSON(http.StatusOK, response) } // HTTPJavaAPIStreams Java项目专用的流列表API func HTTPJavaAPIStreams(c *gin.Context) { if !Storage.ServerHTTPDemo() { c.JSON(http.StatusForbidden, JavaAPIResponse{ Code: 403, Message: "Demo mode is disabled", Success: false, }) return } page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) size, _ := strconv.Atoi(c.DefaultQuery("size", "20")) streamsList := Storage.Streams var streams []Stream for streamID, streamData := range streamsList { stream := Stream{ ID: streamID, Name: fmt.Sprintf("Stream %s", streamID), Channels: make(map[string]string), PlayURLs: generatePlayURLs(streamID), } // 获取通道信息 if len(streamData.Channels) > 0 { for channelID := range streamData.Channels { stream.Channels[channelID] = fmt.Sprintf("Channel %s", channelID) } } streams = append(streams, stream) } total := len(streams) // 分页处理 start := (page - 1) * size end := start + size if start > total { streams = []Stream{} } else if end > total { streams = streams[start:] } else { streams = streams[start:end] } response := JavaAPIResponse{ Code: 200, Message: "Success", Success: true, Data: StreamListResponse{ Total: total, Streams: streams, }, } c.JSON(http.StatusOK, response) } // HTTPJavaAPICameraDetail 获取摄像头详情 func HTTPJavaAPICameraDetail(c *gin.Context) { cameraID := c.Param("id") if cameraID == "" { c.JSON(http.StatusBadRequest, JavaAPIResponse{ Code: 400, Message: "Camera ID is required", Success: false, }) return } if Storage.Server.DatabaseEnabled { camera, err := Storage.DatabaseGetCamera(cameraID) if err != nil { c.JSON(http.StatusNotFound, JavaAPIResponse{ Code: 404, Message: "Camera not found", Success: false, }) return } apiCamera := JavaCamera{ ID: fmt.Sprintf("%d", camera.CameraID), Name: getStringValue(camera.CameraName), IP: camera.IP, Port: camera.Port, Username: getStringValue(camera.Username), RTSPURL: camera.URL, Status: "online", Enabled: camera.DelFlag == "0", DeviceType: getStringValue(camera.DeviceType), UnitCode: getStringValue(camera.UnitCode), CreatedAt: getTimeValue(camera.CreateTime), UpdatedAt: getTimeValue(camera.UpdateTime), PlayURLs: generatePlayURLs(fmt.Sprintf("%d", camera.CameraID)), } c.JSON(http.StatusOK, JavaAPIResponse{ Code: 200, Message: "Success", Success: true, Data: apiCamera, }) } else { // 从流配置获取 if !Storage.StreamExist(cameraID) { c.JSON(http.StatusNotFound, JavaAPIResponse{ Code: 404, Message: "Stream not found", Success: false, }) return } camera := JavaCamera{ ID: cameraID, Name: fmt.Sprintf("Stream %s", cameraID), Status: "online", Enabled: true, PlayURLs: generatePlayURLs(cameraID), } c.JSON(http.StatusOK, JavaAPIResponse{ Code: 200, Message: "Success", Success: true, Data: camera, }) } } // HTTPJavaAPISystemInfo 获取系统信息 func HTTPJavaAPISystemInfo(c *gin.Context) { systemInfo := map[string]interface{}{ "version": "1.0.0", "database_enabled": Storage.Server.DatabaseEnabled, "demo_enabled": Storage.ServerHTTPDemo(), "total_streams": len(Storage.Streams), "server_time": time.Now().Format(time.RFC3339), } if Storage.Server.DatabaseEnabled { cameras, err := Storage.DatabaseGetCameras() if err == nil { systemInfo["total_cameras"] = len(cameras) onlineCount := 0 for _, camera := range cameras { if camera.DelFlag == "0" { // 删除标志为0表示在线 onlineCount++ } } systemInfo["online_cameras"] = onlineCount } } c.JSON(http.StatusOK, JavaAPIResponse{ Code: 200, Message: "Success", Success: true, Data: systemInfo, }) } // generatePlayURLs 生成播放地址 func generatePlayURLs(streamID string) PlayURLs { baseURL := "http://localhost:8083" // 可以从配置获取 return PlayURLs{ HLS: fmt.Sprintf("%s/stream/%s/channel/0/hls/live/index.m3u8", baseURL, streamID), WebRTC: fmt.Sprintf("%s/pages/player/webrtc/%s/0", baseURL, streamID), MSE: fmt.Sprintf("%s/pages/player/mse/%s/0", baseURL, streamID), All: fmt.Sprintf("%s/pages/player/all/%s/0", baseURL, streamID), } }