Inserting more detailed weather forecasts into a daily note

When I installed Templater, I really liked the developer’s demo of using wttr.in to insert an icon-based day’s weather forecast into a daily note. I wanted to do something similar, but being a bit of a weather geek, I wanted a little more detail in mine. Fortunately, my favorite US weather source (the National Weather Service) has an API that lets one pull just about any element of current conditions or forecast data one could want. So I built a daily note template/process around that and thought I would share for any others interested in doing something similar.

tl;dr — daily cron job → URI scheme → automatic daily note creation → Templater function → custom curl command to get appropriate NWS API JSON document → insertion of extracted forecast text into daily note.

NWS API info

A good place to start learning about the NWS API is their API Github page. There’s a wealth of info there. The main info of relevance to this effort is in the General FAQs page, which steps you through the process of getting the forecast for your location through the API. All you need to start is your location in latitude/longitude. Querying the API using that, you’ll get a JSON document back that includes the link for pulling your forecast. For example, it reveals that mine is https://api.weather.gov/gridpoints/PSR/172,49/forecast.

Within the forecast JSON, you’ll see a “periods” section with several numbered periods beneath it. Those, as you’ll notice, are the different forecast periods (“tonight,” “Friday,” “Friday Night,” etc.). That will be relevant later.

Templater setup

To pull the weather data, I created a user-defined Templater function that runs the following shell command:

curl -s https://api.weather.gov/gridpoints/PSR/172,49/forecast | /usr/local/bin/fx-macos .properties.periods[1].detailedForecast

It has two parts. The part before the pipe uses cURL to retrieve the JSON document. The part after the pipe passes the document to a macOS-compatible binary of the FX tool (available as “fx-macos” here under the “releases” subfolder) to efficiently extract the text I want (from the “detailedForecast” field under the “periods” section labeled “1”).

Auto-creating the daily note

Since the period containing the day’s forecast changes with time (and goes away altogether once the day is ending), just counting on myself to manually create the note at the right time each day was a non-starter. I needed a way to automatically create the daily note at the same time each day. To do this, I brought four tools together to join forces: Obsidian’s URI scheme, the Obsidian Advanced URI plugin, AppleScript, and macOS’s trusty crontab. Here’s what they each bring to the table:

  • URI scheme: provides a way to execute actions in Obsidian from outside the app
  • Advanced Obsidian URI plugin: lets me use a URI to open the daily note
  • AppleScript: provides a way to open/run a URI
  • crontab: lets me schedule the triggering of an AppleScript command

Here’s the command I call from the cron job:

58 04 * * * osascript -e 'open location "obsidian://advanced-uri?vault=ObsidianBeta&daily=true"'

What this does: at 4:58am every day, that URI runs on my main computer (which is always on), causing Obsidian to go to the current daily note. Since that note doesn’t exist yet, it creates it, at which point Templater does its thing, getting the text from the NWS forecast and inserting it into my daily note. (It gets the text from period 1 instead of period 0 since at 4:58am period 0 is still the overnight forecast.) Here’s what today’s looked like, for example:

Mostly sunny. High near 100, with temperatures falling to around 97 in the afternoon. South wind 5 to 10 mph.

Whew! It took a bit of effort to get that text flowing, but it now works like a charm. Whenever I get around to opening my daily note that day, the forecast is right there at the top, concisely capturing the forecast for easy reference throughout the day and for posterity’s enjoyment for as long as the note lives.

Anyhow, hopefully this proves helpful to someone—or at least spurs some other Obsidian automation ideas using these components.


EDIT (07 December 2022)

Thanks to some tips from the Templater folks, I’ve refined the use of the template a bit. Instead of creating a custom user function in Templater’s settings, I now use the following code right in the body of the template MD file:

<%*
    try {
        const forecast = await fetch("https://api.weather.gov/gridpoints/GRR/45,15/forecast").then(res => res.json())
		const detailedForecast = forecast.properties.periods[1].detailedForecast
		tR += detailedForecast
    } catch (err) {
        new Notice("Error: \n" + err , 2000);
        tR += "Data access error :("
    }
%>

That effectively does the same thing as before but handles data errors such as 500 and 503 errors (which are annoyingly common with the NWS API, it seems) gracefully rather than halting the processing of the template. If the right data comes back, it inserts it. If not, it prints an alternative message to let me know what happened.

4 Likes

Nice, I like it!

There is also this website: https://wttr.in/:help for a full list of options and flags.

So you can run curl wttr.in and get a text-based weather report.

There is also curl v2.wttr.in for one with some graphs.

By default the color codes won’t render properly in Obsidian. You can specify options to make it render only text with no colors. So you’d still have to change the formatting a bit so it spit out valid Markdown or a code-block, otherwise the spaces won’t render properly.

curl wttr.in/?0?T - This would show text only and only the current weather:

In one terminal command, this would surround the output with code block backticks. I like how you use the URL scheme, but I’m just piping it to a file:

echo "\`\`\`" > ~/ObsidianNotes/weather.md && curl wttr.in/London?0?T >> ~/ObsidianNotes/weather.md && echo "\`\`\`" >> ~/ObsidianNotes/weather.md

How it looks in the terminal by default:


1 Like

I like…but Im always traveling. Any ideas to accomplish something similar but instead of the location being hardcoded it would be based on a geoip lookup

1 Like

I’m not sure about 2fifty6’s example. But in wttr.in the location is not hard-coded unless you specify it with a city name. If you provide no city name, it looks your location up.

I’d have to think about how you’d script this, but it should be pretty straightforward as long as you can provide the script with your current lat/long. The NWS API is designed to look up the forecast link using the following URL: https://api.weather.gov/points/[decimal lat],[decimal long]. For example, if I were to find myself in Kalamazoo, Michigan, I would use https://api.weather.gov/points/42.2871,-85.5885. It would then return a JSON file with the appropriate set of links contained in the Properties section:

        "forecast": "https://api.weather.gov/gridpoints/GRR/45,15/forecast",
        "forecastHourly": "https://api.weather.gov/gridpoints/GRR/45,15/forecast/hourly",
        "forecastGridData": "https://api.weather.gov/gridpoints/GRR/45,15",
        "observationStations": "https://api.weather.gov/gridpoints/GRR/45,15/stations",

The first link listed there is the one I use for the process I described.

So basically you’ll need to:

  1. Generate decimal lat/long coordinates for your current location (within a couple miles should do)
  2. Query the API using the URL structure above
  3. Extract the desired URL from the returned JSON file (the process I described previously uses the “forecast” URL)
  4. Perform the steps in the original process using that URL

You can probably do it all there in a Templater user function, but it might be more robust to use a separate script file that the Templater function runs.

I really liked the simplicity of using wttr.in as demoed by the Templater dev, but it didn’t provide the level of forecast detail I was looking for (especially on dynamic weather days). That v2 of wttr.in wasn’t available (or I wasn’t aware of it) at the time, though, and I do like the looks of that new text-based plot. I may have to experiment with including it below the text forecast. Thanks for pointing that out!

I did not realize that, just tried with wttr and no location is required…thanks

Could you use the Templater ‘Prompt’ function to have the user input long/lat when creating the note?

Possibly? I haven’t experimented with it, but as long as it can assemble those string inputs into the URL it calls, I would think it would work. The problem then becomes handling the JSON that returns, since you have to extract the corresponding gridpoint-based forecast URL and then query that URL to finally get the weather data you’re actually after.

So basically what you’re envisioning would require a two-step API query to get you weather data, and whether or not Templater can append user-input text to URLs, I don’t know enough to say whether it can also handle a two-step query like that.