- Published on
Adding the Current Weather to your Obsidian Templates
- Authors
-
-
- Name
- David Mohundro
- Bluesky
- @david.mohundro.com
-
Last year, I started a renewed effort to use Obsidian and I’ve stuck with it - in fact, I haven’t missed a day to get at least a short bullet journal post up. I’ve slowly been tweaking my templates, though. Recently, I added the option to include the weather forecast to my files.
The key here is the excellent wttr.in project - see https://github.com/chubin/wttr.in. A simple curl wttr.in
is all it takes to use it. I’ve found that many widget based tools use it to grab the weather and include it… for example, you could use it to put it in your Terminal title or even your shell prompt.
For me, though, I really just wanted a short snippet in my bullet journals. When we’re done, this is what it will output:
# ☀️ Weather
Clear 31(27) °F ☀️
I’ll drop the snippet and then explain it below:
const forecast = await fetch("https://wttr.in/Memphis?format=j1").then((res) =>
res.json(),
);
const temp = forecast.current_condition[0].temp_F;
const feelsLike = forecast.current_condition[0].FeelsLikeF;
const description = forecast.current_condition[0].weatherDesc[0].value;
const weatherCode = forecast.current_condition[0].weatherCode;
// via https://github.com/chubin/wttr.in/blob/4d384f9efe727b28a595d4f502bcb9593fa19c99/lib/constants.py
const WWO_CODE = {
113: "Sunny",
116: "PartlyCloudy",
119: "Cloudy",
122: "VeryCloudy",
143: "Fog",
176: "LightShowers",
179: "LightSleetShowers",
182: "LightSleet",
185: "LightSleet",
200: "ThunderyShowers",
227: "LightSnow",
230: "HeavySnow",
248: "Fog",
260: "Fog",
263: "LightShowers",
266: "LightRain",
281: "LightSleet",
284: "LightSleet",
293: "LightRain",
296: "LightRain",
299: "HeavyShowers",
302: "HeavyRain",
305: "HeavyShowers",
308: "HeavyRain",
311: "LightSleet",
314: "LightSleet",
317: "LightSleet",
320: "LightSnow",
323: "LightSnowShowers",
326: "LightSnowShowers",
329: "HeavySnow",
332: "HeavySnow",
335: "HeavySnowShowers",
338: "HeavySnow",
350: "LightSleet",
353: "LightShowers",
356: "HeavyShowers",
359: "HeavyRain",
362: "LightSleetShowers",
365: "LightSleetShowers",
368: "LightSnowShowers",
371: "HeavySnowShowers",
374: "LightSleetShowers",
377: "LightSleet",
386: "ThunderyShowers",
389: "ThunderyHeavyRain",
392: "ThunderySnowShowers",
395: "HeavySnowShowers",
};
const WEATHER_SYMBOL = {
Unknown: "✨",
Cloudy: "☁️",
Fog: "🌫",
HeavyRain: "🌧",
HeavyShowers: "🌧",
HeavySnow: "❄️",
HeavySnowShowers: "❄️",
LightRain: "🌦",
LightShowers: "🌦",
LightSleet: "🌧",
LightSleetShowers: "🌧",
LightSnow: "🌨",
LightSnowShowers: "🌨",
PartlyCloudy: "⛅️",
Sunny: "☀️",
ThunderyHeavyRain: "🌩",
ThunderyShowers: "⛈",
ThunderySnowShowers: "⛈",
VeryCloudy: "☁️",
};
const weatherLookupName = WWO_CODE[weatherCode] || "Unknown";
const weatherIcon = WEATHER_SYMBOL[weatherLookupName] || WEATHER_SYMBOL.Unknown;
const output = `${description} ${temp}(${feelsLike}) °F ${weatherIcon}`;
tR += `# ${weatherIcon} Weather\n\n`
tR += output
First off, the following just grabs the weather info. Something that is super nice is that you can use modern JavaScript, though, so I’m using await
here without any problem. I’m also explicitly specifying my location instead of relying on the IP. The format=j1
returns the results in JSON format.
const forecast = await fetch("https://wttr.in/Memphis?format=j1").then((res) =>
res.json(),
);
Next, these lines pull out the relevant information that I’m looking for… pretty straighforward.
const temp = forecast.current_condition[0].temp_F;
const feelsLike = forecast.current_condition[0].FeelsLikeF;
const description = forecast.current_condition[0].weatherDesc[0].value;
const weatherCode = forecast.current_condition[0].weatherCode;
The next lines are snipped a bit, but they’re entirely for getting the emoji weather descriptor. The JSON returns the WWO_CODE
, but I wanted to convert that to the emoji value. I couldn’t find that in the JSON results, so I just went to the source and then dropped the JS version of it in here. So… I look up the WWO_CODE
, then use it to index into the WEATHER_SYMBOL
values.
// via https://github.com/chubin/wttr.in/blob/4d384f9efe727b28a595d4f502bcb9593fa19c99/lib/constants.py
const WWO_CODE = {
113: "Sunny",
// snipped...
395: "HeavySnowShowers",
};
const WEATHER_SYMBOL = {
Unknown: "✨",
// snipped...
VeryCloudy: "☁️",
};
const weatherLookupName = WWO_CODE[weatherCode] || "Unknown";
const weatherIcon = WEATHER_SYMBOL[weatherLookupName] || WEATHER_SYMBOL.Unknown;
Finally, we just output the header and description. Again, I like that I can use string interpolation here. Modern JS!
const output = `${description} ${temp}(${feelsLike}) °F ${weatherIcon}`;
tR += `# ${weatherIcon} Weather\n\n`
tR += output
One note - this will be the weather for the time the template is evaluated. So, if you’re going back and catching up on old posts, it won’t do you any good as it is just for the day.
I’ve also included this in a Gist at https://gist.github.com/drmohundro/44a4e3c865a7250b0b128a55a6fc1415 if that’s easier to remember.