The Making of TS-MPPT Remote Monitor Page in Python with Graphs, Part 2: Generating HTML and Canvas Gauges

The Making of TS-MPPT Remote Monitor Page in Python with Graphs, Part 2: Generating HTML and Canvas Gauges

Today’s programming/debug time will be spent on adding in the code that generates the HTML page and adds in the Canvas gauges.

So first thing to do is to copy the Canvas Gauges Java Script into the program working directory since this will be the base directory for the HTML pages. I have attached the 7Zip file here or you can get it from here: https://canvas-gauges.com/download/ if you prefer.

The next step is to put the code that will generate the HTML page that is mostly borrowed code from the QuickCPM.py program that has been stripped down to just one gauge to start with:

def getGaugePage(Voltage,Current,Amp_hrs,Gauge_size,Graph_width,Graph_height):
    hpg = "<html><head><meta http-equiv=\"refresh\" content=\"10\"><meta http-equiv=\"Cache-Control\" content=\"no-store\" />"#"refresh\" content=\"60\"
    hpg += "<meta charset=\"UTF-8\"/><title>TS-MPPT Monitor</title>"
    hpg += "<style>._PR {font-size:15px;box-shadow: 4px 4px 4px black;color:#333;border-top-left-radius: 8px;border-top-right-radius: 8px;border-bottom-right-radius: 8px;border-bottom-left-radius: 8px;border-width:1px;border-style: solid;border-color:silver;text-align: left;margin:4px 4px 4px 4px;padding:4px 4px 4px 4px;}</style>"
    hpg += "<script src=\"gauge.min.js\"></script>"
    #hpg += "<link rel=\"icon\" href=\"icon.png\">"
    hpg += "<div>"
    hpg += gaugeVoltageScrpt("Volts",Voltage,"Volts","Volts",Gauge_size) 
    hpg += "</a>"
    hpg += "</div>"
    hpg += "</div>"
    hpg += "<div>"
       #future spot for buttons
    hpg += "</div>"
    hpg += "</div>"
    hpg += "</div>"
    hpg += "<div></body></html>"
    return(hpg)

And then the next step will be to add in the first gauge. Editing the gauges are almost self explanatory. For help on the settings just Google ‘Canvas Gauge settings’ there are plenty of great example out there. As for the colors I use https://rgbacolorpicker.com/ to quickly pick the colors that I would like to have.

## Voltage gauge 21V-32V for 24V system

