2025-01-11 22:34:36 +08:00
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2025-01-14 15:00:40 +08:00
|
|
|
|
"VideoStream/dao"
|
2025-01-11 22:34:36 +08:00
|
|
|
|
"VideoStream/handler"
|
|
|
|
|
|
"VideoStream/proto"
|
2025-01-12 15:18:58 +08:00
|
|
|
|
"VideoStream/service"
|
2025-01-11 22:34:36 +08:00
|
|
|
|
"VideoStream/worker"
|
2025-01-16 23:40:08 +08:00
|
|
|
|
"fmt"
|
2025-01-11 22:34:36 +08:00
|
|
|
|
"github.com/gin-gonic/gin"
|
2025-01-14 15:00:40 +08:00
|
|
|
|
"github.com/golang-jwt/jwt"
|
2025-01-11 22:34:36 +08:00
|
|
|
|
"github.com/robfig/cron/v3"
|
|
|
|
|
|
"gocv.io/x/gocv"
|
|
|
|
|
|
"log"
|
2025-01-16 23:40:08 +08:00
|
|
|
|
"runtime"
|
2025-01-14 15:00:40 +08:00
|
|
|
|
"strconv"
|
|
|
|
|
|
"strings"
|
2025-01-11 22:34:36 +08:00
|
|
|
|
"sync"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-01-16 23:40:08 +08:00
|
|
|
|
var configPath string
|
|
|
|
|
|
|
2025-01-11 22:34:36 +08:00
|
|
|
|
func main() {
|
2025-01-16 23:40:08 +08:00
|
|
|
|
fmt.Println("start server")
|
2025-01-14 23:08:59 +08:00
|
|
|
|
gin.SetMode(gin.DebugMode) //设置为debug模式
|
2025-01-11 22:34:36 +08:00
|
|
|
|
r := gin.Default()
|
2025-01-14 15:49:10 +08:00
|
|
|
|
//数据库初始
|
|
|
|
|
|
err0 := dao.Init()
|
|
|
|
|
|
defer dao.Close()
|
|
|
|
|
|
if err0 != nil {
|
|
|
|
|
|
panic("failed to connect database:" + err0.Error())
|
|
|
|
|
|
}
|
|
|
|
|
|
err0 = worker.InitRedis()
|
|
|
|
|
|
defer worker.CloseRedis()
|
|
|
|
|
|
if err0 != nil {
|
|
|
|
|
|
panic("failed to connect redis:" + err0.Error())
|
|
|
|
|
|
}
|
2025-01-14 15:00:40 +08:00
|
|
|
|
r.Use(handler.CrosHandler())
|
|
|
|
|
|
r.Use(JWTAuthMiddleware()) // 使用 JWT 认证中间件
|
|
|
|
|
|
handler.SetUpToolGroup(r) // Tool
|
2025-01-11 22:34:36 +08:00
|
|
|
|
err := worker.InitRedis()
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
panic("failed to connect redis:" + err.Error())
|
|
|
|
|
|
}
|
|
|
|
|
|
//定时任务
|
|
|
|
|
|
c := cron.New(cron.WithSeconds())
|
|
|
|
|
|
// 添加每 10 秒执行一次的任务
|
|
|
|
|
|
_, err2 := c.AddFunc("@every 10s", myTask)
|
|
|
|
|
|
if err2 != nil {
|
|
|
|
|
|
log.Fatal("添加定时任务失败: ", err2)
|
|
|
|
|
|
}
|
|
|
|
|
|
c.Start()
|
2025-01-16 23:40:08 +08:00
|
|
|
|
fmt.Println("定时任务已启动")
|
2025-01-11 22:34:36 +08:00
|
|
|
|
err3 := r.Run(":" + proto.Config.SERVER_PORT)
|
|
|
|
|
|
if err3 != nil {
|
|
|
|
|
|
panic("failed to run server:" + err3.Error())
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
|
|
//读取配置文件
|
|
|
|
|
|
//文件地址/home/videoplayer/vp.conf
|
2025-01-16 23:40:08 +08:00
|
|
|
|
os := runtime.GOOS
|
|
|
|
|
|
if os == "windows" {
|
|
|
|
|
|
configPath = "D:/File/vp_stream.conf"
|
|
|
|
|
|
} else {
|
|
|
|
|
|
configPath = "/home/videoplayer/vp_stream.conf"
|
|
|
|
|
|
}
|
2025-01-11 22:34:36 +08:00
|
|
|
|
//读取配置文件
|
|
|
|
|
|
err := proto.ReadConfig(configPath)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
panic("failed to read config file:" + err.Error())
|
|
|
|
|
|
}
|
2025-01-18 19:59:32 +08:00
|
|
|
|
service.DeviceFrameCount = make(map[int]int)
|
2025-01-11 22:34:36 +08:00
|
|
|
|
for _, device := range proto.Config.DeviceInfo {
|
2025-01-15 00:25:10 +08:00
|
|
|
|
//service.DeviceRWMap[device.ID] = sync.RWMutex{}
|
|
|
|
|
|
//service.DeviceCurrentFrameMap[device.ID] = gocv.NewMat()
|
|
|
|
|
|
//service.DeviceIsGettingFrame[device.ID] = false
|
|
|
|
|
|
service.DeviceRWMap.Store(device.ID, &sync.RWMutex{})
|
|
|
|
|
|
service.DeviceCurrentFrameMap.Store(device.ID, gocv.NewMat())
|
2025-01-18 19:59:32 +08:00
|
|
|
|
service.DeviceFrameCount[device.ID] = 0
|
2025-01-15 00:25:10 +08:00
|
|
|
|
service.DeviceIsGettingFrame.Store(device.ID, false)
|
2025-01-11 22:34:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func myTask() {
|
2025-01-12 15:18:58 +08:00
|
|
|
|
ReadConfigAndSetSystem()
|
2025-01-11 22:34:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func ReadConfigAndSetSystem() {
|
2025-01-16 23:40:08 +08:00
|
|
|
|
//configPath := "/home/videoplayer/vp_stream.conf"
|
2025-01-11 22:34:36 +08:00
|
|
|
|
//读取配置文件
|
|
|
|
|
|
err := proto.ReadConfig(configPath)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
panic("failed to read config file:" + err.Error())
|
|
|
|
|
|
}
|
2025-01-12 15:18:58 +08:00
|
|
|
|
//检测是否需要获取设备流,如果需要则开启
|
2025-01-11 22:34:36 +08:00
|
|
|
|
for _, device := range proto.Config.DeviceInfo {
|
2025-01-18 20:21:38 +08:00
|
|
|
|
//isGet, ok := service.DeviceIsGettingFrame.Load(device.ID)
|
|
|
|
|
|
//isGet_ := isGet.(bool)
|
|
|
|
|
|
isGetting := worker.GetRedis(fmt.Sprintf("device_%d_is_getting", device.ID))
|
|
|
|
|
|
if isGetting == "" {
|
2025-01-15 00:25:10 +08:00
|
|
|
|
//说明没有这个设备,需初始化添加
|
|
|
|
|
|
service.DeviceRWMap.Store(device.ID, &sync.RWMutex{})
|
|
|
|
|
|
service.DeviceCurrentFrameMap.Store(device.ID, gocv.NewMat())
|
2025-01-18 19:59:32 +08:00
|
|
|
|
service.DeviceFrameCount[device.ID] = 0
|
2025-01-15 00:25:10 +08:00
|
|
|
|
service.DeviceIsGettingFrame.Store(device.ID, false)
|
2025-01-18 20:21:38 +08:00
|
|
|
|
worker.SetRedis(fmt.Sprintf("device_%d_is_getting", device.ID), "false")
|
2025-01-15 00:25:10 +08:00
|
|
|
|
}
|
2025-01-18 20:21:38 +08:00
|
|
|
|
if isGetting == "false" && device.NextStop == false { //如果设备流已经停止且不暂停,则开启
|
2025-01-18 14:21:04 +08:00
|
|
|
|
switch device.ID {
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
service.Device1CurrentFrame = gocv.NewMat()
|
|
|
|
|
|
case 50:
|
|
|
|
|
|
service.Device50CurrentFrame = gocv.NewMat()
|
2025-01-18 20:04:50 +08:00
|
|
|
|
case 73:
|
|
|
|
|
|
service.Device73CurrentFrame = gocv.NewMat()
|
2025-01-18 14:21:04 +08:00
|
|
|
|
}
|
2025-01-12 15:18:58 +08:00
|
|
|
|
go service.GetVideoStream(device.ID)
|
2025-01-15 23:41:01 +08:00
|
|
|
|
log.Printf("device:%d has started!\n", device.ID)
|
2025-01-12 15:18:58 +08:00
|
|
|
|
}
|
2025-01-11 22:34:36 +08:00
|
|
|
|
}
|
2025-01-16 23:40:08 +08:00
|
|
|
|
log.Println("每10秒执行一次,当前设备:", proto.Config.DeviceInfo)
|
2025-01-11 22:34:36 +08:00
|
|
|
|
}
|
2025-01-14 15:00:40 +08:00
|
|
|
|
|
|
|
|
|
|
func JWTAuthMiddleware() gin.HandlerFunc {
|
|
|
|
|
|
return func(c *gin.Context) {
|
|
|
|
|
|
// 从请求头中获取 JWT 令牌
|
|
|
|
|
|
tokenString := c.Request.Header.Get("token")
|
|
|
|
|
|
|
|
|
|
|
|
//请求方式为get时,从url中获取token
|
|
|
|
|
|
if tokenString == "" {
|
|
|
|
|
|
tokenString = c.Query("token")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//如果请求为login或register,则不需要验证token
|
|
|
|
|
|
for k, _ := range proto.Url_map {
|
|
|
|
|
|
if strings.Contains(c.Request.URL.Path, k) {
|
|
|
|
|
|
c.Next()
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if tokenString == "" {
|
|
|
|
|
|
//c.AbortWithStatus(200)
|
|
|
|
|
|
c.JSON(200, gin.H{
|
|
|
|
|
|
"message": "Unauthorized",
|
|
|
|
|
|
"error": "token is empty",
|
|
|
|
|
|
"code": 3,
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if proto.Config.TOKEN_USE_REDIS {
|
|
|
|
|
|
redisToken := worker.GetRedis(tokenString)
|
|
|
|
|
|
if redisToken == "" {
|
|
|
|
|
|
c.AbortWithStatus(200)
|
|
|
|
|
|
c.JSON(200, gin.H{
|
|
|
|
|
|
"message": "NOT_LOGIN",
|
|
|
|
|
|
"error": "server token is empty",
|
|
|
|
|
|
"code": 3,
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
//查看token是否在超级token中
|
|
|
|
|
|
if worker.IsContainSet("super_permission_tokens", tokenString) {
|
|
|
|
|
|
s_id := c.Request.Header.Get("super_id")
|
|
|
|
|
|
if s_id == "" {
|
|
|
|
|
|
c.AbortWithStatus(200)
|
|
|
|
|
|
c.JSON(200, gin.H{
|
|
|
|
|
|
"message": "NOT_LOGIN",
|
|
|
|
|
|
"error": "super_id is empty",
|
|
|
|
|
|
"code": 3,
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
id, _ := strconv.Atoi(s_id)
|
|
|
|
|
|
//查看s_id类型
|
|
|
|
|
|
c.Set("id", id)
|
|
|
|
|
|
c.Next()
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 使用加密secret 解析 JWT 令牌
|
|
|
|
|
|
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
|
|
|
|
|
return proto.SigningKey, nil
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// 验证令牌
|
|
|
|
|
|
if err != nil || !token.Valid {
|
|
|
|
|
|
c.AbortWithStatus(200)
|
|
|
|
|
|
c.JSON(200, gin.H{
|
|
|
|
|
|
"message": "NOT_LOGIN",
|
|
|
|
|
|
"error": "Invalid token",
|
|
|
|
|
|
"code": 4,
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
userId := int(token.Claims.(jwt.MapClaims)["id"].(float64))
|
|
|
|
|
|
// 将用户信息添加到上下文中
|
|
|
|
|
|
c.Set("id", userId)
|
|
|
|
|
|
// 继续处理请求
|
|
|
|
|
|
c.Next()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|