Reload Image Source in Dashboard

With that I can show and overwrite the Image source in Template node from the msg.payload

<div><img src="{{msg.payload}}" name="camera"></div>

with that I would outreload an Image in a plain html page

<div id="cameraStream"><img src="" name="camera"></div>
<script>
   function loadNewImage()
   {
       let time =  new Date().getTime().toLocaleString();
       time = time = time.replace(/,/g,"");
       document.images.camera.src = "http://127.0.0.1:9080/camera/stream.jpeg??time=" + time;
       setTimeout(loadNewImage, 100);
   }
   loadNewImage();
</script>

how would I change the HTML version to run inside the scope of the Template node ?

You could just send in a timestamp to the template node from an inject node:

[
    {
        "id": "ad47ce9f.bc4bb",
        "type": "ui_template",
        "z": "110fbb70.97c19d",
        "group": "aff659f4.4b64b",
        "name": "",
        "order": 0,
        "width": 0,
        "height": 0,
        "format": "<div><img src=\"http://127.0.0.1:9080/camera/stream.jpeg?time={{msg.payload}}\" name=\"camera\"></div>",
        "storeOutMessages": true,
        "fwdInMessages": true,
        "resendOnRefresh": true,
        "templateScope": "local",
        "x": 500,
        "y": 794.75,
        "wires": [
            []
        ]
    },
    {
        "id": "ae516cc8.bde318",
        "type": "inject",
        "z": "110fbb70.97c19d",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "1",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 332,
        "y": 794.75,
        "wires": [
            [
                "ad47ce9f.bc4bb"
            ]
        ]
    }
]

Resending the Timestamp would requiere every 100 milliseconds an update. I would like to keep the noise in the template node not in the flow

What exactly do you mean here? This code, once in the browser, runs only in the browser.

Also, does the camera not have an mpeg or h264 stream instead of using a timeout to fetch a static image every 100ms? What type of camera is this?

@Steve-Mcl
I have to admit the camera is actually some python code I put together to stream a camera video through OpenCV for aruco detection and than to web with augmented results..
Not sure If I can change it for mpeg streaming.
So I have to stick withe the Image reload for the moment.

So what I mean exactly is I would need a simply template node which does a constant image reload

Hi, if I am understanding you, then you want something like this?

Demo flow...

