ZoneMinder Binding in Marketplace (Beta)

Yeah, I started to use my motion detectors to trigger rules that use the force alarm channel to turn recording ON and OFF. I got disenchanted with the quality of Zoneminder’s motion detection. I know it’s quite powerful, but no amount of tuning and tweaking would prevent lighting changes, rain, snow, etc. from triggering the motion detection. I was starting to hate waking up to dozens of bogus events just because it rained heavily during the night. I suppose it can be done, but it’s beyond me. :roll_eyes:

If I could figure out how to pull the PR into my local openhab2-addons repo, I’d make a few changes to reduce the logging level, fix the config changes, and handle some of these exceptions differently.

I would be glad if somebody could help finishing the pull request. Right now I don’t have the time for finalising it. I also see the need for a major rework, first of all since ZM API seems to change, but also to make the Binding more clean.

Yes… I know what you mean. I’ve got mine close to not annoying, but still a battle, especially on sunny days with clouds. Couple weeks ago a blustery snow storm made me disable one of the cameras. Setting brightness and contrast levels helped me a bit with motion detection, but reduced the quality of the images. There’s still more to tweak, but hard to get all scenarios to work with one set of settings. I haven’t tried automating them yet…

I’ve been tempted to jump in, but I have a few other OH related things in the queue. If nobody has snatched it when I get done, then I’ll gladly help out!

I pulled the PR into my local repo. I’m going to take a look at what’s necessary to wrap it up.

2 Likes

Here is another error that often comes up…

2018-12-14 05:19:42.359 [ERROR] [org.openhab.binding.zoneminder.handler.ZoneMinderServerBridgeHandler] - [BRIDGE (99ec8cf6)]: context='validateConnection' check='FAILED' - General error when creating ConnectionInfo. Retrying next cycle...
com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 12 path $
        at com.google.gson.JsonParser.parse(JsonParser.java:65) ~[21:com.google.gson:2.7.0.v20170129-0911]
        at com.google.gson.JsonParser.parse(JsonParser.java:45) ~[21:com.google.gson:2.7.0.v20170129-0911]
        at name.eskildsen.zoneminder.jetty.JettyConnectionInfo.fetchContentResponse(JettyConnectionInfo.java:159) ~[200:org.openhab.binding.zoneminder:2.3.0.201805211219]
        at name.eskildsen.zoneminder.jetty.JettyConnectionInfo.doItSync(JettyConnectionInfo.java:75) ~[200:org.openhab.binding.zoneminder:2.3.0.201805211219]
        at name.eskildsen.zoneminder.jetty.JettyConnectionInfo.onConnect(JettyConnectionInfo.java:227) ~[200:org.openhab.binding.zoneminder:2.3.0.201805211219]
        at name.eskildsen.zoneminder.internal.GenericConnectionHandler.connect(GenericConnectionHandler.java:141) ~[200:org.openhab.binding.zoneminder:2.3.0.201805211219]
        at name.eskildsen.zoneminder.ZoneMinderFactory.CreateConnection(ZoneMinderFactory.java:34) ~[200:org.openhab.binding.zoneminder:2.3.0.201805211219]
        at org.openhab.binding.zoneminder.handler.ZoneMinderServerBridgeHandler.validateConnection(ZoneMinderServerBridgeHandler.java:801) [200:org.openhab.binding.zoneminder:2.3.0.201805211219]
        at org.openhab.binding.zoneminder.handler.ZoneMinderServerBridgeHandler.initializeAvaliabilityStatus(ZoneMinderServerBridgeHandler.java:1036) [200:org.openhab.binding.zoneminder:2.3.0.201805211219]
        at org.openhab.binding.zoneminder.handler.ZoneMinderServerBridgeHandler.updateAvaliabilityStatus(ZoneMinderServerBridgeHandler.java:1197) [200:org.openhab.binding.zoneminder:2.3.0.201805211219]
        at org.openhab.binding.zoneminder.handler.ZoneMinderServerBridgeHandler$1.run(ZoneMinderServerBridgeHandler.java:114) [200:org.openhab.binding.zoneminder:2.3.0.201805211219]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:?]
        at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) [?:?]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) [?:?]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [?:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:?]
        at java.lang.Thread.run(Thread.java:748) [?:?]
