Skip to content

sqeeswy/neolink

 
 

Repository files navigation

Neolink

CI dependency status Buy Me a Coffee at ko-fi.com

Neolink is a small program that acts as a proxy between Reolink IP cameras and normal RTSP clients. Certain cameras, such as the Reolink B800, do not implement ONVIF or RTSP, but instead use a proprietary "Baichuan" protocol only compatible with their apps and NVRs (any camera that uses "port 9000" will likely be using this protocol). Neolink allows you to use NVR software such as Shinobi or Blue Iris to receive video from these cameras instead. The Reolink NVR is not required, and the cameras are unmodified. Your NVR software connects to Neolink, which forwards the video stream from the camera.

The Neolink project is not affiliated with Reolink in any way; everything it does has been reverse engineered.

This Fork

This fork is an extension of thirtythreeforty's with additional features not yet in upstream master.

Major Features:

  • MQTT
  • Motion Detection
  • Paused Streams (when no rtsp client or no motion detected)
  • Save a still image to disk

Minor Features:

  • Improved error messages when your missing gstreamer plugins
  • Protocol more closely follows offical reolink format
    • Possibly can handle more simulatenous connections
  • More ways to connect to the camera. Including Relaying through reolink servers
  • Camera battery levels can be displayed in the log

Installation

Download from the release page

Extract the zip

Install the latest gstreamer (1.20.5 as of writing this).

  • Windows: ensure you install full when prompted in the MSI options.
  • Mac: Install the dpkg version on the offical gstreamer website over the brew version
  • Ubuntu/Debian: These packages should work
sudo apt install \
  libgstrtspserver-1.0-0 \
  libgstreamer1.0-0 \
  libgstreamer-plugins-bad1.0-0 \
  gstreamer1.0-x \
  gstreamer1.0-plugins-base \
  gstreamer1.0-plugins-good \
  gstreamer1.0-plugins-bad

Make a config file see below.

Config/Usage

RTSP

To use neolink you need a config file.

There's a more complete example here, but the following should work as a minimal example.

bind = "0.0.0.0"

[[cameras]]
name = "Camera01"
username = "admin"
password = "password"
uid = "ABCDEF0123456789"

[[cameras]]
name = "Camera02"
username = "admin"
password = "password"
uid = "BCDEF0123456789A"
address = "192.168.1.10"

Create a text file with called neolink.toml in the same folder as the neolink binary. With your config options.

When ready start neolink with the following command using the terminal in the same folder the neolink binary is in.

./neolink rtsp --config=neolink.toml

Discovery

To connect to a camera using a UID we need to find the IP address of the camera with that UID

The IP is discovered with four methods

  1. Local discovery: Here we send a broadcast on all visible networks asking the local network if there is a camera with this UID. This only works if the network supports broadcasts

    If you know the ip address you can put it into the address field of the config and attempt a direct connection without broadcasts. This requires a route from neolink to the camera.

  2. Remote discovery: Here a ask the reolink servers what the IP address is. This requires that we contact reolink and provide some basic information like the UID. Once we have this information we connect directly to the local IP address. This requires a route from neolink to the camera and for the camera to be able to contact the reolink IPs.

  3. Map discovery: In this case we register our IP address with reolink and ask the camera to connect to us. Once the camera either polls/recives a connect request from the reolink servers the camera will then initiate a connect to neolink. This requires that our IP and the reolink IPs are reacable from the camera.

  4. Relay: In this case we request that reolink relay our connection. Neolink nor the camera need to be able to direcly contact each other. But both neolink and the camera need to be able to contact reolink.

This can be controlled with the config

discovery = "local"

In the [[cameras]] section of the toml.

Possible values are local, remote, map, relay later values implictly enable prior methods.

Cellular

Cellular cameras should select "cellular" which only enables map and relay since local and remote will always fail

discovery = "cellular"

See the sample config file for more details.

MQTT

To use mqtt you will to adjust your config file as such:

bind = "0.0.0.0"

[[cameras]]
name = "Camera01"
username = "admin"
password = "password"
uid = "ABCDEF0123456789"
  [cameras.mqtt]
  server = "127.0.0.1" # Address of the mqtt server
  port = 1883 # mqtt servers port
  credentials = ["username", "password"] # mqtt server login details

Then to start the mqtt connection run the following:

./neolink mqtt --config=neolink.toml

Neolink will publish these messages:

Messages are prefixed with neolink/{CAMERANAME}

