Synology Surveillance Station IP Camera

How can i detect motion on synology camera?

Regards

The synology itself does the motion detection. You can set the recording mode to always on, or record on motion. I don’t know that you can get the motion events via HA, I haven’t looked into it.

Thanks. I have enabled this under synology but I want to react on move with example light on so I need that HA can trigger this “on move” event but I have always “idle” state.
Regards
Artur

Hi!

I’m not sure whether there is a “native” way of doing this, or not. Anyway, you can easily setup an “interface” between your Synology Surveillance Station and HA. The original idea came from Styxit blog.

The logic is the following: create an Action Rule in Surveillance Station, using External Device as an action device. Since SS only lets you call URL-s instead of executing curl or bash commands, you have to create a PHP interface which translates the commands sent from SS to HA.

So, here’s a simple step-by-step tutorial:

  1. You have to enable Web Station on your DSM (I’m running DSM 6.0.2)
  2. Enable “Personal Website” with PHP 5.6 under “General Settings” in Web Station
  3. make sure you checked the “CURL” extension for PHP under “PHP Settings” in Web Station

If you did all these correctly, you should be able to browse your “web” shared folder on your NAS.

Now, create the interface.
Create a new PHP file with the following contents and name it whatever you want:

<?php
/************************************/
/********** CONFING START ***********/

// Only allow request made by localhost?
// Set this to false if this script is not running on your synology webserver (less secure)
$localOnly = true;

/********** CONFING END *************/
/************************************/
echo time();
// Validate httpHost and/or remote addr?
if ($localOnly) {
  if ($_SERVER['HTTP_HOST'] != 'localhost') {
    // Not locahost
    die;
  }
}

// Set variables
$options = array(
  'state' => isset($_GET['state']) ? $_GET['state'] : false,
// you can insert as many variables here as you want

);
// Remove empty values
$options = array_filter($options);

// Quit if not exactly 1 get values were found
if (count($options) != 1) {
  echo 'invalid options';
  die;
}


// Do Pushover curl
curl_setopt_array($ch = curl_init(), array(
  CURLOPT_URL => "http://YOUR_HA_IP:8123/api/states/sensor.YOURSENSOR",
  CURLOPT_POST => true,
  CURLOPT_HEADER => "Content-Type: application/json",
  CURLOPT_POSTFIELDS => "{\"state\":\"$options[state]\"}"
));
curl_exec($ch);
curl_close($ch);

?>

This is a simple PHP file, which executes CURL commands and communicates with your HA instance through RESTful API. Please note, that I’m not a PHP dev guy (in fact I’m not any kind of coder), so this might not be most elegant PHP code in the universe… But it does the job.

Now, all you have to do is to set up the Action Rule in SS, select External Device as Action device, and use the following URL:
http://localhost/YOUR_PHP_FILE.php?state=WHATEVER_STATE_YOU_WANT_TO_SET

Feel free to modify the PHP code to pass the sensor name AND the status as a variable for example:
http://localhost/YOUR_PHP_FILE.php?sensor=CAM_NAME&state=WHATEVER_STATE_YOU_WANT_TO_SET

That’s it. You have your SS Motion Alert in HA.

Cheers,
Ben

Is this implemented in HA? Currently, SS does not recognize (and start recording on) line crossing on intrusion alerts. Hikvision Binary sensors provide those sensors and it will be nice to start recording on any of these events through HA.

No, it is not. I have written my own little Python script which takes the camera id and start/stop/status as arguments. Note that you have to edit the ip address, port, username and password in this script, if you decide to use it:

#!/usr/bin/python3

import sys
import requests
import json


PROTOCOL = "http"
IP_ADDRESS = "xxx.xxx.x.x"    #your Synology NAS ip address
PORT = "xxxx"                 #the port used by Synology DiskStation Manager
API_PATH = "/webapi/"
BASE_URL = PROTOCOL + "://" + IP_ADDRESS + ":" + PORT + API_PATH
API_AUTH_FILE = "auth.cgi"
API_CAMERA_FILE = "entry.cgi"

