Compare commits
54 Commits
28482d201d
...
main
Author | SHA1 | Date | |
---|---|---|---|
f709807ce7 | |||
207001c1f8 | |||
43ffa61470 | |||
0b7b5bc54e | |||
78ae4ca00b | |||
e67a294ff6 | |||
ee5efb0f5a | |||
87da521e2e | |||
d39363c8a1 | |||
b90db27e15 | |||
8b7e7a3f85 | |||
3085195290 | |||
ce77821c2b | |||
6c98a35488 | |||
99c9303517 | |||
4262b1aaea | |||
e28fd1a0b9 | |||
f4c8b5ed21 | |||
f2c5cb5f8d | |||
c2683ab03f | |||
6539495e4d | |||
8871ebeb41 | |||
4fbdbb15cc | |||
b1ad068073 | |||
254b41e160 | |||
c8b33a27f6 | |||
ae9fd0d5b0 | |||
2bd63388cc | |||
a641d6846d | |||
67de79e230 | |||
0ef8af021f | |||
ff5cc66a55 | |||
63fb12901b | |||
219116c961 | |||
de3667f957 | |||
82d3f99404 | |||
a6cc98a32b | |||
2a1852188e | |||
7eee4cfc26 | |||
00d2b30658 | |||
0493c3b1e6 | |||
74c955a3f7 | |||
85c90ec1e1 | |||
efae826049 | |||
b5c1ec3bda | |||
8992b65e76 | |||
228ec26904 | |||
0f4c565250 | |||
d82a83cca1 | |||
09d4d305cd | |||
d4bc25fa59 | |||
fcce8f78b0 | |||
a417edcfed | |||
77d8153b43 |
51
.gitea/workflows/template-cleanup.yaml
Normal file
51
.gitea/workflows/template-cleanup.yaml
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
name: Template Cleanup
|
||||||
|
on:
|
||||||
|
# create:
|
||||||
|
# push:
|
||||||
|
# branches: [ main ]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
# 当前仓库名不为 zabbix-agent2-plugin-template 时触发
|
||||||
|
template-cleanup:
|
||||||
|
name: Template Cleanup
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event.repository.name != 'zabbix-agent2-plugin-template'
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Fetch Sources
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
# 项目清理
|
||||||
|
- name: Cleanup
|
||||||
|
run: |
|
||||||
|
export LC_CTYPE=C
|
||||||
|
export LANG=C
|
||||||
|
|
||||||
|
# 准备变量
|
||||||
|
OWNER=$(echo $GITHUB_REPOSITORY_OWNER | tr '[:upper:]' '[:lower:]')
|
||||||
|
REPO_NAME="${GITHUB_REPOSITORY##*/}"
|
||||||
|
SAFE_OWNER=$(echo $OWNER | sed 's/[^a-zA-Z0-9]//g' | tr '[:upper:]' '[:lower:]')
|
||||||
|
SAFE_REPO_NAME=$(echo $REPO_NAME | sed 's/[^a-zA-Z0-9]//g' | tr '[:upper:]' '[:lower:]')
|
||||||
|
PLUGIN_NAME=$(echo "$SAFE_REPO_NAME" | sed 's/^\(.\)/\U\1/')
|
||||||
|
|
||||||
|
# 替换包名
|
||||||
|
find . -type f -exec sed -i "s/zabbixagent2plugintemplate/$SAFE_REPO_NAME/g" {} +
|
||||||
|
find . -type f -exec sed -i "s/Zabbixagent2plugintemplate/$PLUGIN_NAME/g" {} +
|
||||||
|
find . -type f -exec sed -i "s/Zabbix Agent 2 Plugin Template/$REPO_NAME/g" {} +
|
||||||
|
|
||||||
|
- name: Commit files
|
||||||
|
run: |
|
||||||
|
git config --local user.email "action@github.com"
|
||||||
|
git config --local user.name "GitHub Action"
|
||||||
|
git add .
|
||||||
|
git commit -m "Template cleanup"
|
||||||
|
|
||||||
|
- name: Push changes
|
||||||
|
uses: ad-m/github-push-action@master
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
branch: ${{ github.ref }}
|
138
.gitignore
vendored
138
.gitignore
vendored
@ -13,29 +13,6 @@
|
|||||||
# .nfs files are created when an open file is removed but is still being accessed
|
# .nfs files are created when an open file is removed but is still being accessed
|
||||||
.nfs*
|
.nfs*
|
||||||
|
|
||||||
### Go template
|
|
||||||
# If you prefer the allow list template instead of the deny list, see community template:
|
|
||||||
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
|
||||||
#
|
|
||||||
# Binaries for programs and plugins
|
|
||||||
*.exe
|
|
||||||
*.exe~
|
|
||||||
*.dll
|
|
||||||
*.so
|
|
||||||
*.dylib
|
|
||||||
|
|
||||||
# Test binary, built with `go test -c`
|
|
||||||
*.test
|
|
||||||
|
|
||||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
|
||||||
*.out
|
|
||||||
|
|
||||||
# Dependency directories (remove the comment below to include it)
|
|
||||||
# vendor/
|
|
||||||
|
|
||||||
# Go workspace file
|
|
||||||
go.work
|
|
||||||
|
|
||||||
### Windows template
|
### Windows template
|
||||||
# Windows thumbnail cache files
|
# Windows thumbnail cache files
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
@ -62,85 +39,6 @@ $RECYCLE.BIN/
|
|||||||
# Windows shortcuts
|
# Windows shortcuts
|
||||||
*.lnk
|
*.lnk
|
||||||
|
|
||||||
### GoLand template
|
|
||||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
|
||||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
|
||||||
|
|
||||||
# User-specific stuff
|
|
||||||
.idea/**/workspace.xml
|
|
||||||
.idea/**/tasks.xml
|
|
||||||
.idea/**/usage.statistics.xml
|
|
||||||
.idea/**/dictionaries
|
|
||||||
.idea/**/shelf
|
|
||||||
|
|
||||||
# AWS User-specific
|
|
||||||
.idea/**/aws.xml
|
|
||||||
|
|
||||||
# Generated files
|
|
||||||
.idea/**/contentModel.xml
|
|
||||||
|
|
||||||
# Sensitive or high-churn files
|
|
||||||
.idea/**/dataSources/
|
|
||||||
.idea/**/dataSources.ids
|
|
||||||
.idea/**/dataSources.local.xml
|
|
||||||
.idea/**/sqlDataSources.xml
|
|
||||||
.idea/**/dynamic.xml
|
|
||||||
.idea/**/uiDesigner.xml
|
|
||||||
.idea/**/dbnavigator.xml
|
|
||||||
|
|
||||||
# Gradle
|
|
||||||
.idea/**/gradle.xml
|
|
||||||
.idea/**/libraries
|
|
||||||
|
|
||||||
# Gradle and Maven with auto-import
|
|
||||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
|
||||||
# since they will be recreated, and may cause churn. Uncomment if using
|
|
||||||
# auto-import.
|
|
||||||
# .idea/artifacts
|
|
||||||
# .idea/compiler.xml
|
|
||||||
# .idea/jarRepositories.xml
|
|
||||||
# .idea/modules.xml
|
|
||||||
# .idea/*.iml
|
|
||||||
# .idea/modules
|
|
||||||
# *.iml
|
|
||||||
# *.ipr
|
|
||||||
|
|
||||||
# CMake
|
|
||||||
cmake-build-*/
|
|
||||||
|
|
||||||
# Mongo Explorer plugin
|
|
||||||
.idea/**/mongoSettings.xml
|
|
||||||
|
|
||||||
# File-based project format
|
|
||||||
*.iws
|
|
||||||
|
|
||||||
# IntelliJ
|
|
||||||
out/
|
|
||||||
|
|
||||||
# mpeltonen/sbt-idea plugin
|
|
||||||
.idea_modules/
|
|
||||||
|
|
||||||
# JIRA plugin
|
|
||||||
atlassian-ide-plugin.xml
|
|
||||||
|
|
||||||
# Cursive Clojure plugin
|
|
||||||
.idea/replstate.xml
|
|
||||||
|
|
||||||
# SonarLint plugin
|
|
||||||
.idea/sonarlint/
|
|
||||||
|
|
||||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
|
||||||
com_crashlytics_export_strings.xml
|
|
||||||
crashlytics.properties
|
|
||||||
crashlytics-build.properties
|
|
||||||
fabric.properties
|
|
||||||
|
|
||||||
# Editor-based Rest Client
|
|
||||||
.idea/httpRequests
|
|
||||||
|
|
||||||
# Android studio 3.1+ serialized cache file
|
|
||||||
.idea/caches/build_file_checksums.ser
|
|
||||||
|
|
||||||
### macOS template
|
### macOS template
|
||||||
# General
|
# General
|
||||||
.DS_Store
|
.DS_Store
|
||||||
@ -171,6 +69,38 @@ Temporary Items
|
|||||||
|
|
||||||
# Application
|
# Application
|
||||||
log/
|
log/
|
||||||
config.dev.yaml
|
|
||||||
compose.dev.yaml
|
### Go template
|
||||||
|
# If you prefer the allow list template instead of the deny list, see community template:
|
||||||
|
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
||||||
|
#
|
||||||
|
# Binaries for programs and plugins
|
||||||
|
*.exe
|
||||||
|
*.exe~
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Test binary, built with `go test -c`
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
|
*.out
|
||||||
|
|
||||||
|
# Dependency directories (remove the comment below to include it)
|
||||||
|
# vendor/
|
||||||
|
|
||||||
|
# Go workspace file
|
||||||
|
go.work
|
||||||
|
|
||||||
|
### GoLand
|
||||||
|
|
||||||
|
# General
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
8
.idea/.gitignore
generated
vendored
8
.idea/.gitignore
generated
vendored
@ -1,8 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
# Editor-based HTTP Client requests
|
|
||||||
/httpRequests/
|
|
||||||
# Datasource local storage ignored files
|
|
||||||
/dataSources/
|
|
||||||
/dataSources.local.xml
|
|
6
.idea/git_toolbox_blame.xml
generated
6
.idea/git_toolbox_blame.xml
generated
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="GitToolBoxBlameSettings">
|
|
||||||
<option name="version" value="2" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectModuleManager">
|
|
||||||
<modules>
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/onvif-agent.iml" filepath="$PROJECT_DIR$/.idea/onvif-agent.iml" />
|
|
||||||
</modules>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
13
.idea/onvif-agent.iml
generated
13
.idea/onvif-agent.iml
generated
@ -1,13 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module type="WEB_MODULE" version="4">
|
|
||||||
<component name="Go" enabled="true">
|
|
||||||
<buildTags>
|
|
||||||
<option name="os" value="linux" />
|
|
||||||
</buildTags>
|
|
||||||
</component>
|
|
||||||
<component name="NewModuleRootManager">
|
|
||||||
<content url="file://$MODULE_DIR$" />
|
|
||||||
<orderEntry type="inheritedJdk" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
9
Dockerfile
Normal file
9
Dockerfile
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
FROM golang:1.23 AS builder
|
||||||
|
WORKDIR /build
|
||||||
|
COPY . ./
|
||||||
|
RUN GOPROXY=https://goproxy.cn go mod download
|
||||||
|
RUN CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -o out/app
|
||||||
|
|
||||||
|
FROM zabbix/zabbix-agent2:ubuntu-7.0-latest
|
||||||
|
COPY --from=builder /build/out/app /usr/sbin/zabbix-agent2-plugin/zabbixagent2plugintemplate
|
||||||
|
RUN echo "Plugins.Zabbixagent2plugintemplate.System.Path=/usr/sbin/zabbix-agent2-plugin/zabbixagent2plugintemplate" >> /etc/zabbix/zabbix_agent2.d/plugins.d/zabbixagent2plugintemplate.conf
|
19
README.md
19
README.md
@ -1,15 +1,14 @@
|
|||||||
# Wukong: Simplified Management of ONVIF IP Devices
|
# Zabbix Agent 2 Plugin Template
|
||||||
|
|
||||||
Wukong is a robust implementation of the ONVIF protocol designed for the efficient management of ONVIF-compliant IP devices, including cameras. This project aims to provide a user-friendly and streamlined solution for the convenient management of IP cameras and other devices that adhere to the ONVIF standard.
|
## 快速开始
|
||||||
|
|
||||||
With Wukong, users can easily configure, monitor, and control their ONVIF devices, enhancing the overall experience of managing surveillance systems and ensuring seamless integration within various environments.
|
### 先决条件
|
||||||
|
|
||||||
## Requirements
|
- Go >= 1.20
|
||||||
|
- Zabbix agent 2 >=6.0.0
|
||||||
|
- [预编译二进制文件](https://www.zabbix.com/download_agents)
|
||||||
|
- [Docker 镜像](https://hub.docker.com/r/zabbix/zabbix-agent2)
|
||||||
|
|
||||||
- Zabbix agent 2 version 6.0.0 or newer
|
### 从源代码构建
|
||||||
- Go programming language version 1.20 or newer (required only for building the plugin from the source)
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
The plugin can be compiled using `go build`.
|
|
||||||
|
|
||||||
|
`go build`.
|
||||||
|
@ -5,22 +5,21 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"onvif-agent/config"
|
|
||||||
"onvif-agent/constant"
|
|
||||||
"onvif-agent/integration/zabbixagent"
|
|
||||||
"onvif-agent/router"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
"zabbixagent2plugintemplate/config"
|
||||||
|
"zabbixagent2plugintemplate/constant"
|
||||||
|
"zabbixagent2plugintemplate/integration/zabbixagent"
|
||||||
|
"zabbixagent2plugintemplate/router"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
/**
|
/**
|
||||||
* Logging
|
* Logging
|
||||||
*/
|
*/
|
||||||
date := time.Now().Format("2006-01-02")
|
logFile := fmt.Sprintf("%s.log", time.Now().Format("2006-01-02"))
|
||||||
logFile := fmt.Sprintf("%s.log", date)
|
|
||||||
var logFilePath string
|
var logFilePath string
|
||||||
if runtime.GOOS == "linux" {
|
if runtime.GOOS == "linux" {
|
||||||
logFilePath = fmt.Sprintf("/var/log/%s/%s", constant.AppName, logFile)
|
logFilePath = fmt.Sprintf("/var/log/%s/%s", constant.AppName, logFile)
|
||||||
@ -33,7 +32,12 @@ func main() {
|
|||||||
log.Fatalf("Error opening file: %v", err)
|
log.Fatalf("Error opening file: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer f.Close()
|
defer func(f *os.File) {
|
||||||
|
err := f.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error closing file: %v", err)
|
||||||
|
}
|
||||||
|
}(f)
|
||||||
|
|
||||||
writer := io.MultiWriter(os.Stdout, f)
|
writer := io.MultiWriter(os.Stdout, f)
|
||||||
log.SetOutput(writer)
|
log.SetOutput(writer)
|
||||||
@ -61,15 +65,16 @@ func main() {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Zabbix agent
|
* Zabbix agent integration
|
||||||
*/
|
*/
|
||||||
//go func() {
|
go func() {
|
||||||
// zabbixagent.Run()
|
|
||||||
//}()
|
|
||||||
//
|
|
||||||
//select {}
|
|
||||||
err = zabbixagent.Launch()
|
err = zabbixagent.Launch()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
panic(err)
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {}
|
||||||
}
|
}
|
@ -1,15 +1,13 @@
|
|||||||
services:
|
services:
|
||||||
onvif-agent:
|
zabbixagent2plugintemplate:
|
||||||
build:
|
build: .
|
||||||
context: .
|
|
||||||
dockerfile: zabbixagent.dockerfile
|
|
||||||
environment:
|
environment:
|
||||||
ZBX_HOSTNAME: OnvifAgent plugin
|
ZBX_HOSTNAME: ONVIF
|
||||||
ZBX_SERVER_HOST: server
|
ZBX_SERVER_HOST: server
|
||||||
ZBX_SERVER_PORT: 10051
|
ZBX_SERVER_PORT: 10051
|
||||||
volumes:
|
volumes:
|
||||||
- ./log:/var/log/onvif-agent
|
- ./log:/var/log/zabbixagent2plugintemplate
|
||||||
- ./config.yaml:/etc/onvif-agent/config.yaml
|
- ./config.yaml:/etc/zabbixagent2plugintemplate/config.yaml
|
||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
networks:
|
networks:
|
@ -1,4 +1,4 @@
|
|||||||
app:
|
app:
|
||||||
port: 8080
|
port: 8080
|
||||||
host: "0.0.0.0"
|
host: "0.0.0.0"
|
||||||
url: "http://onvif-agent:8080"
|
url: "http://zabbixagent2plugintemplate:8080"
|
||||||
|
@ -4,8 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"log"
|
"log"
|
||||||
"onvif-agent/constant"
|
|
||||||
"os"
|
"os"
|
||||||
|
"zabbixagent2plugintemplate/constant"
|
||||||
)
|
)
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package constant
|
package constant
|
||||||
|
|
||||||
const (
|
const (
|
||||||
AppName = "onvif-agent"
|
AppName = "zabbixagent2plugintemplate"
|
||||||
AppVersion = "1.0.0"
|
AppVersion = "1.0.0"
|
||||||
)
|
)
|
||||||
|
2
go.mod
2
go.mod
@ -1,4 +1,4 @@
|
|||||||
module onvif-agent
|
module zabbixagent2plugintemplate
|
||||||
|
|
||||||
go 1.23.0
|
go 1.23.0
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
package zabbixagent
|
package zabbixagent
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PluginName = "OnvifAgent"
|
PluginName = "Zabbixagent2plugintemplate"
|
||||||
)
|
)
|
||||||
|
72
integration/zabbixagent/gin_handler.go
Normal file
72
integration/zabbixagent/gin_handler.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package zabbixagent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"zabbixagent2plugintemplate/response"
|
||||||
|
handler "zabbixagent2plugintemplate/router/handler/onvif"
|
||||||
|
service "zabbixagent2plugintemplate/service/onvif"
|
||||||
|
)
|
||||||
|
|
||||||
|
func DiscoverONVIFDevices(c *gin.Context) {
|
||||||
|
type device struct {
|
||||||
|
Xaddr string `json:"{#XADDR}"`
|
||||||
|
}
|
||||||
|
|
||||||
|
devices := make([]device, 0)
|
||||||
|
for xaddr := range service.Sessions {
|
||||||
|
devices = append(devices, device{
|
||||||
|
Xaddr: xaddr,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
response.NewResponse().WithData(devices).Send(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterONVIFDevices(c *gin.Context) {
|
||||||
|
var req []handler.CreateSessionRequest
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
response.NewResponse().Error(err).Send(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用于替换已存在的 Sessions
|
||||||
|
var sessions = make(map[string]*service.Session)
|
||||||
|
|
||||||
|
for _, v := range req {
|
||||||
|
session, err := service.NewSession(v.Xaddr, v.Username, v.Password)
|
||||||
|
if err != nil {
|
||||||
|
response.NewResponse().Error(err).Send(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = session.GetDeviceInfo()
|
||||||
|
if err != nil {
|
||||||
|
response.NewResponse().Error(err).Send(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sessions[session.Device.GetDeviceParams().Xaddr] = session
|
||||||
|
}
|
||||||
|
|
||||||
|
service.Sessions = sessions
|
||||||
|
|
||||||
|
response.NewResponse().Success().WithMessage(fmt.Sprintf("%d device(s) registered", len(sessions))).Send(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConsumeNotificationsRequest struct {
|
||||||
|
Xaddr string `json:"xaddr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func ConsumeONVIFNotifications(c *gin.Context) {
|
||||||
|
var req ConsumeNotificationsRequest
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
response.NewResponse().Error(err).Send(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
n := service.Notifications[req.Xaddr]
|
||||||
|
delete(service.Notifications, req.Xaddr)
|
||||||
|
|
||||||
|
response.NewResponse().WithData(n).Send(c)
|
||||||
|
}
|
@ -6,9 +6,9 @@ import (
|
|||||||
"golang.zabbix.com/sdk/errs"
|
"golang.zabbix.com/sdk/errs"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"onvif-agent/config"
|
|
||||||
"onvif-agent/constant"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
"zabbixagent2plugintemplate/config"
|
||||||
|
"zabbixagent2plugintemplate/constant"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HandlerFunc describes the signature all metric handler functions must have.
|
// HandlerFunc describes the signature all metric handler functions must have.
|
||||||
@ -24,7 +24,7 @@ type Handler struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) GetAppVersion(_ context.Context, _ map[string]string, _ ...string) (any, error) {
|
func (h *Handler) GetAppVersion(_ context.Context, _ map[string]string, _ ...string) (any, error) {
|
||||||
return constant.AppVersion, nil
|
return fmt.Sprintf("%s %s", constant.AppName, constant.AppVersion), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) HTTPClient(ctx context.Context, params map[string]string, _ ...string) (any, error) {
|
func (h *Handler) HTTPClient(ctx context.Context, params map[string]string, _ ...string) (any, error) {
|
||||||
@ -35,12 +35,12 @@ func (h *Handler) HTTPClient(ctx context.Context, params map[string]string, _ ..
|
|||||||
|
|
||||||
url := params["url"]
|
url := params["url"]
|
||||||
if !strings.HasPrefix(url, "http") {
|
if !strings.HasPrefix(url, "http") {
|
||||||
url = fmt.Sprintf("http://localhost:%d/%s", config.Config.App.Port, url)
|
url = fmt.Sprintf("http://localhost:%d%s", config.Config.App.Port, url)
|
||||||
}
|
}
|
||||||
|
|
||||||
body := params["body"]
|
body := params["body"]
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(ctx, method, "https://api.imbytecat.com/ip", strings.NewReader(body)) // TODO: if empty use http.NoBody
|
req, err := http.NewRequestWithContext(ctx, method, url, strings.NewReader(body)) // TODO: if empty use http.NoBody
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errs.Wrapf(err, "failed to create request")
|
return nil, errs.Wrapf(err, "failed to create request")
|
||||||
}
|
}
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
package zabbixagent
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"golang.zabbix.com/sdk/plugin/flag"
|
|
||||||
"golang.zabbix.com/sdk/zbxerr"
|
|
||||||
)
|
|
||||||
|
|
||||||
const copyrightMessage = //
|
|
||||||
`Copyright 2001-%d imbytecat
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
|
||||||
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
|
||||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions
|
|
||||||
of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
||||||
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
||||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
`
|
|
||||||
const (
|
|
||||||
pluginVersionMajor = 1
|
|
||||||
pluginVersionMinor = 0
|
|
||||||
pluginVersionPatch = 0
|
|
||||||
pluginVersionRC = "alpha1"
|
|
||||||
pluginLicenseYear = 2024
|
|
||||||
)
|
|
||||||
|
|
||||||
func Run() {
|
|
||||||
err := flag.HandleFlags(
|
|
||||||
PluginName,
|
|
||||||
os.Args[0],
|
|
||||||
fmt.Sprintf(copyrightMessage, pluginLicenseYear),
|
|
||||||
pluginVersionRC,
|
|
||||||
pluginVersionMajor,
|
|
||||||
pluginVersionMinor,
|
|
||||||
pluginVersionPatch,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, zbxerr.ErrorOSExitZero) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = Launch()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
panic(err)
|
|
||||||
}
|
|
@ -76,17 +76,17 @@ func (p *zabbixAgentPlugin) registerMetrics() error {
|
|||||||
h := NewHandler()
|
h := NewHandler()
|
||||||
|
|
||||||
p.metrics = map[metricKey]*metricBinding{
|
p.metrics = map[metricKey]*metricBinding{
|
||||||
"onvif.version": {
|
"onvif.app.version": {
|
||||||
metric: metric.New(
|
metric: metric.New(
|
||||||
"ONVIF app version",
|
"App version",
|
||||||
nil,
|
nil,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
handler: h.GetAppVersion,
|
handler: h.GetAppVersion,
|
||||||
},
|
},
|
||||||
"onvif.client": {
|
"onvif.httpclient": {
|
||||||
metric: metric.New(
|
metric: metric.New(
|
||||||
"ONVIF client",
|
"ONVIF HTTP client",
|
||||||
[]*metric.Param{
|
[]*metric.Param{
|
||||||
metric.NewParam("method", "HTTP request method."),
|
metric.NewParam("method", "HTTP request method."),
|
||||||
metric.NewParam("url", "HTTP request URL."),
|
metric.NewParam("url", "HTTP request URL."),
|
||||||
|
73
response/response.go
Normal file
73
response/response.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package response
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Response struct {
|
||||||
|
Code int `json:"code"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Data any `json:"data,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewResponse() *Response {
|
||||||
|
return &Response{
|
||||||
|
Code: http.StatusOK,
|
||||||
|
Message: "success",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Response) WithCode(code int) *Response {
|
||||||
|
r.Code = code
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Response) WithMessage(message string) *Response {
|
||||||
|
r.Message = message
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Response) WithData(data any) *Response {
|
||||||
|
r.Data = data
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Response) Error(err error) *Response {
|
||||||
|
r.Code = http.StatusInternalServerError
|
||||||
|
r.Message = err.Error()
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Response) Success(message ...string) *Response {
|
||||||
|
r.Code = http.StatusOK
|
||||||
|
if len(message) > 0 {
|
||||||
|
r.Message = message[0]
|
||||||
|
} else {
|
||||||
|
r.Message = "success"
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Response) Fail(message ...string) *Response {
|
||||||
|
r.Code = http.StatusInternalServerError
|
||||||
|
if len(message) > 0 {
|
||||||
|
r.Message = message[0]
|
||||||
|
} else {
|
||||||
|
r.Message = "fail"
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Response) Send(c *gin.Context) {
|
||||||
|
c.JSON(http.StatusOK, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Response) ToJSON() (string, error) {
|
||||||
|
data, err := json.Marshal(r)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(data), nil
|
||||||
|
}
|
10
router/handler/hello.go
Normal file
10
router/handler/hello.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"zabbixagent2plugintemplate/response"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Hello(c *gin.Context) {
|
||||||
|
response.NewResponse().Success("Hello, World!").Send(c)
|
||||||
|
}
|
@ -1,99 +0,0 @@
|
|||||||
package onvif
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"net/http"
|
|
||||||
"onvif-agent/service/onvif"
|
|
||||||
)
|
|
||||||
|
|
||||||
var conns = make(map[string]*onvif.Connection)
|
|
||||||
|
|
||||||
type CreateConnectionRequest struct {
|
|
||||||
Xaddr string `json:"xaddr"`
|
|
||||||
Username string `json:"username"`
|
|
||||||
Password string `json:"password"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateConnection(c *gin.Context) {
|
|
||||||
var req CreateConnectionRequest
|
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
conn, err := onvif.New(req.Xaddr, req.Username, req.Password)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{
|
|
||||||
"message": err.Error(),
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
info, err := conn.GetDeviceInfo()
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{
|
|
||||||
"message": err.Error(),
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// store connection
|
|
||||||
conns[conn.Device.GetDeviceParams().Xaddr] = conn
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
|
||||||
"device": info,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetConnections(c *gin.Context) {
|
|
||||||
devices := make(map[string]interface{})
|
|
||||||
|
|
||||||
for xaddr, conn := range conns {
|
|
||||||
info, err := conn.GetDeviceInfo()
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{
|
|
||||||
"message": err.Error(),
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
devices[xaddr] = info
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
|
||||||
"connections": devices,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetConnectionByXaddr(c *gin.Context) {
|
|
||||||
xaddr := c.Param("xaddr")
|
|
||||||
|
|
||||||
conn := conns[xaddr]
|
|
||||||
if conn == nil {
|
|
||||||
c.JSON(http.StatusNotFound, gin.H{
|
|
||||||
"message": "Connection not found",
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
info, err := conn.GetDeviceInfo()
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{
|
|
||||||
"message": err.Error(),
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
|
||||||
"device": info,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteConnection(c *gin.Context) {
|
|
||||||
xaddr := c.Param("xaddr")
|
|
||||||
delete(conns, xaddr)
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
|
||||||
"message": "OK",
|
|
||||||
})
|
|
||||||
}
|
|
23
router/handler/onvif/notification.go
Normal file
23
router/handler/onvif/notification.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package onvif
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"zabbixagent2plugintemplate/response"
|
||||||
|
"zabbixagent2plugintemplate/service/onvif"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetNotifications(c *gin.Context) {
|
||||||
|
response.NewResponse().WithData(onvif.Notifications).Send(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetNotificationByXaddr(c *gin.Context) {
|
||||||
|
xaddr := c.Param("xaddr")
|
||||||
|
response.NewResponse().WithData(onvif.Notifications[xaddr]).Send(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteNotificationByXaddr(c *gin.Context) {
|
||||||
|
xaddr := c.Param("xaddr")
|
||||||
|
delete(onvif.Notifications, xaddr)
|
||||||
|
|
||||||
|
response.NewResponse().Success().Send(c)
|
||||||
|
}
|
79
router/handler/onvif/session.go
Normal file
79
router/handler/onvif/session.go
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package onvif
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"net/http"
|
||||||
|
"zabbixagent2plugintemplate/response"
|
||||||
|
"zabbixagent2plugintemplate/service/onvif"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreateSessionRequest struct {
|
||||||
|
Xaddr string `json:"xaddr"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateSession(c *gin.Context) {
|
||||||
|
var req CreateSessionRequest
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
response.NewResponse().Error(err).Send(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
session, err := onvif.NewSession(req.Xaddr, req.Username, req.Password)
|
||||||
|
if err != nil {
|
||||||
|
response.NewResponse().Error(err).Send(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := session.GetDeviceInfo()
|
||||||
|
if err != nil {
|
||||||
|
response.NewResponse().Error(err).Send(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
onvif.Sessions[session.Device.GetDeviceParams().Xaddr] = session
|
||||||
|
|
||||||
|
response.NewResponse().WithData(info).Send(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSessions(c *gin.Context) {
|
||||||
|
devices := make(map[string]any)
|
||||||
|
|
||||||
|
for xaddr, session := range onvif.Sessions {
|
||||||
|
info, err := session.GetDeviceInfo()
|
||||||
|
if err != nil {
|
||||||
|
response.NewResponse().Error(err).Send(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
devices[xaddr] = info
|
||||||
|
}
|
||||||
|
|
||||||
|
response.NewResponse().WithData(devices).Send(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSessionByXaddr(c *gin.Context) {
|
||||||
|
xaddr := c.Param("xaddr")
|
||||||
|
|
||||||
|
session := onvif.Sessions[xaddr]
|
||||||
|
if session == nil {
|
||||||
|
response.NewResponse().Fail("Session not found").WithCode(http.StatusNotFound).Send(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := session.GetDeviceInfo()
|
||||||
|
if err != nil {
|
||||||
|
response.NewResponse().Error(err).Send(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.NewResponse().WithData(info).Send(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteSessionByXaddr(c *gin.Context) {
|
||||||
|
xaddr := c.Param("xaddr")
|
||||||
|
delete(onvif.Sessions, xaddr)
|
||||||
|
|
||||||
|
response.NewResponse().Success().Send(c)
|
||||||
|
}
|
@ -7,48 +7,43 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"onvif-agent/config"
|
"zabbixagent2plugintemplate/config"
|
||||||
|
"zabbixagent2plugintemplate/response"
|
||||||
|
"zabbixagent2plugintemplate/service/onvif"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CreateEventSubscription(c *gin.Context) {
|
func CreateSubscription(c *gin.Context) {
|
||||||
xaddr := c.Param("xaddr")
|
xaddr := c.Param("xaddr")
|
||||||
callbackURL := event.AttributedURIType(fmt.Sprintf("%s/onvif/subscriptions/%s/callback", config.Config.App.URL, xaddr))
|
callbackURL := event.AttributedURIType(fmt.Sprintf("%s/onvif/subscriptions/%s/callback", config.Config.App.URL, xaddr))
|
||||||
log.Printf("CreateEventSubscription callback URL: %s", callbackURL)
|
log.Printf("CreateSubscription callback URL: %s", callbackURL)
|
||||||
|
|
||||||
conn := conns[xaddr]
|
session := onvif.Sessions[xaddr]
|
||||||
if conn == nil {
|
if session == nil {
|
||||||
c.JSON(http.StatusNotFound, gin.H{
|
response.NewResponse().Fail("Connection not found").WithCode(http.StatusNotFound).Send(c)
|
||||||
"message": "Connection not found",
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := conn.SubscribeEvents(callbackURL, "PT60S")
|
result, err := session.EventSubscribe(callbackURL, "PT60S")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusServiceUnavailable, gin.H{
|
response.NewResponse().Error(err).Send(c)
|
||||||
"message": err.Error(),
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, result)
|
response.NewResponse().Success().WithData(result).Send(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func EventNotifyCallback(c *gin.Context) {
|
func NotifyCallback(c *gin.Context) {
|
||||||
xaddr := c.Param("xaddr")
|
xaddr := c.Param("xaddr")
|
||||||
log.Printf("EventNotifyCallback from: %s", xaddr)
|
log.Printf("NotifyCallback xaddr: %s", xaddr)
|
||||||
|
|
||||||
var notify event.Notify
|
var notify event.Notify
|
||||||
envelope := gosoap.NewSOAPEnvelope(¬ify)
|
envelope := gosoap.NewSOAPEnvelope(¬ify)
|
||||||
if err := c.ShouldBindXML(&envelope); err != nil {
|
if err := c.ShouldBindXML(&envelope); err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
response.NewResponse().Error(err).WithCode(http.StatusBadRequest).Send(c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: handle notifications
|
onvif.Notifications[xaddr] = append(onvif.Notifications[xaddr], notify.NotificationMessage...)
|
||||||
for _, msg := range envelope.Body.Content.(*event.Notify).NotificationMessage {
|
|
||||||
log.Printf("Topic: %s, Message: %s", msg.Topic.TopicKinds, msg.Message.Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{"message": "OK"})
|
response.NewResponse().Success().Send(c)
|
||||||
}
|
}
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
package handler
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Ping(c *gin.Context) {
|
|
||||||
c.JSON(200, gin.H{
|
|
||||||
"message": "pong",
|
|
||||||
})
|
|
||||||
}
|
|
@ -2,27 +2,42 @@ package router
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"onvif-agent/router/handler"
|
"zabbixagent2plugintemplate/integration/zabbixagent"
|
||||||
"onvif-agent/router/handler/onvif"
|
"zabbixagent2plugintemplate/router/handler"
|
||||||
|
"zabbixagent2plugintemplate/router/handler/onvif"
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetupRoutes(r *gin.Engine) {
|
func SetupRoutes(r *gin.Engine) {
|
||||||
r.GET("/ping", handler.Ping)
|
r.GET("/", handler.Hello)
|
||||||
|
|
||||||
userGroup := r.Group("/onvif")
|
onvifGroup := r.Group("/onvif")
|
||||||
{
|
{
|
||||||
connectionGroup := userGroup.Group("/connections")
|
connectionGroup := onvifGroup.Group("/sessions")
|
||||||
{
|
{
|
||||||
connectionGroup.POST("/", onvif.CreateConnection)
|
connectionGroup.POST("/", onvif.CreateSession)
|
||||||
connectionGroup.GET("/", onvif.GetConnections)
|
connectionGroup.GET("/", onvif.GetSessions)
|
||||||
connectionGroup.GET("/:xaddr", onvif.GetConnectionByXaddr)
|
connectionGroup.GET("/:xaddr", onvif.GetSessionByXaddr)
|
||||||
connectionGroup.DELETE("/:xaddr", onvif.DeleteConnection)
|
connectionGroup.DELETE("/:xaddr", onvif.DeleteSessionByXaddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
subscriptionGroup := userGroup.Group("/subscriptions")
|
subscriptionGroup := onvifGroup.Group("/subscriptions")
|
||||||
{
|
{
|
||||||
subscriptionGroup.POST("/:xaddr", onvif.CreateEventSubscription)
|
subscriptionGroup.POST("/:xaddr", onvif.CreateSubscription)
|
||||||
subscriptionGroup.POST("/:xaddr/callback", onvif.EventNotifyCallback)
|
subscriptionGroup.POST("/:xaddr/callback", onvif.NotifyCallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
notificationGroup := onvifGroup.Group("/notifications")
|
||||||
|
{
|
||||||
|
notificationGroup.GET("/", onvif.GetNotifications)
|
||||||
|
notificationGroup.GET("/:xaddr", onvif.GetNotificationByXaddr)
|
||||||
|
notificationGroup.DELETE("/:xaddr", onvif.DeleteNotificationByXaddr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
zabbixGroup := r.Group("/zabbix")
|
||||||
|
{
|
||||||
|
zabbixGroup.POST("/DiscoverONVIFDevices", zabbixagent.DiscoverONVIFDevices)
|
||||||
|
zabbixGroup.POST("/RegisterONVIFDevices", zabbixagent.RegisterONVIFDevices)
|
||||||
|
zabbixGroup.POST("/ConsumeONVIFNotifications", zabbixagent.ConsumeONVIFNotifications)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ package onvif
|
|||||||
|
|
||||||
import "github.com/IOTechSystems/onvif/device"
|
import "github.com/IOTechSystems/onvif/device"
|
||||||
|
|
||||||
func (c *Connection) GetDeviceInfo() (*device.GetDeviceInformationResponse, error) {
|
func (c *Session) GetDeviceInfo() (*device.GetDeviceInformationResponse, error) {
|
||||||
resp, err := c.Device.CallMethod(device.GetDeviceInformation{})
|
resp, err := c.Device.CallMethod(device.GetDeviceInformation{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -5,7 +5,9 @@ import (
|
|||||||
"github.com/IOTechSystems/onvif/xsd"
|
"github.com/IOTechSystems/onvif/xsd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Connection) SubscribeEvents(
|
var Notifications = make(map[string][]event.NotificationMessage)
|
||||||
|
|
||||||
|
func (c *Session) EventSubscribe(
|
||||||
consumerAddress event.AttributedURIType,
|
consumerAddress event.AttributedURIType,
|
||||||
terminationTime xsd.String, // PT60S
|
terminationTime xsd.String, // PT60S
|
||||||
) (*event.SubscribeResponse, error) {
|
) (*event.SubscribeResponse, error) {
|
||||||
|
@ -5,11 +5,13 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Connection struct {
|
type Session struct {
|
||||||
Device *onvif.Device `json:"device"`
|
Device *onvif.Device `json:"device"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(xaddr string, username string, password string) (*Connection, error) {
|
var Sessions = make(map[string]*Session)
|
||||||
|
|
||||||
|
func NewSession(xaddr string, username string, password string) (*Session, error) {
|
||||||
// 规范化连接地址
|
// 规范化连接地址
|
||||||
if !strings.Contains(xaddr, ":") {
|
if !strings.Contains(xaddr, ":") {
|
||||||
xaddr += ":80"
|
xaddr += ":80"
|
||||||
@ -25,5 +27,5 @@ func New(xaddr string, username string, password string) (*Connection, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Connection{Device: dev}, nil
|
return &Session{Device: dev}, nil
|
||||||
}
|
}
|
@ -1,9 +0,0 @@
|
|||||||
FROM golang:1.23 AS builder
|
|
||||||
WORKDIR /build
|
|
||||||
COPY . ./
|
|
||||||
RUN GOPROXY=https://goproxy.cn go mod download
|
|
||||||
RUN PROFILE=dev CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -o out/app
|
|
||||||
|
|
||||||
FROM zabbix/zabbix-agent2:ubuntu-7.0-latest
|
|
||||||
COPY --from=builder /build/out/app /usr/sbin/onvif-agent
|
|
||||||
RUN echo "Plugins.Onvif.System.Path=/usr/sbin/onvif-agent" >> /etc/zabbix/zabbix_agent2.d/plugins.d/onvif.conf
|
|
Reference in New Issue
Block a user