Dashboard pie chart to show Raspberry pi GPIO history

I am trying to add to a dashboard to show a pie chart detailing how long a raspberry pi GPIO pin has been high or low during the past hour.

Here is my current flow:

But at the moment all I am getting is a pie chart that is either 100% on:
Screenshot from 2020-04-28 08-21-20
Or off:
Screenshot from 2020-04-28 08-22-24
Depending whether the GPIO pin is currently high or low.

The guage node displays te last value it received. If you want to display how long it has been on or off in the past hour (last hour or last 60 minutes?) you will have to keep a running total of the amount of time that it has been in each state and send that value to the gauge - you will need two gauges - one for 'on' tome and one for 'off' time unless you realize that the filled part of the guage is the 'on' time and the unfilled part of the guage is the 'off' time. If you do it that way,then you only need to track the on time for the 60 minutes.

Thanks for the reply. I only want one chart. What node would I need to use to calculate my on time?

You didn't answer if this is a running total or a per hour - i.e. do you want to display it for the laast 60 minutes or do you want it to reset on the hour?

I'm not sure if there is a node to do this (you can search the flow library to see if you find one) but you could do it programmatically.

Sorry, my mistake, I want it to display for the last 60 minutes. i.e. I want to be able to show the on/off time from 1 hour ago until now.

so how would you do this if you were using a stop watch and writting it down on paper?
You need to think about that and write down what you would do - this will be your pseudo code to build your flow to acheive the results you want.

Once you have the steps you would take, post them here if you have a problem determining how to build the flow.

If I was doing it for logged data in excel I would do it like this:
Where column 1 is if the pin is 1 or 0
Column 2 is the time that the reading was taken
Column 3 is a formula to subtract the time of the row from the time before. ie. b3-b2
Then there are 2 sums which sum if the input is high or low. i.e.=SUMIF(A2:A22,"1",C2:C22)


The trouble is I have no idea which nodes to use to do this as I am on a very steep learning curve.

I know it's not a pie chart - but this node may be an alternative - https://flows.nodered.org/node/node-red-contrib-ui-state-trail

That is a start but what you want to do is write down the steps you would take if you had to do it by hand. This is a hard exercise, but helpful one which will make putting together a flow easier.

Things to think about, what to do if the gpio is on for 20 minutes, off for 35 minutes and then on for 10 minutes. In that case, you have to subtract 5 minutes from the on time because you have passed 60 minutes.

This might be a case for stroring the status of the gpio pin in a database (use Influx which is a time series database) and then you can create a graph showing the status for the last hour.
gpio is 1 - start timer
gpio is 0 - stop timer add timer to 'on' time

Here's a thought....

  1. save the gpio state 0 or 1 into a flow variable (change node)
  2. every minute (repeating inject) - read that value (change node)
  3. feed into a smooth node set to 60 samples.
  4. the output of that will then be an average of all the ones and zeros which will be the proportion of on time vs off
  5. use a function node to create two output with different topics (eg "ontime" and "offtime") - one with the mean value and the other with (1-the mean value) ie the proportion of off time -
  6. feed both to the pie chart.
1 Like

Thank you both zenofmud and dceejay for your help and assistance. I am not networked into the pi at the moment but have tried a quick mock up on my laptop to experiment with and I have come up with this flow based on your feed back:

This is giving me the proportion in the debug nodes:
Screenshot from 2020-04-28 16-33-39
And is feeding into the pie chart node to give me this:
Screenshot from 2020-04-28 16-33-54
I had a bit of trouble because I hadn't assigned a msg.topic in my function nodes but I eventually worked it out so that it looks like this:
return msg;
I know it's not going to be an exact 60 minute average because the flow gets triggered whenever there is a change in state but I think it will be good enough for my purposes. I will give it a try tomorrow.

1 Like

Hi @leeg77,
Nice to see that you have found a solution.
Another way 'might' be this one:

  1. Use a switch node to have the "1" values on one output and the "0" values on another output.
  2. Then use two node-red-contrib-msg-speed nodes to count both the "1" and "0" values (of the last hour).

If you set the frequency of the speed node to "hour", it will create a ring of 3600 values (i.e. 1 value per second). Every value is the total count of messages arrived in that second. And it outputs every second the total count of all messages of the last hour (i.e. the sum of all values). So the ring is a moving window of counts of the messages during the last 3600 seconds.

I didn't design that node for this purpose, but it might be a useful case.

Just a thought ...

Hi, this is also NOT a bar chart but provides an interesting way to automatically collect and store the data before presenting it to a user in an easily-digestible form. Simply set the time period you are interested in and inject whatever events you want to track - it does the rest.



[{"id":"6e76f52b.ec245c","type":"ui_chart","z":"fad0114e.841e8","name":"","group":"8c02c710.08f738","order":1,"width":28,"height":8,"label":"Last {{msg.settings.x_size}} Seconds / {{msg.data_sum}} Event(s)","chartType":"line","legend":"true","xformat":"HH:mm:ss","interpolate":"linear","nodata":"Waiting for data...","dot":false,"ymin":"","ymax":"","removeOlder":"60","removeOlderPoints":"","removeOlderUnit":"1","cutout":0,"useOneColor":true,"colors":["#000000","#00ff00","#ff80ff","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"outputs":1,"x":1150,"y":2200,"wires":[]},{"id":"3c6d5919.8f26c6","type":"bar-chart-data","z":"fad0114e.841e8","name":"bar-chart-data","x_interval":"seconds","x_size":"60","unit":"","precision":"0","is_meter_reading":"False","agg_by":"sum","x":920,"y":2200,"wires":[["fa4baed5.72691","6e76f52b.ec245c"]]},{"id":"ac90e5fd.6a30a8","type":"persist out","z":"fad0114e.841e8","name":"store","storageNode":"7be8165e.84b668","x":830,"y":2280,"wires":[["3c6d5919.8f26c6"]]},{"id":"fa4baed5.72691","type":"persist in","z":"fad0114e.841e8","name":"store","storageNode":"7be8165e.84b668","x":1010,"y":2280,"wires":},{"id":"b9ad71df.3275d","type":"change","z":"fad0114e.841e8","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"Pass","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":570,"y":2200,"wires":[["3c6d5919.8f26c6"]]},{"id":"7bbee89.b264c18","type":"inject","z":"fad0114e.841e8","name":"","topic":"","payload":"1","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":570,"y":2240,"wires":[["b9ad71df.3275d"]]},{"id":"1e26eb41.422f45","type":"change","z":"fad0114e.841e8","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"Fail","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":570,"y":2320,"wires":[["3c6d5919.8f26c6"]]},{"id":"b6d22f5e.e77a8","type":"inject","z":"fad0114e.841e8","name":"","topic":"","payload":"1","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":570,"y":2360,"wires":[["1e26eb41.422f45"]]},{"id":"8c02c710.08f738","type":"ui_group","z":"","name":"Service Portal - Events","tab":"5399e3a0.82e19c","order":1,"disp":true,"width":28,"collapse":false},{"id":"7be8165e.84b668","type":"persist-store","z":"","filename":"~/store.json","interval":"60"},{"id":"5399e3a0.82e19c","type":"ui_tab","z":"","name":"Service Portal - Events","icon":"fa-line-chart","order":9,"disabled":false,"hidden":false}]

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