UniFi Video Compatibility

Thanks for the quick response…my issue ended up being I added the SSL 7443 port to my script instead of the http 7080. i was disappointed that it doesnt seem to be able to add automations or alerts, but its added to the system.

@yeslek I also added the HTTPS port, which worked for about a day. I’ll give the HTTP port a try.

@frelev What I’m using to scrape the logs is based in part off some of the repos I found on PaperTigers GitHub account. Those repos have a more complex setup that writes to a database and generates Pushover notifications. What I’m using is a single script that scrapes the logs and sends the data to a script in Home Assistant. I don’t have it uploaded to my repo as-of-yet, so I’ll post it here.

index.js

var Tail    = require('tail').Tail;
var request = require('request');

var motion_re = /(^\d+\.\d{3}) .+Camera\[(.*)\|(.*)\] MOTION (STARTED|ENDED).+motion:(\d+)/;

function parseMotionEvent(log) {
    logsplit = log.match(motion_re);

    var uevent = {};
        
    uevent.entity_id             = 'script.trigger_unifi_camera_motion';
    uevent.variables             = {}
    uevent.variables.camera_id   = logsplit[2];
    uevent.variables.event       = logsplit[4].toLowerCase();
    uevent.variables.camera_desc = logsplit[3];
    uevent.variables.motion_id   = logsplit[5];
    uevent.variables.timestamp   = new Date(+logsplit[1].replace('.', ""));

    return uevent;
}

tail = new Tail('/var/log/unifi-video/recording.log');

tail.on("line", function lineEvent(line) {
    if(line.indexOf('MOTION') !== -1) {
        data = parseMotionEvent(line);
        
        request({
                    url: 'http://[ip address here]:8123/api/services/script/turn_on ',
                    method: 'POST',
                    headers: {
                        'x-ha-access': 'ha-password-here',
                        'Content-Type': 'application/json'
                    },
                    body: data,
                    json: true
                }, function (error, response, body) {
                    if (error) throw error;
                    console.log(body);
                });        
    }
});

tail.on("error", function(error) {
    throw error;
});

package.json

{
  "name": "unifi-log-tail",
  "version": "1.0.0",
  "description": "Follow UniFi Video's recording.log and send notifications to Home Assistant.",
  "main": "index.js",
  "keywords": [],
  "author": "",
  "dependencies": {
    "tail": "^1.2.1",
    "request": "^2.83.0"
  }
}

Home Assistant Script

alias: Trigger UniFi Camera Motion
sequence:
  - service_template: >
      {% if event == 'started' %}
        homeassistant.turn_on
      {% else %}
        homeassistant.turn_off
      {% endif %}
    data_template:
      entity_id: >
        {% if camera_id == 'camera-id-here' %}
          input_boolean.motion_front_door
        {% endif %}
2 Likes

Seems to work fine, many thanks!

EDIT: I have like 20-25 sec delay. How is it for you?

It’s instantaneous for me. Running Home Assistant, UniFi Video and NodeJS in separate Docker containers, each with persistent storage.

Not sure if it’s helpful, but this is the Dockerfile I’m using to deploy the NodeJS container with the log tailing script. It’s super basic. While I know JavaScript, I know next to nothing about NodeJS, stumbled through getting it to deploy.

FROM node:boron

# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
COPY package.json .

RUN npm install

# Bundle app source
COPY . .

EXPOSE 8080
CMD ["node", "index.js"]
1 Like

Hmm strange then
I run my nodejs and UVC on the same Intel NUC so performance should be good
I can see though that the index.js is spitting out a lot of info about my HASS entities. Should it be like that?

Not sure I follow what you mean about index.js spitting out a lot of info about HASS entities.

The index.js script doesn’t have access to data in Home Assistant. It’s only data source is the UniFi Video log. It’s a one-way information transfer. When it detects a new line, this is all that happens:

  1. Check if the new line contains the string “MOTION”.
  2. Run the regex against the new line to split it into accessible chunks.
  3. Assign various chunks to uevent.variables, which once received, Home Assistant will treat as variables that were passed to the script (script.trigger_unifi_camera_motion).
  4. Send the data to Home Assistant via the RESTful API.

Hi
Here is an example of output:

user@NUC:~/UVC2HASS$ node index.js






[ { attributes:
{ emulated_hue_name: ‘Kitchen Player’,
entity_picture: '/api/media_player_proxy/media_player.kitchen?token=f4401
friendly_name: ‘Kitchen Player’,
icon: ‘mdi:music-circle’,
is_volume_muted: false,
media_artist: ‘No Artist’,
media_content_id: ‘Ready For The Storm’,
media_content_type: ‘music’,
media_duration: 236,
media_position: 0,
media_position_updated_at: ‘2017-11-02T17:34:34.850801+00:00’,
media_title: ‘Ready For The Storm’,
supported_features: 17343,
volume_level: 0.6 },
entity_id: ‘media_player.kitchen’,
last_changed: ‘2017-11-01T20:02:16.174491+00:00’,
last_updated: ‘2017-11-02T17:34:34.866910+00:00’,
state: ‘idle’ },
{ attributes:
{ entity_picture: '/api/media_player_proxy/media_player.bathroom?token=6021
[ { attributes:
{ friendly_name: ‘Ultra CPU Usage’,
icon: ‘mdi:chip’,
unit_of_measurement: ‘%’ },
entity_id: ‘sensor.ultra_cpu_usage’,
last_changed: ‘2017-11-02T18:02:48.779439+00:00’,
last_updated: ‘2017-11-02T18:02:48.779439+00:00’,
state: ‘1.5’ } ]

so it seems that it gets some kind of return?

I have change two things in the index.js

uevent.entity_id = ‘script.uvcmotion’;

and the url to HASS.
I needed to use my external adress since I have https (lets crypt)

Don´t know if that matters though…

The only part of the script that could elicit a response is if HA responds with something to the RESTful API call. That’s the only part that actually touches HA. If my RESTful API calls are returning something like that, I’m not seeing it. My Docker logs for the NodeJS container are empty, unless there’s an error.

OK, maybe it doesn’t matter unless that is the reason for my delay.

@alexb which solution do you use to autostart your node script?

@frelev I’m not doing anything special to auto start the script. I run it in a Docker container and all of my containers auto start on their own.

Just wanted to reply here in hopes someone else spends less time having an issue like I did. I think this needs to be called out specifically in the documentation wiki. Perhaps I’ll look at suggesting an edit.

I spent days trying to understand why I just couldn’t get this connection to work. It turns out, the answer was the port. When I was inputting the port as 7443 (aka secure) - it was constantly failing. I would assume this is due in part to a self-signed cert being presented and the connection failing to be secured properly. Unfortunately I wasted all this time when I should have just ignored the port! :smiley:

Thank you for posting this though and helping me realize it was simply the port.

@1activegeek
Thank you sooo much. You did save me a bunch of time!

1 Like

Do you have any updates for this script?
Going to give it a try, Thanks!

I’m not currently using this script since I switched from UniFi Video to using UniFi Protect on their new CloudKey Plus. I’m not sure if the script still works as posted. If it doesn’t, it likely just needs an adjustment to the regex statement to match whatever their current log format is. UniFi occasionally adjusts how they output logs.

1 Like

Thanks,
Do you get motion events on HASIO with Unifi Protect?

I haven’t investigated integrating UniFi Protect with HA as-of-yet. I moved since I originally worked with that script and do not currently have cameras in locations that aren’t already covered by other motion sensors.