Show Camera Image on Dashboard

So I'm trying to show the image of a raspberry pi cam on the dashboard. Till now I managed to to create a button, which creates a photo when clicked. The image than is shown on the dashboard. The problem here is, that I have to save the image on the pi and then load it to the dashboard. With the camerapi node it also should be possible to save the file to the buffer. But how can I display the image in the buffer. What I want to achieve is to use an injection node to make a photo every two second and display it to the dashboard.

I'd be interested in seeing how you show the image file on the dashboard. I haven't be able to figure it out yet, but I've about zero http skills and am a JavaScript newbie.

This may help

1 Like

Thanks a lot, this mustache and template stuff is a bit confusing to me at the moment so having a working example is a big help!

Unfortunately it didn't seem to work. The exec node showed a pid and appeared to run but I don't see a photo anywhere on the UI or the home directory of user pi. I did add the base64 node with "manage pallet" and then deployed. Do I need to restart node-red first? Or is there something I need to edit that I've not noticed at the moment?
:blush: I really need a Homer Simpson Doh! emoji :slight_smile:
I was about to post this when I realized I already had a UI tab so changing my browser tab to :1880/ui/#/1 instead of :1880/ui/#/0 showed me the picture.

Thanks again this is a good starting point, the base64 step seems inefficient, but I guess that is just the way web rendering works.

Can you point me towards how I'd start with a jpeg file instead of raspistill as I've another python process already capturing and saving files?

This is the approach I'd start with, get the filename via an MQTT message from the other process (python script) read it into a message payload buffer (I think I know how to do this) and then feed this into the base64 node after editing the templates to match my image sized. Be nice to do the with and height dynamically after the image is loaded, but I can live without it for the time being.

Is my approach sound? or flawed because I'm missing something about how it all plays together?

Thanks again for your help!

That sort if thing should work. Or maybe if the python writes a file then use the watch node to spot it. Then read it in with a file node and feed that to the base64 etc

I started out using a watch node, but I had much better results passing filenames and image buffers around via MQTT, which is surprisingly low overhead for the performance. I use a mix of a central MQTT broker to oversee all the pieces and their interactions and local MQTT brokers for what is in effect doing IPC and RPC with a hella of a lot less effort.

The very inner core of my system is C-code, shared memory, semaphores, threads, and UDP, running on a Beaglebone, but since I've discovered MQTT and node-red I'm adding additional advanced functionality with amazingly little work writing code. I'm a believer now!

The quad core of the Raspberry Pi2 B and up really plays well with this design strategy.

Nice, sounds like you have it well sorted. Of course Node-zRED could play UDP as well if you wanted to do it that way also.

This is the simple code I use in a ui_template node to show live camera streams from http sources. If of any help in case you have webcams (my private local ip sources in the example, those needs to be changed to your preferred choice)
In this way you can create a kind of matrix and depending on size of your monitor, just add/modify number of lines and columns in the tables below

    		<!-- put the up address of your camera sources in these lines: -->
        <tr><!-- Row 1 -->
        		<td style="text-align: center"><img src="" width="460px"/></td>
       	        <td style="text-align: center"><img src="" width="460px"/></td>
        		<td style="text-align: center"><img src="" width="460px"/></td>
        		<td style="text-align: center"><img src="" width="460px"/></td>
    		<!-- put the up address of your camera sources in these lines: -->
        <tr><!-- Row 2 -->
        		<td style="text-align: center"><img src="" width="460px"/></td>
         		<td style="text-align: center"><img src="" width="460px"/></td>
        		<td style="text-align: center"><img src="" width="460px"/></td>
1 Like

It looks (to me) that node-red-contrib-camerapi using buffer mode, returns information about the camera settings and that data in the buffer will not display the image. I've raised an issue/question about this in GitHub

Thanks a lot, these html examples are really helping me!

One question, width is specified, is the image resized to fit or does the image width need to match the setting?

I'm short of time to actually get to play with this stuff right now, so I'm trying to improve my understanding of what is supposed to happen before I dive back into it. I'll be taking a few moments throughout the coming days to try to keep up with these very useful threads, but I can't take the time to really try and apply what I'm learning until next week.

Thanks all!

The image is resized to fit and ratio is preserved as well (width/height) what I have been able to see. I have the actual camera resolution set to 640x480 and configured the html with width 460px to make four camera views fit nicely per line on my monitor

1 Like

I have been down the same path. Here is what I am currently using. The picture in this case is from a dlink wifi camera that emails it to another computer for storage and later procesing into a time-lapse video. That server sends the latest picture on via mqtt to node-red.

