Binding Request: Synology Surveillance Station

Hi,
first of many thanks for the binding :slight_smile:

I got following error when I activate or deactivate the “Camera enabled” switch in a rule:

[ERROR] [ternal.webapi.request.SynoApiRequest] - RESPONSE: {“error”:{“code”:401,“errors”:{“param1”:“”,“param2”:“”}},“success”:false}

The error is thrown in both cases OFF and ON

command in my rule to disable the camera completly:
InstarTerCommonEnable.sendCommand(OFF)
and the other command to activate the camera:
InstarTerCommonEnable.sendCommand(ON)

Since the rule is doing what it is intended for (disabling/enabling the camera) I could just ignore this error but if there is a way to not trigger this error it would be even better :slight_smile:

NoTechi

Hi @NoTechi,
Sorry, but I can’t reproduce your error. If you get this response, binding shouldn’t work at all. If it still works, there is a bug somewhere. Please check your credentials/user and whether you have but one copy of this binding running using
bundle:list | grep Syno

Please note that you can just disable all errors with following command:
log:set FATAL org.openhab.binding.synologysurveillancestation

If you encounter further issues, please provide some more information regarding your setup.

BR Pav

Hi @Pavion,

there is only one instance running:

203 x Active x 80 x 2.5.0.201911151402 x openHAB Add-ons :: Bundles :: Synology Surveillance Station Bin

My setup:
Openhab 2.5.4 running in a docker on a Synology NAS (using different ports for openhab then the standard)
org.openhab.binding.synologysurveillancestation-2.5.0-SNAPSHOT.jar in my addon folder

The bridge configuration/credentials should be ok since I get access to my cams. However I looked up the credentials again and saw it is configured to http on port 5000. Shouldn’t it be 9900 (HTTP) or 9901 (HTTPS)?

NoTechi

Update:
After a openhab restart I got:

[WARN ] [.core.thing.binding.BaseThingHandler] - Handler SynoBridgeHandler of thing synologysurveillancestation:station:15b1mhn934300 tried updating channel sid although the handler was already disposed.

Could this be related to the Error?

Hi @NoTechi
I still can’t reproduce your issue. If everything works as expected, please just turn off the logging as shown in the previous post.

As for ports: Surveillance Station uses the common API and port of the Disk Station.
It’s the one you enter in Control Panel - Network - DSM Ports - HTTP and it defaults to 5000.

Your warning is known, not critical and have something to do with the order of thing/item creation upon binding start. I’ve never found out the exact cause but i don’t know of any negative effects either.

Hi @Pavion,

ok will do thanks for your reply and yes most important is that its working as expected :slight_smile:

NoTechi

Is it normal that for each snapshot refresh of each camera a new login is done? I got spammed by failed login attempts within the Synology protocol center and took me some time to find out the surveillance station binding is causing it. After correcting the login information I get spammed with successfull login attempt messages in the protocol center and when I change the snapshot refresh rate of a camera the login protocol messages change accordingly (e.g. every 10 seconds). Just wanted to know if this normal behviour or should there be just one login?

NoTechi

No it’s not. Older versions were having this bug especially when a camera was disabled. Which version are you using?

Normally you’d just connect twice on OH start (discovery and normal logins) and keep your login and SID (as seen in log and some channels) constant a whole time.
BR Pav

You are right I was using 2.5.0. Now I swtiched to 2.5.6 but still get the same login messages. Do I have to remove the things and items and rediscover? I just stopped openhab, replace the jar file in the addons folder and restartet openhab.

Update: Deleted things now and resdicovered them. It is still the same. Is there a even more recent version then 2.5.6 from github?

Update2: I further looked at it. I have two cameras (one Reolink one Instar). When I enable the cameras the login messages are gone. When I deactivate the reolink there are still no login messages. But when I deactivate my Instar camera then I get the messages again.

NoTechi

That’s weird. It looks like some cameras are getting different responses

Could you please enable TRACE for the binding and PM me an extended output?

log:set TRACE org.openhab.binding.synologysurveillancestation

  • please note your credentials are stored in plain text so you may want to remove/replace them
  • please don’t forget to restore logging settings afterwards to avoid log spamming

Thanks in advance
Pav

Hello!

Strange issue 
 the binding is working fine, but I keep having the following message every minute:

2020-07-31 08:56:18.867 [ERROR] [core.karaf.internal.FeatureInstaller] - Failed installing 'openhab-binding-synologysurveillancestation'

I’m on 2.5.8-SNAPSHOT

Any idea ?