CAMERA_ID = sys.argv[1]
CAMERA_ACTION = sys.argv[2]

AUTH_PAYLOAD = {'api': 'SYNO.API.Auth', 'version': '2', 'session': 'SurveillanceStation'}
LOGIN_PAYLOAD = {'method': 'Login', 'account': 'YOUR_ACCOUNT', 'passwd': 'YOUR_PASSWORD', 'format': 'cookie'}
LOGIN_PAYLOAD.update(AUTH_PAYLOAD)
LOGOUT_PAYLOAD = {'method': 'Logout'}
LOGOUT_PAYLOAD.update(AUTH_PAYLOAD)

if CAMERA_ACTION == "status":
    ACTION_PAYLOAD = {'api': 'SYNO.SurveillanceStation.Camera', 'version': '2', 'method': 'GetInfo', 'cameraIds': CAMERA_ID}
else:
    ACTION_PAYLOAD = {'api': 'SYNO.SurveillanceStation.ExternalRecording', 'version': '2', 'method': 'Record', 'cameraId': CAMERA_ID, 'action': CAMERA_ACTION}


session = requests.session()

login = session.get(BASE_URL + API_AUTH_FILE, params=LOGIN_PAYLOAD, timeout=5)
action = session.get(BASE_URL + API_CAMERA_FILE, params=ACTION_PAYLOAD, timeout=5)
logout = session.get(BASE_URL + API_AUTH_FILE, params=LOGOUT_PAYLOAD, timeout=5)

session.close()

if CAMERA_ACTION == "status":
    print(action.text)

And then I have switches like this to control the recording:

- platform: command_line
  switches:
    camera_bedroom_recording:
      command_on: 'python3 /home/hass/.homeassistant/python/camera_recording.py 1 start'
      command_off: 'python3 /home/hass/.homeassistant/python/camera_recording.py 1 stop'
      command_state: 'python3 /home/hass/.homeassistant/python/camera_recording.py 1 status'
      value_template: >
        {% if value_json is defined %}
          {{ value_json.data.cameras[0].recStatus == 6 }}
        {% else %}
          {{ states.switch.camera_bedroom_recording.state == 'on' }}
        {% endif %}

My value_template is a little more complicated than one might expect, but that is to get rid of value_json is undefined errors that I got in my Home Assistant log from time to time. When that happens with this template, the switch will just keep its current state.
When the recStatus is 6, it means it’s doing an external recording, so with my template a recording initiated any other way will not be picked up. When no recording is happening, recStatus will be 0. So one could use the following bit to check for any type of recording: {{ value_json.data.cameras[0].recStatus != 0 }}

Also please note that my script above is probably not perfect. I am not a Python coder, so the script was put together through alot of trial and error. It could also use some error handling, but the script does the trick for me so I figured I’d share. Ymmv.

I keep seeing these in my logs:

17-04-02 16:27:34 ERROR (MainThread) [homeassistant.helpers.template] Error parsing value: list object has no element 0 (value: {"data":{"cameras":[]},"success":true}, template: {% if value_json is defined %}
  {{ value_json.data.cameras[0].recStatus == 6 }}
{% else %}
  {{ states.switch.camera_bedroom_recording.state == 'on' }}
{% endif %}
)

Also, where are you specifying which camera use? I have 4 cameras.

I specify that in my switch, e.g.:

command_on: 'python3 /home/hass/.homeassistant/python/camera_recording.py 1 start'

The ‘1’ in this line is the id of my camera in the bedroom. The id of my other camera is 2. I had to use the API to find these ids, because I don’t think you can find them anywhere in the web interface. I pasted the following URLs into my browser (in the same tab):