Caused by: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 12 path $
        at com.google.gson.stream.JsonReader.syntaxError(JsonReader.java:1559) ~[?:?]
        at com.google.gson.stream.JsonReader.checkLenient(JsonReader.java:1401) ~[?:?]
        at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:542) ~[?:?]
        at com.google.gson.stream.JsonReader.peek(JsonReader.java:425) ~[?:?]
        at com.google.gson.JsonParser.parse(JsonParser.java:60) ~[?:?]
        ... 17 more

This evening, I did some maintenance on our server that runs Zoneminder and did a DNF update. I had forgotten that the binding wasn’t working with the updated ZM. You can guess what happened :roll_eyes:. Since my wife fixed it last time…

… she looked at it again. Good news! Using the previous changes, the binding works and the fix is simple. If you update ZM, the configuration files are dropped into /etc/zm/zm.conf.rpmnew so that they do not overwrite your existing configuration. Included in the updated configuration is a fix to remove a deprecation warning in the JSON response that is causing the error in the binding. Apply the new conf and you’ll be working again.

So, if you upgrade (we’re on 1.32.3) and see this, update your configuration…

2019-05-23 19:20:05.365 [ERROR] [org.openhab.binding.zoneminder.internal.handler.ZoneMinderServerBridgeHandler] - [BRIDGE (99ec8cf6)]: context='validateConnection' check='FAILED' - Error creating ConnectionInfo. Retrying next cycle...
name.eskildsen.zoneminder.exception.ZoneMinderInvalidData: Error occurred when converting response to class.
        at name.eskildsen.zoneminder.jetty.JettyConnectionInfo.fetchDataAsJson(JettyConnectionInfo.java:355) ~[205:org.openhab.binding.zoneminder:2.4.0.201812161831]
        at name.eskildsen.zoneminder.jetty.JettyConnectionInfo.onConnect(JettyConnectionInfo.java:288) ~[205:org.openhab.binding.zoneminder:2.4.0.201812161831]
        at name.eskildsen.zoneminder.internal.GenericConnectionHandler.connect(GenericConnectionHandler.java:141) ~[205:org.openhab.binding.zoneminder:2.4.0.201812161831]
        at name.eskildsen.zoneminder.ZoneMinderFactory.CreateConnection(ZoneMinderFactory.java:34) ~[205:org.openhab.binding.zoneminder:2.4.0.201812161831]
        at org.openhab.binding.zoneminder.internal.handler.ZoneMinderServerBridgeHandler.validateConnection(ZoneMinderServerBridgeHandler.java:782) [205:org.openhab.binding.zoneminder:2.4.0.201812161831]
        at org.openhab.binding.zoneminder.internal.handler.ZoneMinderServerBridgeHandler.initializeAvaliabilityStatus(ZoneMinderServerBridgeHandler.java:998) [205:org.openhab.binding.zoneminder:2.4.0.201812161831]
        at org.openhab.binding.zoneminder.internal.handler.ZoneMinderServerBridgeHandler.updateAvaliabilityStatus(ZoneMinderServerBridgeHandler.java:1139) [205:org.openhab.binding.zoneminder:2.4.0.201812161831]
        at org.openhab.binding.zoneminder.internal.handler.ZoneMinderServerBridgeHandler$1.run(ZoneMinderServerBridgeHandler.java:117) [205:org.openhab.binding.zoneminder:2.4.0.201812161831]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:?]
        at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) [?:?]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) [?:?]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [?:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:?]
        at java.lang.Thread.run(Thread.java:748) [?:?]
Caused by: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 7 path $
        at com.google.gson.stream.JsonReader.syntaxError(JsonReader.java:1568) ~[?:?]
        at com.google.gson.stream.JsonReader.checkLenient(JsonReader.java:1409) ~[?:?]
        at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:542) ~[?:?]
        at com.google.gson.stream.JsonReader.peek(JsonReader.java:425) ~[?:?]
        at com.google.gson.JsonParser.parse(JsonParser.java:60) ~[?:?]
        at com.google.gson.JsonParser.parse(JsonParser.java:45) ~[?:?]
        at name.eskildsen.zoneminder.jetty.JettyConnectionInfo.fetchDataAsJson(JettyConnectionInfo.java:352) ~[?:?]
        ... 14 more