Control messages:

  • /control/led [on|off] Turns status LED on/off
  • /control/ir [on|off|auto] Turn IR lights on/off or automatically via light detection
  • /control/reboot Reboot the camera
  • /control/ptz [up|down|left|right|in|out] (amount) Control the PTZ movements, amount defaults to 32.0
  • /control/ptz/preset [id] Move the camera to a PTZ preset
  • /control/ptz/assign [id] [name] Set the current PTZ position to a preset ID and name
  • /control/pir [on|off]

Status Messages:

  • /status offline Sent when the neolink goes offline this is a LastWill message
  • /status disconnected Sent when the camera goes offline
  • /status/battery Sent in reply to a /query/battery an XML encoded version of the battery status
  • /status/battery_level A simple % value of current battery level
  • /status/pir Sent in reply to a /query/pir an XML encoded version of the pir status
  • /status/motion Contains the motion detection alarm status. on for motion and off for still
  • /status/ptz/preset Sent in reply to a /query/ptz/preset an XML encoded version of the PTZ presets
  • /status/preview a base64 encoded camera image updated every 0.5s

Query Messages:

  • /query/battery Request that the camera reports its battery level
  • /query/pir Request that the camera reports its pir status
  • /query/ptz/preset Request that the camera reports its PTZ presets

MQTT Disable Features

Certain features like preview and motion detection may not be desired you can disable them by them with the following config options. Disabling these may help to conserve battery

enable_motion = false  # motion detection
                       # (limited battery drain since it
                       # is a passive listening connection)

enable_pings = false   # keep alive pings that keep the camera connected

enable_light = false   # flood lights only avaliable on some camera
                       # (limited battery drain since it
                       # is a passive listening connection)

enable_battery = false # battery updates in `/status/battery_level`

enable_preview = false # preview image in `/status/preview`

MQTT Discovery

MQTT Discovery is partially supported. Currently, discovery is opt-in and camera features must be manually specified.

[cameras.mqtt]
  # <see above>
  [cameras.mqtt.discovery]
  topic = "homeassistant"
  features = ["floodlight"]

Avaliable features are:

  • floodlight: This adds a light control to home assistant
  • camera: This adds a camera preview to home assistant. It is only updated every 0.5s and cannot be much more than that since it is updated over mqtt not over RTSP
  • led: This adds a switch to chage the LED status light on/off to home assistant
  • ir: This adds a selection switch to chage the IR light on/off/auto to home assistant
  • motion: This adds a motion detection binary sensor to home assistant
  • reboot: This adds a reboot button to home assistant
  • pt: This adds a selection of buttons to control the pan and tilt of the camera
  • battery: This adds a battery level sensor to home assistant

Pause

To use the pause feature you will need to adjust your config file as such:

bind = "0.0.0.0"

[[cameras]]
name = "Camera01"
username = "admin"
password = "password"
uid = "ABCDEF0123456789"
  [cameras.pause]
  on_motion = true # Should pause when no motion
  on_client = true # Should pause when no rtsp client
  timeout = 2.1 # How long to wait after motion stops before pausing

Then start the rtsp server as usual:

./neolink rtsp --config=neolink.toml

Battery Levels

If you have a battery camera and would like to see the battery messages in th log add the following to your config

[[cameras]]
# Usual camera options like uid etc
print_format = "Human"

You can also print into xml format with print_format = "Xml" which can then b passed by a script for processing.

Docker

Docker builds are also provided in multiple architectures. The latest tag tracks master while each branch gets it's own tag.

docker pull quantumentangledandy/neolink

# Add `-e "RUST_LOG=debug"` to run with debug logs
#
# --network host is only needed if you require to connect
# via local broadcasts. If you can connect via any other
# method then normal bridge mode should work fine
# and you can ommit this option
docker run --network host --volume=$PWD/config.toml:/etc/neolink.toml quantumentangledandy/neolink

Image

You can write an image from the stream to disk using:

neolink image --config=config.toml --file-path=filepath CameraName

Where filepath is the path to save the image to and CameraName is the name of the camera from the config to save the image from.

File is always jpeg and the extension given in filepath will be added or changed to reflect this.

Some cameras do not support the SNAP command that is used to generate the image on the camera. If this is the case with your camera you can try the --use-stream option which will instead create a jpeg by transcoding the video stream.

License

Neolink is free software, released under the GNU Affero General Public License v3.

This means that if you incorporate it into a piece of software available over the network, you must offer that software's source code to your users.

About

An RTSP bridge to Reolink IP cameras

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Rust 95.5%
  • Lua 4.2%
  • Other 0.3%