Skip to content

Commit

Permalink
feat: Update device service example for Levski (edgexfoundry#139)
Browse files Browse the repository at this point in the history
* feat: Update device service example for Levski

Signed-off-by: Leonard Goodell <[email protected]>

build: Update HELM Chart to Levski released images (edgexfoundry#140)

Signed-off-by: Leonard Goodell <[email protected]>

Signed-off-by: Leonard Goodell <[email protected]>

feat: added support for shared and non-shared volumes
Close edgexfoundry#92
Signed-off-by: Kyle Morton <[email protected]>

fix: EdgeX UI in kubernetes was not binding container network IF

Signed-off-by: Bryon Nevis <[email protected]>

feat: Added support for onvif and usb camera Closes edgexfoundry#107

Signed-off-by: Kyle Morton <[email protected]>

feat: Added support for modbus-simulator

Signed-off-by: Kyle Morton <[email protected]>

feat: Add support in helm for ds-mqtt and mqtt-broker

Signed-off-by: Kyle Morton <[email protected]>

feat: Add support in helm for ds-modbus

Signed-off-by: Kyle Morton <[email protected]>

feat: Add support in helm for ds-bacnet

Signed-off-by: Kyle Morton <[email protected]>

feat: Add support in helm for ds-snmp

Signed-off-by: Kyle Morton <[email protected]>

feat: Add support in helm for ds-rfid-llrp

Signed-off-by: Kyle Morton <[email protected]>

feat: Add support in helm for ds-gpio

Signed-off-by: Kyle Morton <[email protected]>

feat: Add support in helm for asc-mqtt and asc-httpexport

Signed-off-by: Kyle Morton <[email protected]>

feat: Add support in helm for asc-sample, asc-metrics, and as-llrp

Signed-off-by: Kyle Morton <[email protected]>

fix: Updated device-onvif-camera and device-usb-camera directory and volume (edgexfoundry#156)

Signed-off-by: Kyle Morton <[email protected]>

Signed-off-by: Kyle Morton <[email protected]>
Co-authored-by: Kyle Morton <[email protected]>

fix: added service for edgex-ui (edgexfoundry#162)

Signed-off-by: Kyle Morton <[email protected]>

Signed-off-by: Kyle Morton <[email protected]>
Co-authored-by: Kyle Morton <[email protected]>

feat: Added support for nats (edgexfoundry#163)

Signed-off-by: Kyle Morton <[email protected]>

Signed-off-by: Kyle Morton <[email protected]>
Co-authored-by: Kyle Morton <[email protected]>

fix: Updated  health checks to appropriate protocol (edgexfoundry#164)

Signed-off-by: Kyle Morton <[email protected]>

Signed-off-by: Kyle Morton <[email protected]>
Co-authored-by: Kyle Morton <[email protected]>

fix: added kuiper-connections and kuipers-sources volumes (edgexfoundry#165)

Signed-off-by: Kyle Morton <[email protected]>

Signed-off-by: Kyle Morton <[email protected]>
Co-authored-by: Kyle Morton <[email protected]>

fix: Correct addConsulRoles list (edgexfoundry#166)

Signed-off-by: Kyle Morton <[email protected]>

Signed-off-by: Kyle Morton <[email protected]>
Co-authored-by: Kyle Morton <[email protected]>

feat: Support optional hostPort binding (edgexfoundry#167)

Signed-off-by: Kyle Morton <[email protected]>

Signed-off-by: Kyle Morton <[email protected]>
Co-authored-by: Kyle Morton <[email protected]>

feat: Expose services on a per-service basis (edgexfoundry#169)

Signed-off-by: Kyle Morton <[email protected]>

Signed-off-by: Kyle Morton <[email protected]>
Co-authored-by: Kyle Morton <[email protected]>

fix: Added container port names (edgexfoundry#170)

Signed-off-by: Kyle Morton <[email protected]>

Signed-off-by: Kyle Morton <[email protected]>
Co-authored-by: Kyle Morton <[email protected]>

feat!: Remove system-mgmt-agent (deprecated) (edgexfoundry#175)

BREAKING CHANGE: Remove system-mgmt-agent (deprectated)

Signed-off-by: Bryon Nevis <[email protected]>

Signed-off-by: Bryon Nevis <[email protected]>

docs: add link to camera app example video

Signed-off-by: Anthony Casagrande <[email protected]>

feat: Add Helm security scanners (edgexfoundry#174)

Signed-off-by: Bryon Nevis <[email protected]>

Signed-off-by: Bryon Nevis <[email protected]>

fix: remove duplicated path from query uri (edgexfoundry#182)

Signed-off-by: Anthony Casagrande <[email protected]>

fix: Modify pan tilt function by getting pan/tilt range dynamically (edgexfoundry#181)

* fix: Get pan/tilt values dynamically

Signed-off-by: preethi-satishcandra <[email protected]>

feat: support for usb cameras and onvif zoom functionality in camera mgmt app (edgexfoundry#184)

Signed-off-by: Anthony Casagrande <[email protected]>
Signed-off-by: Christian Darr <[email protected]>
Signed-off-by: Brian Osburn <[email protected]>
Co-authored-by: Brian Osburn <[email protected]>
Co-authored-by: Christian Darr <[email protected]>

feat: updated app service with target type

Signed-off-by: brianointel <[email protected]>

feat: added code for pipeline function

Signed-off-by: brianointel <[email protected]>

feat: template code for funtion pipelines by topic

Signed-off-by: brianointel <[email protected]>

feat: added initial event handler

Signed-off-by: brianointel <[email protected]>

feat: more device messagebus progress

Signed-off-by: brianointel <[email protected]>

feat: message bus code

Signed-off-by: Brian Osburn <[email protected]>

feat: messagebus progress

Signed-off-by: Brian Osburn <[email protected]>

feat: created defaultpipelinefunction

Signed-off-by: Brian Osburn <[email protected]>

feat: try to start pipelines on startup

Signed-off-by: brianointel <[email protected]>

feat: small changes

Signed-off-by: Brian Osburn <[email protected]>

feat: pr updates

Signed-off-by: Brian Osburn <[email protected]>

feat: added config params

Signed-off-by: Brian Osburn <[email protected]>

feat: pr updates

Signed-off-by: Brian Osburn <[email protected]>

feat: pr updates

Signed-off-by: Brian Osburn <[email protected]>

feat: pr updates

Signed-off-by: Brian Osburn <[email protected]>

feat: handle device delete event to stop pipeline

Signed-off-by: brianointel <[email protected]>

also some minor refactoring

Signed-off-by: Anthony Casagrande <[email protected]>

fix: pr updates

Signed-off-by: Brian Osburn <[email protected]>

refactor: fix imports from merge

Signed-off-by: Anthony Casagrande <[email protected]>

feat: pr updates

Signed-off-by: Brian Osburn <[email protected]>

fix: updated funtion name

Signed-off-by: Brian Osburn <[email protected]>

feat: Add Helm security scanners (edgexfoundry#174)

Signed-off-by: Bryon Nevis <[email protected]>

Signed-off-by: Bryon Nevis <[email protected]>

fix: remove duplicated path from query uri (edgexfoundry#182)

Signed-off-by: Anthony Casagrande <[email protected]>

fix: Modify pan tilt function by getting pan/tilt range dynamically (edgexfoundry#181)

* fix: Get pan/tilt values dynamically

Signed-off-by: preethi-satishcandra <[email protected]>

feat: support for usb cameras and onvif zoom functionality in camera mgmt app (edgexfoundry#184)

Signed-off-by: Anthony Casagrande <[email protected]>
Signed-off-by: Christian Darr <[email protected]>
Signed-off-by: Brian Osburn <[email protected]>
Co-authored-by: Brian Osburn <[email protected]>
Co-authored-by: Christian Darr <[email protected]>

feat: updated app service with target type

Signed-off-by: brianointel <[email protected]>

feat: added code for pipeline function

Signed-off-by: brianointel <[email protected]>

feat: template code for funtion pipelines by topic

Signed-off-by: brianointel <[email protected]>

feat: added initial event handler

Signed-off-by: brianointel <[email protected]>

feat: more device messagebus progress

Signed-off-by: brianointel <[email protected]>

feat: message bus code

Signed-off-by: Brian Osburn <[email protected]>

feat: messagebus progress

Signed-off-by: Brian Osburn <[email protected]>

feat: created defaultpipelinefunction

Signed-off-by: Brian Osburn <[email protected]>

feat: try to start pipelines on startup

Signed-off-by: Brian Osburn <[email protected]>

feat: small changes

Signed-off-by: Brian Osburn <[email protected]>

feat: pr updates

Signed-off-by: Brian Osburn <[email protected]>

feat: added config params

Signed-off-by: Brian Osburn <[email protected]>

feat: pr updates

Signed-off-by: Brian Osburn <[email protected]>

feat: pr updates

Signed-off-by: Brian Osburn <[email protected]>

feat: pr updates

Signed-off-by: Brian Osburn <[email protected]>

feat: handle device delete event to stop pipeline

also some minor refactoring

Signed-off-by: Anthony Casagrande <[email protected]>

fix: pr updates

Signed-off-by: Brian Osburn <[email protected]>

refactor: fix imports from merge

Signed-off-by: Anthony Casagrande <[email protected]>

feat: pr updates

Signed-off-by: Brian Osburn <[email protected]>

fix: updated funtion name

Signed-off-by: Brian Osburn <[email protected]>

fix: corrected error message placement

Signed-off-by: brianointel <[email protected]>
  • Loading branch information
Lenny Goodell authored and Brian Osburn committed Apr 27, 2023
1 parent 08c0a1c commit 660873e
Show file tree
Hide file tree
Showing 108 changed files with 4,638 additions and 676 deletions.
4 changes: 2 additions & 2 deletions application-services/custom/camera-management/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#

#build stage
ARG BASE=golang:1.17-alpine3.15
ARG BASE=golang:1.18-alpine3.16
FROM ${BASE} AS builder

ARG ALPINE_PKG_BASE="make git gcc libc-dev libsodium-dev zeromq-dev"
Expand All @@ -37,7 +37,7 @@ ARG MAKE="make build-app"
RUN $MAKE

#final stage
FROM alpine:3.15
FROM alpine:3.16
LABEL license='SPDX-License-Identifier: Apache-2.0' \
copyright='Copyright (c) 2022: Intel'
LABEL Name=app-camera-management Version=${VERSION}
Expand Down
213 changes: 179 additions & 34 deletions application-services/custom/camera-management/README.md
Original file line number Diff line number Diff line change
@@ -1,73 +1,218 @@
# Camera Management Example App Service
Camera management example Edgex application service to auto discover and connect to nearby ONVIF based cameras,
control cameras via commands, create inference pipelines for the camera video streams and publish inference
results to MQTT broker.
Use the Camera Management Example application service to auto discover and connect to nearby ONVIF and USB based cameras. This application will also control cameras via commands, create inference pipelines for the camera video streams and publish inference results to MQTT broker.

This app uses [EdgeX Core Services][edgex-core-services], [Edgex Onvif device service][device-onvif-camera] and [Edge Video Analytics Microservice][evam].
This app uses [EdgeX compose][edgex-compose], [Edgex Onvif Camera device service][device-onvif-camera], [Edgex USB Camera device service][device-usb-camera] and [Edge Video Analytics Microservice][evam].

A brief video demonstration of building and using the example app service can be found [here](https://www.youtube.com/watch?v=vZqd3j2Zn2Y).

## Install Dependencies

### Environment
This example has been tested with a relatively modern Linux environment - Ubuntu 20.04 and later

### Install Docker
Install Docker from the official repository as documented on the [Docker](https://docs.docker.com/engine/install/ubuntu/) site.

### Configure Docker
To enable running Docker commands without the preface of sudo, add the user to the Docker group.

> **Warning**
> The docker group grants root-level privileges to the user. For details on how this impacts security in your system,
> see [Docker Daemon Attack Surface](https://docs.docker.com/engine/security/#docker-daemon-attack-surface).
1. Create Docker group:
```bash
sudo groupadd docker
```
> **Note:** If the group already exists, `groupadd` outputs a message: **groupadd: group `docker` already exists**. This is OK.
2. Add User to group:
```bash
sudo usermod -aG docker $USER
```

3. Restart your computer for the changes to take effect.

### Verify Docker
To verify the Docker installation, run `hello-world`:

```bash
docker run hello-world
```
A **Hello from Docker!** greeting indicates successful installation.

```bash
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:10d7d58d5ebd2a652f4d93fdd86da8f265f5318c6a73cc5b6a9798ff6d2b2e67
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.
...
```

### Install Docker Compose
Install Docker Compose from the official repository as documented on the [Docker Compose](https://docs.docker.com/compose/install/linux/#install-using-the-repository) site.

### Install Golang
Install Golang from the official [Golang](https://go.dev/doc/install) website.

### Install Tools
Install build tools:

```bash
sudo apt install build-essential
```

## Steps for running this example:
We expect you'll be running in a relatively modern Linux environment
with `docker`, `docker-compose`, and `make` installed.

1. Get the [EdgeX Core Services][edgex-core-services] and Edgex device ONVIF service running by referring to docs from
[Edgex Onvif device service][device-onvif-camera].
2. Get [Edge Video Analytics Microservice][evam] running for inference.
### 1. Start the EdgeX Core Services and Device Services.

1. Clone `edgex-compose` from github.com.
```shell
git clone https://github.com/edgexfoundry/edgex-compose.git
```

2. Navigate to the `edgex-compose` directory:

```bash
cd edgex-compose
```

3. Checkout the latest compatible release branch
> **Note:** The `levski` branch is the latest stable branch at the time of this writing.
```shell
git checkout levski
```

4. Navigate to the `compose-builder` subdirectory:

```bash
cd compose-builder/
```

5. (Optional) Update the `add-device-usb-camera.yml` file:
> **Note:** This step is only required if you plan on using USB cameras.
a. Add the rtsp server hostname environment variable to the `device-usb-camera` service,
where `your-local-ip-address` is the ip address of the machine running the `device-usb-camera` service.
```yml
services:
device-usb-camera:
environment:
DRIVER_RTSPSERVERHOSTNAME: "your-local-ip-address"
```
b. Under the `ports` section, find the entry for port 8554 and change the host_ip from `127.0.0.1` to either `0.0.0.0` or the ip address you put in the previous step.

6. Run the following `make` command to run the edgex core services along with the Onvif and Usb device services.

> **Note:** The `ds-onvif-camera` parameter can be omitted if no Onvif cameras are present, or the `ds-usb-camera` parameter can be omitted if no usb cameras are present.
```shell
make run no-secty ds-onvif-camera ds-usb-camera
```


### 2. Start [Edge Video Analytics Microservice][evam] running for inference.

> **Note:** The port for EVAM result streams has been changed from 8554 to 8555 to avoid conflicts with the device-usb-camera service.

```shell
# Go back to the root of this example app
cd edgex-examples/application-services/custom/camera-management
# Run this once to download edge-video-analytics into the edge-video-analytics sub-folder,
# download models, and patch pipelines
make install-edge-video-analytics
# Run the EVAM services (in another terminal)
make run-edge-video-analytics
# ...
# Leave this running. If needed to stop
make stop-edge-video-analytics
# Leave this running
```
3. Configure Camera Credentials

Option 1: Modify the `configuration.toml` file
> **Note:** If you press `Ctrl-C` it will stop the EVAM services. If you then run `make stop-edge-video-analytics`,
> it will also remove the containers and free up the port mappings.

### 3. Build and run the example application service

#### 3.1 (Optional) Configure Onvif Camera Credentials.
> **Note:** This step is only required if you have Onvif cameras. Currently, this example app is limited to supporting
> only 1 username/password combination for all Onvif cameras.

Option 1: Modify the [res/configuration.toml](res/configuration.toml) file

```toml
[Writable.InsecureSecrets.CameraCredentials]
path = "CameraCredentials"
[Writable.InsecureSecrets.CameraCredentials.Secrets]
username = ""
password = ""
username = "<username>"
password = "<password>"
```

Option 2: Export environment variable overrides
```shell
export WRITABLE_INSECURESECRETS_CAMERACREDENTIALS_SECRETS_USERNAME=<username>
export WRITABLE_INSECURESECRETS_CAMERACREDENTIALS_SECRETS_PASSWORD=<passowrd>
export WRITABLE_INSECURESECRETS_CAMERACREDENTIALS_SECRETS_USERNAME="<username>"
export WRITABLE_INSECURESECRETS_CAMERACREDENTIALS_SECRETS_PASSWORD="<password>"
```

#### 3.2 Configure Default Pipeline

Modify the [res/configuration.toml](res/configuration.toml) file with the name and version of the default pipeline to use when a new device is added to the system.

```toml
[AppCustom]
DefaultPipelineName = "object_detection" # Name of the default pipeline used when a new device is added to the system
DefaultPipelineVersion = "person" # Version of the default pipeline used when a new device is added to the system
```

4. Build and run the example application service. Web UI is used to view cameras, select models
and start inference pipelines for camera video streams and also view inference results streams.
#### 3.3 Build and run
```shell
# First make sure you are at the root of this example app
cd edgex-examples/application-services/custom/camera-management
```

```shell
# Build the app.
make build-app
# Run the app.
make run-app
# ...
# Open your browser to http://localhost:59750
# ...
# Ctrl-C to stop it
```

### Development and Testing of UI
Open your browser to [http://localhost:59750](http://localhost:59750) to view the Web-UI.
The Web UI can be used to:
- List USB and Onvif cameras
- Control PTZ cameras
- Select inference models and start inference pipelines
- View inference results from MQTT

### Additional Development

> **Note:** The following steps are only useful for developers who wish to make modifications to the code
> and the Web-UI.

#### Development and Testing of UI
##### 1. Build the production web-ui
This builds the web ui into the `web-ui/dist` folder, which is what is served by the app service on port 59750.
```shell
# Build the production web-ui into the web-ui/dist folder
# This is what is served by the app service on port 59750
make web-ui
```

# Serve the Web-UI in hot-reload mode on port 4200
##### 2. Serve the Web-UI in hot-reload mode
This will serve the web ui in hot reload mode on port 4200 which will recompile and update anytime you make changes to a file. It is useful for
rapidly testing changes to the UI.
```shell
make serve-ui
# ...
# Open your browser to http://localhost:4200
# ...
# Ctrl-C to stop it
```

[edgex-core-services]: https://github.com/edgexfoundry/edgex-go
[device-onvif-camera]: https://github.com/edgexfoundry-holding/device-onvif-camera
Open your browser to [http://localhost:4200](http://localhost:4200)



[edgex-compose]: https://github.com/edgexfoundry/edgex-compose
[device-onvif-camera]: https://github.com/edgexfoundry/device-onvif-camera
[device-usb-camera]: https://github.com/edgexfoundry/device-usb-camera
[evam]: https://www.intel.com/content/www/us/en/developer/articles/technical/video-analytics-service.html
35 changes: 31 additions & 4 deletions application-services/custom/camera-management/appcamera/app.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
//
// Copyright (C) 2022 Intel Corporation
// Copyright (C) 2022-2023 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0

package appcamera

import (
"net/http"
"sync"

"github.com/edgexfoundry/app-functions-sdk-go/v2/pkg/interfaces"
"github.com/edgexfoundry/go-mod-core-contracts/v2/clients/logger"
"github.com/pkg/errors"
"net/http"
"sync"
)

type CameraManagementApp struct {
Expand All @@ -19,6 +20,8 @@ type CameraManagementApp struct {
config *ServiceConfig
pipelinesMap map[string]PipelineInfo
pipelinesMutex sync.RWMutex
ptzRangeMap map[string]PTZRange
ptzRangeMutex sync.RWMutex
fileServer http.Handler
}

Expand All @@ -28,6 +31,7 @@ func NewCameraManagementApp(service interfaces.ApplicationService) *CameraManage
lc: service.LoggingClient(),
config: &ServiceConfig{},
pipelinesMap: make(map[string]PipelineInfo),
ptzRangeMap: make(map[string]PTZRange),
}
}

Expand All @@ -40,7 +44,30 @@ func (app *CameraManagementApp) Run() error {
return err
}

if err := app.service.MakeItRun(); err != nil {
// Subscribe to events.
err := app.service.SetDefaultFunctionsPipeline(
app.processEdgeXDeviceSystemEvent)
if err != nil {
return errors.Wrap(err, "failed to set default pipeline to processEdgeXEvent")
}

if err = app.queryAllPipelineStatuses(); err != nil {
// do not exit, just log
app.lc.Errorf("Unable to query EVAM pipeline statuses. Is EVAM running? %s", err.Error())
}

devices, err := app.getAllDevices()
if err != nil {
app.lc.Errorf("no devices found: %s", err.Error())
} else {
for _, device := range devices {
if err = app.startDefaultPipeline(device); err != nil {
app.lc.Errorf("Error starting default pipeline for %s, %v", device.Name, err)
}
}
}

if err = app.service.MakeItRun(); err != nil {
return errors.Wrap(err, "failed to run pipeline")
}

Expand Down
Loading

0 comments on commit 660873e

Please sign in to comment.