Scott

Thanks for updating on this thread. I have completed the sql inserts and updated the config as described in the fix and I’m still seeing the same “Error occurred when converting response to class” being logged. I was using the 2.4 release of the binding and switched to the market version which appears to be the 2.3 version binding.

I’m unsure if I had actually updated zoneminder to 1.32.3 or if it was fresh reinstall. In either case I’m not seeing a difference in the rpm.save file for the zm.conf so I’m not sure which config item I would look for to supress the json warning.

If anyone has had luck getting the binding to work with 1.32.3 please enlighten me. I know a rewrite is likely necessary long term but I’d love to try to use this with my current set up.

I’m using a version from @mhilbush. I thought this was the same as the version in the marketplace, with some minor fixes that Mark had done, but it looks like there’s more to it than that!

Mark, do you plan on taking this further, or maybe you could post the jar?

I dunno. I back-burned it in order to work on some other things. I need to assess how much work it will be to bring it to conclusion. Posting the jar would suggest I’m ready to support it, and I haven’t made that decision yet…

That’s unfortunate. Could you help refresh my memory… you forked mr_eskildsen’s branch with the changes from the PR that never got merged, right? I guess I could start there, but it would be missing the additional fixes you’ve made. Could you at least please put your fork in GH so that we don’t lose those fixes? I’m still completely immersed in automation, but I’ll put that down to get the official ZM binding working again.

Correct.

Sure, but I’m traveling right now and may not get to it for a few days.

It also will require the inclusion of the private interface lib, zoneminder4j, which I looked at, but never got around to building. It throws NPEs occasionally, which are hard to deal with in the binding.

2 Likes

The Workaround needs to be slightly modified with latest Zoneminder releases.
The Config table Id 225 & 226 have been used for other stuffs, so the DB update should use different Ids. I append 1000 to them for safety, and it works fine:

use zm; #Assuming your zoneminder database is actually named zm
INSERT INTO `Config` VALUES (1225,'ZM_PATH_ZMS','/cgi-bin/nph-zms','string','/cgi-bin/nph-zms','relative/path/to/somewhere','(?^:^((?:[^/].*)?)/?$)',' $1 ','Web path to zms streaming server',' The ZoneMinder streaming server is required to send streamed images to your browser. It will be installed into the cgi-bin path given at configuration time. This option determines what the web path to the server is rather than the local path on your machine. Ordinarily the streaming server runs in parser-header mode however if you experience problems with streaming you can change this to non-parsed-header (nph) mode by changing \'zms\' to \'nph-zms\'. ','hidden',0,NULL);
INSERT INTO `Config` VALUES (1226,'ZM_OPT_FRAME_SERVER','0','boolean','no','yes|no','(?^i:^([yn]))',' ($1 =~ /^y/) ? \"yes\" : \"no\" ','Should analysis farm out the writing of images to disk',' In some circumstances it is possible for a slow disk to take so long writing images to disk that it causes the analysis daemon to fall behind especially during high frame rate events. Setting this option to yes enables a frame server daemon (zmf) which will be sent the images from the analysis daemon and will do the actual writing of images itself freeing up the analysis daemon to get on with other things. Should this transmission fail or other permanent or transient error occur, this function will fall back to the analysis daemon. ','system',0,NULL);

Note that the path, this time, is mine. It should be updated according to your installation. Issue a locate nph-zms to find the relative directory from zoneminder directory.

1 Like

Hi,

Sometimes, despite of the workaround, OpenHab failed to connect to the zoneminder server.
It looks like the plugin doesn’t get that it is not authenticated anymore.
Hopefully, reloading the plugin (or saving its configuration in PaperUI) solves the problem.
But as this was a pain to maintain for my purpose (i use an alarm thing to set cams to Modect when away and Monitor while ar home), here is a little rule for a workaround:

rule "Zoneminder Watchdog"
when
  Time cron "0 * * * * ?"