[{"id":"e56cb027.484f1","type":"ui_template","z":"38c5e956.a8e786","group":"a63b29d.f4c81d8","name":"","order":0,"width":"12","height":"9","format":"<div id=\"cameraStream\">\n    <img id=\"cameraImg\" src=\"\" name=\"camera\">\n</div>\n<script>\n(function(scope) {\n    var url = \"https://picsum.photos/200/300\";\n    var interval = 1000;\n    var timer = null;\n    scope.$watch('msg', function(msg) {\n        if (msg) {\n            debugger\n            if(msg.topic === \"setURL\") url = msg.payload;\n            if(msg.topic === \"setInterval\") {\n                stop();\n                interval = Number(msg.payload);\n                start();\n            }\n            if(msg.topic === \"stop\") stop();\n            if(msg.topic === \"start\") start();\n        }\n    });\n    function start() {\n        debugger\n        if(isNaN(interval) == false && interval > 0) {\n            timer = setInterval(loadNewImage, interval);\n        } else {\n            console.warn(\"interval is valid\");\n        }\n    }\n    function stop() {\n        if(timer) {\n            clearInterval(timer);\n            timer = null;\n        }\n    }\n    function loadNewImage() {\n        if(url) {\n            let time =  new Date().getTime().toLocaleString().replace(/,/g,\"\");\n            //let time Date.now(); //use epoch as an alternative\n            $(\"#cameraImg\").attr(\"src\", `${url}?time=${time}`);\n        }\n    }\n\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","x":476,"y":384,"wires":[[]]},{"id":"b1160200.58ac5","type":"inject","z":"38c5e956.a8e786","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"stop","payload":"","payloadType":"date","x":272,"y":320,"wires":[["e56cb027.484f1"]]},{"id":"cb4b8ed3.53d22","type":"inject","z":"38c5e956.a8e786","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"start","payload":"","payloadType":"date","x":272,"y":368,"wires":[["e56cb027.484f1"]]},{"id":"384b9999.113856","type":"inject","z":"38c5e956.a8e786","name":"setURL unsplash","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"setURL","payload":"https://source.unsplash.com/random/300x200","payloadType":"str","x":272,"y":416,"wires":[["e56cb027.484f1"]]},{"id":"4384464e.6c2748","type":"inject","z":"38c5e956.a8e786","name":"setURL picsum","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"setURL","payload":"https://picsum.photos/200/300","payloadType":"str","x":272,"y":464,"wires":[["e56cb027.484f1"]]},{"id":"a63b29d.f4c81d8","type":"ui_group","name":"Form","tab":"4bed3390.45d6dc","order":1,"disp":true,"width":"15","collapse":false},{"id":"4bed3390.45d6dc","type":"ui_tab","name":"Home","icon":"dashboard","order":1,"disabled":false,"hidden":false}]
2 Likes

double checked. Yes that's it the start /stop logic works exactly as desired.

Thanks a lot Steve

@Steve-Mcl
having more than one template node. Do they share the same scope ?

Scope is not the issue, you just need something to distinguish the different img tags.

there is a dynamic way but it is so much less difficult to simply modify the template and give imgs different IDs

To make it a little easier, I have put the img ID's into a constant at the top of the function.

So when you add a 3rd one, you change the img id and the const

e.g..

<div class="camera-container">
    <img id="img1" src="" name="camera"> <!--   ā† set the id    -->
</div>
<script>
(function(scope) {
    const imgID = "img1"; // ā† set the id same as img id above
    var url = "https://picsum.photos/200/300";
    var interval = 1000;
//...
//... rest of the code
//...

demo

updated flow...

[{"id":"e56cb027.484f1","type":"ui_template","z":"5e566ed8.e8b42","group":"a63b29d.f4c81d8","name":"","order":0,"width":"12","height":"9","format":"<div class=\"camera-container\">\n    <img id=\"img1\" src=\"\" name=\"camera\">\n</div>\n<script>\n(function(scope) {\n    const imgID = \"img1\";\n    var url = \"https://picsum.photos/200/300\";\n    var interval = 1000;\n    var timer = null;\n    scope.$watch('msg', function(msg) {\n        if (msg) {\n            debugger\n            if(msg.topic === \"setURL\") url = msg.payload;\n            if(msg.topic === \"setInterval\") {\n                stop();\n                interval = Number(msg.payload);\n                start();\n            }\n            if(msg.topic === \"stop\") stop();\n            if(msg.topic === \"start\") start();\n        }\n    });\n    function start() {\n        debugger\n        if(isNaN(interval) == false && interval > 0) {\n            timer = setInterval(loadNewImage, interval);\n        } else {\n            console.warn(\"interval is valid\");\n        }\n    }\n    function stop() {\n        if(timer) {\n            clearInterval(timer);\n            timer = null;\n        }\n    }\n    function loadNewImage() {\n        if(url) {\n            let time =  new Date().getTime().toLocaleString().replace(/,/g,\"\");\n            //let time Date.now(); //use epoch as an alternative\n            $(\"#\" + imgID).attr(\"src\", `${url}?time=${time}`);\n        }\n    }\n\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","x":800,"y":360,"wires":[[]]},{"id":"b1160200.58ac5","type":"inject","z":"5e566ed8.e8b42","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"stop","payload":"","payloadType":"date","x":596,"y":296,"wires":[["e56cb027.484f1"]]},{"id":"cb4b8ed3.53d22","type":"inject","z":"5e566ed8.e8b42","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"start","payload":"","payloadType":"date","x":596,"y":344,"wires":[["e56cb027.484f1"]]},{"id":"384b9999.113856","type":"inject","z":"5e566ed8.e8b42","name":"setURL unsplash","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"setURL","payload":"https://source.unsplash.com/random/300x200","payloadType":"str","x":596,"y":392,"wires":[["e56cb027.484f1"]]},{"id":"4384464e.6c2748","type":"inject","z":"5e566ed8.e8b42","name":"setURL picsum","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"setURL","payload":"https://picsum.photos/200/300","payloadType":"str","x":596,"y":440,"wires":[["e56cb027.484f1"]]},{"id":"d375b4d.0c86348","type":"ui_template","z":"5e566ed8.e8b42","group":"a63b29d.f4c81d8","name":"","order":0,"width":"12","height":"9","format":"<div class=\"camera-container\">\n    <img id=\"img2\" src=\"\" name=\"camera\">\n</div>\n<script>\n(function(scope) {\n    const imgID = \"img2\";\n    var url = \"https://picsum.photos/200/300\";\n    var interval = 1000;\n    var timer = null;\n    scope.$watch('msg', function(msg) {\n        if (msg) {\n            debugger\n            if(msg.topic === \"setURL\") url = msg.payload;\n            if(msg.topic === \"setInterval\") {\n                stop();\n                interval = Number(msg.payload);\n                start();\n            }\n            if(msg.topic === \"stop\") stop();\n            if(msg.topic === \"start\") start();\n        }\n    });\n    function start() {\n        debugger\n        if(isNaN(interval) == false && interval > 0) {\n            timer = setInterval(loadNewImage, interval);\n        } else {\n            console.warn(\"interval is valid\");\n        }\n    }\n    function stop() {\n        if(timer) {\n            clearInterval(timer);\n            timer = null;\n        }\n    }\n    function loadNewImage() {\n        if(url) {\n            let time =  new Date().getTime().toLocaleString().replace(/,/g,\"\");\n            //let time Date.now(); //use epoch as an alternative\n            $(\"#\" + imgID).attr(\"src\", `${url}?time=${time}`);\n        }\n    }\n\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","x":800,"y":560,"wires":[[]]},{"id":"bacba6b3.bd1ac8","type":"inject","z":"5e566ed8.e8b42","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"stop","payload":"","payloadType":"date","x":596,"y":496,"wires":[["d375b4d.0c86348"]]},{"id":"c2b974ea.c8ec08","type":"inject","z":"5e566ed8.e8b42","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"start","payload":"","payloadType":"date","x":596,"y":544,"wires":[["d375b4d.0c86348"]]},{"id":"e774b53e.254218","type":"inject","z":"5e566ed8.e8b42","name":"setURL unsplash","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"setURL","payload":"https://source.unsplash.com/random/300x200","payloadType":"str","x":596,"y":592,"wires":[["d375b4d.0c86348"]]},{"id":"50154eec.61267","type":"inject","z":"5e566ed8.e8b42","name":"setURL picsum","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"setURL","payload":"https://picsum.photos/200/300","payloadType":"str","x":596,"y":640,"wires":[["d375b4d.0c86348"]]},{"id":"a63b29d.f4c81d8","type":"ui_group","name":"Form","tab":"4bed3390.45d6dc","order":1,"disp":true,"width":"15","collapse":false},{"id":"4bed3390.45d6dc","type":"ui_tab","name":"Home","icon":"dashboard","order":1,"disabled":false,"hidden":false}]
1 Like

great thanks for that !!!
If you dont mind one last thing..

To change any other image attribute as width and hight I could add a line as

$("#" + imgID).attr("width": 300);

to the loadNewImage function ?

Sure, or you could do it with CSS in a head template...

all images

<style>
div.camera-container > img {
  width: 300px;
}
</style>

or

style individual images

<style>
#img1 {
  width: 300px;
}
#img2 {
  width: 400px;
}
</style>

great thanks a lot for your detailed answer !!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.