http://xxx.xxx.x.x:yyyy/webapi/auth.cgi?api=SYNO.API.Auth&method=Login&version=2&account=YOUR_ACCOUNT&passwd=YOUR_PASSWORD&session=SurveillanceStation&format=cookie

followed by

http://xxx.xxx.x.x:yyyy/webapi/entry.cgi?api=SYNO.SurveillanceStation.Camera&method=List&version=2

Note that the result after the first URL should contain something like "success":true for the second URL to work. If it works, the second URL will give you a very long result, but all you need to do is search the text for cameraId.

Please also note that all of my work is based on a DS412+ running the latest version of DiskStation Manager and Surveillance Station. API’s are sometimes changed from one version to another, so what works for me may not work for somebody else.

Ahh…that works. My cameraID starts from 2, hence those errors. I wish someone can port it to HA.

Awesome! :slight_smile:

Is it possible to pre-record (so that we don’t miss much), like it is possible through the SS interface? I see an entry for camPreRecTime

I don’t see a need to do that through the API, as it’s something you can just configure in the settings of each camera in Surveillance Station. I’m assuming this setting applies to any type of recording.

Oh…that is perfect (if that is the case). I wasn’t sure if the pre-recording settings would apply to manual recordings as well.

Unfortunately, it doesn’t seem to work that way. I started the recording on my NAS from Home Assistant and stopped it again 10 seconds later, but no extra time was added to the duration of the video. The camera I used it set to pre-record 5 seconds, as well as post-record 5 seconds. The API for external recordings does not give you the option to alter this behaviour.

Indeed, it doesn’t pre-record, which is unfortunate. With the manual recording, we also need to turn off the recording. Guess, we will have to live with motion detection.

There were some improvements related to line-crossing detection in SS8 (https://www.synology.com/en-us/surveillance/8.0), but that does not seem to be working.

BTW, is it possible to set the time_server using the python api?

Soo Synology SS (DMS6) does not work with 0.42.2 and downgrading is the only option?

Error:

[homeassistant.components.camera.synology] Error on http://127.0.0.1:5000/webapi/query.cgi
Traceback (most recent call last):
File “/volume1/@appstore/py3k/usr/local/lib/python3.5/site-packages/homeassistant/components/camera/synology.py”, line 84, in async_setup_platform
query_resp = yield from query_req.json()
File “/volume1/homeassistant/deps/aiohttp/client_reqrep.py”, line 688, in json
headers=self.headers)
aiohttp.client_exceptions.ClientResponseError: 0, message=‘Attempt to decode JSON with unexpected mimetype: text/plain; charset=“utf-8”’

Seeing the same problem here. Just upgraded from 0.38.4 to 0.42.2 and my cameras on the Synology Surveillance Station no longer appear in HASS:

17-04-10 16:49:33 ERROR (MainThread) [homeassistant.components.camera.synology] Error on https://192.168.1.11:5001/webapi/query.cgi
Traceback (most recent call last):
  File "/usr/local/homeassistant/lib/python3.5/site-packages/homeassistant/components/camera/synology.py", line 84, in async_setup_platform
    query_resp = yield from query_req.json()
  File "/home/homeassistant/.homeassistant/deps/aiohttp/client_reqrep.py", line 688, in json
    headers=self.headers)
aiohttp.client_exceptions.ClientResponseError: 0, message='Attempt to decode JSON with unexpected mimetype: text/plain; charset="utf-8"'

Here’s my configuration.yaml entry:

camera:
  - platform: synology
    url: https://192.168.1.11:5001
    username: hass
    password: !secret syno_password
    verify_ssl: False

And my Synology is running DSM 6.1-15047 Update 2.

Same problem as well, Synology camera not working on 0.42.2

Same problem here as well… it was working on 0.41, moving to 42.2 it stopped working…

DS415+
DSM Version : DSM 6.1-15047 Update 2
Surveilance Station : 8.0.2-5158

I found these fixes in GitHub, targeted for 0.42.3. Manually applied them to my synology.py and it fixed the problem: