I just had a short session with Grok in the browser, enhancing a little script I've been using this week (also started by Grok, but then hand tweaked by me). I'd never used jq before this, so it's easier to modify something that already exists.
#!/bin/bash
set -euo pipefail
TOM=$(date -d tomorrow +%Y-%m-%d 2>/dev/null || date -v+1d +%Y-%m-%d)
URL='https://api.open-meteo.com/v1/forecast?latitude=-35.5&longitude=174&hourly=global_tilted_irradiance,temperature_2m,cloud_cover_low&tilt=20&azimuth=180&forecast_days=2&timezone=Pacific/Auckland'
curl -sS "$URL" |
jq --arg d "$TOM" '
[ .hourly.time, .hourly.global_tilted_irradiance, .hourly.temperature_2m, .hourly.cloud_cover_low ] as $cols
| [ range(0; ($cols[0]|length))
| select($cols[0][.] | startswith($d))
| ($cols[0][.][11:13] | tonumber) as $h
| select($h >= 7 and $h <= 18)
| {gti: $cols[1][.], t: $cols[2][.], c: $cols[3][.]}
]
| if length == 0 then
{error: "no hours for \($d)", date: $d}
else
{
date: $d,
hours: length,
# gti_kwh_m2: ((map(.gti) | add) / 1000),
t_min: (map(.t) | min),
t_max: (map(.t) | max),
est_dc_kwh: (((((map(.gti) | add) / 1000) * 12 * 0.225 * 0.8) * 10 | round) / 10),
cloud_8_to_4: (map(.c)[1:9] | join(" "))
}
end
'
Output is like this:
{
"date": "2026-08-30",
"hours": 12,
"t_min": 10.0,
"t_max": 14.5,
"est_dc_kwh": 10.1,
"cloud_8_to_4": "77 52 48 51 100 33 23 37"
}
Basically it's just estimating how much solar power generation I'll get tomorrow.
I wanted to add estimates of the kWh used by my heat pump and dehumidifier tomorrow. And pick a good state of charge to get my 10kWh of battery to overnight, to start the day with at 7 AM — the end of 18.1c night rate and start of 45c (weekends) or 60c (week days) power. The aim: to get to 9 PM without using any day time grid power on the largest practical number of days.
I screen-shot bar graphs of the daily kWh used by the heat pump and by the dehumidifier for June, July, August as well as the monthly totals since September last year (all from my TP-Link P110 smart plugs). I threw those at Grok. It downloaded weather records for my location for that time period, now using hourly data for global_tilted_irradiance, temperature_2m, cloud_cover_low, dew_point_2m, relative_humidity_2m, precipitation. It took a couple of minutes to work up a model for each appliance, run it against the historical data. tweak the parameters, and report the RMS error, which was in the 1-2 kWh/day region.
The script expanded from 27 lines to 200.
Output now looks like this:
{
"date": "2026-08-30",
"hours": 12,
"t_min": 10.0,
"t_max": 14.5,
"est_dc_kwh": 10.1,
"cloud_8_to_4": "77 52 48 51 100 33 23 37",
"t_mean_24": 11.9,
"t_min_24": 10.0,
"t_max_24": 14.5,
"td_mean": 9.7,
"rh_mean": 86.6,
"rain_mm": 11.9,
"rain_today_mm": 61.1,
"est_dh_kwh": 4.8,
"est_dh_litres": 12.1,
"hp_mode": "heat",
"est_hp_kwh": 9.7,
"est_hp_heat_kwh": 9.7,
"est_hp_cool_kwh": 0,
"load_7_21_kwh": 10.1,
"net_7_21_kwh": 0,
"morn_7_10_net_kwh": 1.8,
"mid_10_15_net_kwh": -3.3,
"eve_15_21_net_kwh": 1.6,
"shape": "trough-peak",
"tariff": "weekend 45c shoulder 07-21",
"batt_target_kwh": 4.3,
"batt_target_pct": 43,
"soc_0930_kwh": 2.5,
"soc_1500_kwh": 5.8,
"soc_2100_kwh": 4.2,
"soc_min_kwh": 2.5,
"soc_max_kwh": 6.7,
"clip_kwh": 0,
"short_kwh": 0,
"batt_note": "trough-peak - stays inside 2.5-10 kWh"
}
The numbers all look pretty reasonable to me. It's a little unusual for solar production and load to match so exactly, but that looks right for tomorrow. And, yes, we really have had 50mm rain today. I can see flooding from my window.
The original script has been pretty good, but not perfect at predicting solar production.
Date Pred Act
08-27 10.8 10.375
08-28 6.1 4.134
08-29 1.7 0.39
Clearly the parameters could use a little tweaking, but it's directionally accurate. If I just subtracted 1kWh from each prediction then it would be within 1 kWh every day so far. Obviously I need to gather more data.
I don't even want to think about how long it would have taken me to do this myself, looking up formulas, making a model, testing it against historical data, writing code in an unfamiliar language (of course I could have used Python's JSON library).
The 27 line script took 0.5s user time on VisionFive 2, the 8 times longer one 0.65s. Wall time including the internet query is 1.4-1.5 seconds for the bigger script. It's something I'll run once a day before bedtime.
It's saying that if tomorrow I start with 43% battery at 7 AM then it'll never go lower than 25% or higher than 67%. So I'll actually start at 60% :-)
Good enough.