mirror of
https://github.com/lkmio/gb-cms.git
synced 2025-09-26 19:51:22 +08:00
实现移动位置订阅
This commit is contained in:
48
api.go
48
api.go
@@ -26,26 +26,25 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
type eventInfo struct {
|
||||
Stream string `json:"stream"` //Stream id
|
||||
Protocol string `json:"protocol"` //推拉流协议
|
||||
RemoteAddr string `json:"remote_addr"` //peer地址
|
||||
}
|
||||
|
||||
func withCheckParams(f func(streamId, protocol string, w http.ResponseWriter, req *http.Request)) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, req *http.Request) {
|
||||
if "" != req.URL.RawQuery {
|
||||
logger.Infof("on request %s?%s", req.URL.Path, req.URL.RawQuery)
|
||||
}
|
||||
|
||||
info := eventInfo{}
|
||||
err := HttpDecodeJSONBody(w, req, &info)
|
||||
v := struct {
|
||||
Stream string `json:"stream"` //Stream id
|
||||
Protocol string `json:"protocol"` //推拉流协议
|
||||
RemoteAddr string `json:"remote_addr"` //peer地址
|
||||
}{}
|
||||
|
||||
err := HttpDecodeJSONBody(w, req, &v)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
f(info.Stream, info.Protocol, w, req)
|
||||
f(v.Stream, v.Protocol, w, req)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +101,6 @@ func (api *ApiServer) OnPlay(streamId, protocol string, w http.ResponseWriter, r
|
||||
return
|
||||
}
|
||||
|
||||
//发送invite
|
||||
split := strings.Split(streamId, "/")
|
||||
if len(split) != 2 {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
@@ -376,8 +374,26 @@ func (api *ApiServer) OnRecordList(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (api *ApiServer) OnSubscribePosition(w http.ResponseWriter, r *http.Request) {
|
||||
devices := DeviceManager.AllDevices()
|
||||
httpResponse2(w, devices)
|
||||
v := struct {
|
||||
DeviceID string `json:"device_id"`
|
||||
ChannelID string `json:"channel_id"`
|
||||
}{}
|
||||
|
||||
if err := HttpDecodeJSONBody(w, r, &v); err != nil {
|
||||
httpResponse2(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
device := DeviceManager.Find(v.DeviceID)
|
||||
if device == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := device.DoSubscribePosition(v.ChannelID); err != nil {
|
||||
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func (api *ApiServer) OnSeekPlayback(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -391,8 +407,12 @@ func (api *ApiServer) OnPTZControl(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (api *ApiServer) OnBroadcast(w http.ResponseWriter, r *http.Request) {
|
||||
devices := DeviceManager.AllDevices()
|
||||
httpResponse2(w, devices)
|
||||
//v := struct {
|
||||
// DeviceID string `json:"device_id"`
|
||||
// ChannelID string `json:"channel_id"`
|
||||
// RoomID string `json:"room_id"` //如果要实现群呼功能, 除第一次广播外, 后续请求都携带该参数
|
||||
//}{}
|
||||
|
||||
}
|
||||
|
||||
func (api *ApiServer) OnTalk(w http.ResponseWriter, r *http.Request) {
|
||||
|
@@ -15,6 +15,7 @@ type Config_ struct {
|
||||
Password string `json:"password"`
|
||||
AliveExpires int `json:"alive_expires"`
|
||||
MobilePositionInterval int `json:"mobile_position_interval"`
|
||||
MobilePositionExpires int `json:"mobile_position_expires"`
|
||||
MediaServer string `json:"media_server"`
|
||||
|
||||
SipPort sip.Port
|
||||
|
38
event.go
Normal file
38
event.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/ghettovoice/gosip/sip"
|
||||
)
|
||||
|
||||
type Event string
|
||||
|
||||
func (ev *Event) String() string { return fmt.Sprintf("%s: %s", ev.Name(), ev.Value()) }
|
||||
|
||||
func (ev *Event) Name() string { return "Event" }
|
||||
|
||||
func (ev Event) Value() string { return string(ev) }
|
||||
|
||||
func (ev *Event) Clone() sip.Header { return ev }
|
||||
|
||||
func (ev *Event) Equals(other interface{}) bool {
|
||||
if h, ok := other.(Event); ok {
|
||||
if ev == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return *ev == h
|
||||
}
|
||||
if h, ok := other.(*Event); ok {
|
||||
if ev == h {
|
||||
return true
|
||||
}
|
||||
if ev == nil && h != nil || ev != nil && h == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return *ev == *h
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
64
position.go
Normal file
64
position.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/ghettovoice/gosip/sip"
|
||||
)
|
||||
|
||||
const MobilePositionMessageFormat = "<?xml version=\"1.0\"?>\r\n" +
|
||||
"<Query>\r\n" +
|
||||
"<CmdType>MobilePosition</CmdType>\r\n" +
|
||||
"<SN>%s</SN>\r\n" +
|
||||
"<DeviceID>%s</DeviceID>\r\n" +
|
||||
"<Interval>%d</Interval>\r\n" +
|
||||
"</Query>\r\n"
|
||||
|
||||
type MobilePositionNotify struct {
|
||||
DeviceID string `xml:"DeviceID"`
|
||||
CmdType string `xml:"CmdType"`
|
||||
SN int `xml:"SN"`
|
||||
Time string `xml:"Time"`
|
||||
Longitude string `xml:"Longitude"`
|
||||
Latitude string `xml:"Latitude"`
|
||||
Speed string `xml:"Speed"`
|
||||
Direction string `xml:"Direction"`
|
||||
Altitude string `xml:"Altitude"`
|
||||
}
|
||||
|
||||
func (d *DBDevice) DoSubscribePosition(channelId string) error {
|
||||
if channelId == "" {
|
||||
channelId = d.Id
|
||||
}
|
||||
|
||||
//暂时不考虑级联
|
||||
builder := d.NewRequestBuilder(sip.SUBSCRIBE, Config.SipId, Config.SipRealm, channelId)
|
||||
body := fmt.Sprintf(MobilePositionMessageFormat, "1", channelId, Config.MobilePositionInterval)
|
||||
|
||||
expiresHeader := sip.Expires(Config.MobilePositionExpires)
|
||||
builder.SetExpires(&expiresHeader)
|
||||
builder.SetContentType(&XmlMessageType)
|
||||
builder.SetContact(globalContactAddress)
|
||||
builder.SetBody(body)
|
||||
|
||||
request, err := builder.Build()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event := Event("Catalog;id=2")
|
||||
request.AppendHeader(&event)
|
||||
response, err := SipUA.SendRequestWithTimeout(5, request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if response.StatusCode() != 200 {
|
||||
return fmt.Errorf("err code %d", response.StatusCode())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DBDevice) OnMobilePositionNotify(notify *MobilePositionNotify) {
|
||||
Sugar.Infof("收到位置信息 device:%s data:%v", d.Id, notify)
|
||||
}
|
@@ -2,12 +2,14 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/xml"
|
||||
"github.com/ghettovoice/gosip"
|
||||
"github.com/ghettovoice/gosip/log"
|
||||
"github.com/ghettovoice/gosip/sip"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -41,6 +43,8 @@ type SipServer interface {
|
||||
|
||||
SendRequest(request sip.Request)
|
||||
|
||||
SendRequestWithTimeout(seconds int, request sip.Request, options ...gosip.RequestWithContextOption) (sip.Response, error)
|
||||
|
||||
Send(msg sip.Message) error
|
||||
}
|
||||
|
||||
@@ -99,6 +103,19 @@ func (s *sipServer) OnBye(req sip.Request, tx sip.ServerTransaction) {
|
||||
}
|
||||
|
||||
func (s *sipServer) OnNotify(req sip.Request, tx sip.ServerTransaction) {
|
||||
response := sip.NewResponseFromRequest("", req, 200, "OK", "")
|
||||
sendResponse(tx, response)
|
||||
|
||||
body := strings.Replace(req.Body(), "GB2312", "UTF-8", 1)
|
||||
mobilePosition := MobilePositionNotify{}
|
||||
if err := xml.Unmarshal([]byte(body), &mobilePosition); err != nil {
|
||||
Sugar.Errorf("解析位置通知失败 err:%s body:%s", err.Error(), body)
|
||||
return
|
||||
}
|
||||
|
||||
if device := DeviceManager.Find(mobilePosition.DeviceID); device != nil {
|
||||
device.OnMobilePositionNotify(&mobilePosition)
|
||||
}
|
||||
}
|
||||
|
||||
func sendResponse(tx sip.ServerTransaction, response sip.Response) bool {
|
||||
@@ -116,6 +133,12 @@ func (s *sipServer) SendRequestWithContext(ctx context.Context, request sip.Requ
|
||||
s.sip.RequestWithContext(ctx, request, options...)
|
||||
}
|
||||
|
||||
func (s *sipServer) SendRequestWithTimeout(seconds int, request sip.Request, options ...gosip.RequestWithContextOption) (sip.Response, error) {
|
||||
Sugar.Infof("send reqeust:%s", request.String())
|
||||
reqCtx, _ := context.WithTimeout(context.Background(), time.Duration(seconds)*time.Second)
|
||||
return s.sip.RequestWithContext(reqCtx, request, options...)
|
||||
}
|
||||
|
||||
func (s *sipServer) SendRequest(request sip.Request) {
|
||||
Sugar.Infof("send reqeust:%s", request.String())
|
||||
|
||||
|
Reference in New Issue
Block a user