Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a new unifi-protect node #48

Merged
merged 43 commits into from
Nov 20, 2022
Merged

Conversation

marcus-j-davies
Copy link
Member

@marcus-j-davies marcus-j-davies commented Oct 23, 2022

@crxporter @Shaquu
Below is what I have built and is ready for review.

  • Adds the bootstrap object to the Access Controller object self.bootstrapObject
  • Adds a shared protect web socket to the Access Controller self.protectSharedWS
    This has 2 important methods
    • registerInterest
    • degisterInterest
  • Updates the bootstrap for each token refresh
  • Adds a unifi-protect node - that allows controlling and listening for camera events

self.bootstrapObject and self.protectSharedWS are only instantiated if the bootstrap was successfully retrieved.
the Protect node will warn the user if a Protect instance was not found.

I issue a 501 - Not Implemented when the node is trying to obtain the cameras.

Screenshot 2022-10-24 at 19 40 45

unifi-protect will call into

const I: Interest = {
    deviceId: this.config.cameraId,
    callback: handleUpdate,
}
  • self.accessControllerNode.protectSharedWS?.registerInterest(self.id, I)
  • self.accessControllerNode.protectSharedWS?.degisterInterest(self.id)

accoridngly, i.e when such node is deployed and removed

Each event type is based on an EventModel

shapeProfile
Is the object that is designed to match (at least) the incoming payload (it uses lodash.isMatch)

metadata
Is the settings/behaviour for that event. the HTML file uses the metadata.id to subscribe to that event (supports multiple)

some models have a valueExpression property and this uses JSONata to extract a value from the payload and passes it on to the user (as payload.value)- these do not support a duration (hasDuration: false) as these are more a constant value change as opposed to an on going event

The combination of hasDuration: true with a valueExpression is marked as invalid in the typescript

Lastley, there is thumbnailSupport : enum and this states whether or not a snapshot is supported with this event.
the motion detection event for example, does not seem to produce a snapshot in my early testing.

Below is the thumbnailSupport enum

export enum ThumbnailSupport {
    START_END = 0,                         /* Supports instant Start And End snapshots */
    START_WITH_DELAYED_END,                /* End snapshots need a delay - user adjustable */
    SINGLE_DELAYED,                        /* Example : A door Bell, where the snapshot is not ready right away  */
    SINGLE,                                /* Why not? */
    NONE,                                  /* No snapshots are produced with this event */
}

There is snapshotAvailability in the payloads to identify to the user the readiness of a snapshot, a 2nd pin is used for delayed snapshots - with the associated event id

https://github.com/marcus-j-davies/node-red-contrib-unifi-os/blob/protect-node/src/EventModels.ts

Some areas may have room for improvements of course, such as creating a new access controller, from within a protect node, it will try and call into the bootstrap before the bootstrap has had a chance to be fetched by the controller (it does this to fetch the cameras using an HTTPAdmin endpoint

they will get a 501 - Not Implemented because the bootstrap has not yet been received.

But other than delaying this request (for new controllers being spawned) - not sure how else it can be achieved, as waiting will add some delay to the cameras being listed.

For already running access controllers - this is not a problem (as the Bootstrap is ready before hand), that is if Protect is running on the target hardware of course else 501

@marcus-j-davies marcus-j-davies marked this pull request as ready for review October 24, 2022 19:06
build/nodes/Protect.html Outdated Show resolved Hide resolved
package.json Show resolved Hide resolved
package.json Show resolved Hide resolved
src/EventModels.ts Outdated Show resolved Hide resolved
src/EventModels.ts Outdated Show resolved Hide resolved
src/EventModels.ts Outdated Show resolved Hide resolved
I needed to put back:  `valueExpression?: undefined` as checking this value later returns valueExpression does not exist.... but it must not be set if hasDuration is true
@marcus-j-davies
Copy link
Member Author

@Shaquu @crxporter
I feel this can be put to BETA?

Please review the last commit.: 3bf7a97
This commit adds a robust (in testing 😅) recovery mechanism via the web socket Ping/Pong protocol.

The Web socket reconfiguring after a new update ID has been fetched - usually triggered by the 30 minutely re-login that occurs in the access controller.

image

A recovery after a network connection drop.
This recovery is only put into high alert after we first successfully get a connection to the web socket, adding recovery to a web socket that was never successful could cause a continuous recovery loop, that will never end.

image

@Shaquu Shaquu changed the base branch from main to dev November 17, 2022 18:27
src/nodes/AccessController.ts Outdated Show resolved Hide resolved
src/types/AccessControllerNodeType.ts Outdated Show resolved Hide resolved
package.json Show resolved Hide resolved
src/EventModels.ts Outdated Show resolved Hide resolved
build/nodes/Protect.html Show resolved Hide resolved
src/SharedProtectWebSocket.ts Outdated Show resolved Hide resolved
src/SharedProtectWebSocket.ts Outdated Show resolved Hide resolved
src/SharedProtectWebSocket.ts Outdated Show resolved Hide resolved
src/SharedProtectWebSocket.ts Outdated Show resolved Hide resolved
src/types/AccessControllerNodeType.ts Outdated Show resolved Hide resolved
@marcus-j-davies
Copy link
Member Author

marcus-j-davies commented Nov 20, 2022

@crxporter @Shaquu

All comments have been addressed.
I have also found out that in NR, if a config node has user properties set to undefined (Evan if not required), it causes an error flag on the nodes that use it (this @Shaquu was the reason for the error indicator) normal nodes don't seem to have this problem (at least I have never seen this happen for non config nodes)

This becomes a problem if an update means new config params are added - as they will be undefined, therefore I have made them required.

Users just need to open up the config node and save to apply a value of 0, 0 sets timeouts to use defaults (90000/15000).

Bootstrap is now a type (types/Bootstrap.ts)

Lastly, my PR is based on the Main branch, since switching to dev - the PR brings in changes that were not apart of the dev branch.

@marcus-j-davies marcus-j-davies changed the base branch from dev to main November 20, 2022 15:36
@marcus-j-davies marcus-j-davies changed the base branch from main to dev November 20, 2022 15:45
@Shaquu Shaquu merged commit ae1c040 into NRCHKB:dev Nov 20, 2022
marcus-j-davies added a commit that referenced this pull request May 30, 2023
* Add a new `unifi-protect` node (#48)

* Update publish to use Node 14 (#50)

* Update package.json

* Beta 2 (Dev 1) (#53)

* Update Deps, Fix Duplicated Cams (hopefully), 2 new events (Boiler plate)

* Cleanup + Add Alarm

* Small typo

* Renew Package lock and small bump to WS type

* Keep it pretty!

* Address comment #1

* Add Event slit

* Add topic (Camera Name)

* Small optimisation

* Improve protect status (#56)

* Add better status logic

* Fix status logic

* Add custom port for WS

* Dev 2

* Update package.json

---------

Co-authored-by: Tadeusz Wyrzykowski <shaquu@icloud.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants