neilenns / node-deepstackai-trigger

Detects motion using Deepstack AI and calls registered triggers based on trigger rules.
MIT License
167 stars 28 forks source link

Is it possible to show latest Trigger as a camera in home assistant? #397

Closed SurfingSpider closed 4 years ago

SurfingSpider commented 4 years ago

I am migrating from the "HASS-Deepstack-object" Hassio Addon. One of the features I really like is that I can have a display of the latest trigger event as a camera in the home assistant dashboard because it saves a copy under the file name Latest than I can point home assistant to to display a picture of the latest trigger.

https://github.com/robmarkcole/HASS-Deepstack-object#displaying-the-deepstack-latest-jpg-file

Is there a way I can do this with your version? I have enabled the webserver, but each file name its date stamped so I cant point a home assistant camera entity at it. If it saved two copies one called latest and the other time stamped you could e.g.

camera:
  - platform: generic
    name: Doorbell
    still_image_url: 'http://192.168.86.46:4242/annotations/Road-HD.Latest.jpg'  
neilenns commented 4 years ago

Hmmm, interesting. So I have this working now but I'm using NodeRed to do it. Here's what I have set up:

  1. The trigger sends an MQTT event
  2. NodeRed receives the MQTT event and uses it to generate a snapshot from the camera directly (I have all the cameras as entities in HA as well)
  3. The snapshot is saved to a folder
  4. I show a card in my dashboard showing that snapshot

The reason I do it this way is because I also use the image to send in a notification to my mobile device, and in order for that to work the image has to be accessible outside my home network. I only have the HA device exposed, not the Docker container running the triggers, so the snapshot has to exist on HA in the right location.

Would something like the above work for your situation?

SurfingSpider commented 4 years ago

Yes I believe it would. I will give it a go Thank you

neilenns commented 4 years ago

It's a little tricky to get it working properly on the HA side, it's kind of a pain in the ass to be honest getting the files to write to the correct location for them to actually be accessible. Let me know if you run into any trouble.

SurfingSpider commented 4 years ago

I made that solution work. The only problem I can see with it is the amount of time it takes to trigger the alert and call the snapshot service the subject could well have walked out of shot.

neilenns commented 4 years ago

Yup, I've had that issue occasionally too although usually in practice I haven't found it to be a problem. It seems to work fine for delivery people etc. coming to my door, and it's really just meant to be a quick glance in lieu of firing up UI3 to watch the complete alert clip.

SurfingSpider commented 3 years ago

I thought I would let you know I manged to make a work around using node-red. I was having the situation where I missed the subject of the alert quite often. As the camera angle is quite tight on some of my cameras. Hopefully someone in the future might find this post and it might help them.

Because one of the attributes passed in MQTT is the basename of the JPEG. I was able to use that to create the URL and download the JPEG from the Web interface to use as a Home assistant Camera.

Create the URL using a Template node to create payload msg.url with the template http://<IP ADDR of docker>:4242/annotations/{{payload.basename}}

I had multiple cameras so used a switch node to decide where to save the image.

Then use a HTTP node to download the JPEG. Finally use a file out node to save the JPEG to disk.

Capture

Home assistant camera setup Configuration.yaml

camera:
  - platform: local_file
    file_path: "/config/deepstack-snapshots-Road/Road_person_detector_latest.jpg"
    name: "Road Camera latest person"  