Actually yes :slight_smile:
It looks like you’ve added the binding into addons.cfg, which is not necessary and forces OH to look for this binding in a main repository in vain.

oh! very nice catch !

I thought it was necessary to add the binding in the addons to get it loaded ! awesome

Thanks :slight_smile:

Got this installed and discovered all my cameras today. Great binding, thanks for all your hard work!

I wanted to share some notes from my experience in case they help other folks in the future.

First, my Synology serves only HTTPS on port 5001 with an ACME generated certificate from a self-signed root ca (via a local stepca acme server).

I have installed the root certificate on all my end user devices (laptops, tablets, phones, etc.); however, I needed to make it available as a Java Key Store to the OpenHab JVM for the binding to be able to communicate with Surveillance Station over HTTPS.

Note, that there were no error messages and the binding showed as “Online”. I found the problem by increasing the log level to debug (offending debug log message at the end of the post).

To do this, I took my public certificate and ran Java keytool like this:

keytool -import -alias myopenhab -file /var/tmp/public.crt -storetype JKS -keystore /var/tmp/public.truststore.jks

Note, that you will be prompted for a password; however, this does not appear to be used by the JVM for truststores (as you will see below I don’t pass the password to the OH2 JVM).

Then I mounted it into my OpenHab docker container and told the JVM to use it:

-v /opt/openhab/public.truststore.jks:/etc/public.truststore.jks:ro
-e JAVA_OPTS='-Djavax.net.ssl.trustStore=/etc/public.truststore.jks'

If you are not using Docker, you can set the JAVA_OPTS by modifying openhab2/runtime/bin/setenv.

Unfortunately, you are not done yet. The Surveillance Station binding was initially configured with an IP address. However, you need to use the domain name in order to look-up and verify the server’s key in the trust store. Unless your domain name is public, you need to tell Docker about your DNS server and possibly any DNS search suffixes:

--dns 192.168.1.1
--dns-search private.foo

To check if your domain name resolves you can do this:

$ docker exec -it <OH_CONTAINER_ID> /bin/bash
<container>$ apt update
<container>$ apt install iputils-ping
<container>$ ping synology.private.foo
<container>$ ping: synology.private.foo: Name or service not known

Now you can reconfigure the binding to use the domain name (e.g. synology.private.foo) and everything should work as expected.

If you are having trouble getting it to work, I found this SSLPoke utility from Atlassian made it very easy to try different trust stores and JVM arguments (I ran it from inside the OpenHab docker container to reduce the number of moving parts).

e.g.
$ docker exec -it <OH_CONTAINER_ID> /bin/bash
<container>$ apt update
<container>$ apt install wget
<container>$ wget https://confluence.atlassian.com/kb/files/779355358/779355357/1/1441897666313/SSLPoke.class
<container>$ java SSLPoke synology.private.foo 5001

Some suggestions for improving the plugin:

  • Detect connection failures due to misconfigured SSL and log warnings or errors
  • Relabel the configuration input box as hostname or ip address
  • Allow ignoring invalid (e.g. unverifiable) server certificates (useful for testing)

The only other thing I noticed, is that every time I go to edit the bridge thing settings, it shows my custom username and then quickly changes to “admin”. I checked the thing file on disk and it has the correct username and password. This was very strange.

Here’s the debug message that I saw in the logs indicating there was a problem with the SSL setup:

javax.net.ssl.SSLHandshakeException: General SSLEngine problem at sun.security.ssl.Handshaker.checkThrown(Handshaker.java:1523) ~[?:1.8.0_232] at sun.security.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:528) ~[?:1.8.0_232] at sun.security.ssl.SSLEngineImpl.writeAppRecord(SSLEngineImpl.java:1197) ~[?:1.8.0_232] at sun.security.ssl.SSLEngineImpl.wrap(SSLEngineImpl.java:1165) ~[?:1.8.0_232] at javax.net.ssl.SSLEngine.wrap(SSLEngine.java:509) ~[?:1.8.0_232] at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.flush(SslConnection.java:891) ~[?:?] at org.eclipse.jetty.io.WriteFlusher.flush(WriteFlusher.java:422) ~[?:?] at org.eclipse.jetty.io.WriteFlusher.completeWrite(WriteFlusher.java:378) ~[?:?] at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.lambda$fill$1(SslConnection.java:669) ~[?:?] at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:782) [bundleFile:9.4.20.v20190813] at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:918) [bundleFile:9.4.20.v20190813] at java.lang.Thread.run(Thread.java:748) [?:1.8.0_232] Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) ~[?:1.8.0_232] at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1709) ~[?:1.8.0_232] at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:320) ~[?:1.8.0_232] at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:312) ~[?:1.8.0_232] at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1640) ~[?:1.8.0_232] at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:223) ~[?:1.8.0_232] at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1039) ~[?:1.8.0_232] at sun.security.ssl.Handshaker$1.run(Handshaker.java:972) ~[?:1.8.0_232] at sun.security.ssl.Handshaker$1.run(Handshaker.java:969) ~[?:1.8.0_232] at java.security.AccessController.doPrivileged(Native Method) ~[?:1.8.0_232] at sun.security.ssl.Handshaker$DelegatedTask.run(Handshaker.java:1461) ~[?:1.8.0_232] at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.fill(SslConnection.java:526) ~[?:?] at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.process(HttpReceiverOverHTTP.java:128) ~[?:?] at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.receive(HttpReceiverOverHTTP.java:73) ~[?:?] at org.eclipse.jetty.client.http.HttpChannelOverHTTP.receive(HttpChannelOverHTTP.java:133) ~[?:?] at org.eclipse.jetty.client.http.HttpConnectionOverHTTP.onFillable(HttpConnectionOverHTTP.java:154) ~[?:?] at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311) ~[?:?] at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103) ~[?:?] at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.onFillable(SslConnection.java:426) ~[?:?] at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:320) ~[?:?] at org.eclipse.jetty.io.ssl.SslConnection$2.succeeded(SslConnection.java:158) ~[?:?] at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103) ~[?:?] at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117) ~[?:?] at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336) ~[?:?] at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313) ~[?:?] at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171) ~[?:?] at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:129) ~[?:?] at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:367) ~[?:?] ... 3 more Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:397) ~[?:1.8.0_232] at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:302) ~[?:1.8.0_232] at sun.security.validator.Validator.validate(Validator.java:262) ~[?:1.8.0_232] at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:327) ~[?:1.8.0_232] at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:279) ~[?:1.8.0_232] at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:144) ~[?:1.8.0_232] at org.eclipse.smarthome.io.net.http.internal.ExtensibleTrustManagerImpl.checkServerTrusted(ExtensibleTrustManagerImpl.java:119) ~[?:?] at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1627) ~[?:1.8.0_232] at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:223) ~[?:1.8.0_232] at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1039) ~[?:1.8.0_232] at sun.security.ssl.Handshaker$1.run(Handshaker.java:972) ~[?:1.8.0_232] at sun.security.ssl.Handshaker$1.run(Handshaker.java:969) ~[?:1.8.0_232] at java.security.AccessController.doPrivileged(Native Method) ~[?:1.8.0_232] at sun.security.ssl.Handshaker$DelegatedTask.run(Handshaker.java:1461) ~[?:1.8.0_232] at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.fill(SslConnection.java:526) ~[?:?] at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.process(HttpReceiverOverHTTP.java:128) ~[?:?] at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.receive(HttpReceiverOverHTTP.java:73) ~[?:?] at org.eclipse.jetty.client.http.HttpChannelOverHTTP.receive(HttpChannelOverHTTP.java:133) ~[?:?] at org.eclipse.jetty.client.http.HttpConnectionOverHTTP.onFillable(HttpConnectionOverHTTP.java:154) ~[?:?] at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311) ~[?:?] at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103) ~[?:?] at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.onFillable(SslConnection.java:426) ~[?:?] at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:320) ~[?:?] at org.eclipse.jetty.io.ssl.SslConnection$2.succeeded(SslConnection.java:158) ~[?:?] at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103) ~[?:?] at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117) ~[?:?] at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336) ~[?:?] at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313) ~[?:?] at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171) ~[?:?] at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:129) ~[?:?] at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:367) ~[?:?] ... 3 more Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141) ~[?:1.8.0_232] at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126) ~[?:1.8.0_232] at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280) ~[?:1.8.0_232] at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:392) ~[?:1.8.0_232] at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:302) ~[?:1.8.0_232] at sun.security.validator.Validator.validate(Validator.java:262) ~[?:1.8.0_232] at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:327) ~[?:1.8.0_232] at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:279) ~[?:1.8.0_232] at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:144) ~[?:1.8.0_232] at org.eclipse.smarthome.io.net.http.internal.ExtensibleTrustManagerImpl.checkServerTrusted(ExtensibleTrustManagerImpl.java:119) ~[?:?] at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1627) ~[?:1.8.0_232] at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:223) ~[?:1.8.0_232] at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1039) ~[?:1.8.0_232] at sun.security.ssl.Handshaker$1.run(Handshaker.java:972) ~[?:1.8.0_232] at sun.security.ssl.Handshaker$1.run(Handshaker.java:969) ~[?:1.8.0_232] at java.security.AccessController.doPrivileged(Native Method) ~[?:1.8.0_232] at sun.security.ssl.Handshaker$DelegatedTask.run(Handshaker.java:1461) ~[?:1.8.0_232] at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.fill(SslConnection.java:526) ~[?:?] at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.process(HttpReceiverOverHTTP.java:128) ~[?:?] at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.receive(HttpReceiverOverHTTP.java:73) ~[?:?] at org.eclipse.jetty.client.http.HttpChannelOverHTTP.receive(HttpChannelOverHTTP.java:133) ~[?:?] at org.eclipse.jetty.client.http.HttpConnectionOverHTTP.onFillable(HttpConnectionOverHTTP.java:154) ~[?:?] at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311) ~[?:?] at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103) ~[?:?] at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.onFillable(SslConnection.java:426) ~[?:?] at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:320) ~[?:?] at org.eclipse.jetty.io.ssl.SslConnection$2.succeeded(SslConnection.java:158) ~[?:?] at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103) ~[?:?] at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117) ~[?:?] at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336) ~[?:?] at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313) ~[?:?] at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171) ~[?:?] at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:129) ~[?:?] at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:367) ~[?:?]

