mirror of
https://github.com/kerberos-io/agent.git
synced 2026-10-22 18:08:24 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aac2150a3a | ||
|
|
9b713637b9 | ||
|
|
699660d472 | ||
|
|
751aa17534 | ||
|
|
2681bd2fe3 | ||
|
|
93adb3dabc | ||
|
|
0e15e58a88 | ||
|
|
ef2ea999df | ||
|
|
ca367611d7 | ||
|
|
eb8f073856 | ||
|
|
3ae43eba16 | ||
|
|
9719a08eaa | ||
|
|
1e165cbeb8 | ||
|
|
8be8cafd00 | ||
|
|
e74d2aadb5 | ||
|
|
9c97422f43 | ||
|
|
deb0a3ff1f | ||
|
|
95ed1f0e97 | ||
|
|
6a111dadd6 | ||
|
|
95b3623c04 | ||
|
|
326d62a640 | ||
|
|
9d990650f3 | ||
|
|
4bc891b640 |
@@ -6,6 +6,8 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-amd64:
|
build-amd64:
|
||||||
|
# If contains the keyword "#release" in the commit message.
|
||||||
|
if: ${{ !contains(github.event.head_commit.message, '#release') }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
@@ -31,6 +33,8 @@ jobs:
|
|||||||
- name: Create new and append to latest manifest
|
- name: Create new and append to latest manifest
|
||||||
run: docker buildx imagetools create -t kerberos/agent-dev:latest kerberos/agent-dev:arch-$(echo ${{matrix.architecture}} | tr / -)-$(echo $GITHUB_SHA | cut -c1-7)
|
run: docker buildx imagetools create -t kerberos/agent-dev:latest kerberos/agent-dev:arch-$(echo ${{matrix.architecture}} | tr / -)-$(echo $GITHUB_SHA | cut -c1-7)
|
||||||
build-other:
|
build-other:
|
||||||
|
# If contains the keyword "#release" in the commit message.
|
||||||
|
if: ${{ !contains(github.event.head_commit.message, '#release') }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-amd64:
|
build-amd64:
|
||||||
|
# If contains the keyword "[release]" in the commit message.
|
||||||
|
if: "contains(github.event.head_commit.message, '[release]')"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
@@ -26,10 +28,12 @@ jobs:
|
|||||||
- name: Available platforms
|
- name: Available platforms
|
||||||
run: echo ${{ steps.buildx.outputs.platforms }}
|
run: echo ${{ steps.buildx.outputs.platforms }}
|
||||||
- name: Run Buildx
|
- name: Run Buildx
|
||||||
run: docker buildx build --platform linux/${{matrix.architecture}} -t kerberos/agent-nightly:arch-$(echo ${{matrix.architecture}} | tr / -)-$(echo $GITHUB_SHA | cut -c1-7) --push .
|
run: cd agent && docker buildx build --platform linux/${{matrix.architecture}} -t kerberos/agent-nightly:arch-$(echo ${{matrix.architecture}} | tr / -)-$(echo $GITHUB_SHA | cut -c1-7) --push .
|
||||||
- name: Create new and append to manifest
|
- name: Create new and append to manifest
|
||||||
run: docker buildx imagetools create -t kerberos/agent-nightly:$(echo $GITHUB_SHA | cut -c1-7) kerberos/agent-nightly:arch-$(echo ${{matrix.architecture}} | tr / -)-$(echo $GITHUB_SHA | cut -c1-7)
|
run: cd agent && docker buildx imagetools create -t kerberos/agent-nightly:$(echo $GITHUB_SHA | cut -c1-7) kerberos/agent-nightly:arch-$(echo ${{matrix.architecture}} | tr / -)-$(echo $GITHUB_SHA | cut -c1-7)
|
||||||
build-other:
|
build-other:
|
||||||
|
# If contains the keyword "[release]" in the commit message.
|
||||||
|
if: "contains(github.event.head_commit.message, '[release]')"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
@@ -49,6 +53,6 @@ jobs:
|
|||||||
- name: Available platforms
|
- name: Available platforms
|
||||||
run: echo ${{ steps.buildx.outputs.platforms }}
|
run: echo ${{ steps.buildx.outputs.platforms }}
|
||||||
- name: Run Buildx
|
- name: Run Buildx
|
||||||
run: docker buildx build --platform linux/${{matrix.architecture}} -t kerberos/agent-nightly:arch-$(echo ${{matrix.architecture}} | tr / -)-$(echo $GITHUB_SHA | cut -c1-7) --push .
|
run: cd agent && docker buildx build --platform linux/${{matrix.architecture}} -t kerberos/agent-nightly:arch-$(echo ${{matrix.architecture}} | tr / -)-$(echo $GITHUB_SHA | cut -c1-7) --push .
|
||||||
- name: Create new and append to manifest
|
- name: Create new and append to manifest
|
||||||
run: docker buildx imagetools create --append -t kerberos/agent-nightly:$(echo $GITHUB_SHA | cut -c1-7) kerberos/agent-nightly:arch-$(echo ${{matrix.architecture}} | tr / -)-$(echo $GITHUB_SHA | cut -c1-7)
|
run: cd agent && docker buildx imagetools create --append -t kerberos/agent-nightly:$(echo $GITHUB_SHA | cut -c1-7) kerberos/agent-nightly:arch-$(echo ${{matrix.architecture}} | tr / -)-$(echo $GITHUB_SHA | cut -c1-7)
|
||||||
@@ -2,6 +2,7 @@ name: Docker master build
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
# If pushed to master branch.
|
||||||
branches: [ master ]
|
branches: [ master ]
|
||||||
|
|
||||||
env:
|
env:
|
||||||
@@ -9,6 +10,8 @@ env:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-amd64:
|
build-amd64:
|
||||||
|
# If contains the keyword "[release]" in the commit message.
|
||||||
|
if: "contains(github.event.head_commit.message, '[release]')"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
@@ -67,6 +70,8 @@ jobs:
|
|||||||
#- name: Use Snapcraft
|
#- name: Use Snapcraft
|
||||||
# run: tar -xf agent-${{matrix.architecture}}.tar && snapcraft
|
# run: tar -xf agent-${{matrix.architecture}}.tar && snapcraft
|
||||||
build-other:
|
build-other:
|
||||||
|
# If contains the keyword "[release]" in the commit message.
|
||||||
|
if: "contains(github.event.head_commit.message, '[release]')"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ This repository contains everything you'll need to know about our core product,
|
|||||||
- Simplified and modern user interface.
|
- Simplified and modern user interface.
|
||||||
- Multi architecture (ARMv7, ARMv8, amd64, etc).).
|
- Multi architecture (ARMv7, ARMv8, amd64, etc).).
|
||||||
- Multi stream, for example recording in H265, live streaming and motion detection in H264.
|
- Multi stream, for example recording in H265, live streaming and motion detection in H264.
|
||||||
- Multi camera support: IP Cameras (H264 and H265), USB cameras and Raspberry Pi Cameras [through a RTSP proxy](https://github.com/kerberos-io/camera-to-rtsp
|
- Multi camera support: IP Cameras (H264 and H265), USB cameras and Raspberry Pi Cameras [through a RTSP proxy](https://github.com/kerberos-io/camera-to-rtsp).
|
||||||
- Single camera per instance (e.g. one container per camera).
|
- Single camera per instance (e.g. one container per camera).
|
||||||
- Low resolution streaming through MQTT and high resolution streaming through WebRTC (only supports H264/PCM).
|
- Low resolution streaming through MQTT and high resolution streaming through WebRTC (only supports H264/PCM).
|
||||||
- Backchannel audio from Kerberos Hub to IP camera (requires PCM ULAW codec)
|
- Backchannel audio from Kerberos Hub to IP camera (requires PCM ULAW codec)
|
||||||
@@ -226,6 +226,7 @@ Next to attaching the configuration file, it is also possible to override the co
|
|||||||
| `AGENT_TURN_USERNAME` | TURN username used for WebRTC. | "username1" |
|
| `AGENT_TURN_USERNAME` | TURN username used for WebRTC. | "username1" |
|
||||||
| `AGENT_TURN_PASSWORD` | TURN password used for WebRTC. | "password1" |
|
| `AGENT_TURN_PASSWORD` | TURN password used for WebRTC. | "password1" |
|
||||||
| `AGENT_CLOUD` | Store recordings in Kerberos Hub (s3), Kerberos Vault (kstorage) or Dropbox (dropbox). | "s3" |
|
| `AGENT_CLOUD` | Store recordings in Kerberos Hub (s3), Kerberos Vault (kstorage) or Dropbox (dropbox). | "s3" |
|
||||||
|
| `AGENT_HUB_ENCRYPTION` | Turning on/off encryption of traffic from your Kerberos Agent to Kerberos Hub. | "true" |
|
||||||
| `AGENT_HUB_URI` | The Kerberos Hub API, defaults to our Kerberos Hub SAAS. | "https://api.hub.domain.com" |
|
| `AGENT_HUB_URI` | The Kerberos Hub API, defaults to our Kerberos Hub SAAS. | "https://api.hub.domain.com" |
|
||||||
| `AGENT_HUB_KEY` | The access key linked to your account in Kerberos Hub. | "" |
|
| `AGENT_HUB_KEY` | The access key linked to your account in Kerberos Hub. | "" |
|
||||||
| `AGENT_HUB_PRIVATE_KEY` | The secret access key linked to your account in Kerberos Hub. | "" |
|
| `AGENT_HUB_PRIVATE_KEY` | The secret access key linked to your account in Kerberos Hub. | "" |
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ Kerberos Agents are now also shipped as static binaries. Within the Docker image
|
|||||||
|
|
||||||
You can run the binary as following on port `8080`:
|
You can run the binary as following on port `8080`:
|
||||||
|
|
||||||
main run cameraname 8080
|
main -action=run -port=80
|
||||||
|
|
||||||
## Systemd
|
## Systemd
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ When running on a Linux OS you might consider to auto-start the Kerberos Agent u
|
|||||||
[Unit]
|
[Unit]
|
||||||
Wants=network.target
|
Wants=network.target
|
||||||
[Service]
|
[Service]
|
||||||
ExecStart=/home/pi/agent/main run camera 80
|
ExecStart=/home/pi/agent/main -action=run -port=80
|
||||||
WorkingDirectory=/home/pi/agent/
|
WorkingDirectory=/home/pi/agent/
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|||||||
@@ -107,6 +107,7 @@
|
|||||||
"turn_username": "username1",
|
"turn_username": "username1",
|
||||||
"turn_password": "password1",
|
"turn_password": "password1",
|
||||||
"heartbeaturi": "",
|
"heartbeaturi": "",
|
||||||
|
"hub_encryption": "true",
|
||||||
"hub_uri": "https://api.cloud.kerberos.io",
|
"hub_uri": "https://api.cloud.kerberos.io",
|
||||||
"hub_key": "",
|
"hub_key": "",
|
||||||
"hub_private_key": "",
|
"hub_private_key": "",
|
||||||
|
|||||||
+34
-34
@@ -279,6 +279,40 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/camera/onvif/verify": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Will verify the ONVIF connectivity.",
|
||||||
|
"tags": [
|
||||||
|
"onvif"
|
||||||
|
],
|
||||||
|
"summary": "Will verify the ONVIF connectivity.",
|
||||||
|
"operationId": "verify-onvif",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "OnvifCredentials",
|
||||||
|
"name": "config",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.OnvifCredentials"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.APIResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/camera/onvif/zoom": {
|
"/api/camera/onvif/zoom": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "Zooming in or out the camera.",
|
"description": "Zooming in or out the camera.",
|
||||||
@@ -590,40 +624,6 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/api/onvif/verify": {
|
|
||||||
"post": {
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"Bearer": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Will verify the ONVIF connectivity.",
|
|
||||||
"tags": [
|
|
||||||
"onvif"
|
|
||||||
],
|
|
||||||
"summary": "Will verify the ONVIF connectivity.",
|
|
||||||
"operationId": "verify-onvif",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"description": "OnvifCredentials",
|
|
||||||
"name": "config",
|
|
||||||
"in": "body",
|
|
||||||
"required": true,
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/models.OnvifCredentials"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/models.APIResponse"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/api/persistence/verify": {
|
"/api/persistence/verify": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
|
|||||||
+34
-34
@@ -271,6 +271,40 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/camera/onvif/verify": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Will verify the ONVIF connectivity.",
|
||||||
|
"tags": [
|
||||||
|
"onvif"
|
||||||
|
],
|
||||||
|
"summary": "Will verify the ONVIF connectivity.",
|
||||||
|
"operationId": "verify-onvif",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "OnvifCredentials",
|
||||||
|
"name": "config",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.OnvifCredentials"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.APIResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/camera/onvif/zoom": {
|
"/api/camera/onvif/zoom": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "Zooming in or out the camera.",
|
"description": "Zooming in or out the camera.",
|
||||||
@@ -582,40 +616,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/api/onvif/verify": {
|
|
||||||
"post": {
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"Bearer": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Will verify the ONVIF connectivity.",
|
|
||||||
"tags": [
|
|
||||||
"onvif"
|
|
||||||
],
|
|
||||||
"summary": "Will verify the ONVIF connectivity.",
|
|
||||||
"operationId": "verify-onvif",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"description": "OnvifCredentials",
|
|
||||||
"name": "config",
|
|
||||||
"in": "body",
|
|
||||||
"required": true,
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/models.OnvifCredentials"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/models.APIResponse"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/api/persistence/verify": {
|
"/api/persistence/verify": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
|
|||||||
+21
-21
@@ -494,6 +494,27 @@ paths:
|
|||||||
summary: Will return the ONVIF presets for the specific camera.
|
summary: Will return the ONVIF presets for the specific camera.
|
||||||
tags:
|
tags:
|
||||||
- onvif
|
- onvif
|
||||||
|
/api/camera/onvif/verify:
|
||||||
|
post:
|
||||||
|
description: Will verify the ONVIF connectivity.
|
||||||
|
operationId: verify-onvif
|
||||||
|
parameters:
|
||||||
|
- description: OnvifCredentials
|
||||||
|
in: body
|
||||||
|
name: config
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.OnvifCredentials'
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.APIResponse'
|
||||||
|
security:
|
||||||
|
- Bearer: []
|
||||||
|
summary: Will verify the ONVIF connectivity.
|
||||||
|
tags:
|
||||||
|
- onvif
|
||||||
/api/camera/onvif/zoom:
|
/api/camera/onvif/zoom:
|
||||||
post:
|
post:
|
||||||
description: Zooming in or out the camera.
|
description: Zooming in or out the camera.
|
||||||
@@ -700,27 +721,6 @@ paths:
|
|||||||
summary: Get Authorization token.
|
summary: Get Authorization token.
|
||||||
tags:
|
tags:
|
||||||
- authentication
|
- authentication
|
||||||
/api/onvif/verify:
|
|
||||||
post:
|
|
||||||
description: Will verify the ONVIF connectivity.
|
|
||||||
operationId: verify-onvif
|
|
||||||
parameters:
|
|
||||||
- description: OnvifCredentials
|
|
||||||
in: body
|
|
||||||
name: config
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/models.OnvifCredentials'
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: OK
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/models.APIResponse'
|
|
||||||
security:
|
|
||||||
- Bearer: []
|
|
||||||
summary: Will verify the ONVIF connectivity.
|
|
||||||
tags:
|
|
||||||
- onvif
|
|
||||||
/api/persistence/verify:
|
/api/persistence/verify:
|
||||||
post:
|
post:
|
||||||
description: Will verify the persistence.
|
description: Will verify the persistence.
|
||||||
|
|||||||
@@ -351,7 +351,7 @@ func (g *Golibrtsp) ConnectBackChannel(ctx context.Context) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start the RTSP client, and start reading packets.
|
// Start the RTSP client, and start reading packets.
|
||||||
func (g *Golibrtsp) Start(ctx context.Context, queue *packets.Queue, configuration *models.Configuration, communication *models.Communication) (err error) {
|
func (g *Golibrtsp) Start(ctx context.Context, streamType string, queue *packets.Queue, configuration *models.Configuration, communication *models.Communication) (err error) {
|
||||||
log.Log.Debug("capture.golibrtsp.Start(): started")
|
log.Log.Debug("capture.golibrtsp.Start(): started")
|
||||||
|
|
||||||
// called when a MULAW audio RTP packet arrives
|
// called when a MULAW audio RTP packet arrives
|
||||||
@@ -360,7 +360,7 @@ func (g *Golibrtsp) Start(ctx context.Context, queue *packets.Queue, configurati
|
|||||||
// decode timestamp
|
// decode timestamp
|
||||||
pts, ok := g.Client.PacketPTS(g.AudioG711Media, rtppkt)
|
pts, ok := g.Client.PacketPTS(g.AudioG711Media, rtppkt)
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Log.Warning("capture.golibrtsp.Start(): " + "unable to get PTS")
|
log.Log.Debug("capture.golibrtsp.Start(): " + "unable to get PTS")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,7 +443,7 @@ func (g *Golibrtsp) Start(ctx context.Context, queue *packets.Queue, configurati
|
|||||||
// decode timestamp
|
// decode timestamp
|
||||||
pts, ok := g.Client.PacketPTS(g.VideoH264Media, rtppkt)
|
pts, ok := g.Client.PacketPTS(g.VideoH264Media, rtppkt)
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Log.Warning("capture.golibrtsp.Start(): " + "unable to get PTS")
|
log.Log.Debug("capture.golibrtsp.Start(): " + "unable to get PTS")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -527,10 +527,17 @@ func (g *Golibrtsp) Start(ctx context.Context, queue *packets.Queue, configurati
|
|||||||
if idrPresent {
|
if idrPresent {
|
||||||
// Increment packets, so we know the device
|
// Increment packets, so we know the device
|
||||||
// is not blocking.
|
// is not blocking.
|
||||||
|
if streamType == "main" {
|
||||||
r := communication.PackageCounter.Load().(int64)
|
r := communication.PackageCounter.Load().(int64)
|
||||||
log.Log.Debug("capture.golibrtsp.Start(): packet size " + strconv.Itoa(len(pkt.Data)))
|
log.Log.Debug("capture.golibrtsp.Start(): packet size " + strconv.Itoa(len(pkt.Data)))
|
||||||
communication.PackageCounter.Store((r + 1) % 1000)
|
communication.PackageCounter.Store((r + 1) % 1000)
|
||||||
communication.LastPacketTimer.Store(time.Now().Unix())
|
communication.LastPacketTimer.Store(time.Now().Unix())
|
||||||
|
} else if streamType == "sub" {
|
||||||
|
r := communication.PackageCounterSub.Load().(int64)
|
||||||
|
log.Log.Debug("capture.golibrtsp.Start(): packet size " + strconv.Itoa(len(pkt.Data)))
|
||||||
|
communication.PackageCounterSub.Store((r + 1) % 1000)
|
||||||
|
communication.LastPacketTimerSub.Store(time.Now().Unix())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,7 +561,7 @@ func (g *Golibrtsp) Start(ctx context.Context, queue *packets.Queue, configurati
|
|||||||
// decode timestamp
|
// decode timestamp
|
||||||
pts, ok := g.Client.PacketPTS(g.VideoH265Media, rtppkt)
|
pts, ok := g.Client.PacketPTS(g.VideoH265Media, rtppkt)
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Log.Warning("capture.golibrtsp.Start(): " + "unable to get PTS")
|
log.Log.Debug("capture.golibrtsp.Start(): " + "unable to get PTS")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,10 +644,17 @@ func (g *Golibrtsp) Start(ctx context.Context, queue *packets.Queue, configurati
|
|||||||
if isRandomAccess {
|
if isRandomAccess {
|
||||||
// Increment packets, so we know the device
|
// Increment packets, so we know the device
|
||||||
// is not blocking.
|
// is not blocking.
|
||||||
|
if streamType == "main" {
|
||||||
r := communication.PackageCounter.Load().(int64)
|
r := communication.PackageCounter.Load().(int64)
|
||||||
log.Log.Debug("capture.golibrtsp.Start(): packet size " + strconv.Itoa(len(pkt.Data)))
|
log.Log.Debug("capture.golibrtsp.Start(): packet size " + strconv.Itoa(len(pkt.Data)))
|
||||||
communication.PackageCounter.Store((r + 1) % 1000)
|
communication.PackageCounter.Store((r + 1) % 1000)
|
||||||
communication.LastPacketTimer.Store(time.Now().Unix())
|
communication.LastPacketTimer.Store(time.Now().Unix())
|
||||||
|
} else if streamType == "sub" {
|
||||||
|
r := communication.PackageCounterSub.Load().(int64)
|
||||||
|
log.Log.Debug("capture.golibrtsp.Start(): packet size " + strconv.Itoa(len(pkt.Data)))
|
||||||
|
communication.PackageCounterSub.Store((r + 1) % 1000)
|
||||||
|
communication.LastPacketTimerSub.Store(time.Now().Unix())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ type RTSPClient interface {
|
|||||||
ConnectBackChannel(ctx context.Context) error
|
ConnectBackChannel(ctx context.Context) error
|
||||||
|
|
||||||
// Start the RTSP client, and start reading packets.
|
// Start the RTSP client, and start reading packets.
|
||||||
Start(ctx context.Context, queue *packets.Queue, configuration *models.Configuration, communication *models.Communication) error
|
Start(ctx context.Context, streamType string, queue *packets.Queue, configuration *models.Configuration, communication *models.Communication) error
|
||||||
|
|
||||||
// Start the RTSP client, and start reading packets.
|
// Start the RTSP client, and start reading packets.
|
||||||
StartBackChannel(ctx context.Context) (err error)
|
StartBackChannel(ctx context.Context) (err error)
|
||||||
|
|||||||
@@ -564,6 +564,8 @@ func VerifyCamera(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err := rtspClient.Close()
|
||||||
|
if err == nil {
|
||||||
if videoIdx > -1 {
|
if videoIdx > -1 {
|
||||||
c.JSON(200, models.APIResponse{
|
c.JSON(200, models.APIResponse{
|
||||||
Message: "All good, detected a H264 codec.",
|
Message: "All good, detected a H264 codec.",
|
||||||
@@ -574,7 +576,11 @@ func VerifyCamera(c *gin.Context) {
|
|||||||
Message: "Stream doesn't have a H264 codec, we only support H264 so far.",
|
Message: "Stream doesn't have a H264 codec, we only support H264 so far.",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
c.JSON(400, models.APIResponse{
|
||||||
|
Message: "Something went wrong while closing the connection " + err.Error(),
|
||||||
|
})
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
c.JSON(400, models.APIResponse{
|
c.JSON(400, models.APIResponse{
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
|
|||||||
@@ -290,7 +290,7 @@ loop:
|
|||||||
onvifPresetsList = []byte("[]")
|
onvifPresetsList = []byte("[]")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Log.Error("cloud.HandleHeartBeat(): error while getting PTZ configurations: " + err.Error())
|
log.Log.Debug("cloud.HandleHeartBeat(): error while getting PTZ configurations: " + err.Error())
|
||||||
onvifPresetsList = []byte("[]")
|
onvifPresetsList = []byte("[]")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,6 +320,12 @@ loop:
|
|||||||
} else {
|
} else {
|
||||||
log.Log.Debug("cloud.HandleHeartBeat(): no pull point address found.")
|
log.Log.Debug("cloud.HandleHeartBeat(): no pull point address found.")
|
||||||
onvifEventsList = []byte("[]")
|
onvifEventsList = []byte("[]")
|
||||||
|
|
||||||
|
// Try again
|
||||||
|
pullPointAddress, err = onvif.CreatePullPointSubscription(device)
|
||||||
|
if err != nil {
|
||||||
|
log.Log.Debug("cloud.HandleHeartBeat(): error while creating pull point subscription: " + err.Error())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -444,8 +450,9 @@ loop:
|
|||||||
}`, config.Key, system.Version, system.CPUId, username, key, name, isEnterprise, system.Hostname, system.Architecture, system.TotalMemory, system.UsedMemory, system.FreeMemory, system.ProcessUsedMemory, macs, ips, "0", "0", "0", uptimeString, boottimeString, config.HubSite, onvifEnabled, onvifZoom, onvifPanTilt, onvifPresets, onvifPresetsList, onvifEventsList, cameraConnected, hasBackChannel)
|
}`, config.Key, system.Version, system.CPUId, username, key, name, isEnterprise, system.Hostname, system.Architecture, system.TotalMemory, system.UsedMemory, system.FreeMemory, system.ProcessUsedMemory, macs, ips, "0", "0", "0", uptimeString, boottimeString, config.HubSite, onvifEnabled, onvifZoom, onvifPanTilt, onvifPresets, onvifPresetsList, onvifEventsList, cameraConnected, hasBackChannel)
|
||||||
|
|
||||||
// Get the private key to encrypt the data using symmetric encryption: AES.
|
// Get the private key to encrypt the data using symmetric encryption: AES.
|
||||||
|
HubEncryption := config.HubEncryption
|
||||||
privateKey := config.HubPrivateKey
|
privateKey := config.HubPrivateKey
|
||||||
if privateKey != "" {
|
if HubEncryption == "true" && privateKey != "" {
|
||||||
// Encrypt the data using AES.
|
// Encrypt the data using AES.
|
||||||
encrypted, err := encryption.AesEncrypt([]byte(object), privateKey)
|
encrypted, err := encryption.AesEncrypt([]byte(object), privateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -486,7 +493,9 @@ loop:
|
|||||||
// If we have a Kerberos Vault connected, we will also send some analytics
|
// If we have a Kerberos Vault connected, we will also send some analytics
|
||||||
// to that service.
|
// to that service.
|
||||||
vaultURI = config.KStorage.URI
|
vaultURI = config.KStorage.URI
|
||||||
if vaultURI != "" {
|
accessKey := config.KStorage.AccessKey
|
||||||
|
secretAccessKey := config.KStorage.SecretAccessKey
|
||||||
|
if vaultURI != "" && accessKey != "" && secretAccessKey != "" {
|
||||||
|
|
||||||
var object = fmt.Sprintf(`{
|
var object = fmt.Sprintf(`{
|
||||||
"key" : "%s",
|
"key" : "%s",
|
||||||
|
|||||||
@@ -36,12 +36,20 @@ func Bootstrap(configDirectory string, configuration *models.Configuration, comm
|
|||||||
packageCounter.Store(int64(0))
|
packageCounter.Store(int64(0))
|
||||||
communication.PackageCounter = &packageCounter
|
communication.PackageCounter = &packageCounter
|
||||||
|
|
||||||
|
var packageCounterSub atomic.Value
|
||||||
|
packageCounterSub.Store(int64(0))
|
||||||
|
communication.PackageCounterSub = &packageCounterSub
|
||||||
|
|
||||||
// This is used when the last packet was received (timestamp),
|
// This is used when the last packet was received (timestamp),
|
||||||
// this metric is used to determine if the camera is still online/connected.
|
// this metric is used to determine if the camera is still online/connected.
|
||||||
var lastPacketTimer atomic.Value
|
var lastPacketTimer atomic.Value
|
||||||
packageCounter.Store(int64(0))
|
packageCounter.Store(int64(0))
|
||||||
communication.LastPacketTimer = &lastPacketTimer
|
communication.LastPacketTimer = &lastPacketTimer
|
||||||
|
|
||||||
|
var lastPacketTimerSub atomic.Value
|
||||||
|
packageCounterSub.Store(int64(0))
|
||||||
|
communication.LastPacketTimerSub = &lastPacketTimerSub
|
||||||
|
|
||||||
// This is used to understand if we have a working Kerberos Hub connection
|
// This is used to understand if we have a working Kerberos Hub connection
|
||||||
// cloudTimestamp will be updated when successfully sending heartbeats.
|
// cloudTimestamp will be updated when successfully sending heartbeats.
|
||||||
var cloudTimestamp atomic.Value
|
var cloudTimestamp atomic.Value
|
||||||
@@ -245,7 +253,10 @@ func RunAgent(configDirectory string, configuration *models.Configuration, commu
|
|||||||
log.Log.Info("components.Kerberos.RunAgent(): SetMaxGopCount was set with: " + strconv.Itoa(int(config.Capture.PreRecording)+1))
|
log.Log.Info("components.Kerberos.RunAgent(): SetMaxGopCount was set with: " + strconv.Itoa(int(config.Capture.PreRecording)+1))
|
||||||
queue.SetMaxGopCount(int(config.Capture.PreRecording) + 1) // GOP time frame is set to prerecording (we'll add 2 gops to leave some room).
|
queue.SetMaxGopCount(int(config.Capture.PreRecording) + 1) // GOP time frame is set to prerecording (we'll add 2 gops to leave some room).
|
||||||
queue.WriteHeader(videoStreams)
|
queue.WriteHeader(videoStreams)
|
||||||
go rtspClient.Start(context.Background(), queue, configuration, communication)
|
go rtspClient.Start(context.Background(), "main", queue, configuration, communication)
|
||||||
|
|
||||||
|
// Main stream is connected and ready to go.
|
||||||
|
communication.MainStreamConnected = true
|
||||||
|
|
||||||
// Try to create backchannel
|
// Try to create backchannel
|
||||||
rtspBackChannelClient := captureDevice.SetBackChannelClient(rtspUrl)
|
rtspBackChannelClient := captureDevice.SetBackChannelClient(rtspUrl)
|
||||||
@@ -261,7 +272,10 @@ func RunAgent(configDirectory string, configuration *models.Configuration, commu
|
|||||||
communication.SubQueue = subQueue
|
communication.SubQueue = subQueue
|
||||||
subQueue.SetMaxGopCount(1) // GOP time frame is set to prerecording (we'll add 2 gops to leave some room).
|
subQueue.SetMaxGopCount(1) // GOP time frame is set to prerecording (we'll add 2 gops to leave some room).
|
||||||
subQueue.WriteHeader(videoSubStreams)
|
subQueue.WriteHeader(videoSubStreams)
|
||||||
go rtspSubClient.Start(context.Background(), subQueue, configuration, communication)
|
go rtspSubClient.Start(context.Background(), "sub", subQueue, configuration, communication)
|
||||||
|
|
||||||
|
// Sub stream is connected and ready to go.
|
||||||
|
communication.SubStreamConnected = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle livestream SD (low resolution over MQTT)
|
// Handle livestream SD (low resolution over MQTT)
|
||||||
@@ -320,6 +334,8 @@ func RunAgent(configDirectory string, configuration *models.Configuration, commu
|
|||||||
|
|
||||||
// If we reach this point, we are stopping the stream.
|
// If we reach this point, we are stopping the stream.
|
||||||
communication.CameraConnected = false
|
communication.CameraConnected = false
|
||||||
|
communication.MainStreamConnected = false
|
||||||
|
communication.SubStreamConnected = false
|
||||||
|
|
||||||
// Cancel the main context, this will stop all the other goroutines.
|
// Cancel the main context, this will stop all the other goroutines.
|
||||||
(*communication.CancelContext)()
|
(*communication.CancelContext)()
|
||||||
@@ -397,14 +413,19 @@ func RunAgent(configDirectory string, configuration *models.Configuration, commu
|
|||||||
func ControlAgent(communication *models.Communication) {
|
func ControlAgent(communication *models.Communication) {
|
||||||
log.Log.Debug("components.Kerberos.ControlAgent(): started")
|
log.Log.Debug("components.Kerberos.ControlAgent(): started")
|
||||||
packageCounter := communication.PackageCounter
|
packageCounter := communication.PackageCounter
|
||||||
|
packageSubCounter := communication.PackageCounterSub
|
||||||
go func() {
|
go func() {
|
||||||
// A channel to check the camera activity
|
// A channel to check the camera activity
|
||||||
var previousPacket int64 = 0
|
var previousPacket int64 = 0
|
||||||
|
var previousPacketSub int64 = 0
|
||||||
var occurence = 0
|
var occurence = 0
|
||||||
|
var occurenceSub = 0
|
||||||
for {
|
for {
|
||||||
|
|
||||||
// If camera is connected, we'll check if we are still receiving packets.
|
// If camera is connected, we'll check if we are still receiving packets.
|
||||||
if communication.CameraConnected {
|
if communication.CameraConnected {
|
||||||
|
|
||||||
|
// First we'll check the main stream.
|
||||||
packetsR := packageCounter.Load().(int64)
|
packetsR := packageCounter.Load().(int64)
|
||||||
if packetsR == previousPacket {
|
if packetsR == previousPacket {
|
||||||
// If we are already reconfiguring,
|
// If we are already reconfiguring,
|
||||||
@@ -416,16 +437,42 @@ func ControlAgent(communication *models.Communication) {
|
|||||||
occurence = 0
|
occurence = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Log.Info("components.Kerberos.ControlAgent(): Number of packets read " + strconv.FormatInt(packetsR, 10))
|
log.Log.Info("components.Kerberos.ControlAgent(): Number of packets read from mainstream: " + strconv.FormatInt(packetsR, 10))
|
||||||
|
|
||||||
// After 15 seconds without activity this is thrown..
|
// After 15 seconds without activity this is thrown..
|
||||||
if occurence == 3 {
|
if occurence == 3 {
|
||||||
log.Log.Info("components.Kerberos.ControlAgent(): Restarting machinery.")
|
log.Log.Info("components.Kerberos.ControlAgent(): Restarting machinery because of blocking mainstream.")
|
||||||
communication.HandleBootstrap <- "restart"
|
communication.HandleBootstrap <- "restart"
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
occurence = 0
|
occurence = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now we'll check the sub stream.
|
||||||
|
packetsSubR := packageSubCounter.Load().(int64)
|
||||||
|
if communication.SubStreamConnected {
|
||||||
|
if packetsSubR == previousPacketSub {
|
||||||
|
// If we are already reconfiguring,
|
||||||
|
// we dont need to check if the stream is blocking.
|
||||||
|
if !communication.IsConfiguring.IsSet() {
|
||||||
|
occurenceSub = occurenceSub + 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
occurenceSub = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Log.Info("components.Kerberos.ControlAgent(): Number of packets read from substream: " + strconv.FormatInt(packetsSubR, 10))
|
||||||
|
|
||||||
|
// After 15 seconds without activity this is thrown..
|
||||||
|
if occurenceSub == 3 {
|
||||||
|
log.Log.Info("components.Kerberos.ControlAgent(): Restarting machinery because of blocking substream.")
|
||||||
|
communication.HandleBootstrap <- "restart"
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
occurenceSub = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
previousPacket = packageCounter.Load().(int64)
|
previousPacket = packageCounter.Load().(int64)
|
||||||
|
previousPacketSub = packageSubCounter.Load().(int64)
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
|
|||||||
@@ -406,6 +406,9 @@ func OverrideWithEnvironmentVariables(configuration *models.Configuration) {
|
|||||||
break
|
break
|
||||||
|
|
||||||
/* When connected and storing in Kerberos Hub (SAAS) */
|
/* When connected and storing in Kerberos Hub (SAAS) */
|
||||||
|
case "AGENT_HUB_ENCRYPTION":
|
||||||
|
configuration.Config.HubEncryption = value
|
||||||
|
break
|
||||||
case "AGENT_HUB_URI":
|
case "AGENT_HUB_URI":
|
||||||
configuration.Config.HubURI = value
|
configuration.Config.HubURI = value
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ type Communication struct {
|
|||||||
CancelContext *context.CancelFunc
|
CancelContext *context.CancelFunc
|
||||||
PackageCounter *atomic.Value
|
PackageCounter *atomic.Value
|
||||||
LastPacketTimer *atomic.Value
|
LastPacketTimer *atomic.Value
|
||||||
|
PackageCounterSub *atomic.Value
|
||||||
|
LastPacketTimerSub *atomic.Value
|
||||||
CloudTimestamp *atomic.Value
|
CloudTimestamp *atomic.Value
|
||||||
HandleBootstrap chan string
|
HandleBootstrap chan string
|
||||||
HandleStream chan string
|
HandleStream chan string
|
||||||
@@ -33,5 +35,7 @@ type Communication struct {
|
|||||||
SubQueue *packets.Queue
|
SubQueue *packets.Queue
|
||||||
Image string
|
Image string
|
||||||
CameraConnected bool
|
CameraConnected bool
|
||||||
|
MainStreamConnected bool
|
||||||
|
SubStreamConnected bool
|
||||||
HasBackChannel bool
|
HasBackChannel bool
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ type Config struct {
|
|||||||
TURNUsername string `json:"turn_username" bson:"turn_username"`
|
TURNUsername string `json:"turn_username" bson:"turn_username"`
|
||||||
TURNPassword string `json:"turn_password" bson:"turn_password"`
|
TURNPassword string `json:"turn_password" bson:"turn_password"`
|
||||||
HeartbeatURI string `json:"heartbeaturi" bson:"heartbeaturi"` /*obsolete*/
|
HeartbeatURI string `json:"heartbeaturi" bson:"heartbeaturi"` /*obsolete*/
|
||||||
|
HubEncryption string `json:"hub_encryption" bson:"hub_encryption"`
|
||||||
HubURI string `json:"hub_uri" bson:"hub_uri"`
|
HubURI string `json:"hub_uri" bson:"hub_uri"`
|
||||||
HubKey string `json:"hub_key" bson:"hub_key"`
|
HubKey string `json:"hub_key" bson:"hub_key"`
|
||||||
HubPrivateKey string `json:"hub_private_key" bson:"hub_private_key"`
|
HubPrivateKey string `json:"hub_private_key" bson:"hub_private_key"`
|
||||||
|
|||||||
@@ -312,12 +312,17 @@ func GetPositionFromDevice(configuration models.Configuration) (xsdonvif.PTZVect
|
|||||||
// Get the PTZ configurations from the device
|
// Get the PTZ configurations from the device
|
||||||
position, err := GetPosition(device, token)
|
position, err := GetPosition(device, token)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
if position.PanTilt != nil && position.Zoom != nil {
|
||||||
// float to string
|
// float to string
|
||||||
x := strconv.FormatFloat(position.PanTilt.X, 'f', 6, 64)
|
x := strconv.FormatFloat(position.PanTilt.X, 'f', 6, 64)
|
||||||
y := strconv.FormatFloat(position.PanTilt.Y, 'f', 6, 64)
|
y := strconv.FormatFloat(position.PanTilt.Y, 'f', 6, 64)
|
||||||
z := strconv.FormatFloat(position.Zoom.X, 'f', 6, 64)
|
z := strconv.FormatFloat(position.Zoom.X, 'f', 6, 64)
|
||||||
log.Log.Info("onvif.GetPositionFromDevice(): successfully got position (" + x + ", " + y + ", " + z + ")")
|
log.Log.Info("onvif.GetPositionFromDevice(): successfully got position (" + x + ", " + y + ", " + z + ")")
|
||||||
return position, err
|
return position, err
|
||||||
|
} else {
|
||||||
|
log.Log.Debug("onvif.GetPositionFromDevice(): position is nil")
|
||||||
|
return position, errors.New("position is nil")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Log.Debug("onvif.GetPositionFromDevice(): " + err.Error())
|
log.Log.Debug("onvif.GetPositionFromDevice(): " + err.Error())
|
||||||
return position, err
|
return position, err
|
||||||
@@ -893,7 +898,7 @@ func GetPTZFunctionsFromDevice(configurations ptz.GetConfigurationsResponse) ([]
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VerifyOnvifConnection godoc
|
// VerifyOnvifConnection godoc
|
||||||
// @Router /api/onvif/verify [post]
|
// @Router /api/camera/onvif/verify [post]
|
||||||
// @ID verify-onvif
|
// @ID verify-onvif
|
||||||
// @Security Bearer
|
// @Security Bearer
|
||||||
// @securityDefinitions.apikey Bearer
|
// @securityDefinitions.apikey Bearer
|
||||||
@@ -987,7 +992,7 @@ func CreatePullPointSubscription(dev *onvif.Device) (string, error) {
|
|||||||
stringBody := string(b2)
|
stringBody := string(b2)
|
||||||
decodedXML, et, err := getXMLNode(stringBody, "CreatePullPointSubscriptionResponse")
|
decodedXML, et, err := getXMLNode(stringBody, "CreatePullPointSubscriptionResponse")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log.Error("onvif.main.CreatePullPointSubscription(): " + err.Error())
|
log.Log.Debug("onvif.main.CreatePullPointSubscription(): " + err.Error())
|
||||||
} else {
|
} else {
|
||||||
if err := decodedXML.DecodeElement(&createPullPointSubscriptionResponse, et); err != nil {
|
if err := decodedXML.DecodeElement(&createPullPointSubscriptionResponse, et); err != nil {
|
||||||
log.Log.Error("onvif.main.CreatePullPointSubscription(): " + err.Error())
|
log.Log.Error("onvif.main.CreatePullPointSubscription(): " + err.Error())
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ import (
|
|||||||
|
|
||||||
func StartServer(configDirectory string, configuration *models.Configuration, communication *models.Communication, captureDevice *capture.Capture) {
|
func StartServer(configDirectory string, configuration *models.Configuration, communication *models.Communication, captureDevice *capture.Capture) {
|
||||||
|
|
||||||
|
// Set release mode
|
||||||
|
gin.SetMode(gin.ReleaseMode)
|
||||||
|
|
||||||
// Initialize REST API
|
// Initialize REST API
|
||||||
r := gin.Default()
|
r := gin.Default()
|
||||||
|
|
||||||
|
|||||||
@@ -54,11 +54,6 @@ func AddRoutes(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware, configDirect
|
|||||||
components.UpdateConfig(c, configDirectory, configuration, communication)
|
components.UpdateConfig(c, configDirectory, configuration, communication)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Will verify the current onvif settings.
|
|
||||||
api.POST("/onvif/verify", func(c *gin.Context) {
|
|
||||||
onvif.VerifyOnvifConnection(c)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Will verify the current hub settings.
|
// Will verify the current hub settings.
|
||||||
api.POST("/hub/verify", func(c *gin.Context) {
|
api.POST("/hub/verify", func(c *gin.Context) {
|
||||||
cloud.VerifyHub(c)
|
cloud.VerifyHub(c)
|
||||||
@@ -94,7 +89,8 @@ func AddRoutes(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware, configDirect
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Onvif specific methods. Doesn't require any authorization.
|
// Onvif specific methods. Doesn't require any authorization.
|
||||||
|
// Will verify the current onvif settings.
|
||||||
|
api.POST("/camera/onvif/verify", onvif.VerifyOnvifConnection)
|
||||||
api.POST("/camera/onvif/login", LoginToOnvif)
|
api.POST("/camera/onvif/login", LoginToOnvif)
|
||||||
api.POST("/camera/onvif/capabilities", GetOnvifCapabilities)
|
api.POST("/camera/onvif/capabilities", GetOnvifCapabilities)
|
||||||
api.POST("/camera/onvif/presets", GetOnvifPresets)
|
api.POST("/camera/onvif/presets", GetOnvifPresets)
|
||||||
|
|||||||
Vendored
-6
@@ -1,6 +0,0 @@
|
|||||||
#!/bin/sh -e
|
|
||||||
|
|
||||||
cp -R $SNAP/data $SNAP_COMMON/
|
|
||||||
cp -R $SNAP/www $SNAP_COMMON/
|
|
||||||
cp -R $SNAP/version $SNAP_COMMON/
|
|
||||||
cp -R $SNAP/mp4fragment $SNAP_COMMON/
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
name: kerberosio # you probably want to 'snapcraft register <name>'
|
|
||||||
base: core22 # the base snap is the execution environment for this snap
|
|
||||||
version: '3.1.0' # just for humans, typically '1.2+git' or '1.3.2'
|
|
||||||
summary: A stand-alone open source video surveillance system # 79 char long summary
|
|
||||||
description: |
|
|
||||||
Kerberos Agent is an isolated and scalable video (surveillance) management
|
|
||||||
agent made available as Open Source under the MIT License. This means that
|
|
||||||
all the source code is available for you or your company, and you can use,
|
|
||||||
transform and distribute the source code; as long you keep a reference of
|
|
||||||
the original license. Kerberos Agent can be used for commercial usage.
|
|
||||||
|
|
||||||
grade: stable # stable # must be 'stable' to release into candidate/stable channels
|
|
||||||
confinement: strict # use 'strict' once you have the right plugs and slots
|
|
||||||
environment:
|
|
||||||
GIN_MODE: release
|
|
||||||
apps:
|
|
||||||
agent:
|
|
||||||
command: main -config /var/snap/kerberosio/common
|
|
||||||
plugs: [ network, network-bind ]
|
|
||||||
parts:
|
|
||||||
agent:
|
|
||||||
source: https://github.com/kerberos-io/agent/releases/download/21c0e01/agent-amd64.tar
|
|
||||||
plugin: dump
|
|
||||||
+1
-1
@@ -100,7 +100,7 @@ class App extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div id="page-root">
|
<div id="page-root">
|
||||||
<Sidebar logo={logo} title="Kerberos Agent" version="v1-beta" mobile>
|
<Sidebar logo={logo} title="Kerberos Agent" version="v3.1.1" mobile>
|
||||||
<Profilebar
|
<Profilebar
|
||||||
username={username}
|
username={username}
|
||||||
email="support@kerberos.io"
|
email="support@kerberos.io"
|
||||||
|
|||||||
Reference in New Issue
Block a user