def gaugeVoltageScrpt(id,value,title,unit,size):
    ghpg = "\n\n<canvas id=\"gauge-ps{0}\"></canvas>\n".format(id)
    ghpg += "<script>\n"
    ghpg += "var gaugePStemp = new RadialGauge({\n"
    ghpg += "renderTo: 'gauge-ps{0}',\n".format(id)
    ghpg += "width:{0},\n".format(size)
    ghpg += "height:{0},\n".format(size)
    ghpg += "units: '{0}',\n".format(unit);
    ghpg += "minValue: 21,\n"
    ghpg += "maxValue: 32,\n"
    ghpg += "majorTicks: [\n"
    ghpg += "'21',\n"
    ghpg += "'22',\n"
    ghpg += "'23',\n"
    ghpg += "'24',\n"
    ghpg += "'25',\n"
    ghpg += "'26',\n"
    ghpg += "'27',\n"
    ghpg += "'28',\n"
    ghpg += "'29',\n"
    ghpg += "'30',\n"
    ghpg += "'31',\n"
    ghpg += "'32',\n"
    ghpg += "],\n"
    ghpg += "minorTicks: 5,\n"
    ghpg += "ticksAngle: 280,\n"
    ghpg += "startAngle: 40,\n"
    ghpg += "strokeTicks: true,\n"
    ghpg += "highlights  : [\n"
    ghpg += "{ from : 21,  to : 22.8, color : 'rgba(230, 47, 52, 0.8)' },\n"
    ghpg += "{ from : 22.8,  to : 28.8, color : 'rgba(58, 226, 147, 0.8)' },\n"
    ghpg += "{ from : 28.8,  to : 31.8, color : 'rgba(230, 136, 53, 0.8)' },\n"
    ghpg += "{ from : 31.8,  to : 32, color : 'rgba(230, 47, 52, 0.8)' },\n"
    ghpg += "],\n"
    ghpg += "valueInt: 1,\n"
    ghpg += "valueDec: 2,\n"
    ghpg += "colorPlate: \"#fff\",\n"
    ghpg += "colorMajorTicks: \"#686868\",\n"
    ghpg += "colorMinorTicks: \"#686868\",\n"
    ghpg += "colorTitle: \"#000\",\n"
    ghpg += "colorUnits: \"#000\",\n"
    ghpg += "colorNumbers: \"#686868\",\n"
    ghpg += "valueBox: true,\n"
    ghpg += "colorValueText: \"#000\",\n"
    ghpg += "colorValueBoxRect: \"#fff\",\n"
    ghpg += "colorValueBoxRectEnd: \"#fff\",\n"
    ghpg += "colorValueBoxBackground: \"#ddd\",\n"
    ghpg += "colorValueBoxShadow: true,\n"
    ghpg += "colorValueTextShadow: true,\n"
    ghpg += "colorNeedleShadowUp: true,\n"
    ghpg += "colorNeedleShadowDown: true,\n"
    ghpg += "colorNeedle: \"rgba(200, 50, 50, .75)\",\n"
    ghpg += "colorNeedleEnd: \"rgba(200, 50, 50, .75)\",\n"
    ghpg += "colorNeedleCircleOuter: \"rgba(200, 200, 200, 1)\",\n"
    ghpg += "colorNeedleCircleOuterEnd: \"rgba(200, 200, 200, 1)\",\n"
    ghpg += "borderShadowWidth: 4,\n"
    ghpg += "borders: true,\n"
    ghpg += "borderInnerWidth: 0,\n"
    ghpg += "borderMiddleWidth: 0,\n"
    ghpg += "borderOuterWidth: 5,\n"
    ghpg += "colorBorderOuter: \"silver\",\n"
    ghpg += "colorBorderOuterEnd: \"#cdcdcd\",\n"
    ghpg += "needleType: \"arrow\",\n"
    ghpg += "needleWidth: 2,\n"
    ghpg += "needleCircleSize: 7,\n"
    ghpg += "needleCircleOuter: true,\n"
    ghpg += "needleCircleInner: false,\n"
    ghpg += "animationDuration: 2000,\n"
    ghpg += "animationRule: \"dequint\",\n"
    ghpg += "fontNumbers: \"Verdana\",\n"
    ghpg += "fontTitle: \"Verdana\",\n"
    ghpg += "fontUnits: \"Verdana\",\n"
    ghpg += "fontValue: \"Led\",\n"
    ghpg += "fontValueStyle: 'italic',\n"
    ghpg += "fontNumbersSize: 20,\n"
    ghpg += "fontNumbersStyle: 'italic',\n"
    ghpg += "fontNumbersWeight: 'bold',\n"
    ghpg += "fontTitleSize: 24,\n"
    ghpg += "fontUnitsSize: 22,\n"
    ghpg += "fontValueSize: 35,\n"
    ghpg += "animatedValue: true\n,"
    ghpg += "});\n"
    ghpg += "gaugePStemp.draw();\n"
    ghpg += "gaugePStemp.value = \"{0}\";\n".format(value)
    ghpg += "gaugePStemp.title = \"{0}\";\n".format(title)
    ghpg += "</script>\n"
    return ghpg
    #The Mad Scientist Hut.
    

Then the call to the getGaugePage routine gets added into the program for the testing of the py code with a real call to read data from the TS-MPPT-60 then display it on the gauge page

        writeToFile("Solar.html",getGaugePage(Battery_Voltage,Charge_Amps,Amp_hrs,Gauge_size,Graph_width,Graph_height),0,1)

This is what the generated web page looks like at this point

Canvas Gauge for solar system monitor generated by Python

Okay the Voltage gauge looks good, time to add in the Amperage gauge. In the def getGaugePage add a call to the new def gaugeAmperageScrpt just below the Voltage Gauge call

    hpg += "<div>"
    hpg += gaugeVoltageScrpt("Volts",Voltage,"Volts","Volts",Gauge_size) 
    hpg += gaugeAmperageScrpt("Amps",Current,"Amps","Amps",Gauge_size) 

And add in the Amperage gauge code

## Amperage gauge 0-65A the TS-MPPT-60 can source a hair over 60 Amps at peak