then
  logInfo("Zoneminder Watchdog", "Checking Zoneminder state")
  // Check the logs for the error message
  var log1 = executeCommandLine("grep 'Unable to authenticate in ZoneMinder' /var/log/openhab2/openhab.log | grep getMonitorData | tail -1", 1000)
  // Check again after 15 seconds - depending on your experience with the logs.
  // I had logs comming every 10 seconds on my setup
  Thread::sleep(15000)
  var log2 = executeCommandLine("grep 'Unable to authenticate in ZoneMinder' /var/log/openhab2/openhab.log | grep getMonitorData | tail -1", 1000)
  // If log lines are different (if there was a new 'Unable to authenticate...' log within 15 seconds) restart the plugin through openhab-cli
  if (log1 != log2) {
    logWarn("Zoneminder Watchdog", "Zoneminder Down, restarting...")
    executeCommandLine("openhab-cli console 'bundle:restart org.openhab.binding.zoneminder'",1000)
    // After 10 seconds, just to let everything come up properly, i then just reapplied my Monitor or Modect mode to the cams.
    Thread::sleep(10000)
    // Do whatever you want, or remove this sleep timer.
  } else {
    logInfo("Zoneminder Watchdog", "Zoneminder UP.")
  }
end

I hope it would help some of you.

1 Like

Still images does not work for me:

2019-08-08 13:05:28.654 [ERROR] [andler.ZoneMinderThingMonitorHandler] - [MONITOR-1]: context='onFetchData' error in call to 'getMonitorStillImage'

What am I missing?
Everything else appears to be work fine.
I am running the version available on Marketplace (market:binding-3761448 - 1.0) on Openhab 2.5 snapshot.

Does anybody have this working on Zoneminder 1.33.x ?

I have followed all above and couldn’t get the thing to cone online.

Same here. I tried everything


I even tried with no Auth enabled. The JSON is just fine when I make a API request. But OpenHab2 wouldn’t still connect.

Should this binding work with ZM 1.32.3? If so then can I have some pointers as I can’t seem to get this working.

After assessing load on our OH server, which also runs ZM, I’ve removed this binding. With 5 cameras and 5s polling to quickly get motion alerts, the load was just too high. Before the binding, I had used ZM filters to send REST API calls for turning on and off Items for motion detection. Unfortunately, it seems ZM changed the filters so that this solution would not work for us. Here is some detail on ZM filters. Currently, we are using SQL triggers to make the REST API calls and it’s been working great… https://www.rushworth.us/lisa/?p=5470. Motion detection is immediate and the load is significantly improved. Using this, there’s no dependency on the changing ZM API or an OH binding. You can do more than motion detection too. It’s not in the example, but there’s also a shell script called in the SQL trigger that that emails an image of the 25th alarm frame.

doesn’t seem to work for me on zm 1.32.3

bundle:list | grep ZoneMinder
233 │ Active │ 80 │ 2.5.0.M1 │ ZoneMinder Binding

I can see the OH connecting to the ZM, and the traffic is being exchanged, but the binding claims the wrong user credentials were specified.

openhab> smarthome:things list | grep zone
zoneminder:server:ZoneMinderHome (Type=Bridge, Status=OFFLINE (CONFIGURATION_ERROR): Cannot access ZoneMinder Server. Check provided usercredentials, Label=ZoneMinder Server, Bridge=null)

Here is a tcpdump of the connection
GET /zm/index.php HTTP/1.1
User-Agent: Mozilla/5.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: en-US,en;q=0.5
Cache-Control: no-cache
Pragma: no-cache
Host: homenas.kos.home
Connection: keep-alive

HTTP/1.1 200 OK
Date: Sat, 31 Aug 2019 06:05:36 GMT
Server: Apache
Set-Cookie: ZMSESSID=p1l3jvtjd8u8sn6notbkrrltco; path=/; HttpOnly
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Set-Cookie: zmSkin=classic; expires=Mon, 09-Jul-2029 06:05:37 GMT; Max-Age=311040000
Set-Cookie: zmCSS=base; expires=Mon, 09-Jul-2029 06:05:37 GMT; Max-Age=311040000
Vary: Accept-Encoding
Content-Length: 5564
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8

SKIP

This topic is about the updated version of the binding in the marketplace. I don’t think the production version of the binding has been updated for a very long time. But the marketplace version will not function on newer versions of ZM without the workarounds I’ve posted.

1 Like