This was produced with lunchtime strolls in mind, but can be used for many other purposes, but some people do not like the wind or the rain or both no could I produce a website that would give me a predications based on the current weather condition for the week outlining how likely that person would go outside.
First we need an open source weather API to use and for this I have used open-meteo as you can pull all the information you require from that API:
$url = "https://api.open-meteo.com/v1/forecast?latitude=$latitude&longitude=$longitude&hourly=temperature_2m,precipitation_probability,cloudcover,windspeed_10m&daily=weathercode,temperature_2m_max,temperature_2m_min,precipitation_probability_max&timezone=Europe%2FLondon"
This should then produce a report that is easy to read, and this is an example for an "indoor" person:
Whereas this same example for an outdoor person would look more like this:
The weather conditions are the same, but the variables have been changed
# Calculate walk probability
$walkScore = 100
$walkReason = ""
# Temperature impact
if ($dailyTemp -lt 15) {
$walkScore -= (15 - $dailyTemp) * 5
$walkReason += "❄️ Too cold for <name> delicate constitution. "
}
elseif ($dailyTemp -gt 22) {
$walkScore -= ($dailyTemp - 22) * 5
$walkReason += "🥵 Too toasty for <name> taste. "
}
# Rain impact
if ($dailyPrecip -gt 20) {
$walkScore -= $dailyPrecip * 0.5
$walkReason += "🌧️ <name> umbrella might get a workout. "
}
# Cloud impact
if ($dailyCloud -gt 60) {
$walkScore -= ($dailyCloud - 60) * 0.3
$walkReason += "☁️ Typical Coventry skies. "
}
# Wind impact
if ($dailyWind -gt 20) {
$walkScore -= ($dailyWind - 20)
$walkReason += "💨 <name> concerned about impromptu flying lessons. "
}
$walkScore = [Math]::Max(0, [Math]::Min(100, $walkScore))
$processedData += @{
Date = $date.ToString("dddd, MMMM dd")
Temperature = [math]::Round($dailyTemp, 1)
PrecipitationChance = [math]::Round($dailyPrecip)
CloudCover = [math]::Round($dailyCloud)
WindSpeed = [math]::Round($dailyWind, 1)
WalkProbability = [math]::Round($walkScore)
WalkReason = $walkReason
}
Then when you run the code you get the HTML produced by Powershell based on the live data and the desired defined variables (the values above in bold).
Script : OutdoorAssessment.ps1
# Weather Dashboard for Coventry
$ErrorActionPreference = 'Stop'
# Location coordinates for Coventry
$latitude = "52.4068"
$longitude = "-1.5197"
function Get-WeatherData {
try {
Write-Host "Fetching weather data for Coventry..."
# Direct API call to Open-Meteo
$url = "https://api.open-meteo.com/v1/forecast?latitude=$latitude&longitude=$longitude&hourly=temperature_2m,precipitation_probability,cloudcover,windspeed_10m&daily=weathercode,temperature_2m_max,temperature_2m_min,precipitation_probability_max&timezone=Europe%2FLondon"
Write-Host "Requesting data from: $url"
$weatherData = Invoke-RestMethod -Uri $url -Method Get
Write-Host "Data retrieved successfully"
# Process and format the data
$processedData = @()
for ($i = 0; $i -lt 7; $i++) {
$date = (Get-Date).AddDays($i)
$dayIndex = $i * 24
$dailyTemp = ($weatherData.daily.temperature_2m_max[$i] + $weatherData.daily.temperature_2m_min[$i]) / 2
$dailyPrecip = $weatherData.daily.precipitation_probability_max[$i]
$dailyCloud = ($weatherData.hourly.cloudcover | Select-Object -Skip $dayIndex -First 24 | Measure-Object -Average).Average
$dailyWind = ($weatherData.hourly.windspeed_10m | Select-Object -Skip $dayIndex -First 24 | Measure-Object -Average).Average
# Calculate walk probability
$walkScore = 100
$walkReason = ""
# Temperature impact
if ($dailyTemp -lt 15) {
$walkScore -= (15 - $dailyTemp) * 5
$walkReason += "❄️ Too cold for John's delicate constitution. "
}
elseif ($dailyTemp -gt 22) {
$walkScore -= ($dailyTemp - 22) * 5
$walkReason += "🥵 Too toasty for John's taste.
}
# Rain impact
if ($dailyPrecip -gt 20) {
$walkScore -= $dailyPrecip * 0.5
$walkReason += "🌧️ John's umbrella might get a workout. "
}
# Cloud impact
if ($dailyCloud -gt 60) {
$walkScore -= ($dailyCloud - 60) * 0.3
$walkReason += "☁️ Typical Coventry skies. "
}
# Wind impact
if ($dailyWind -gt 20) {
$walkScore -= ($dailyWind - 20)
$walkReason += "💨 John's concerned about impromptu flying lessons. "
}
$walkScore = [Math]::Max(0, [Math]::Min(100, $walkScore))
$processedData += @{
Date = $date.ToString("dddd, MMMM dd")
Temperature = [math]::Round($dailyTemp, 1)
PrecipitationChance = [math]::Round($dailyPrecip)
CloudCover = [math]::Round($dailyCloud)
WindSpeed = [math]::Round($dailyWind, 1)
WalkProbability = [math]::Round($walkScore)
WalkReason = $walkReason
}
}
# Generate HTML
$html = @"
<!DOCTYPE html>
<html>
<head>
<title>Coventry Lunctime Walkies Walk-o-meter</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
background: #f0f2f5;
}
.header {
text-align: center;
background: linear-gradient(135deg, #1e88e5, #1565c0);
color: white;
padding: 20px;
border-radius: 10px;
margin-bottom: 20px;
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
}
.card {
background: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.probability {
font-size: 24px;
font-weight: bold;
text-align: center;
padding: 10px;
margin: 10px 0;
border-radius: 5px;
}
.high { background: #4CAF50; color: white; }
.low { background: #f44336; color: white; }
.weather-info div {
display: flex;
justify-content: space-between;
padding: 8px 0;
border-bottom: 1px solid #eee;
}
.verdict {
font-style: italic;
color: #666;
margin-top: 15px;
padding-top: 15px;
border-top: 1px dashed #ccc;
}
</style>
</head>
<body>
<div class="header">
<h1>🌈 Coventry Weather Walk-o-meter 🚶♂️</h1>
<p>Last Updated: $(Get-Date -Format "dddd, MMMM dd, yyyy HH:mm")</p>
</div>
<div class="grid">
"@
foreach ($day in $processedData) {
$probabilityClass = if ($day.WalkProbability -ge 70) { "high" } else { "low" }
$walkEmoji = if ($day.WalkProbability -ge 70) { "🚶♂️" } else { "🛋️" }
$html += @"
<div class="card">
<h2>$($day.Date)</h2>
<div class="probability $probabilityClass">
Walk Probability: $($day.WalkProbability)% $walkEmoji
</div>
<div class="weather-info">
<div><span>Temperature:</span> <span>$($day.Temperature)°C</span></div>
<div><span>Rain Chance:</span> <span>$($day.PrecipitationChance)%</span></div>
<div><span>Cloud Cover:</span> <span>$($day.CloudCover)%</span></div>
<div><span>Wind Speed:</span> <span>$($day.WindSpeed) km/h</span></div>
</div>
<div class="verdict">$($day.WalkReason)</div>
</div>
"@
}
$html += @"
</div>
</body>
</html>
"@
# Save and open the report
$outputPath = Join-Path $PSScriptRoot "WalkiesDashboard.html"
$html | Out-File -FilePath $outputPath -Encoding utf8
Write-Host "Dashboard generated at: $outputPath"
Start-Process $outputPath
}
catch {
Write-Host "Error: $_"
Write-Host "Response: $($_.ErrorDetails.Message)"
Write-Host "Stack Trace: $($_.ScriptStackTrace)"
}
}
# Run the script
Get-WeatherData