Unifi camera integration


(Patrik Granholm) #1

Just want to share some integration of unifi G3 cameras into my openhab that has four items per camera:

  • Last recording time
  • Turn on/off motion detection recording
  • Status
  • Take camera snapshot

I use openhab 2.2 and had to make changes in the sitemap, item and the rules files.

<API key> is configured in the UniFi Video server on the admin account
<unifi video server> is the ip or address to your UniFi video server
<camera id> Take the camera id from rtsp service on your UniFi video server
Example: rtsp://172.17.0.2:7447/5a5a1b93e4b0b0b6e2fc8e8b_1
Will be camera id: 5a5a1b93e4b0b0b6e2fc8e8b

<Camera name> Used in the rules file, change to name that you named your camera

items file

String	cameraFront	"Camera Status [%s]" <camera>	{ http="<[http://<unifi video server>:7080/api/2.0/camera/<camera id>?apiKey=<API key>:60000:JSONPATH($.data[0].state)]" }
Number cameraFrontLastRecording	"Last recording [%d]" <time>	{ http="<[http://<unifi video server>:7080/api/2.0/camera/<camera id>?apiKey=<API key>:60000:JSONPATH($.data[0].lastRecordingStartTime)]" }
String cameraFrontLast "Last recording [%s]" <time>
String cameraFrontMotionState " [%s]" { http="<[http://<unifi video server>:7080/api/2.0/camera/<camera id>?apiKey=<API key>:10000:JSONPATH($.data[0].recordingSettings.motionRecordEnabled)]" }
Switch motionCameraFront "Motion detection" <motion>

sitemap

Text item=cameraFront valuecolor=[CONNECTED="green",DISCONNECTED="red"]
Text item=cameraFrontLast
Switch item=motionCameraFront
Image url="http://<unifi video server>:7080/api/2.0/snapshot/camera/<camera id>?apiKey=<API key>&width=500&force=true&t=1516046678" item=ImageURL refresh=10000

rules

import java.text.SimpleDateFormat
import java.util.Date

// Transform epoc time to human string
rule "cameraFrontLastRecording"
when
	Item cameraFrontLastRecording received update
then
  logInfo("cameraFrontLastRecording", "front:"+cameraFrontLastRecording.state)
  val timestampEpoch = (cameraFrontLastRecording.state as Number).longValue
	val SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
	val String timestampString = sdf.format(new Date(timestampEpoch))
  cameraFrontLast.sendCommand(""+timestampString)

end

// Camera front motion
rule "cameraFrontMotionState"
when
	Item cameraFrontMotionState received update
then
  logInfo("cameraFrontMotionState", "front motion state:"+cameraFrontMotionState.state)
  if(cameraFrontMotionState.state == "true"){
    motionCameraFront.sendCommand("ON");
  } else {
    motionCameraFront.sendCommand("OFF");
  }

end

rule "cameraFrontMotionChangeState"
when
	Item motionCameraFront received update
then
  var preStateChangeContent='{"name": "<Camera name>","recordingSettings": {"fullTimeRecordEnabled": false,"motionRecordEnabled":'
  var postStateChangeContent=',"channel": 0 }}'
  var httpUrl='<unifi video server>:7080/api/2.0/camera/<camera id>?apiKey=<API key>'

  logInfo("motionCameraFront", "front motion state change:"+motionCameraFront.state)

  if(motionCameraFront.state == ON){
    sendHttpPutRequest(httpUrl, "application/json", preStateChangeContent+'true'+postStateChangeContent)
  } else {
    sendHttpPutRequest(httpUrl, "application/json", preStateChangeContent+'false'+postStateChangeContent)
  }

end
// End Camera front motion

(Rich Koshak) #2

Thanks for posting. Please How to use code fences.

After doing that, go through and correct the quotes. when you paste in code without using code fences, not only is it really hard to read but the forum software replaces regular quotes " " with smart quotes “ ” which will not work when users paste in the rule and try to use it in their OH.

We love to see examples. Keep them coming!


(Manuel Martínez Valls) #3

Hi Patrik,

Thanks for sharing this. It works great!

Just as a feedback:

  • To make it work on my OH I’ve needed to install: HTTP Binding and JSONPath Transformation.
  • Another point is to add “http://” to the var httpUrl in the rule “cameraFrontMotionChangeState”, otherwise I was getting the error “Illegal character in scheme name at index 0:”.
  • And finally, I’ve also needed to remove the “item=ImageURL” on the definition of Image url in the sitemap file, otherwise I get the error: “Cannot retrieve item ‘ImageURL’ for widget org.eclipse.smarthome.model.sitemap.Image”

Kind regards,

Manuel Martínez


(jmccoy555) #4

Just to save others from a bit of head scratching… the http binding is still an openHAB 1 binding so you need to add ‘http1’ in the addons.cfg

Otherwise, working nicely.

Now I’m wondering if this would work reliably as a ‘PIR’ sensor to turn on the outside lights…

Edit…

Added a couple of items and the expire binding ‘expire1’

Contact cameraFrontMovemet “Front Movement [%s]” (gUniFiVideo) { expire=“5s,state=CLOSED” }
String cameraFrontLastRecordingOld

and updated the first rule

rule “cameraFrontLastRecording”
when
Item cameraFrontLastRecording received update
then
val timestampEpoch = (cameraFrontLastRecording.state as Number).longValue
val SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”)
val String timestampString = sdf.format(new Date(timestampEpoch))
cameraFrontLast.sendCommand(""+timestampString)
if ((cameraFrontLastRecordingOld.state.toString) != (cameraFrontLastRecording.state.toString)) {
cameraFrontMovemet.sendCommand(OPEN)
cameraFrontLastRecordingOld.postUpdate(cameraFrontLastRecording.state.toString)
}
end

And it works quite well. May need to tweek my movement triger time and sensativity in UniFI Video and also the refresh rate for

Number cameraFrontLastRecording

But I think it could work quite well… Got a few months until winter comes back to make it work!!!


(Adam Menzel) #6

I am implementing this now. Did you get any further with your testing on the motion side of things?


(Justin Jackson) #7

I may be missing it as I have yet to dive in to rules/code on this, but is there a way to start recording with Unifi/G3… I am thinking of not using continuous recording, but dont want the camera motion detection to miss something when it finally detects motion. For example, I have a camera on my front porch that wont pick up motion of someone walking up the walk way. If I put a motion sensor that captures the motion out front ahead of where the camera motion detector can see… I want to turn on recording early (and basically ignore the on camera motion detector) so as to potentially record the person/dog/cat etc walking in to the porch area. Currently the camera seems to miss a couple seconds by the time it picks up motion and records.

It would be fantastic if there was a continual “buffered” recording mode… where by it records continuously a couple of seconds, then when it detects motion saves that couple of seconds and continues to record and save until motion has stopped for 15 seconds or so. No chance that works heh?


(Roel) #8

Yes there is… The examples as listed above already contain the solution you are looking for.

The API allows for the control of both Continues and Motion based recording.
Take a look at a part of my JSON message allowing you to set these parameters for each individual camera.

I use this in combination with my Home State (Home, Away or Sleep) to enable/disable motion based recording.

'{"name": "Front Door","recordingSettings": {"fullTimeRecordEnabled": false,"motionRecordEnabled": true,"channel": 0 }}'

This example JSON sets FullTimeRecording to “false” and MotionRecording to “true”.

I use Node-Red for my rules processing so if you are interested i can show you what i have.

Br
Roel