Deth

Fitness and everything else

Finally Wrote A Hugo Shortcode To Deal With Generating Tables For My Weather Station Data

The Go templates that Hugo uses to make short codes and partials just are not all that intuitive to me. I don’t know why, but I feel like I am seeing double at times looking at them. The curly brackets all over the place only make matters worse for me. I forget to close them so often, and then it’s a bitch to trouble shoot them because of the shape and size of them I don’t see them too well. With practice, it will get better. I really do like everything else about using Hugo, and its flexibility has really been great for me.

I’ve been trying to brainstorm an idea of how to generate more organized data for my data from my Ambient weather station to post on here. It would have been a lot easier if I wanted to use all the fields from my CSV file, but there’s no need to have my indoor temperatures and stuff.

I had originally done a short code to generate one big table of all the data, but that was too wide for the screen and not nearly as organized as I would have liked it to have been. I wanted to split it up by day having each on a separate page, then have smaller tables of the related data in a more sensible way.

The biggest issue I had was figuring out a way to skip the first line of the CSV file. The first line is headers, so I didn’t need them once I knew the fields. Then after that I needed to take five lines at a time since the daily average, high, low, and time of high and low are each on separate lines.

1,Date,Outdoor Temperature,Feels Like,Dew Point
2Average,2022-01-14,33.7,33.7,28.8
3High,2022-01-14,35.6,35.6,29.9
4High Datetime,2022-01-14,2022-01-14T04:57:00-05:00,2022-01-14T04:57:00-05:00,2022-01-14T04:41:00-05:00,
5Low,2022-01-14,32,30.2,28
6Low Datetime,2022-01-14,2022-01-14T02:21:00-05:00,2022-01-14T02:12:00-05:00,2022-01-14T00:13:00-05:00,2022-01-14T00:00:00-05:0

Hugo has range for loops, in this case it would loop through the array one line at a time. I could then access the fields as an array, but what I was stuck on is how to get five at a time after the first one.

What I eventually ended up doing is creating a variable for each line number for one to five, with names that are a better description of what the line contains than just the number. Then I created variables for each field number that I want to use to be more descriptive, plus it allows easier editing should the CSV lines and fields layout from Ambient Weather ever change.

I got the index number of the first line of the date that I wanted with several ifs to filter out the non-related lines. The date for the current page is a field that’s passed to the shortcode from the markdown file, so it wasn’t that complicated. I only needed the first one, then added the various line variable numbers to get the specific lines I wanted, then used the column number variables to get the field I wanted. Eventually, I got things as close to just right as I think I will get using just Hugo. I have no doubt that I will continue tweaking it as I see fit, but this is where it is now. Here’s the code.

