Hi @bceyresy ,
looks like we are working similar projects
.. as mentioned above (2nd item) I'm showcasing the last 10 pictures of each camera in NR dashboard

I'm using BlueIris but there are other products (like frigate as mentioned by @craigcurtin ) which can achieve the same results .. but for all of them you need enough processing power to analyse the picture quickly enough.. especially when using multiple cameras.
i'm using a normal FIFO buffer to secure the last 10 mqtt messages (incl picture) per camera and showing them, in a simple ui-template (still on Dashboard v1) .. see code below for 1 camera
[
{
"id": "8cd152086dfd436a",
"type": "group",
"z": "1c76686932178a74",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"d45d705db2ebe914",
"adc54e4ac0f8532d",
"101246083dad963c",
"0af616a7b9303b90",
"71a7c3d12c733125",
"ce2fa4be836a7c34",
"dacd9cc1798effc9",
"41b36893b203fcc6",
"695a4920fbd486a9",
"4e400edf5cfe7bd8",
"11b2e326b2320f17"
],
"x": 564,
"y": 239,
"w": 742,
"h": 202
},
{
"id": "1b99e955a9f97cad",
"type": "subflow",
"name": "FIFO",
"info": "# FIFO\n## First in First Out subflow\nThis flow receives a series of msg.payloads and builds a queue using FIFO (First in First out) method. The LIFO size is configurabe through subflow enviroment variables.\n\n### Input\n`msg.topic == put`\nWill add the `msg.payload` to the end of the array. Everytime a new item is received the second output sends the complete queue.\n\n`msg.topic == get`\nWill remove the first item of the stack and will send it in the first output\n\n`msg.topic == list`\nSends the complete list on the second output.\n\n### Output 1\nThe first item on the top of the stack. It is sent only when `msg.topic == get`.\n\n### Output 2\nThe complete queue in Array format. It is sent everytime a new item is added, removed or when `msg.topic == list`\n\n### Status\nAlways show the queue size.\n\n### Enviroment Variables\n`Buffer_Size` defines the size of the queue. If a new item arrives and the queue is full, the oldest item will be removed.",
"category": "",
"in": [
{
"x": 100,
"y": 120,
"wires": [
{
"id": "f4e8af593dda8bf3"
}
]
}
],
"out": [
{
"x": 1120,
"y": 60,
"wires": [
{
"id": "7c0a144c051ed66f",
"port": 0
}
]
},
{
"x": 1120,
"y": 100,
"wires": [
{
"id": "39b6b38f614a42a6",
"port": 0
}
]
}
],
"env": [
{
"name": "Buffer_Size",
"type": "num",
"value": "6"
}
],
"icon": "font-awesome/fa-ellipsis-v",
"status": {
"x": 1120,
"y": 140,
"wires": [
{
"id": "de6a9df2eede30c3",
"port": 0
}
]
}
},
{
"id": "90f14a6dfe5ca406",
"type": "switch",
"z": "1b99e955a9f97cad",
"name": "Topic",
"property": "topic",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "get",
"vt": "str"
},
{
"t": "eq",
"v": "put",
"vt": "str"
},
{
"t": "eq",
"v": "list",
"vt": "str"
},
{
"t": "eq",
"v": "clear",
"vt": "str"
},
{
"t": "else"
}
],
"checkall": "true",
"repair": false,
"outputs": 5,
"x": 390,
"y": 120,
"wires": [
[
"0d69c5fc4283a7c4"
],
[
"53d55044c54ffeb2"
],
[
"ddc1eb7421e343d9"
],
[
"4cbf1be47dfafd93"
],
[]
]
},
{
"id": "0d69c5fc4283a7c4",
"type": "function",
"z": "1b99e955a9f97cad",
"name": "get",
"func": "let xxx = flow.get(\"queue\");\nvar item;\n\nif (!Array.isArray(xxx)){\n //queue = [];\n //queue.length=0;\n xxx.splice(0, xxx.length);\n}else\n{\n item = xxx.pop();\n}\n\n\nflow.set(\"queue\", xxx)\nmsg.payload = item;\n\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 550,
"y": 60,
"wires": [
[
"c535b4175dfdd648"
]
]
},
{
"id": "de6a9df2eede30c3",
"type": "change",
"z": "1b99e955a9f97cad",
"name": "Count",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "$count(msg.payload)\t",
"tot": "jsonata"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 850,
"y": 140,
"wires": [
[]
]
},
{
"id": "4cbf1be47dfafd93",
"type": "change",
"z": "1b99e955a9f97cad",
"name": "",
"rules": [
{
"t": "delete",
"p": "queue",
"pt": "flow"
},
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "queue",
"tot": "flow"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 580,
"y": 180,
"wires": [
[
"de6a9df2eede30c3"
]
]
},
{
"id": "ddc1eb7421e343d9",
"type": "change",
"z": "1b99e955a9f97cad",
"name": "queue",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "queue",
"tot": "flow"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 550,
"y": 140,
"wires": [
[
"de6a9df2eede30c3",
"422b417b1cf9e0ea"
]
]
},
{
"id": "53d55044c54ffeb2",
"type": "function",
"z": "1b99e955a9f97cad",
"name": "put",
"func": "var queue = flow.get(\"queue\")\n\n\nif (!Array.isArray(queue)){\n queue = [];\n}else if ( queue.length >= env.get(\"Buffer_Size\") ){\n queue.pop(1);\n}\n\nqueue.unshift(msg.payload);\n\nflow.set(\"queue\", queue);\nmsg.payload = queue;\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 550,
"y": 100,
"wires": [
[
"422b417b1cf9e0ea"
]
]
},
{
"id": "f4e8af593dda8bf3",
"type": "json",
"z": "1b99e955a9f97cad",
"name": "",
"property": "payload",
"action": "str",
"pretty": false,
"x": 230,
"y": 120,
"wires": [
[
"90f14a6dfe5ca406"
]
]
},
{
"id": "422b417b1cf9e0ea",
"type": "split",
"z": "1b99e955a9f97cad",
"name": "",
"splt": "\\n",
"spltType": "str",
"arraySplt": 1,
"arraySpltType": "len",
"stream": false,
"addname": "",
"x": 710,
"y": 100,
"wires": [
[
"2ccfc1845e1122fe"
]
]
},
{
"id": "2ccfc1845e1122fe",
"type": "json",
"z": "1b99e955a9f97cad",
"name": "",
"property": "payload",
"action": "obj",
"pretty": false,
"x": 850,
"y": 100,
"wires": [
[
"39b6b38f614a42a6"
]
]
},
{
"id": "39b6b38f614a42a6",
"type": "join",
"z": "1b99e955a9f97cad",
"name": "",
"mode": "auto",
"build": "object",
"property": "payload",
"propertyType": "msg",
"key": "topic",
"joiner": "\\n",
"joinerType": "str",
"accumulate": "false",
"timeout": "",
"count": "",
"reduceRight": false,
"x": 990,
"y": 100,
"wires": [
[]
]
},
{
"id": "c535b4175dfdd648",
"type": "split",
"z": "1b99e955a9f97cad",
"name": "",
"splt": "\\n",
"spltType": "str",
"arraySplt": 1,
"arraySpltType": "len",
"stream": false,
"addname": "",
"x": 710,
"y": 60,
"wires": [
[
"acaad2afe7f73430"
]
]
},
{
"id": "acaad2afe7f73430",
"type": "json",
"z": "1b99e955a9f97cad",
"name": "",
"property": "payload",
"action": "obj",
"pretty": false,
"x": 850,
"y": 60,
"wires": [
[
"7c0a144c051ed66f"
]
]
},
{
"id": "7c0a144c051ed66f",
"type": "join",
"z": "1b99e955a9f97cad",
"name": "",
"mode": "auto",
"build": "object",
"property": "payload",
"propertyType": "msg",
"key": "topic",
"joiner": "\\n",
"joinerType": "str",
"accumulate": "false",
"timeout": "",
"count": "",
"reduceRight": false,
"x": 990,
"y": 60,
"wires": [
[]
]
},
{
"id": "d45d705db2ebe914",
"type": "change",
"z": "1c76686932178a74",
"g": "8cd152086dfd436a",
"name": "Driveway -> Buffer",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "mqtt",
"tot": "msg"
},
{
"t": "set",
"p": "topic",
"pt": "msg",
"to": "put",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 830,
"y": 320,
"wires": [
[
"dacd9cc1798effc9"
]
]
},
{
"id": "adc54e4ac0f8532d",
"type": "link in",
"z": "1c76686932178a74",
"g": "8cd152086dfd436a",
"name": "link in 48",
"links": [
"2942673c5bf7d2a8",
"d0d0ce31c8a83f36",
"137a398dfa469bb3",
"2a805b8a5539d768"
],
"x": 605,
"y": 320,
"wires": [
[
"d45d705db2ebe914"
]
]
},
{
"id": "101246083dad963c",
"type": "ui_ui-button",
"z": "1c76686932178a74",
"g": "8cd152086dfd436a",
"action": "click",
"actionType": "str",
"name": "",
"group": "c8ac5f2f9243b373",
"order": 1,
"width": "6",
"height": "1",
"passthru": false,
"label": "Driveway",
"tooltip": "",
"color": "",
"bgcolor": "",
"icon": "",
"x": 710,
"y": 360,
"wires": [
[
"0af616a7b9303b90"
]
]
},
{
"id": "0af616a7b9303b90",
"type": "change",
"z": "1c76686932178a74",
"g": "8cd152086dfd436a",
"name": "list",
"rules": [
{
"t": "set",
"p": "topic",
"pt": "msg",
"to": "list",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 870,
"y": 360,
"wires": [
[
"dacd9cc1798effc9"
]
]
},
{
"id": "71a7c3d12c733125",
"type": "inject",
"z": "1c76686932178a74",
"g": "8cd152086dfd436a",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 700,
"y": 400,
"wires": [
[
"0af616a7b9303b90"
]
]
},
{
"id": "ce2fa4be836a7c34",
"type": "ui_template",
"z": "1c76686932178a74",
"g": "8cd152086dfd436a",
"group": "c8ac5f2f9243b373",
"name": "Drivway image",
"order": 2,
"width": "9",
"height": 24,
"format": "\n{{msg.payload[0].time}} {{msg.payload[0].date}} {{msg.payload[0].ai}}\n<img width=\"100%\" height=\"100%\" alt=\"\" src=\"data:image/png;base64,{{msg.payload[0].pic}}\" />\n{{msg.payload[1].time}} {{msg.payload[1].date}} {{msg.payload[1].ai}}\n<img width=\"100%\" height=\"100%\" alt=\"\" src=\"data:image/png;base64,{{msg.payload[1].pic}}\" />\n{{msg.payload[2].time}} {{msg.payload[2].date}} {{msg.payload[2].ai}}\n<img width=\"100%\" height=\"100%\" alt=\"\" src=\"data:image/png;base64,{{msg.payload[2].pic}}\" />\n{{msg.payload[3].time}} {{msg.payload[3].date}} {{msg.payload[3].ai}}\n<img width=\"100%\" height=\"100%\" alt=\"\" src=\"data:image/png;base64,{{msg.payload[3].pic}}\" />\n{{msg.payload[4].time}} {{msg.payload[4].date}} {{msg.payload[4].ai}}\n<img width=\"100%\" height=\"100%\" alt=\"\" src=\"data:image/png;base64,{{msg.payload[4].pic}}\" />\n{{msg.payload[5].time}} {{msg.payload[5].date}} {{msg.payload[5].ai}}\n<img width=\"100%\" height=\"100%\" alt=\"\" src=\"data:image/png;base64,{{msg.payload[5].pic}}\" />\n{{msg.payload[6].time}} {{msg.payload[6].date}} {{msg.payload[6].ai}}\n<img width=\"100%\" height=\"100%\" alt=\"\" src=\"data:image/png;base64,{{msg.payload[6].pic}}\" />\n{{msg.payload[7].time}} {{msg.payload[7].date}} {{msg.payload[7].ai}}\n<img width=\"100%\" height=\"100%\" alt=\"\" src=\"data:image/png;base64,{{msg.payload[7].pic}}\" />\n{{msg.payload[8].time}} {{msg.payload[8].date}} {{msg.payload[8].ai}}\n<img width=\"100%\" height=\"100%\" alt=\"\" src=\"data:image/png;base64,{{msg.payload[8].pic}}\" />\n{{msg.payload[9].time}} {{msg.payload[9].date}} {{msg.payload[9].ai}}\n<img width=\"100%\" height=\"100%\" alt=\"\" src=\"data:image/png;base64,{{msg.payload[9].pic}}\" />\n\n",
"storeOutMessages": true,
"fwdInMessages": true,
"resendOnRefresh": false,
"templateScope": "local",
"className": "",
"x": 1200,
"y": 340,
"wires": [
[]
]
},
{
"id": "dacd9cc1798effc9",
"type": "junction",
"z": "1c76686932178a74",
"g": "8cd152086dfd436a",
"x": 960,
"y": 340,
"wires": [
[
"41b36893b203fcc6"
]
]
},
{
"id": "41b36893b203fcc6",
"type": "subflow:1b99e955a9f97cad",
"z": "1c76686932178a74",
"g": "8cd152086dfd436a",
"name": "",
"env": [
{
"name": "Buffer_Size",
"value": "10",
"type": "num"
}
],
"x": 1030,
"y": 340,
"wires": [
[],
[
"ce2fa4be836a7c34",
"695a4920fbd486a9"
]
]
},
{
"id": "695a4920fbd486a9",
"type": "debug",
"z": "1c76686932178a74",
"g": "8cd152086dfd436a",
"name": "debug 137",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1150,
"y": 380,
"wires": []
},
{
"id": "4e400edf5cfe7bd8",
"type": "change",
"z": "1c76686932178a74",
"g": "8cd152086dfd436a",
"name": "list",
"rules": [
{
"t": "set",
"p": "topic",
"pt": "msg",
"to": "list",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 870,
"y": 280,
"wires": [
[
"dacd9cc1798effc9"
]
]
},
{
"id": "11b2e326b2320f17",
"type": "ui_ui-button",
"z": "1c76686932178a74",
"g": "8cd152086dfd436a",
"action": "click",
"actionType": "str",
"name": "Clear",
"group": "c8ac5f2f9243b373",
"order": 1,
"width": "3",
"height": "1",
"passthru": false,
"label": "Clear",
"tooltip": "",
"color": "",
"bgcolor": "",
"icon": "",
"x": 730,
"y": 280,
"wires": [
[
"4e400edf5cfe7bd8"
]
]
},
{
"id": "c8ac5f2f9243b373",
"type": "ui_group",
"name": "Driveway",
"tab": "cfb78f60fecf7ee2",
"order": 3,
"disp": false,
"width": "9",
"collapse": false,
"className": ""
},
{
"id": "cfb78f60fecf7ee2",
"type": "ui_tab",
"name": "Cameras",
"icon": "dashboard",
"order": 5,
"disabled": false,
"hidden": false
}
]
- the mqtt image is converted into base64 in a previous node
- the entire mqtt message including img is moved to payload
- the FIFO subflow is moving the entire payload into a buffer structure
- the FIFO is providing an array of payload on the output
- the last image / mqtt message is always the first in the list
- there is a CLEAR button/cmd to empty the FIFO buffer
- there is a REFRESH button/cmd to send the entire buffer to output for displat
- the ui-template is displaying the last 10 images with mqtt details
- my mqtt details are ( msg.payload.pic ,msg.payload.time, msg.payload.date) .. you will have to update your ui-template based on your structure
Hope this will help you .. have fun 