mirror of
https://github.com/Monibuca/plugin-gb28181.git
synced 2025-12-24 13:27:57 +08:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f967679763 | ||
|
|
db8ce0d94f |
32
channel.go
32
channel.go
@@ -10,6 +10,7 @@ import (
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/ghettovoice/gosip/sip"
|
||||
"github.com/goccy/go-json"
|
||||
"go.uber.org/zap"
|
||||
. "m7s.live/engine/v4"
|
||||
"m7s.live/engine/v4/log"
|
||||
@@ -112,13 +113,38 @@ type Channel struct {
|
||||
device *Device // 所属设备
|
||||
status atomic.Int32 // 通道状态,0:空闲,1:正在invite,2:正在播放
|
||||
LiveSubSP string // 实时子码流,通过rtsp
|
||||
GpsTime time.Time //gps时间
|
||||
Longitude string //经度
|
||||
Latitude string //纬度
|
||||
GpsTime time.Time // gps时间
|
||||
Longitude string // 经度
|
||||
Latitude string // 纬度
|
||||
*log.Logger `json:"-" yaml:"-"`
|
||||
ChannelInfo
|
||||
}
|
||||
|
||||
func (c *Channel) MarshalJSON() ([]byte, error) {
|
||||
m := map[string]any{
|
||||
"DeviceID": c.DeviceID,
|
||||
"ParentID": c.ParentID,
|
||||
"Name": c.Name,
|
||||
"Manufacturer": c.Manufacturer,
|
||||
"Model": c.Model,
|
||||
"Owner": c.Owner,
|
||||
"CivilCode": c.CivilCode,
|
||||
"Address": c.Address,
|
||||
"Port": c.Port,
|
||||
"Parental": c.Parental,
|
||||
"SafetyWay": c.SafetyWay,
|
||||
"RegisterWay": c.RegisterWay,
|
||||
"Secrecy": c.Secrecy,
|
||||
"Status": c.Status,
|
||||
"Longitude": c.Longitude,
|
||||
"Latitude": c.Latitude,
|
||||
"GpsTime": c.GpsTime,
|
||||
"LiveSubSP": c.LiveSubSP,
|
||||
"LiveStatus": c.status.Load(),
|
||||
}
|
||||
return json.Marshal(m)
|
||||
}
|
||||
|
||||
// Channel 通道
|
||||
type ChannelInfo struct {
|
||||
DeviceID string // 通道ID
|
||||
|
||||
@@ -85,14 +85,13 @@ type Device struct {
|
||||
func (d *Device) MarshalJSON() ([]byte, error) {
|
||||
type Alias Device
|
||||
data := &struct {
|
||||
Channels []*ChannelInfo
|
||||
Channels []*Channel
|
||||
*Alias
|
||||
}{
|
||||
Alias: (*Alias)(d),
|
||||
}
|
||||
d.channelMap.Range(func(key, value interface{}) bool {
|
||||
c := value.(*Channel)
|
||||
data.Channels = append(data.Channels, &c.ChannelInfo)
|
||||
data.Channels = append(data.Channels, value.(*Channel))
|
||||
return true
|
||||
})
|
||||
return json.Marshal(data)
|
||||
|
||||
8
main.go
8
main.go
@@ -98,13 +98,13 @@ func (c *GB28181Config) OnEvent(event any) {
|
||||
c.ReadDevices()
|
||||
go c.initRoutes()
|
||||
c.startServer()
|
||||
case *Stream:
|
||||
case InvitePublish:
|
||||
if c.InviteMode == INVIDE_MODE_ONSUBSCRIBE {
|
||||
//流可能是回放流,stream path是device/channel/start-end形式
|
||||
streamNames := strings.Split(e.StreamName, "/")
|
||||
if channel := FindChannel(e.AppName, streamNames[0]); channel != nil {
|
||||
streamNames := strings.Split(e.Target, "/")
|
||||
if channel := FindChannel(streamNames[0], streamNames[1]); channel != nil {
|
||||
opt := InviteOptions{}
|
||||
if len(streamNames) > 1 {
|
||||
if len(streamNames) > 2 {
|
||||
last := len(streamNames) - 1
|
||||
timestr := streamNames[last]
|
||||
trange := strings.Split(timestr, "-")
|
||||
|
||||
89
restful.go
89
restful.go
@@ -1,7 +1,6 @@
|
||||
package gb28181
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
@@ -16,14 +15,18 @@ var (
|
||||
)
|
||||
|
||||
func (c *GB28181Config) API_list(w http.ResponseWriter, r *http.Request) {
|
||||
util.ReturnJson(func() (list []*Device) {
|
||||
query := r.URL.Query()
|
||||
if query.Get("interval") == "" {
|
||||
query.Set("interval", "5s")
|
||||
}
|
||||
util.ReturnFetchValue(func() (list []*Device) {
|
||||
list = make([]*Device, 0)
|
||||
Devices.Range(func(key, value interface{}) bool {
|
||||
list = append(list, value.(*Device))
|
||||
return true
|
||||
})
|
||||
return
|
||||
}, time.Second*5, w, r)
|
||||
}, w, r)
|
||||
}
|
||||
|
||||
func (c *GB28181Config) API_records(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -40,12 +43,12 @@ func (c *GB28181Config) API_records(w http.ResponseWriter, r *http.Request) {
|
||||
if c := FindChannel(id, channel); c != nil {
|
||||
res, err := c.QueryRecord(startTime, endTime)
|
||||
if err == nil {
|
||||
WriteJSONOk(w, res)
|
||||
util.ReturnValue(res, w, r)
|
||||
} else {
|
||||
WriteJSON(w, err.Error(), http.StatusInternalServerError)
|
||||
util.ReturnError(util.APIErrorInternal, err.Error(), w, r)
|
||||
}
|
||||
} else {
|
||||
http.NotFound(w, r)
|
||||
util.ReturnError(util.APIErrorNotFound, fmt.Sprintf("device %q channel %q not found", id, channel), w, r)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,9 +57,9 @@ func (c *GB28181Config) API_control(w http.ResponseWriter, r *http.Request) {
|
||||
channel := r.URL.Query().Get("channel")
|
||||
ptzcmd := r.URL.Query().Get("ptzcmd")
|
||||
if c := FindChannel(id, channel); c != nil {
|
||||
w.WriteHeader(c.Control(ptzcmd))
|
||||
util.ReturnError(0, fmt.Sprintf("control code:%d", c.Control(ptzcmd)), w, r)
|
||||
} else {
|
||||
http.NotFound(w, r)
|
||||
util.ReturnError(util.APIErrorNotFound, fmt.Sprintf("device %q channel %q not found", id, channel), w, r)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,30 +74,30 @@ func (c *GB28181Config) API_ptz(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
hsN, err := strconv.ParseUint(hs, 10, 8)
|
||||
if err != nil {
|
||||
WriteJSON(w, "hSpeed parameter is invalid", 400)
|
||||
util.ReturnError(util.APIErrorQueryParse, "hSpeed parameter is invalid", w, r)
|
||||
return
|
||||
}
|
||||
vsN, err := strconv.ParseUint(vs, 10, 8)
|
||||
if err != nil {
|
||||
WriteJSON(w, "vSpeed parameter is invalid", 400)
|
||||
util.ReturnError(util.APIErrorQueryParse, "vSpeed parameter is invalid", w, r)
|
||||
return
|
||||
}
|
||||
zsN, err := strconv.ParseUint(zs, 10, 8)
|
||||
if err != nil {
|
||||
WriteJSON(w, "zSpeed parameter is invalid", 400)
|
||||
util.ReturnError(util.APIErrorQueryParse, "zSpeed parameter is invalid", w, r)
|
||||
return
|
||||
}
|
||||
|
||||
ptzcmd, err := toPtzStrByCmdName(cmd, uint8(hsN), uint8(vsN), uint8(zsN))
|
||||
if err != nil {
|
||||
WriteJSON(w, err.Error(), 400)
|
||||
util.ReturnError(util.APIErrorQueryParse, err.Error(), w, r)
|
||||
return
|
||||
}
|
||||
if c := FindChannel(id, channel); c != nil {
|
||||
code := c.Control(ptzcmd)
|
||||
WriteJSON(w, "device received", code)
|
||||
util.ReturnError(code, "device received", w, r)
|
||||
} else {
|
||||
WriteJSON(w, fmt.Sprintf("device %q channel %q not found", id, channel), 404)
|
||||
util.ReturnError(util.APIErrorNotFound, fmt.Sprintf("device %q channel %q not found", id, channel), w, r)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,13 +121,17 @@ func (c *GB28181Config) API_invite(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
opt.Validate(startTime, endTime)
|
||||
if c := FindChannel(id, channel); c == nil {
|
||||
http.NotFound(w, r)
|
||||
util.ReturnError(util.APIErrorNotFound, fmt.Sprintf("device %q channel %q not found", id, channel), w, r)
|
||||
} else if opt.IsLive() && c.status.Load() > 0 {
|
||||
http.Error(w, "live stream already exists", http.StatusNotModified)
|
||||
util.ReturnError(util.APIErrorQueryParse, "live stream already exists", w, r)
|
||||
} else if code, err := c.Invite(&opt); err == nil {
|
||||
w.WriteHeader(code)
|
||||
if code == 200 {
|
||||
util.ReturnOK(w, r)
|
||||
} else {
|
||||
util.ReturnError(util.APIErrorInternal, fmt.Sprintf("invite return code %d", code), w, r)
|
||||
}
|
||||
} else {
|
||||
http.Error(w, err.Error(), code)
|
||||
util.ReturnError(util.APIErrorInternal, err.Error(), w, r)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,9 +140,9 @@ func (c *GB28181Config) API_bye(w http.ResponseWriter, r *http.Request) {
|
||||
channel := r.URL.Query().Get("channel")
|
||||
streamPath := r.URL.Query().Get("streamPath")
|
||||
if c := FindChannel(id, channel); c != nil {
|
||||
w.WriteHeader(c.Bye(streamPath))
|
||||
util.ReturnError(0, fmt.Sprintf("bye code:%d", c.Bye(streamPath)), w, r)
|
||||
} else {
|
||||
http.NotFound(w, r)
|
||||
util.ReturnError(util.APIErrorNotFound, fmt.Sprintf("device %q channel %q not found", id, channel), w, r)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,9 +151,9 @@ func (c *GB28181Config) API_play_pause(w http.ResponseWriter, r *http.Request) {
|
||||
channel := r.URL.Query().Get("channel")
|
||||
streamPath := r.URL.Query().Get("streamPath")
|
||||
if c := FindChannel(id, channel); c != nil {
|
||||
w.WriteHeader(c.Pause(streamPath))
|
||||
util.ReturnError(0, fmt.Sprintf("pause code:%d", c.Pause(streamPath)), w, r)
|
||||
} else {
|
||||
http.NotFound(w, r)
|
||||
util.ReturnError(util.APIErrorNotFound, fmt.Sprintf("device %q channel %q not found", id, channel), w, r)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,9 +162,9 @@ func (c *GB28181Config) API_play_resume(w http.ResponseWriter, r *http.Request)
|
||||
channel := r.URL.Query().Get("channel")
|
||||
streamPath := r.URL.Query().Get("streamPath")
|
||||
if c := FindChannel(id, channel); c != nil {
|
||||
w.WriteHeader(c.Resume(streamPath))
|
||||
util.ReturnError(0, fmt.Sprintf("resume code:%d", c.Resume(streamPath)), w, r)
|
||||
} else {
|
||||
http.NotFound(w, r)
|
||||
util.ReturnError(util.APIErrorNotFound, fmt.Sprintf("device %q channel %q not found", id, channel), w, r)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,13 +175,13 @@ func (c *GB28181Config) API_play_seek(w http.ResponseWriter, r *http.Request) {
|
||||
secStr := r.URL.Query().Get("second")
|
||||
sec, err := strconv.ParseUint(secStr, 10, 32)
|
||||
if err != nil {
|
||||
WriteJSON(w, "second parameter is invalid: "+err.Error(), 400)
|
||||
util.ReturnError(util.APIErrorQueryParse, "second parameter is invalid: "+err.Error(), w, r)
|
||||
return
|
||||
}
|
||||
if c := FindChannel(id, channel); c != nil {
|
||||
w.WriteHeader(c.PlayAt(streamPath, uint(sec)))
|
||||
util.ReturnError(0, fmt.Sprintf("play code:%d", c.PlayAt(streamPath, uint(sec))), w, r)
|
||||
} else {
|
||||
http.NotFound(w, r)
|
||||
util.ReturnError(util.APIErrorNotFound, fmt.Sprintf("device %q channel %q not found", id, channel), w, r)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,13 +193,13 @@ func (c *GB28181Config) API_play_forward(w http.ResponseWriter, r *http.Request)
|
||||
speed, err := strconv.ParseFloat(speedStr, 32)
|
||||
secondErrMsg := "speed parameter is invalid, should be one of 0.25,0.5,1,2,4"
|
||||
if err != nil || !playScaleValues[float32(speed)] {
|
||||
WriteJSON(w, secondErrMsg, 400)
|
||||
util.ReturnError(util.APIErrorQueryParse, secondErrMsg, w, r)
|
||||
return
|
||||
}
|
||||
if c := FindChannel(id, channel); c != nil {
|
||||
w.WriteHeader(c.PlayForward(streamPath, float32(speed)))
|
||||
util.ReturnError(0, fmt.Sprintf("playforward code:%d", c.PlayForward(streamPath, float32(speed))), w, r)
|
||||
} else {
|
||||
http.NotFound(w, r)
|
||||
util.ReturnError(util.APIErrorNotFound, fmt.Sprintf("device %q channel %q not found", id, channel), w, r)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,9 +224,9 @@ func (c *GB28181Config) API_position(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if v, ok := Devices.Load(id); ok {
|
||||
d := v.(*Device)
|
||||
w.WriteHeader(d.MobilePositionSubscribe(id, expiresInt, intervalInt))
|
||||
util.ReturnError(0, fmt.Sprintf("mobileposition code:%d", d.MobilePositionSubscribe(id, expiresInt, intervalInt)), w, r)
|
||||
} else {
|
||||
http.NotFound(w, r)
|
||||
util.ReturnError(util.APIErrorNotFound, fmt.Sprintf("device %q not found", id), w, r)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,8 +241,10 @@ func (c *GB28181Config) API_get_position(w http.ResponseWriter, r *http.Request)
|
||||
query := r.URL.Query()
|
||||
//设备id
|
||||
id := query.Get("id")
|
||||
|
||||
util.ReturnJson(func() (list []*DevicePosition) {
|
||||
if query.Get("interval") == "" {
|
||||
query.Set("interval", fmt.Sprintf("%ds", c.Position.Interval.Seconds()))
|
||||
}
|
||||
util.ReturnFetchValue(func() (list []*DevicePosition) {
|
||||
if id == "" {
|
||||
Devices.Range(func(key, value interface{}) bool {
|
||||
d := value.(*Device)
|
||||
@@ -249,15 +258,5 @@ func (c *GB28181Config) API_get_position(w http.ResponseWriter, r *http.Request)
|
||||
list = append(list, &DevicePosition{ID: d.ID, GpsTime: d.GpsTime, Longitude: d.Longitude, Latitude: d.Latitude})
|
||||
}
|
||||
return
|
||||
}, c.Position.Interval, w, r)
|
||||
}
|
||||
|
||||
func WriteJSONOk(w http.ResponseWriter, data interface{}) {
|
||||
WriteJSON(w, data, 200)
|
||||
}
|
||||
|
||||
func WriteJSON(w http.ResponseWriter, data interface{}, status int) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(status)
|
||||
json.NewEncoder(w).Encode(data)
|
||||
}, w, r)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user