Skip to content

dm-imdy/frigate-onvif2cgi-proxy

Repository files navigation

Frigate ONVIF to CGI Proxy (fo2cp)

Frigate supports controlling the PTZ (Pan, Tilt, Zoom) of a configured camera using onvif protocol. The purpose of this proxy is to enable Frigate to control PTZ of a non-onvif camera that only supports CGI.

Motivation

After installing Frigate at home, I've realized that Frigate can stream my old Foscam FI9821P camera but can't control it's PTZ (FI9821P has a limited onvif support). The solution was to create fo2cp (this proxy) to listen to Frigate onvif requests and "translate" those requests to CGI Commands before forwarding them to the camera. Currently fo2cp supports one camera per instance and is made specifically for FI9821P (although it should work for any CGI supported Foscam camera).

Getting Started

To get a local copy up and running follow these simple steps.

Prerequisites

The following are to be installed globally.

  • tsconfig-paths, typescript, tsx
    npm install tsconfig-paths typescript tsx -g
    

Installation

  • Create a new directory in your system where fo2cp will be installed. For this guide we will assume you created the directory ~/fo2cp/.
  • Download the latest release and extract the files to the newly created directory ~/fo2cp/.
  • Change directory into the installation directory where the package.json file is
    cd ~/fo2cp
    
  • Install npm packages
    npm install
    
  • Run the typescript compiler
    npx tsc
    
  • Start the proxy server
    node ./dist/server.mjs
    

Configuration

fo2cp configuration

There are two ways to use fo2cp configuration file:

  • Editing the default config file at the root installation directory (e.g. ~/fo2cp/appConfig.json5)
  • Creating a new config file and pass it as argument when starting fo2cp
    node ./dist/server.mjs --config='/home/user/myAppConfig.json5'
    

Important

The fo2cp config file format is JSON5

Here is the default config file:

  {
      //ip: "0.0.0.0",
      port: 3000,
      camera: {
          ip: "192.168.1.100",
          cgiPort: 88,
          //cgiUrl: "http://192.168.1.100:88", // [Optional] The cgi url of the camera
          isCameraHaveZoom: false, // Set to true if your camera have Zoom capability
          cgiPath: "/cgi-bin/CGIProxy.fcgi",
          cgiProtocol: "foscam",
          user: "operator",
          password: "12345678"
      }
  }
  • ip: [optional] This is the ip of the host on which fo2cp is running. Normally you don't need to specify this property. The first detected ipv4 ip address on the host will be used.
  • port: The port on which fo2cp will be listening for incoming requests from Frigate.
  • camera: The specific camera config.
    • ip: The ip of the camera.
    • cgiPort: The HTTP port configured in the camera's setup.
    • cgiUrl: [optional] The base url of the camera for cgi requests. Normally you don't specify this property. It will be calculated as http://<ip>:<cgiPort>.
    • cgiPath: The url path as configured in the camera's setup.
    • cgiProtocol: The name of the protocol module located in src/protocols directory (see details).
    • user: A user that is configured in the camera's setup. Make sure to use a user that is privileged to execute PTZ commands.
    • password: The password that is configured in the camera's setup for the specific user.

Frigate configuration

In the onvif configuration section, we need to define the fo2cp proxy instead of the actual camera.
The Frigate config is <path-to-frigate-dir>/config/config.yaml (e.g. ~/frigate/config/config.yaml)

cameras:
  MYFI9821P: # <------ Name the camera
    enabled: true
    ffmpeg:
      ...
    detect:
      ...
    onvif:
      host: 192.168.1.25
      port: 3000
      user: 'AAAAAA'
      password: 'BBBBBBB'

onvif section properties:

  • host: The ip of the host on which the fo2cp proxy server is running.
  • port: The port on which the fo2cp proxy server is listening.
  • user/password - Must not be blanks, but values will be ignored. fo2cp will use its own configured user/password when communicating with the camera.

Protocols (for developers)

CGI Protocols are typescript mudules (*.mts) located in src/protocols directory. Currently, two CGI protocols are implemented: foscam (src/protocols/foscam.mts) and reolink (src/protocols/reolink.mts).

Implementing a new CGI Protocol

If you have a non-onvif camera that is not supported by the existing protocols, you can implement a new protocol. Following are the steps for creating a new protocol:

  1. Think of a name for the protocol (for now, let's assume the name is myproto).
  2. Create a new empty file src/protocols/myproto.mts.
  3. A protocol is an implementation of the base abstract class CGIProtocolAbstract. We first need to import that class and the error class:
    import {CGIProtocolAbstract, ONVIFError} from '../CGIProtocolAbstract.mjs';
    
  4. Now we need to create our class and export it as default. So your file should look like:
    import {CGIProtocolAbstract, ONVIFError} from '../CGIProtocolAbstract.mjs';
    
    export default class myproto extends CGIProtocolAbstract
    {
    
    }
    
  5. Now implement the abstract methods per your camera CGI specifications
  6. For error handling in your protocol, use ONVIFError to throw an error. E.g.
    throw new ONVIFError('Oops, something went wrong!');
    

Tip

Any error text thrown by the protocol using ONVIFError, will be reflected in Frigate system log.

Unit-testing the new CGI Protocol

To test/debug the new protocol class, use your browser to navigate to http://<fo2cp-ip>:<fo2cp-port>/testproto?help. The page will show a list of the abstract methods enabling you to trigger those methods from that page itself.

Disclaimer

I'm new to typescript! I actually used this project to learn and practice typescript.
You shouldn't use the code of this project as "the proper" typescript coding :)

About

Enable Frigate to control Pan/Tilt/Zoom (PTZ) of non-onvif cameras

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published