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 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
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.
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
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
-
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. -
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.
-
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.
-
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 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.
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 andoff
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
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 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 assistantcamera
: 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 RTSPled
: This adds a switch to chage the LED status light on/off to home assistantir
: This adds a selection switch to chage the IR light on/off/auto to home assistantmotion
: This adds a motion detection binary sensor to home assistantreboot
: This adds a reboot button to home assistantpt
: This adds a selection of buttons to control the pan and tilt of the camerabattery
: This adds a battery level sensor to home assistant
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
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 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
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.
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.