[{"id":"85861b6d.74d278","type":"mqtt in","z":"47f4c5f8.c6c55c","name":"","topic":"aimotion/triggers/BackDoor","qos":"2","datatype":"json","broker":"1df19456.a2ad8c","x":190,"y":220,"wires":[["80330bf.ce389f8"]]},{"id":"a1f0331.b4910d","type":"mqtt in","z":"47f4c5f8.c6c55c","name":"","topic":"aimotion/triggers/FrontDoor","qos":"2","datatype":"json","broker":"1df19456.a2ad8c","x":190,"y":160,"wires":[["80330bf.ce389f8"]]},{"id":"f6bab02d.adbe1","type":"mqtt in","z":"47f4c5f8.c6c55c","name":"","topic":"aimotion/triggers/Road","qos":"2","datatype":"json","broker":"1df19456.a2ad8c","x":180,"y":100,"wires":[["80330bf.ce389f8","fd83dfbe.0a51"]]},{"id":"80330bf.ce389f8","type":"switch","z":"47f4c5f8.c6c55c","name":"Stop if State off","property":"payload.state","propertyType":"msg","rules":[{"t":"neq","v":"off","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":460,"y":160,"wires":[["67c3a661.f27a58"]]},{"id":"67c3a661.f27a58","type":"template","z":"47f4c5f8.c6c55c","name":"Convert basename to URL","field":"url","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"http://192.168.86.46:4242/annotations/{{payload.basename}}","output":"str","x":680,"y":160,"wires":[["38cbe86b.2ba648","12b34820.9cd3c8"]]},{"id":"38cbe86b.2ba648","type":"http request","z":"47f4c5f8.c6c55c","name":"","method":"GET","ret":"bin","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":950,"y":160,"wires":[["a3953993.110278","9ff11950.368af8"]]},{"id":"9ff11950.368af8","type":"switch","z":"47f4c5f8.c6c55c","name":"","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"aimotion/triggers/Road","vt":"str"},{"t":"eq","v":"aimotion/triggers/FrontDoor","vt":"str"},{"t":"eq","v":"aimotion/triggers/BackDoor","vt":"str"}],"checkall":"true","repair":false,"outputs":3,"x":1140,"y":160,"wires":[["6a3a71f2.9a306"],["53af788.5416788"],["6e85ab0a.43dc64"]]},{"id":"6a3a71f2.9a306","type":"file","z":"47f4c5f8.c6c55c","name":"","filename":"/config/deepstack-snapshots-Road/Road_person_detector_latest.jpg","appendNewline":false,"createDir":false,"overwriteFile":"true","encoding":"none","x":1510,"y":100,"wires":[["31bf5eb4.efbb92"]]},{"id":"53af788.5416788","type":"file","z":"47f4c5f8.c6c55c","name":"","filename":"/config/deepstack-snapshots-frontdoor/frontdoor_camera_person_detector_latest.jpg","appendNewline":false,"createDir":false,"overwriteFile":"true","encoding":"none","x":1560,"y":160,"wires":[["ce3bff69.94466"]]},{"id":"6e85ab0a.43dc64","type":"file","z":"47f4c5f8.c6c55c","name":"","filename":"/config/deepstack-snapshots-backdoor/backdoor_camera_person_detector_latest.jpg","appendNewline":false,"createDir":false,"overwriteFile":"true","encoding":"none","x":1560,"y":220,"wires":[["ae7096a4.3a2078"]]},{"id":"1df19456.a2ad8c","type":"mqtt-broker","name":"Hassio MQTT","broker":"192.168.86.40","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""}]

neilenns commented 3 years ago

Ah yeah! Good idea, I should have remembered that was in the MQTT data. I put it there for this exact reason. Oops :D

ghzgod commented 3 years ago

I re-did this flow to be a little more efficient. Please see below, and here is screenshot. This keeps everything in a single dir and names files based on camera name from trigger. This also works with hassio.

My homeassistant config is as follows:

camera:
  - platform: local_file
    file_path: "/share/deepstack/Dome.jpg"
    name: "Dome"
  - platform: local_file
    file_path: "/share/deepstack/Backyard.jpg"
    name: "Backyard" 
  - platform: local_file
    file_path: "/share/deepstack/Fence.jpg"
    name: "Fence" 
  - platform: local_file
    file_path: "/share/deepstack/Inside.jpg"
    name: "Inside" 
  - platform: local_file
    file_path: "/share/deepstack/Driveway.jpg"
    name: "Driveway" 

Let me know if you have any questions!

[
    {
        "id": "f3d27a1f.49efb8",
        "type": "tab",
        "label": "Deepstack",
        "disabled": false,
        "info": ""
    },
    {
        "id": "80330bf.ce389f8",
        "type": "switch",
        "z": "f3d27a1f.49efb8",
        "name": "State On?",
        "property": "payload.state",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "on",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 1,
        "x": 520,
        "y": 120,
        "wires": [
            [
                "73573a66.d441cc"
            ]
        ]
    },
    {
        "id": "67c3a661.f27a58",
        "type": "template",
        "z": "f3d27a1f.49efb8",
        "name": "Convert basename to URL",
        "field": "url",
        "fieldType": "msg",
        "format": "handlebars",
        "syntax": "mustache",
        "template": "http://192.168.1.9:4242/annotations/{{payload.basename}}",
        "output": "str",
        "x": 940,
        "y": 120,
        "wires": [
            [
                "38cbe86b.2ba648"
            ]
        ]
    },
    {
        "id": "38cbe86b.2ba648",
        "type": "http request",
        "z": "f3d27a1f.49efb8",
        "name": "",
        "method": "GET",
        "ret": "bin",
        "paytoqs": "ignore",
        "url": "",
        "tls": "",
        "persist": false,
        "proxy": "",
        "authType": "",
        "x": 110,
        "y": 180,
        "wires": [
            [
                "371286ee.00576a"
            ]
        ]
    },
    {
        "id": "dda721d5.7241f",
        "type": "mqtt in",
        "z": "f3d27a1f.49efb8",
        "name": "",
        "topic": "node-deepstackai-trigger/alert/#",
        "qos": "2",
        "datatype": "auto",
        "broker": "136f17b0.dd6c7",
        "x": 160,
        "y": 120,
        "wires": [
            [
                "10089e32.ab7e6a"
            ]
        ]
    },
    {
        "id": "10089e32.ab7e6a",
        "type": "json",
        "z": "f3d27a1f.49efb8",
        "name": "",
        "property": "payload",
        "action": "",
        "pretty": false,
        "x": 370,
        "y": 120,
        "wires": [
            [
                "80330bf.ce389f8"
            ]
        ]
    },
    {
        "id": "7f88f5e5.ca007c",
        "type": "file",
        "z": "f3d27a1f.49efb8",
        "name": "Load File",
        "filename": "",
        "appendNewline": false,
        "createDir": true,
        "overwriteFile": "true",
        "encoding": "none",
        "x": 500,
        "y": 180,
        "wires": [
            []
        ]
    },
    {
        "id": "371286ee.00576a",
        "type": "change",
        "z": "f3d27a1f.49efb8",
        "name": "Format Filename",
        "rules": [
            {
                "t": "set",
                "p": "filename",
                "pt": "msg",
                "to": "\"/share/deepstack/\" & msg.topic & \".jpg\"",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 310,
        "y": 180,
        "wires": [
            [
                "7f88f5e5.ca007c"
            ]
        ]
    },
    {
        "id": "73573a66.d441cc",
        "type": "change",
        "z": "f3d27a1f.49efb8",
        "name": "Set Topic",
        "rules": [
            {
                "t": "set",
                "p": "topic",
                "pt": "msg",
                "to": "payload.name",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 680,
        "y": 120,
        "wires": [
            [
                "67c3a661.f27a58"
            ]
        ]
    },
    {
        "id": "136f17b0.dd6c7",
        "type": "mqtt-broker",
        "name": "HASS-MQTT",
        "broker": "192.168.1.10",
        "port": "1883",
        "tls": "",
        "clientid": "NodeRed",
        "usetls": false,
        "compatmode": false,
        "keepalive": "300",
        "cleansession": true,
        "birthTopic": "nodered",
        "birthQos": "0",
        "birthPayload": "connected",
        "closeTopic": "nodered",
        "closeQos": "0",
        "closePayload": "disconnected",
        "willTopic": "nodered",
        "willQos": "0",
        "willPayload": "unexpected disconnect"
    }
]
SurfingSpider commented 3 years ago

Nicely done. 👍