Custom Component: Unifi Protect

The easiest way to resolve image caching is to append a timestamp to the end of the captured image, making it unique. I work in YAML so set a variable with the image name as a first action in the automation and then reference that variable for the other actions.
I use a nightly cron job to clean images older than 14 days from the storage folder.

That link proved very useful - I’ve moved my notification images to a sub-directory of /media after testing it out as part of my prep to move to docker.
As part of the move I also tidied up my automations to use a folder_watcher to automatically update the last motion event image for the dashboard which removed the need for a file copy in the camera automation.
Just the venv->docker and zwave->zwavejs move to go now (all tested, just need a window to migrate with the time to bugfix if needed).

Hello all, clean install of HA and working very well, however im not able to find Unifi protect when i search for it under integrations. Any idea?

Have you installed the integration files using HACs or another method per https://github.com/briis/unifiprotect#installation?
The integration is not yet one of the core integrations included with a installation of HA.

Ah thank you :slight_smile:

Thanks so much for this! Your component is why I dug in and started using Home Assistant (as of yesterday) I have a newb question if you don’t mind. Everything seems to be working great except I notice a good 10 second delay on the feed with this method. Is there any way to improve on that?

alias: Doorbell Nest Display
description: ''
trigger:
  - platform: state
    entity_id: binary_sensor.motion_front_door
    to: 'on'
condition: []
action:
  - data:
      media_player: media_player.kitchen_display
    service: camera.play_stream
    entity_id: camera.front_door
  - delay:
      hours: 0
      minutes: 0
      seconds: 20
      milliseconds: 0
  - service: media_player.turn_off
    data: {}
    entity_id: media_player.kitchen_display
mode: single

Welcome to Home Assistant - hope you will enjoy it.

The Protect integration uses the stream component built-in to Home Assistant, and that gives a 10-20 seconds delay in the stream. I assume it is due to conversion of the RTSP stream.
If you don’t need the Audio, you can disable all the RTSP streams in the Protect APP, and then restart Home Assistant. This will improve the video delay, but you loose the audio.

Thanks! It seems that the same automation doesn’t work after turning off the streams:

Logger: homeassistant.components.stream.worker
Source: components/stream/worker.py:83
Integration: Stream (documentation, issues)
First occurred: 8:11:13 AM (4 occurrences)
Last logged: 8:12:47 AM

Error opening stream rtsp://192.168.1.1:7447/MyFWLhUVZ9qhSXId

It will work in Lovelace, displaying the stream, in a Picture Glance card. I can see it still uses the RTSP stream, so you might need to restart HA. I am not sure it will work though, as the camera.play_streammight require a real stream. I will play a little with it, to see if I can get it to work. Until then, enable the stream again in the Protect App, to at least get the stream with delay.

1 Like

hey @briis

I’m using this with a G4 doorbell. I don’t like how the stock app’s notification doesn’t send a thumbnail, by the time you get into the protect app, the person is gone.

So I successfully built an automation to push a notification to my mobile apps with a screenshot of the camera in HA. This notification has buttons for ‘view in HA’ and ‘view in Protect’.

For ‘view in protect’, I’m trying to grab the intent, so that I can take the user straight to the doorbell live view, just like the protect app does. So I grabbed a logcat and found this intent:

