You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
343 lines
8.5 KiB
Go
343 lines
8.5 KiB
Go
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),
|
|
}
|
|
}
|