Save Chart as picture to attach to mail

How do I save a ui_chart as a picture so that I can attach the same in a Mail or PDF ?

Is there anyone who can help me ?

I need to save a chart that is appearing on the dashboard as a JPG file and then attach it to a pdf file to send through a mail.

any expert can also reply it is not possible, then i can explore some other avenue.

A google search (using node-red email a chart) came up with this which might be helpful:
https://flows.nodered.org/flow/74fefaaaad28e28b074535660378fea3

1 Like

Thanks, (I need to improve my google search skills.)

will give it a look and comeback for any more suggestions.

Got it to work sending the graph converted to image in telegram, now looking at changes required to convert the flow to make the static data to take input from my mysql query output.
would a template node do the trick with a mustache template ?

Did you try it? Did it work?

I give up. If someone can help me getting my sample data (generated out of mysql query, i have attached the query output in a change node in the below flow) into the function node of the sample flow I would try further. how do i replace the hard coded data in the function node from my query result array, which is in the change node

[{"id":"fcd97a333e99d5ac","type":"inject","z":"b3d99a67c97a53ca","name":"Line Chart","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":540,"y":2860,"wires":[["017e0487326c6b56"]]},{"id":"017e0487326c6b56","type":"function","z":"b3d99a67c97a53ca","name":"Line Chart","func":"function getGetOrdinal(n) {\n    var s=[\"th\",\"st\",\"nd\",\"rd\"],\n    v=n%100;\n    return n+(s[(v-20)%10]||s[v]||s[0]);\n }\n\nvar dL = [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"];\nvar dS = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"];\nvar mL = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];\nvar mS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'];\n\nlet now = new Date();\n\n// Create the chart object\nlet m = {\n    type: 'line',\n    options: {\n        title: {\n            display:true,\n            text:'Line chart example'\n        },\n        legend: {\n            display:false\n        },\n        chartArea: {\n            backgroundColor: 'white'\n        },\n        plugins: {\n            datalabels: {\n                display:true,\n                backgroundColor:'whitesmoke',\n                borderRadius:1,\n                padding:1,\n                align: 'right',\n                anchor: function(context) {\n                    //node.send({debug:{dataindex:context.dataIndex}});\n                    if (context.dataIndex == context.dataset.data.length - 1) {\n                        return 'center';\n                    } else {\n                        return 'end';\n                    }\n                },\n                offset:8,\n                formatter:function(value) {\n                    return value > 0 ? value.toLocaleString() : '';\n                }\n            }\n        }\n    },\n    data: {\n        labels:[],\n        datasets: [\n            {\n                label:\"Sample data\",\n                borderColor:'rgba(57,97,184,0.8)',\n                fill:false,\n                data:[]\n            }\n        ]\n    }\n}\n\nlet l = Math.floor(Math.random()*50);\n\nfor (let i=0; i<10; i++) {\n    l = l + Math.floor(Math.random()*6)-3;\n    m.data.datasets[0].data.push(l);\n    var d = new Date();\n    d.setTime(now.getTime()-1000*60*60*24*(10-i));\n    m.data.labels.push(dL[d.getDay()]+\", \"+getGetOrdinal(d.getDate()));\n}\n\nmsg.payload = m;\n\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":730,"y":2860,"wires":[["625a9dac54746ae0"]]},{"id":"625a9dac54746ae0","type":"chart-image","z":"b3d99a67c97a53ca","name":"","width":500,"height":"500","x":950,"y":2860,"wires":[["88d15e3dc26985d3"]]},{"id":"88d15e3dc26985d3","type":"file","z":"b3d99a67c97a53ca","name":"Image dump","filename":"C:/temp/test.png","filenameType":"str","appendNewline":true,"createDir":false,"overwriteFile":"true","encoding":"none","x":1150,"y":2860,"wires":[[]]},{"id":"08b54444b6a14012","type":"inject","z":"b3d99a67c97a53ca","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":560,"y":2980,"wires":[["8249caac1d7dbbae"]]},{"id":"8249caac1d7dbbae","type":"change","z":"b3d99a67c97a53ca","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"[{\"series\":[{\"mname\":\"%\"}],\"data\":[[251516,116517,102573,49067]],\"labels\":[\"C I P\",\"Batch Preparation Delay\",\"Other\",\"CIP Delay\"]}]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":740,"y":2980,"wires":[["b083aeb1ac332c09"]]},{"id":"b083aeb1ac332c09","type":"ui_chart","z":"b3d99a67c97a53ca","name":"Bar Chart","group":"bd84e0696fc82168","order":10,"width":"20","height":"16","label":"{{mname}}","chartType":"horizontalBar","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"className":"","x":940,"y":2980,"wires":[[]]},{"id":"6d83526cbe303c50","type":"comment","z":"b3d99a67c97a53ca","name":"Sample flow for getting a chart into an image and then later send through telegram","info":"","x":750,"y":2800,"wires":[]},{"id":"e8e011eda93cfde3","type":"comment","z":"b3d99a67c97a53ca","name":"my sample data which i can generate with mysql query","info":"","x":680,"y":2940,"wires":[]},{"id":"bd84e0696fc82168","type":"ui_group","name":"SELECT","tab":"fd99c36c90ce6f3a","order":2,"disp":false,"width":"42","collapse":false,"className":""},{"id":"fd99c36c90ce6f3a","type":"ui_tab","name":"DOWNTIME","icon":"dashboard","order":3,"disabled":false,"hidden":false}]

What does your MySQL ouput look like? Add a debug node to the output of the MySQL node and copy/paste the results to a reply.

Also the flow you provided doesn't show what you tried, please show me what you tried to convert the data to send to the chart.

i have copied the result of the debug node to the change node in the flow i have given, here it is again.

[{"series":[{"mname":"BOATOPACK"}],"data":[[23632,21486,10445,9714]],"labels":["C I P","No Plan","Other","Holiday"]}]

unfortunately i deleted the part which did not work, basically i tried to copy one of my other function from the forum help which is working for getting similar mysql result into a pdfmaker node to get dynamic content into pdf. since i have no idea how it works, i could not replicate it to get the same result in required format for chart.

That is not what I asked for. In order to guide you, I will need to see is what the output from your mySQL node looks like.

If you don't provide the information I request I will not be able to help you.

must be a case of mis-understanding your requirement, when you say copy-paste, do you mean like this below ?

image

in-fact below is the output of the mysql query. the picture in above post is the debug AFTER i process the output to prepare for the chart.

image

There’s a great page in the docs (Working with messages : Node-RED) that will explain how to use the debug panel to find the right path to any data item.

Pay particular attention to the part about the buttons that appear under your mouse pointer when you over hover a debug message property in the sidebar.

BX00Cy7yHi

After you have copied the object, you can paste it in a response

In order to make code readable and usable it is necessary to surround your code with three backticks (also known as a left quote or backquote ```)

``` 
   code goes here 
```

You can edit and correct your post by clicking the pencil :pencil2: icon.

See this post for more details - How to share code or flow json

This saves someone from having to hand enter your data to help you out.

that is what i had posted in the change node in my first response post.

please bear with me, if i am unable to understand the requirement, i understand how to get the data from mysql and get the chart done. my only problem is i have a sample example which you directed me to where the post uses a random number generator to populate the data for chart, i just dont know how to use for loop in a function to get the data from my mysql output into the function node.

Here is a function that will do most of the conversion except the labels. I've been interuppted by the arrival of my 2 yr old granddaughter who has a cold so I'll be off my computer most of the dayand won't be able to do more testing most of the day.

let mydata = msg.payload;

const chart = [{
    "series": [{ "mname": "BOATOPACK" }],
    "data": [
        mydata.map(a => a.Duration )
    ],
    "labels": labels2
    "labels": [
        Array.from(mydata.map(a => a.Reason))
    ]
}];

msg.payload = chart;
return msg;

@zenofmud does the example that you posted earlier use the same data format for driving the chart as the dashboard chart does? That isn't clear from a glance at the flow.

Try using this function node

let mydata = msg.payload;
let labels = mydata.map(a => a.Reason);

const chart = [{
    "series": [{ "mname": "BOATOPACK" }],
    "data": [
        mydata.map(a => a.Duration )
    ],
    "labels": labels

}];

msg.payload = chart;
return msg;

@colin, the example I postes earlier was a flow that Generate chart images in Node-Red for email or chat messages. After that the request was made to show how to format the data coming out of MySQL which is what this function node does.

What I am not certain of is whether it formats it correctly for the chart image node you linked to, which doesn't use the dashboard chart node. The function node in the examples there creates the chart object as well as the data and passes it to the image node.

1 Like

I'm just working off the flow that @smanjunath211 provided in post #6 with the comment over it labeled

my sample data which i can generate with mysql query

I think what @smanjunath211 is trying to understand is how to incorporate that data into the sample chart in the flow you linked to. He is already able to show it on the node-red dashboard chart but doesn't know how to integrate the data with the chart image node. Can you confirm that is what you are trying to do please @smanjunath211? Or if not then please try and explain.

1 Like