def gaugeAmperageScrpt(id,value,title,unit,size):
    ghpg = "\n\n<canvas id=\"gauge-ps{0}\"></canvas>\n".format(id)
    ghpg += "<script>\n"
    ghpg += "var gaugePStemp = new RadialGauge({\n"
    ghpg += "renderTo: 'gauge-ps{0}',\n".format(id)
    ghpg += "width:{0},\n".format(size)
    ghpg += "height:{0},\n".format(size)
    ghpg += "units: '{0}',\n".format(unit);
    ghpg += "minValue: 0,\n"
    ghpg += "maxValue: 65,\n"
    ghpg += "majorTicks: [\n"
    ghpg += "'0',\n"
    ghpg += "'5',\n"
    ghpg += "'10',\n"
    ghpg += "'15',\n"
    ghpg += "'20',\n"
    ghpg += "'25',\n"
    ghpg += "'30',\n"
    ghpg += "'35',\n"
    ghpg += "'40',\n"
    ghpg += "'45',\n"
    ghpg += "'50',\n"
    ghpg += "'55',\n"
    ghpg += "'60',\n"
    ghpg += "'65',\n"
    ghpg += "],\n"
    ghpg += "minorTicks: 5,\n"
    ghpg += "ticksAngle: 280,\n"
    ghpg += "startAngle: 40,\n"
    ghpg += "strokeTicks: true,\n"
    ghpg += "highlights  : [\n"
    #ghpg += "{ from : 21,  to : 22.8, color : 'rgba(230, 47, 52, 0.8)' },\n" #going to add in a color mark for peak amperage over last hour later
    ghpg += "{ from : 0,  to : 65, color : 'rgba(173, 196, 250, 0.8)' },\n"
    ghpg += "],\n"
    ghpg += "valueInt: 1,\n"
    ghpg += "valueDec: 2,\n"
    ghpg += "colorPlate: \"#fff\",\n"
    ghpg += "colorMajorTicks: \"#686868\",\n"
    ghpg += "colorMinorTicks: \"#686868\",\n"
    ghpg += "colorTitle: \"#000\",\n"
    ghpg += "colorUnits: \"#000\",\n"
    ghpg += "colorNumbers: \"#686868\",\n"
    ghpg += "valueBox: true,\n"
    ghpg += "colorValueText: \"#000\",\n"
    ghpg += "colorValueBoxRect: \"#fff\",\n"
    ghpg += "colorValueBoxRectEnd: \"#fff\",\n"
    ghpg += "colorValueBoxBackground: \"#ddd\",\n"
    ghpg += "colorValueBoxShadow: true,\n"
    ghpg += "colorValueTextShadow: true,\n"
    ghpg += "colorNeedleShadowUp: true,\n"
    ghpg += "colorNeedleShadowDown: true,\n"
    ghpg += "colorNeedle: \"rgba(200, 50, 50, .75)\",\n"
    ghpg += "colorNeedleEnd: \"rgba(200, 50, 50, .75)\",\n"
    ghpg += "colorNeedleCircleOuter: \"rgba(200, 200, 200, 1)\",\n"
    ghpg += "colorNeedleCircleOuterEnd: \"rgba(200, 200, 200, 1)\",\n"
    ghpg += "borderShadowWidth: 4,\n"
    ghpg += "borders: true,\n"
    ghpg += "borderInnerWidth: 0,\n"
    ghpg += "borderMiddleWidth: 0,\n"
    ghpg += "borderOuterWidth: 5,\n"
    ghpg += "colorBorderOuter: \"silver\",\n"
    ghpg += "colorBorderOuterEnd: \"#cdcdcd\",\n"
    ghpg += "needleType: \"arrow\",\n"
    ghpg += "needleWidth: 2,\n"
    ghpg += "needleCircleSize: 7,\n"
    ghpg += "needleCircleOuter: true,\n"
    ghpg += "needleCircleInner: false,\n"
    ghpg += "animationDuration: 2000,\n"
    ghpg += "animationRule: \"dequint\",\n"
    ghpg += "fontNumbers: \"Verdana\",\n"
    ghpg += "fontTitle: \"Verdana\",\n"
    ghpg += "fontUnits: \"Verdana\",\n"
    ghpg += "fontValue: \"Led\",\n"
    ghpg += "fontValueStyle: 'italic',\n"
    ghpg += "fontNumbersSize: 20,\n"
    ghpg += "fontNumbersStyle: 'italic',\n"
    ghpg += "fontNumbersWeight: 'bold',\n"
    ghpg += "fontTitleSize: 24,\n"
    ghpg += "fontUnitsSize: 22,\n"
    ghpg += "fontValueSize: 35,\n"
    ghpg += "animatedValue: true\n,"
    ghpg += "});\n"
    ghpg += "gaugePStemp.draw();\n"
    ghpg += "gaugePStemp.value = \"{0}\";\n".format(value)
    ghpg += "gaugePStemp.title = \"{0}\";\n".format(title)
    ghpg += "</script>\n"
    return ghpg
    

A quick test run of the code and this is what the page now:

Canvas Gauges setup from python code

I guess this is a good stopping point for today. Tomorrow I think it will be time to start adding in the graphs.

Leave a Reply

Your email address will not be published. Required fields are marked *