03-03 15:25:08.880  1335  4546 D OemSceneCallBlock: isCallBlockedWithUidIntent { flg=0x1000c000 cmp=com.ubnt.unifi.protect/com.ubnt.activities.DashboardActivity (has extras) }, ResolveInfo{307d3d2 com.ubnt.unifi.protect/com.ubnt.activities.DashboardActivity m=0x0}
03-03 15:25:08.881  1335  4546 I ActivityTaskManager: START u0 {flg=0x1000c000 cmp=com.ubnt.unifi.protect/com.ubnt.activities.DashboardActivity (has extras)} from uid 10692 pid -1
03-03 15:25:08.887  1335  4546 E ANDR-PERF-JNI: com_qualcomm_qtiperformance_native_perf_io_prefetch_start
03-03 15:25:08.894  1335  4546 D ActivityTrigger: ActivityTrigger activityPauseTrigger
03-03 15:25:08.896  1630  1632 E ANDR-IOP: io prefetch is disabled
03-03 15:25:08.897  3796  3796 D Launcher: onPause# hashcode: 165350502
03-03 15:25:08.897  3796  3796 I ShelfLauncherCallbacks: onPause
03-03 15:25:08.898  3796  3961 I WeatherProvider: un-subscribe the weather callback:
03-03 15:25:08.898  1335  1402 D OpPowerConsumpStatsInjector: notifyPkgEvent
03-03 15:25:08.898  1335  1402 D OpRestartProcessManager: updateSelf :  com.ubnt.unifi.protect, size : 30
03-03 15:25:08.900 12671 12671 W ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy@2af5800
03-03 15:25:08.900  1335  4497 D OemSceneModeActivityStack: [scene] evaluateGameModes :  gameMsg.arg1=0 gameMsg.arg2=1
03-03 15:25:08.901  1335  4497 D OpQuickReply: setQuickReplyResumed focusedApp AppWindowToken{986f755 token=Token{53defa7 ActivityRecord{83f10a3 u0 com.ubnt.unifi.protect/com.ubnt.activities.DashboardActivity t23672}}} pkgName com.ubnt.unifi.protect

(I changed around some numbers in case there is identifying info here)

Is there any chance you know how to make sense of this? I have no clue how to sort out which part of this is the “intent”

cheers!

image

Hi @VinistoisR
Unfortunately I cannot help here. I think we need someone with mobile skills to help out.

I’m familiar with mobile, whatever @VinistoisR is trying to do is what I’d like to do as well.

How are you jumping directly to the specific camera view in HA? I can only figure out how to go to a “dashboard” in HA, not the actual live view. I think this is a limitation.

However, for jumping directly to Unifi Protect I think they have some protected adb intents. Jumping directly to a camera activity seems to result in a permission denial / security exception

./adb.exe shell am start -n com.ubnt.unifi.protect/com.ubnt.activities.timelapse.CameraActivity


Starting: Intent { cmp=com.ubnt.unifi.protect/com.ubnt.activities.timelapse.CameraActivity }

Exception occurred while executing 'start':
java.lang.SecurityException: Permission Denial: starting Intent { flg=0x10000000 cmp=com.ubnt.unifi.protect/com.ubnt.activities.timelapse.CameraActivity } from null (pid=15243, uid=2000) not exported from uid 10340
        at com.android.server.wm.ActivityStackSupervisor.checkStartAnyActivityPermission(ActivityStackSupervisor.java:1043)
        at com.android.server.wm.ActivityStarter.executeRequest(ActivityStarter.java:999)
        at com.android.server.wm.ActivityStarter.execute(ActivityStarter.java:669)
        at com.android.server.wm.ActivityTaskManagerService.startActivityAsUser(ActivityTaskManagerService.java:1096)
        at com.android.server.wm.ActivityTaskManagerService.startActivityAsUser(ActivityTaskManagerService.java:1068)
        at com.android.server.am.ActivityManagerService.startActivityAsUserWithFeature(ActivityManagerService.java:3662)
        at com.android.server.am.ActivityManagerShellCommand.runStartActivity(ActivityManagerShellCommand.java:544)
        at com.android.server.am.ActivityManagerShellCommand.onCommand(ActivityManagerShellCommand.java:186)
        at android.os.BasicShellCommandHandler.exec(BasicShellCommandHandler.java:98)
        at android.os.ShellCommand.exec(ShellCommand.java:44)
        at com.android.server.am.ActivityManagerService.onShellCommand(ActivityManagerService.java:10505)
        at android.os.Binder.shellCommand(Binder.java:929)
        at android.os.Binder.onTransact(Binder.java:813)
        at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:5053)
        at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2867)
        at android.os.Binder.execTransactInternal(Binder.java:1159)
        at android.os.Binder.execTransact(Binder.java:1123)

However, when issuing

./adb.exe shell am start -n com.ubnt.unifi.protect/com.ubnt.sections.splash.SplashActivity

Starting: Intent { cmp=com.ubnt.unifi.protect/com.ubnt.sections.splash.SplashActivity }

This results in opening the Unifi Protect app’s last activity, which if the last thing you were on was the main activity, or a live camera view, it will be that.

Sending this as a HA notification would be the following, but it appears that you can lose the specific activity addition and just call on the app as the URI (https://companion.home-assistant.io/docs/notifications/actionable-notifications#android-example)

service: notify.mobile_app_pixel_3
data:
  message: 'test'
  data:
    actions:
      - action: "URI"
        title: "Open Unifi"
        uri: 'app://com.ubnt.unifi.protect'

According to the HA docs, actionable notifications only show two examples: URI / URL

However, it appears if you change the action using the following example, you can achieve specific intents to launch into apps with: https://companion.home-assistant.io/docs/notifications/notification-commands/#broadcast-intent

automation:
  - alias: Send broadcast intent
    trigger:
      ...
    action:
      service: notify.mobile_app_<your_device_id_here>
      data:
        message: "command_broadcast_intent"
        title: "action"
        data:
          channel: "com.ubnt.unifi.protect"

I’ve tried executing the above action FROM the notification shade via the android app, but I am afraid the android app doesn’t support this kind of response. If you wanted a specific intent, you’d probably have to send an action to your HA instance, which then would reply via an automation. However, I couldn’t get this to work as I think you need to be part of the correct “category” for the action, which the HA android app doesn’t allow doing via actions at the moment.

service: notify.mobile_app_pixel_3
data:
  message: command_broadcast_intent
  title: android.intent.action.MAIN
  data:
    channel: "com.ubnt.unifi.protect/com.ubnt.sections.splash.SplashActivity"

Spent a few hours looking at this for fun this morning. Hope this is helpful

1 Like

Hi @VinistoisR - can you post your automation for doing this? Sounds useful! Thanks!

FWIW, here’s what you’d be looking for:

- alias: ALERT (AWAY) - Motion at Front Door, notify Mobile App
  mode: single # Only run once at a time  
  max_exceeded: silent # Hide warnings when triggered while in delay.
  trigger:
    platform: state
    entity_id:
     - binary_sensor.front_outdoor_motion_sensor
    to: 'on'
  condition:
    - condition: state
      entity_id: variable.family_status
      state: 'Away'
  action:
    - service: notify.mobile_app_pixel_3
      data:
        title: "Front Door Motion"
        message: ""
        data:
          image: "/api/camera_proxy/camera.front_door" #Captures image immediately, sends via notification
          ttl: 0
          priority: high
          clickAction: ""
          actions:
          - action: "URI"
            title: "Open Unifi"
            uri: 'app://com.ubnt.unifi.protect'
          - action: "URI"
            title: "Open HASS"
            uri: '/lovelace/camera_view'
2 Likes

@briis Do you mind explaining what exactly is

event_score

and

event_length

is? I assume event_length is the length of time motion was detected, but what is event_score?

I have SO many false positives, and it seems like these might help out. It’s so annoying. Not sure if it’d be worth adding to the github repo. Looked around there but couldn’t find an explanation.

The Event Score is a number Protect assigns to a Motion or Smart event. It is a number between 0 and 100, and without knowing the algorithm behind it, it seems that the higher the number, the more certain you are of a ‘real’ motion event occurring. So if you have false positives, you could try and test for the event_score attribute, maybe only act on numbers over 70 as a starting point. Please note that score normally only is set, when the event has ended.

And event_length, is the length in seconds of the last occurred motion event.

1 Like

I would love to be able to set the “custom text” of the doorbel, but I think that still not part of the API or is it?

Hi Greg,
Oh yes, this is possible and has been for a while. You can use the following service:

service: unifiprotect.set_doorbell_lcd_message
data:
  entity_id: camera.doorbell
  message: Ring the bell
  duration: 15

duration is optional, if you leave it out, the message will stay.

1 Like

SOMG COOL! Directly set actions for my notifications!

1 Like

Has anyone found a way to deep link from Home Assistant to a specific camera in the Unifi Protect app?

I read that both @marcelod and @dts asked about it before, did you ever manage to solve this?

I had no success, sadly. Tried looking into the iOS app bundle but the only URL in CFBundleURLSchemes is unifi-protect:// which just launches the app. I don’t think Ubiquiti have implemented deep linking to specific screens of the app by the looks of it.

What I don’t understand though is that if you enable push notifications for motion events, the notification banners do link straight to the motion event in the timeline view, so there must be a URI scheme to make this work.

Maybe someone with more iOS app expertise can chime in but I couldn’t get it to work by just trial and error.