1 Like

Hi @vjkoskela and thank you for your contribution. Perhaps your solution can help other people with similar setup. As for your questions / ideas:

  • I can’t really reproduce your issue. This binding (as many others) uses OH-internal HttpServer (Jetty) to establish and keep connection. This server is not modified by this binding in any way. This error you’ve provided is not thrown from inside the binding but from OH core (or you’ve omitted some lines?). That’s also why your solution had to be applied to JVM itself. I’m curious which DEBUG you’ve enabled to be able to see this message: that of OH or of this binding? If you can provide some more information as to when/where this error is thrown, please mail/PM me.

  • Yes, normally IP is used in the binding as it is also returned upon Bridge discovery. To keep input fields short, it’s also the label of this config item. I assume most users are familiar with the concept of host name being equal to IP in most cases. I’ll consider to change the description in a 3.x release though.

  • Frankly, certificates (and Docker) are not quite my field of expertise. If you think your proposal would be a good improvement, please contact me on GitHub or PM me. I may need your help/description for preparing a simple test case.

BR Pav

Thanks @Pavion! PM sent.

Hi all,
The binding works so far. But I have an issue with zooming with my reolink RLC-511. Zooming in with “START_IN” works fine. But zooming out with “START_OUT” neither cause any action nor any warning/error in the logs.

Items

String Surveillance_Zooming "Camera zooming" {channel="synologysurveillancestation:camera:diskstation:1:ptz#zoom"}

Sitemap

Switch item=Surveillance_Zooming mappings=[START_IN="Start ZoomIn", STOP_IN="Stop ZoomIn"]
Switch item=Surveillance_Zooming mappings=[START_OUT="Start ZoomOut", STOP_OUT="Stop ZoomOut"]

Hi @vavo01
Please check the latest release for a fix. Obviously this feature never worked as intended due to a typo, thanks for reporting it.
Pav

Now it works like a charm👍! Thanks

1 Like

Hi all,
trying to use External Event Trigger to start an event in Surveillance Station. However, it is not working and I don’t see any errors. Seems nothing is triggered in OH. Cameras and Home Mode work perfectly with this binding. Configured an Item as described (Number:Dimensionless Surveillance_Event_Trigger “External event trigger” {channel=“synologysurveillancestation:station:diskstation:eventtrigger”}
). I can change the state of this item, but seems no http request ist send. Do I need any additional bindings or addons for this Add-on to work?

Using OH 2.5.10 and version 2.5.6.202006130946 of this add-on (Synology Surveillance Station Binding).

Thanks for some hints!

Hi @RobRock
I can’t confirm your issue. Let’s try to retrace the steps:


In Surveillance Station I have a following action rule:
Rule Type: Triggered
Action Type: Interruptible
Event Interval: 10 s
Event Source: External device
Event: External Event 1 [note the 1 here]
Action device: Camera
Action: Start action rule recording
Duration: 10 seconds
Schedule: always on


With PaperUI I’m now sending 1 to event channel, camera runs for 10 seconds.
I can now see my video in the Timeline app and in Action rule history (Triggered - Finished).

BR Pav