while true
	  unset -v latest
	  for file in "$dir"/*; do
	      [[ $file -nt $latest ]] && latest=$file
#echo $latest
mosquitto_pub  -f $latest -h -t tubby/dlink 
sleep 1

Then node-red puts it on the dashboard. This is a two-step process because the dashboard requires a "new" file name to make it refresh. Convoluted yes, but it works. Flow follows...

[{"id":"c1e6892b.e8bd98","type":"mqtt in","z":"51a80f01.26ddc","name":"dlink picture","topic":"tubby/dlink","qos":"0","broker":"be7f0732.137608","x":109.69317626953125,"y":1306.4545059204102,"wires":[["92ff6274.9eff8"]]},{"id":"221afac6.0e53a6","type":"ui_template","z":"51a80f01.26ddc","group":"cda123a6.6c78a","name":"dlink picture","order":7,"width":"6","height":"5","format":"<div height=\"210\" style=\"height: 210px;\">\n<img ng-src= {{msg.payload}} width=\"280\"</img>\n<a href=\"/dlink.jpg\" target=\"_blank\">Full screen</a>\n</div>","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":1107.0140533447266,"y":1309.2786350250244,"wires":[[]]},{"id":"92ff6274.9eff8","type":"file","z":"51a80f01.26ddc","name":"","filename":"/home/pi/node-red-static/dlink.jpg","appendNewline":false,"createDir":false,"overwriteFile":"true","x":349.01422119140625,"y":1307.2784423828125,"wires":[]},{"id":"78a8f752.6db3d8","type":"watch","z":"51a80f01.26ddc","name":"watch for new dlink pic","files":"/home/pi/node-red-static/dlink.jpg","recursive":"","x":631.0142211914062,"y":1317.2784423828125,"wires":[["924a629c.7cfe3"]]},{"id":"924a629c.7cfe3","type":"function","z":"51a80f01.26ddc","name":"timestamp pic file","func":"var d = new Date();\nvar n = d.getTime();\nmsg.payload = \"/dlink.jpg?ts=\" + n;\nreturn msg;","outputs":1,"noerr":0,"x":877.1989517211914,"y":1312.5626583099365,"wires":[["221afac6.0e53a6"]]},{"id":"be7f0732.137608","type":"mqtt-broker","z":"","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"willTopic":"","willQos":"0","willPayload":"","birthTopic":"","birthQos":"0","birthPayload":""},{"id":"cda123a6.6c78a","type":"ui_group","z":"","name":"switches","tab":"276ffa64.974e16","order":2,"disp":true,"width":"6","collapse":true},{"id":"276ffa64.974e16","type":"ui_tab","z":"","name":"home","icon":"dashboard","order":1}]

Hope this helps.


I have inserted a video feed into my dashboard with a simple one-liner in a template node. This embeds a video stream from motion running on a Pi. Change IP to yours of course. If you have no username and password set up, you can omit all the code starting with ? and keep the ">
In a template node (dashboard) add this HTML:
<img name="main" id="main" border="0" width="640" height="480" src=";loginpas=">


If you are running Motion, can't you just get the video stream from cam 1 (default for one camera) via and from cam 2 via etc etc if you have multiple cameras? At least this is the way it works for me.

1 Like

I've actually found it easier to send the status updates that other devices need to be aware of, by modifying my UDP server to send MQTT messages (with retain) on status changes instead of having the other devices read the UDP stream.

I set up my UDP server to be "ask and you shall receive" instead of just streaming the status to whoever is listening, since most of the time the status remains unchanged. The UDP server runs on the same machine as the MQTT broker.

In terms of the UDP usage now, the way the system has evolved it is little more that a "heartbeat" so I can be notified if its computer dies, and so I can log all the sensor status changes for debugging/troubleshooting.

My design goal is "set and forget" so a big part of it is to have the various parts of the system monitor each other and send a message via Email and SMS. So unless I'm making modifications and testing them I never look at anything from the system. I am finding that the Android cell phone I use is the least reliable piece by far, (second is the power company :slight_smile: ) as every two or three weeks an update or something makes it reboot and the node-red/termux-api that impliments the SMS server stops until I manually reatart it. It may be time to spring for the paid termux "auto start" app.

Did you post this in the wrong topic? What is the relevance to the title "Show Camera on Dashboard"???

It was a reply to dceejay's post #6 about node-red could also use UDP. Bit of a sideline I'll admit.

I've gotten lots of great info and ideas from this thread so far, things seem to be falling in to place nicely. My ignorance of HTML and Mustache Templates was what was holding me back.

I don't know if this is appropriate here or if I should start a new thread, but I can't seem to load the base64encode node on my stand-alone system I had no issue getting it with "manage pallet" on my test system so I'm kind of stuck here :frowning:

I ran the upgrade script and all seemed fine, started node-red and my flow appears to be running fine but still no results for base64 in the manage pallet search. What have I missed here?

I'm not sure I understand what is going on here, but it seems the update script fixed the issue but manage pallet wasn't updated until I reloaded my browser tab that I'm "programming" node-red from.

Perhaps a comment about this on the web-page with the update script is in order, or am I the only one who reboots and/or closes browser tabs as little as possible?

Please include the console logs that are output when node-red is started... this will show the versions of the software in use, as well as any missing nodes or modules. Which OS is your standalone system?

Seems its an issue with "distributed computing" :slight_smile: I remembered something that made me refresh my browser tab which fixed the issue.

But for reference my desktop is Ubuntu 16.04 with all updates save the ones pending because I don't want to reboot right now. My Pi systems are Raspbian Stretch (headless, after initial configuration) regularly kept up to date with apt-get update apt-get dist-upgrade. But once development and testing are done and its doing its job 100% after it goes into "service" I stop with the updates -- "if it ain't broke, don't fix it!"

My IOT devices are on a local private network "double NAT" behind my ISP provided router accepting no connections from outside.