refactor(router): 改为结构化 web 项目
This commit is contained in:
parent
7047d896f8
commit
9ba49e0742
95
main.go
95
main.go
@ -2,34 +2,15 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/IOTechSystems/onvif/event"
|
||||
"github.com/IOTechSystems/onvif/gosoap"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"onvif-agent/router"
|
||||
)
|
||||
|
||||
var connections = make(map[string]*Connection)
|
||||
|
||||
func main() {
|
||||
|
||||
r := gin.Default()
|
||||
|
||||
r.GET("/ping", func(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "pong",
|
||||
})
|
||||
})
|
||||
|
||||
r.POST("/onvif", createConnection)
|
||||
r.GET("/onvif", getConnections)
|
||||
r.GET("/onvif/:xaddr", getConnectionByXaddr)
|
||||
r.DELETE("/onvif/:xaddr", deleteConnection)
|
||||
|
||||
r.POST("/events/subscribe/:xaddr", eventsSubscribe)
|
||||
r.POST("/events/callback", eventsCallback)
|
||||
router.SetupRoutes(r)
|
||||
|
||||
go func() {
|
||||
if err := r.Run(":8080"); err != nil {
|
||||
@ -44,75 +25,3 @@ func main() {
|
||||
// block main()
|
||||
select {}
|
||||
}
|
||||
|
||||
func createConnection(c *gin.Context) {
|
||||
conn, err := NewConnection("172.16.19.239", "admin", "admin123")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusServiceUnavailable, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
connections[conn.Device.GetDeviceParams().Xaddr] = conn
|
||||
|
||||
info, err := conn.GetDeviceInformation()
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"connectionParams": conn.Params,
|
||||
"deviceInfo": info,
|
||||
})
|
||||
}
|
||||
|
||||
func getConnections(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, connections)
|
||||
}
|
||||
|
||||
func getConnectionByXaddr(c *gin.Context) {
|
||||
xaddr := c.Param("xaddr")
|
||||
c.JSON(http.StatusOK, connections[xaddr])
|
||||
}
|
||||
|
||||
func deleteConnection(c *gin.Context) {
|
||||
xaddr := c.Param("xaddr")
|
||||
delete(connections, xaddr)
|
||||
}
|
||||
|
||||
func eventsSubscribe(c *gin.Context) {
|
||||
xaddr := c.Param("xaddr")
|
||||
result, err := connections[xaddr].SubscribeEvents("http://172.16.19.230:8080/events/callback", "PT60S")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusServiceUnavailable, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
func eventsCallback(c *gin.Context) {
|
||||
var notify event.Notify
|
||||
envelope := gosoap.NewSOAPEnvelope(¬ify)
|
||||
if err := c.ShouldBindXML(&envelope); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
for _, msg := range envelope.Body.Content.(*event.Notify).NotificationMessage {
|
||||
log.Println(msg.Topic.TopicKinds, msg.Message.Message)
|
||||
}
|
||||
|
||||
c.String(http.StatusOK, "OK")
|
||||
}
|
||||
|
||||
func printTime() {
|
||||
ticker := time.NewTicker(1 * time.Second) // 每秒触发一次
|
||||
defer ticker.Stop() // 确保在函数结束时停止 ticker
|
||||
|
||||
for {
|
||||
select {
|
||||
case t := <-ticker.C:
|
||||
fmt.Println("当前时间:", t.Format("2006-01-02 15:04:05"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
113
onvif.go
113
onvif.go
@ -1,113 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
goonvif "github.com/IOTechSystems/onvif"
|
||||
"github.com/IOTechSystems/onvif/device"
|
||||
"github.com/IOTechSystems/onvif/event"
|
||||
"github.com/IOTechSystems/onvif/gosoap"
|
||||
"github.com/IOTechSystems/onvif/xsd"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type Connection struct {
|
||||
Params DeviceParams `json:"params"`
|
||||
Device *goonvif.Device `json:"device"`
|
||||
}
|
||||
|
||||
type DeviceParams struct {
|
||||
Xaddr string `json:"xaddr"`
|
||||
EndpointRefAddress string `json:"endpointRefAddress"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
AuthMode string `json:"authMode"`
|
||||
}
|
||||
|
||||
func readResponse(resp *http.Response) (string, error) {
|
||||
b, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
func unmarshalResponse(resp *http.Response, target any) error {
|
||||
b, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = xml.Unmarshal(b, gosoap.NewSOAPEnvelope(target)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewConnection(addr string, username string, password string) (*Connection, error) {
|
||||
dev, err := goonvif.NewDevice(goonvif.DeviceParams{
|
||||
Xaddr: addr,
|
||||
Username: username,
|
||||
Password: password,
|
||||
//AuthMode: goonvif.UsernameTokenAuth,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Connection{
|
||||
Params: DeviceParams{
|
||||
Xaddr: dev.GetDeviceParams().Xaddr,
|
||||
EndpointRefAddress: dev.GetDeviceParams().EndpointRefAddress,
|
||||
Username: dev.GetDeviceParams().Username,
|
||||
Password: dev.GetDeviceParams().Password,
|
||||
AuthMode: dev.GetDeviceParams().AuthMode,
|
||||
},
|
||||
Device: dev,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Connection) GetDeviceInformation() (*device.GetDeviceInformationResponse, error) {
|
||||
resp, err := c.Device.CallMethod(device.GetDeviceInformation{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := &device.GetDeviceInformationResponse{}
|
||||
err = unmarshalResponse(resp, result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *Connection) SubscribeEvents(
|
||||
consumerAddress event.AttributedURIType,
|
||||
terminationTime xsd.String, // PT60S
|
||||
) (*event.SubscribeResponse, error) {
|
||||
resp, err := c.Device.CallMethod(event.Subscribe{
|
||||
ConsumerReference: &event.EndpointReferenceType{
|
||||
Address: consumerAddress,
|
||||
},
|
||||
Filter: &event.FilterType{
|
||||
TopicExpression: &event.TopicExpressionType{
|
||||
TopicKinds: "tns1:VideoSource//.",
|
||||
},
|
||||
},
|
||||
TerminationTime: &terminationTime,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := &event.SubscribeResponse{}
|
||||
err = unmarshalResponse(resp, result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
41
router/handler/onvif/connection.go
Normal file
41
router/handler/onvif/connection.go
Normal file
@ -0,0 +1,41 @@
|
||||
package onvif
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"onvif-agent/service/onvif"
|
||||
)
|
||||
|
||||
var conns = make(map[string]*onvif.Connection)
|
||||
|
||||
func CreateConnection(c *gin.Context) {
|
||||
conn, err := onvif.NewConnection("172.16.19.239", "admin", "admin123")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusServiceUnavailable, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
conns[conn.Device.GetDeviceParams().Xaddr] = conn
|
||||
|
||||
info, err := conn.GetDeviceInformation()
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"connectionParams": conn.Params,
|
||||
"deviceInfo": info,
|
||||
})
|
||||
}
|
||||
|
||||
func GetConnections(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, conns)
|
||||
}
|
||||
|
||||
func GetConnectionByXaddr(c *gin.Context) {
|
||||
xaddr := c.Param("xaddr")
|
||||
c.JSON(http.StatusOK, conns[xaddr])
|
||||
}
|
||||
|
||||
func DeleteConnection(c *gin.Context) {
|
||||
xaddr := c.Param("xaddr")
|
||||
delete(conns, xaddr)
|
||||
}
|
38
router/handler/onvif/subscription.go
Normal file
38
router/handler/onvif/subscription.go
Normal file
@ -0,0 +1,38 @@
|
||||
package onvif
|
||||
|
||||
import (
|
||||
"github.com/IOTechSystems/onvif/event"
|
||||
"github.com/IOTechSystems/onvif/gosoap"
|
||||
"github.com/gin-gonic/gin"
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func CreateEventSubscription(c *gin.Context) {
|
||||
xaddr := c.Param("xaddr")
|
||||
// FIXME: 把参数变成传入的参数
|
||||
result, err := conns[xaddr].SubscribeEvents("http://172.16.19.230:8080/events/callback", "PT60S")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusServiceUnavailable, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
func EventNotifyCallback(c *gin.Context) {
|
||||
var notify event.Notify
|
||||
envelope := gosoap.NewSOAPEnvelope(¬ify)
|
||||
if err := c.ShouldBindXML(&envelope); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
for _, msg := range envelope.Body.Content.(*event.Notify).NotificationMessage {
|
||||
log.Println(msg.Topic.TopicKinds, msg.Message.Message)
|
||||
}
|
||||
|
||||
c.String(http.StatusOK, "OK")
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func GetConnections(c *gin.Context) {
|
||||
// 这里可以添加获取产品的逻辑
|
||||
c.JSON(http.StatusOK, gin.H{"message": "Get Connections"})
|
||||
}
|
||||
|
||||
func CreateConnection(c *gin.Context) {
|
||||
// 这里可以添加创建产品的逻辑
|
||||
c.JSON(http.StatusCreated, gin.H{"message": "Connection Created"})
|
||||
}
|
@ -2,7 +2,7 @@ package router
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"onvif-agent/router/handler"
|
||||
"onvif-agent/router/handler/onvif"
|
||||
)
|
||||
|
||||
func SetupRoutes(r *gin.Engine) {
|
||||
@ -11,8 +11,16 @@ func SetupRoutes(r *gin.Engine) {
|
||||
{
|
||||
connectionGroup := userGroup.Group("/connections")
|
||||
{
|
||||
connectionGroup.GET("/", handler.GetConnections)
|
||||
connectionGroup.POST("/", handler.CreateConnection)
|
||||
connectionGroup.POST("/", onvif.CreateConnection)
|
||||
connectionGroup.GET("/", onvif.GetConnections)
|
||||
connectionGroup.GET("/:xaddr", onvif.GetConnectionByXaddr)
|
||||
connectionGroup.DELETE("/:xaddr", onvif.DeleteConnection)
|
||||
}
|
||||
|
||||
subscriptionGroup := userGroup.Group("/subscriptions")
|
||||
{
|
||||
subscriptionGroup.POST("/:xaddr", onvif.CreateEventSubscription)
|
||||
subscriptionGroup.POST("/callback", onvif.EventNotifyCallback)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
40
service/onvif/connection.go
Normal file
40
service/onvif/connection.go
Normal file
@ -0,0 +1,40 @@
|
||||
package onvif
|
||||
|
||||
import (
|
||||
"github.com/IOTechSystems/onvif"
|
||||
)
|
||||
|
||||
type Connection struct {
|
||||
Params DeviceParams `json:"params"`
|
||||
Device *onvif.Device `json:"device"`
|
||||
}
|
||||
|
||||
type DeviceParams struct {
|
||||
Xaddr string `json:"xaddr"`
|
||||
EndpointRefAddress string `json:"endpointRefAddress"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
AuthMode string `json:"authMode"`
|
||||
}
|
||||
|
||||
func NewConnection(addr string, username string, password string) (*Connection, error) {
|
||||
dev, err := onvif.NewDevice(onvif.DeviceParams{
|
||||
Xaddr: addr,
|
||||
Username: username,
|
||||
Password: password,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Connection{
|
||||
Params: DeviceParams{
|
||||
Xaddr: dev.GetDeviceParams().Xaddr,
|
||||
EndpointRefAddress: dev.GetDeviceParams().EndpointRefAddress,
|
||||
Username: dev.GetDeviceParams().Username,
|
||||
Password: dev.GetDeviceParams().Password,
|
||||
AuthMode: dev.GetDeviceParams().AuthMode,
|
||||
},
|
||||
Device: dev,
|
||||
}, nil
|
||||
}
|
18
service/onvif/device.go
Normal file
18
service/onvif/device.go
Normal file
@ -0,0 +1,18 @@
|
||||
package onvif
|
||||
|
||||
import "github.com/IOTechSystems/onvif/device"
|
||||
|
||||
func (c *Connection) GetDeviceInformation() (*device.GetDeviceInformationResponse, error) {
|
||||
resp, err := c.Device.CallMethod(device.GetDeviceInformation{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := &device.GetDeviceInformationResponse{}
|
||||
err = unmarshalResponse(resp, result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
34
service/onvif/event.go
Normal file
34
service/onvif/event.go
Normal file
@ -0,0 +1,34 @@
|
||||
package onvif
|
||||
|
||||
import (
|
||||
"github.com/IOTechSystems/onvif/event"
|
||||
"github.com/IOTechSystems/onvif/xsd"
|
||||
)
|
||||
|
||||
func (c *Connection) SubscribeEvents(
|
||||
consumerAddress event.AttributedURIType,
|
||||
terminationTime xsd.String, // PT60S
|
||||
) (*event.SubscribeResponse, error) {
|
||||
resp, err := c.Device.CallMethod(event.Subscribe{
|
||||
ConsumerReference: &event.EndpointReferenceType{
|
||||
Address: consumerAddress,
|
||||
},
|
||||
Filter: &event.FilterType{
|
||||
TopicExpression: &event.TopicExpressionType{
|
||||
TopicKinds: "tns1:VideoSource//.",
|
||||
},
|
||||
},
|
||||
TerminationTime: &terminationTime,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := &event.SubscribeResponse{}
|
||||
err = unmarshalResponse(resp, result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
30
service/onvif/util.go
Normal file
30
service/onvif/util.go
Normal file
@ -0,0 +1,30 @@
|
||||
package onvif
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"github.com/IOTechSystems/onvif/gosoap"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func readResponse(resp *http.Response) (string, error) {
|
||||
b, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
func unmarshalResponse(resp *http.Response, target any) error {
|
||||
b, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = xml.Unmarshal(b, gosoap.NewSOAPEnvelope(target)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user