videoplayer/handler/device.go

282 lines
8.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package handler
import (
"context"
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"github.com/gorilla/websocket"
"net/http"
"strconv"
"time"
"videoplayer/proto"
"videoplayer/service"
"videoplayer/worker"
)
type DeviceAddReq struct {
DeviceName string `json:"device_name" form:"device_name"`
DeviceIP string `json:"device_ip" form:"device_ip"`
DeviceStatus string `json:"device_status" form:"device_status"`
AuthID int `json:"auth_id" form:"auth_id"`
DeviceInfo string `json:"device_info" form:"device_info"`
DeviceType string `json:"device_type" form:"device_type"`
DeviceLocation string `json:"device_location" form:"device_location"`
}
type DeviceUpdateReq struct {
ID int `json:"id" form:"id"`
DeviceName string `json:"device_name" form:"device_name" `
DeviceIP string `json:"device_ip" form:"device_ip" `
DeviceStatus string `json:"device_status" form:"device_status" `
AuthID int `json:"auth_id" form:"auth_id" `
DeviceInfo string `json:"device_info" form:"device_info" `
DeviceType string `json:"device_type" form:"device_type" `
DeviceLocation string `json:"device_location" form:"device_location" `
}
type DeviceStatus struct {
IP string `json:"ip" form:"ip" `
Status string `json:"status" form:"status" `
ID int `json:"id" form:"id" `
}
type DeviceDelReq struct {
ID int `json:"id" form:"id" `
}
type DeviceRestartReq struct {
ID int `json:"id" form:"id" `
Option string `json:"option" form:"option" `
}
func SetUpDeviceGroup(router *gin.Engine) {
deviceGroup := router.Group("/device")
deviceGroup.POST("/get_device_list", GetDeviceList)
deviceGroup.POST("/restart", RestartDevice)
deviceGroup.POST("/add_device", AddDevice)
deviceGroup.POST("/set_device_status", SetDeviceStatus)
deviceGroup.POST("/update_device", UpdateDevice)
deviceGroup.POST("/delete_device", DeleteDevice)
deviceGroup.GET("/get_real_time_image", GetRealTimeImage)
}
func DeleteDevice(c *gin.Context) {
id, _ := c.Get("id")
//获取post参数
var req DeviceDelReq
if err := c.ShouldBind(&req); err == nil {
if service.DeleteDevice(req.ID, int(id.(float64))) {
c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success"})
} else {
c.JSON(200, gin.H{"code": proto.OperationFailed, "message": "failed"})
}
} else {
c.JSON(200, gin.H{"code": proto.ParameterError, "message": "failed"})
}
}
func UpdateDevice(c *gin.Context) {
var req DeviceUpdateReq
user_id, _ := c.Get("id")
if err := c.ShouldBind(&req); err == nil {
res := service.UpdateDevice(req.DeviceName, req.DeviceIP, req.DeviceStatus, req.DeviceInfo, req.DeviceType, req.DeviceLocation, req.ID, int(user_id.(float64)))
if res {
c.JSON(200, gin.H{
"code": 0,
"message": "success",
})
} else {
c.JSON(200, gin.H{
"code": proto.DeviceUpdateFailed,
"message": "failed",
})
}
} else {
c.JSON(200, gin.H{
"code": proto.ParameterError,
"message": "failed",
})
}
}
func SetDeviceStatus(c *gin.Context) {
var req DeviceStatus
id, _ := c.Get("id")
if err := c.ShouldBind(&req); err == nil {
if req.IP != "" {
if service.SetDeviceStatus(req.Status, req.ID, int(id.(float64))) {
c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success"})
} else {
c.JSON(200, gin.H{"code": 1, "message": "failed"})
}
}
} else {
c.JSON(200, gin.H{"code": proto.ParameterError, "message": "failed", "data": err.Error()})
}
}
func AddDevice(c *gin.Context) {
var req DeviceAddReq
id, _ := c.Get("id")
if err := c.ShouldBind(&req); err == nil {
user_id := int(id.(float64))
fmt.Println(req)
device_id := service.AddDevice(req.DeviceName, req.DeviceIP, req.DeviceStatus, req.DeviceInfo, req.DeviceType, req.DeviceLocation, user_id)
if device_id != 0 {
c.JSON(200, gin.H{
"code": proto.SuccessCode,
"message": "success",
"data": device_id,
})
} else {
c.JSON(200, gin.H{
"code": proto.DeviceAddFailed,
"message": "failed",
"data": "device add failed",
})
}
} else {
c.JSON(200, gin.H{
"code": proto.ParameterError,
"message": "failed",
"data": err.Error(),
})
}
}
func GetDeviceList(c *gin.Context) {
id, _ := c.Get("id")
devices := service.GetDeviceList(int(id.(float64)))
c.JSON(200, gin.H{
"code": proto.SuccessCode,
"message": "success",
"data": devices,
})
}
func RestartDevice(c *gin.Context) {
user_id, _ := c.Get("id")
var req DeviceRestartReq
if err := c.ShouldBind(&req); err != nil {
c.JSON(200, gin.H{"code": proto.ParameterError, "message": "failed", "data": err.Error()})
return
}
device_id := req.ID
if req.Option == "one" {
device := service.GetDevice(device_id, int(user_id.(float64)))
if device.ID != 0 {
if device.DeviceIP != "" {
if Restart(device.DeviceIP) {
c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success"})
} else {
c.JSON(200, gin.H{"code": proto.DeviceRestartFailed, "message": "failed"})
}
}
} else {
c.JSON(200, gin.H{"code": proto.DataNotFound, "message": "failed", "data": string(device_id) + ": device not found"})
}
} else if req.Option == "all" {
devices := service.GetDeviceList(int(user_id.(float64)))
if len(devices) > 0 {
for _, device := range devices {
if device.DeviceIP != "" {
if !Restart(device.DeviceIP) {
c.JSON(200, gin.H{"code": proto.DeviceRestartFailed, "message": "failed"})
return
}
}
}
} else {
c.JSON(200, gin.H{"code": proto.DataNotFound, "message": "failed", "data": "device not found"})
}
c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success"})
}
}
func Restart(ip string) bool {
url := "http://" + ip + "/restart"
resp, err := http.Get(url)
if err != nil {
return false
}
defer resp.Body.Close()
if resp.StatusCode == 200 {
return true
}
return false
}
// 发送实时视频流
func GetRealTimeImage(c *gin.Context) {
id, _ := c.Get("id")
id1 := int(id.(float64))
device_id := c.Query("device_id")
device_id_int, _ := strconv.Atoi(device_id)
device := service.GetDevice(device_id_int, id1)
if device.ID == 0 {
c.JSON(http.StatusOK, gin.H{"code": proto.DataNotFound, "message": "device not found"})
return
}
ws, err := upgrader.Upgrade(c.Writer, c.Request, nil)
clients[ws] = true
if err != nil {
fmt.Println("connect wss err:", err)
return
}
worker.SetRedisWithExpire(strconv.Itoa(int(device.ID))+"_is_play", "1", time.Minute*5)
fmt.Println("device_id:", device_id_int, " has set is_play to 1")
go subscribeAndHandleMessages(ws, device_id_int)
}
func subscribeAndHandleMessages(ws *websocket.Conn, device_id int) {
ctx := context.Background()
pubsub := worker.RedisClient.Subscribe(ctx, strconv.Itoa(device_id)+"_frames_msgs")
//生成唯一连接uuid
con_id := uuid.New().String()
online_conn_key := "device_" + strconv.Itoa(device_id) + "_online_conn_ids"
//加入设备在线连接集合
worker.SetRedisSetAdd(online_conn_key, con_id)
defer pubsub.Close()
defer ws.Close()
ch := pubsub.Channel()
var check_cnt int
for msg := range ch {
var res3 []byte
var msgObj proto.Message
if msg.Payload != "" {
msgObj.Type = "img"
msgObj.Msg = msg.Payload
msgObj.From_user_id = -1
res3, _ = json.Marshal(msgObj)
} else {
if check_cnt < 5 {
check_cnt++
time.Sleep(time.Millisecond * 200)
continue
}
check_cnt = 0
msgObj.Type = "check"
msgObj.Msg = "check"
msgObj.From_user_id = -1
res3, _ = json.Marshal(msgObj)
}
//fmt.Println("send message to client length:", len(res3))
err2 := ws.WriteMessage(websocket.TextMessage, res3)
if err2 != nil {
clientsMux.Lock()
clients[ws] = false
clientsMux.Unlock()
fmt.Println("send message to client err:", err2)
worker.SetRedisSetRemove(online_conn_key, con_id)
break
}
}
//查看是否还有其他连接没有则设置is_play为0
if worker.GetRedisSetMembers(online_conn_key) == nil {
worker.SetRedisWithExpire(strconv.Itoa(device_id)+"_is_play", "0", time.Minute*5)
fmt.Println("device_id:", device_id, " has set is_play to 0")
}
}