1{{/*
2Set up the CVS file and and open it.
3*/}}
4{{- $csvfile := .Get "src" -}}
5{{- if fileExists $csvfile -}}
6
7{{- $seperator := "," -}}
8{{- $data := getCSV $seperator $csvfile -}}
9{{/*
10Get the date that we want and set it to the same format as the CSV file so we can find that group of records.
11*/}}
12{{- $Thedate := .Get "Day" -}}
13{{- $Previousdate := $Thedate -}}
14{{- $Nextdate := $Thedate -}}
15
16{{- $Thedate := dateFormat "1-2-2006" ($Thedate) -}}
17{{/*
18Set up the variables for the columns of the fields that we want to use.
19*/}}
20{{- $FeelsLike := 3 -}}
21{{- $DewPoint := 4 -}}
22{{- $Temperature := 2 -}}
23{{- $Humidity := 16 -}}
24{{- $UVRadiation := 17 -}}
25{{- $SolarRadiation := 18 -}}
26{{- $StrikesPerDay := 19 -}}
27{{- $StrikesPerHour := 20 -}}
28{{- $Wind := 6 -}}
29{{- $WindGust := 7 -}}
30{{- $Pressure := 15 -}}
31{{- $WindDirection := 8 -}}
32{{- $DailyRain := 10 -}}
33{{- $MaxHourly := 9 -}}
34{{- $EventRain := 14 -}}
35{{- $WeeklyRain := 11 -}}
36{{- $MonthlyRain := 12 -}}
37{{- $YearlyRain := 13 -}}
38{{/*
39Find the row number for the date that we want to pull the rocrods from.
40*/}}
41 {{- range $index, $col := getCSV $seperator $csvfile -}}
42
43 {{- if (ne $index 0 ) -}}
44 {{- if and ( eq ($Thedate) ( dateFormat "1-2-2006" (index $col 1) )) ( eq (index $col 0) "Average") -}}
45{{/*
46This is the line number of the first group of lines that we want. We can set up the rest from here.
47*/}}
48 {{- $average := $index -}}
49{{- $high := add $index 1 -}}
50{{- $hightime := add $index 2 -}}
51{{- $low := add $index 3 -}}
52{{- $lowtime := add $index 4 -}}
53{{- $YesterdaysHigh := add $high 5 -}}
54{{- $YesterdaysLow:= add $low 5 -}}
55{{/*
56Set up all of the values I want to get as variables. This will make it easier to clean up and rearrange the tables if I want to in the future.
57*/}}
58{{- $AverageTemperature := float (index $data $average $Temperature ) -}}
59{{- $HighTemperature := float ( index $data $high $Temperature ) -}}
60{{- $HighTemperatureTime := index $data $hightime $Temperature -}}
61{{- $LowTempterature := float (index $data $low $Temperature ) -}}
62{{- $LowTemperatureTime := index $data $lowtime $Temperature -}}
63{{- $HighTemperatureFromYesterday := float ( index $data $YesterdaysHigh $Temperature) -}}
64{{- $LowTempteratureFromYesterday := float ( index $data $YesterdaysLow $Temperature) -}}
65{{- $TempteratureRange := sub $HighTemperature $LowTempterature | lang.FormatNumber 1 -}}
66{{- $AverageFeelsLike := float (index $data $average $FeelsLike ) -}}
67{{- $HighFeelsLike := float ( index $data $high $FeelsLike) -}}
68{{- $HighFeelsLikeTime := index $data $hightime $FeelsLike -}}
69{{- $LowFeelsLike := float (index $data $low $FeelsLike) -}}
70{{- $LowFeelsLikeTime := index $data $lowtime $FeelsLike -}}
71{{- $FeelsLikeRange := sub $HighFeelsLike $LowFeelsLike | lang.FormatNumber 1 -}}
72{{- $HighFeelsLikeFromYesterday := float ( index $data $YesterdaysHigh $FeelsLike) -}}
73{{- $LowFeelsLikeFromYesterday := float ( index $data $YesterdaysLow $FeelsLike) -}}
74{{- $AverageDewPoint := float (index $data $average $DewPoint) -}}
75{{- $HighDewPoint := float ( index $data $high $DewPoint) -}}
76{{- $HighDewPointTime := index $data $hightime $DewPoint -}}
77{{- $LowDewPoint := float (index $data $low $DewPoint) -}}
78{{- $LowDewPointTime:= index $data $lowtime $DewPoint -}}
79{{- $DewPointRange := sub $HighDewPoint $LowDewPoint | lang.FormatNumber 1 -}}
80{{- $HighDewPointFromYesterday := float ( index $data $YesterdaysHigh $DewPoint) -}}
81{{- $LowDewPointFromYesterday := float ( index $data $YesterdaysLow $DewPoint) -}}
82{{- $AverageHumidity := float (index $data $average $Humidity ) -}}
83{{- $HighHumidity := int (index $data $high $Humidity ) -}}
84{{- $HighHumidityTime := index $data $hightime $Humidity -}}
85{{- $LowHumidity := int (index $data $low $Humidity ) -}}
86{{- $LowHumidityTime := index $data $hightime $Humidity -}}
87{{- $HumidityRange := sub $HighHumidity $LowHumidity -}}
88{{- $AveragePressure := float (index $data $average $Pressure ) -}}
89{{- $HighPressure := float ( index $data $high $Pressure ) -}}
90{{- $HighPressureTime := index $data $hightime $Pressure -}}
91{{- $LowPressure := float (index $data $low $Pressure) -}}
92{{- $LowPressureTime := index $data $lowtime $Pressure -}}
93{{- $PressureRange := sub $HighPressure $LowPressure | lang.FormatNumber 2 -}}
94{{- $UVRadiationTime := index $data $hightime $UVRadiation -}}
95{{- $UVRadiationHigh := index $data $high $UVRadiation -}}
96{{- $SolarRadiationTime := index $data $hightime $SolarRadiation -}}
97{{- $SolarRadiationHigh := index $data $high $SolarRadiation -}}
98{{- $HighStrikesPerHour := index $data $high $StrikesPerHour -}}
99{{- $HighStrikesPerHourTime := index $data $hightime $StrikesPerHour -}}
100{{- $HighStrikesPerDay := index $data $high $StrikesPerDay -}}
101{{- $HighDailyRain := index $data $high $DailyRain -}}
102{{- $HighMaxHourlyRain := index $data $high $MaxHourly -}}
103{{- $HighEventRain := index $data $high $EventRain -}}
104{{- $HighYesterdaysRain := index $data $YesterdaysHigh $DailyRain -}}
105{{- $HighWeeklyRain := index $data $high $WeeklyRain -}}
106{{- $HighMonthlyRain := index $data $high $MonthlyRain -}}
107{{- $HighYearlyRain := index $data $high $YearlyRain -}}
108{{- $AverageWind :=index $data $average $Wind -}}
109{{- $HighWind := index $data $high $Wind -}}
110{{- $HighWindTime := index $data $hightime $Wind -}}
111{{- $AverageGust:= index $data $average $WindGust -}}
112{{- $HighGust := index $data $high $WindGust -}}
113{{- $HighGustTime := index $data $hightime $WindGust -}}
114{{- $AverageWindDirection := index $data $average $WindDirection -}}
115{{/* Set up Variables for differences */}}
116{{- $HighTemperatureDifference := sub $HighTemperature $HighTemperatureFromYesterday | lang.FormatNumber 1 -}}
117{{- $LowTemperatureDifference := sub $LowTempterature $LowTempteratureFromYesterday | lang.FormatNumber 1 -}}
118{{- $HighDewPointDifference := sub $HighDewPoint $HighDewPointFromYesterday| lang.FormatNumber 1 -}}
119{{- $HighFeelsLikeDifference := sub $HighFeelsLike $HighFeelsLikeFromYesterday | lang.FormatNumber 1 -}}
120{{- $LowDewPointDifference := sub $LowDewPoint $LowDewPointFromYesterday| lang.FormatNumber 1 -}}
121{{- $LowFeelsLikeDifference := sub $LowFeelsLike $LowFeelsLikeFromYesterday | lang.FormatNumber 1 -}}
122{{/*
123We'll start with a table for the temperature fields
124*/}}
125 <table> <caption>Temperature </caption><thead><tr>
126 <th></th><th>Temperature</th><th>Time</th><th>Dew Point</th><th>Time</th> <th>Feels Like</th><th>Time</th> </tr></thead><tbody>
127<tr><td>Average</td><td>{{- $AverageTemperature }} &#8457; </td><td></td><td>{{- $AverageDewPoint }} &#8457; </td><td></td><td>{{- $AverageFeelsLike }} &#8457; </td><td></td></tr>
128<tr><td>Today's High</td><td>{{- $HighTemperature }} &#8457; </td><td><time datetime="{{ $HighTemperatureTime }}"> {{- $HighTemperatureTime | time.Format ":time_short" -}}</time></td><td>{{- $HighDewPoint }} &#8457;</td><td><time datetime="{{ $HighDewPointTime}}"> {{- $HighDewPointTime | time.Format ":time_short" -}}</time></td><td>{{- $HighFeelsLike }} &#8457; </td><td><time datetime="{{ $HighFeelsLikeTime }}"> {{- $HighFeelsLikeTime | time.Format ":time_short" -}}</time></td></tr>
129<tr><td>Today's Low</td><td>{{- $LowTempterature }} &#8457; </td><td><time datetime="{{ $LowTemperatureTime }}"> {{- $LowTemperatureTime | time.Format ":time_short" -}}</time></td><td>{{- $LowDewPoint }} &#8457; </td><td><time datetime="{{ $LowDewPointTime }}"> {{- $LowDewPointTime | time.Format ":time_short" -}}</time></td><td>{{- $LowFeelsLike }} &#8457; </td><td><time datetime="{{ $LowFeelsLikeTime }}"> {{- $LowFeelsLikeTime | time.Format ":time_short" -}}</time></td></tr>
130<tr><td>Range</td><td>{{ $TempteratureRange }} &#8457; </td><td></td><td>{{- $DewPointRange }} &#8457; </td><td></td><td>{{- $FeelsLikeRange }} &#8457; </td><td></td></tr>
131<tr><td>Yesterday's High</td><td>{{- $HighTemperatureFromYesterday }} &#8457; </td><td></td><td>{{- $HighDewPointFromYesterday }} &#8457;</td><td></td><td>{{- $HighFeelsLikeFromYesterday }} &#8457; </td><td></td></tr>
132<tr><td>Yesterday's Low</td><td>{{- $LowTempteratureFromYesterday }} &#8457; </td><td></td><td>{{- $LowDewPointFromYesterday }} &#8457;</td><td></td><td>{{- $LowFeelsLikeFromYesterday }} &#8457; </td><td></td></tr>
133<tr><td>High Difference</td><td>{{- $HighTemperatureDifference }} &#8457; </td><td></td><td>{{- $HighDewPointDifference }} &#8457;</td><td></td><td>{{- $HighFeelsLikeDifference }} &#8457; </td><td></td></tr>
134<tr><td>Low Difference</td><td>{{- $LowTemperatureDifference }} &#8457; </td><td></td><td>{{- $LowDewPointDifference }} &#8457;</td><td></td><td>{{- $LowFeelsLikeDifference }} &#8457; </td><td></td></tr>
135</tbody>
136</table>
137{{/*
138Next we'll generate the table for the humidity values.
139*/}}
140<table> <caption>Humidity</caption> <thead><tr>
141<th></th><th>Humidity</th><th>Time</th> </tr> </thead>
142<tbody>
143<tr><td>Average</td><td>{{- $AverageHumidity -}} %</td><td></td></tr>
144<tr><td>High</td><td>{{- $HighHumidity -}} %</td><td><time datetime="{{ $HighHumidityTime }}"> {{- $HighHumidityTime | time.Format ":time_short" -}}</time>
145</td></tr>
146<tr><td>Low</td><td>{{- $LowHumidity -}} %</td><td><time datetime="{{ $LowHumidityTime }}"> {{- $LowHumidityTime | time.Format ":time_short" -}}</time>
147</td></tr>
148<tr><td>Range</td><td>{{- $HumidityRange -}} %</td><td></td></tr></tbody>
149</table>
150{{/*
151Now we'll to a table with the barometer information..
152*/}}
153<table> <caption>Releative Pressure</caption> <thead><tr>
154<th></th><th>Pressure</th><th>Time</th> </tr> </thead>
155<tbody>
156<tr><td>Average</td><td>{{ $AveragePressure -}} &#8243;</td><td></td></tr>
157<tr><td>High</td><td>{{ $HighPressure -}} &#8243;</td><td><time datetime="{{ $HighPressureTime }}"> {{- $HighPressureTime | time.Format ":time_short" -}}</time></td></tr>
158<tr><td>Low</td><td>{{ $LowPressure -}} &#8243;</td><td><time datetime="{{ $LowPressureTime }}"> {{- $LowPressureTime | time.Format ":time_short" -}}</time> </td></tr>
159<tr><td>Range</td><td>{{ $PressureRange -}} &#8243;</td><td></td></tr></tbody>
160</table>
161
162{{/*
163Next we will do a table for UV and solar radation.
164*/}}
165<table>
166<caption>Sun</caption><thead><tr>
167<th><th>Max</th><th>Time</th></tr></thead>
168<tbody>
169<tr><td>UV Radiation</td><td>{{ $UVRadiationHigh }}</td><td><time datetime="{{ $UVRadiationTime }}">{{- $UVRadiationTime | time.Format ":time_short" -}}</time></td></tr>
170<tr><td>Solar Radiation</td><td>{{ $SolarRadiationHigh }} W/m&#178;</td><td><time datetime="{{ $SolarRadiationTime }}"> {{- $SolarRadiationTime | time.Format ":time_short" -}}</time> </td></tr>
171</tbody>
172</table>
173{{/*
174Next we'll set up a table for the wind values.
175*/}}
176<table>
177<thead><tr><th></th><th>Wind</th><th>Gust</th><th>Time</th></tr></thead><tbody>
178<tr><td>Wind</td><td>{{ $AverageWind }} mph</td><td>{{ $HighWind }} mph<td><time datetime="{{ $HighWindTime }}"> {{- $HighWindTime | time.Format ":time_short" -}}</time>
179</td></tr>
180<tr><td>Gust</td><td>{{ $AverageGust }} mph</td><td>{{ $HighGust }} mph<td><time datetime="{{ $HighGustTime }}"> {{- $HighGustTime | time.Format ":time_short" -}}</time></tr>
181<tr><td>Direction</td><td>{{- $AverageWindDirection -}} </td><td></td><td></td></tr></tbody></table>
182{{/*
183Next we'll generate the table with the rainfall values.
184*/}}
185 <table> <caption> Rainfall</caption> <thead><tr>
186 <th>Daily Rain</th> <th>Max Hourly</th><th>Event Rain</th><th>Yesterday's Rain</th><th>Weekly Rain</th><th>Monthly Rain</th><th>Yearly Rain</th></tr></thead><tbody>
187<tr><td>{{ $HighDailyRain -}} &#8243;</td><td>{{ $HighMaxHourlyRain -}} &#8243; per hour</td><td>{{ $HighEventRain }} in</td><td>{{ $HighYesterdaysRain -}} &#8243;</td><td>{{ $HighWeeklyRain -}} &#8243;</td><td>{{ $HighMonthlyRain -}} &#8243;</td><td>{{ $HighYearlyRain -}} &#8243;</td></tr></tbody>
188</table>
189{{/*
190Last we will generate the table for the lightning sensor data but only if there were strikes on
191this day.
192*/}}
193{{- if ne "0" $HighStrikesPerDay -}}
194 <table>
195 <caption>Lightning</caption><thead><tr>
196 <th><th>Max</th><th>Time</th></tr></thead>
197<tbody>
198<tr><td>Strikes Per Hour</td><td>{{ $HighStrikesPerHour }}</td><td>{{- if ( $HighStrikesPerHour) }} <time datetime="{{ $HighStrikesPerHourTime }}"> {{- $HighStrikesPerHourTime | time.Format ":time_short" -}}</time> {{- end -}}</td></tr>
199<tr><td>Strikes Per Day</td><td>{{ $HighStrikesPerDay }} </td><td></td></tr>
200 </tbody>
201 </table>
202 {{- end -}}
203{{- break -}}
204{{- end -}}
205{{- else -}}
206{{- continue -}}
207
208{{- end -}}
209{{- end -}}
210{{- $PreviousYear := (time $Previousdate).AddDate 0 0 -1 | dateFormat "2006" -}}
211{{- $PreviousYearMonthDay := (time $Previousdate).AddDate 0 0 -1 | dateFormat "01-02-2006" -}}
212{{- $NextYear := (time $Previousdate).AddDate 0 0 1 | dateFormat "2006" -}}
213{{- $NextYearMonthDay := (time $Previousdate).AddDate 0 0 1 | dateFormat "01-02-2006" -}}
214
215{{- $Nextdate := (time $Nextdate).AddDate 0 0 -1 | dateFormat "01-02-2006" -}}
216{{- $PreviousFile := printf "%s" "wx/history/" | printf "%s%s" $PreviousYear | printf "%s%s%s" $PreviousYearMonthDay "/"| printf "%s%s" ".md" -}}
217
218{{- $PreviousFile := printf "%s%s%s%s%s" "/wx/history/" $PreviousYear "/" $PreviousYearMonthDay ".md" -}}
219{{- $PreviousURL := printf "%s%s%s%s%s" "/wx/history/" $PreviousYear "/" $PreviousYearMonthDay "/" -}}
220
221{{- $NextFile := printf "%s%s%s%s%s" "wx/history/" $NextYear "/" $NextYearMonthDay ".md" -}}
222{{- $NextURL := printf "%s%s%s%s%s" "wx/history/" $NextYear "/" $NextYearMonthDay "/" -}}
223<div class="wx-footer"><p>
224{{- if os.FileExists $PreviousFile -}} <a href="{{- $PreviousURL | absURL -}}" title="Previous Day">Previous Day</a> {{- end -}}
225{{- if os.FileExists $NextFile -}} <a href ="{{- $NextURL | absURL -}}" title="Next Day">Next Day</a> {{- end -}}</div></p>
226{{- else -}}
227CSV file Missing
228{{- end -}}

Please don’t hesitate to use this if it will help you, and modify it as you need to make it work for your requirements.

I may come up with a way to work with the JSON files I can generate from Ambient Weather’s API, but that’s not a project I want to deal with right at this moment. I just wanted to get something more or less working now and maybe improve upon it later. Those files are better organized and have much more data, but don’t have highs and lows already calculated. I would have to do that myself and if I choose to go that route I want to take my time with it. I’d also like to see if I can’t generate charts from them if I go there too, since they have all the data I could plot.


updated on 02-11-22

I have made a few tweaks to this to add some ranges in, so I updated this post to include the changed shortcode.