Detailed rain intensity forecast for the next hour
Weather alerts
Customizable length and interval for hourly weather
Customizable time (12 or 24 hour) and temp display (celsius, fahrenheit, kelvin)
Usable as a dependency or standalone CLI
Weather lookup by ZIP code and country code
Mock weather responses to test responses for varying conditions
This has been my pet project to level up my Elixir skills. Please leave any and all feedback you have (even if it’s just nitpicks about style/code organization, etc.). Thank you!
Just released v0.3.0. Please take a look at the README or the docs.
Define a module in lib/weather/report/custom that implements the Weather.Report behaviour (definines generate/1).
defmodule Weather.Report.Custom.FullMoon do
@moduledoc """
A custom `Weather.Report` that prints when there's a full moon.
"""
use Weather.Report
@full_moon_phase 0.5
@doc """
Generates a full moon report.
"""
@impl Weather.Report
def generate({report, %{"daily" => [%{"moon_phase" => @full_moon_phase} | _]} = body, opts}) do
{
["🌝🌚 OMG FULL MOON TONIGHT 🌚🌝" | report],
body,
opts
}
end
def generate(weather), do: weather
end
Add that module to the list of custom reports in your config/config.exs
Issue a pull request to have your custom report added to the repo so others can use it! (please don’t include the changes you made to config/config.exs in your PR)
Would love to see what kind of custom reports you all build! <3
Fix a bug where the hourly rain report would report rain for the current hour when no more rain was expected between now and the end of the hour (752e374)
Very cool project! Also nice to see how you’ve been working on it the last couple of months (deducing from the commit history). Nice work.
Since you’ve taken the effort to add support running it as an escript, you could consider updating the instructions to install from github (or hex). This worked without any problem for me:
mix escript.install github spencerolson/weather
This installs it somewhere in an escripts folder that can be added to your $PATH. Probably also possible to install from hex (didn’t try). See the escript docs for more options.
One minor remark: the time shows up in the correct time zone when running through the CLI. But when showing the report in Livebook for example, the times are off (they seem to appear in UTC).
I have no idea what to do with this library yet but it was a nice time fiddling with it, and a good example of how to grow and document such a library/cli-tool.
First of all, thank you for the kind words! It’s been a fun project and I’ve learned so much from the Elixir community (especially on this forum) already.
Since you’ve taken the effort to add support running it as an escript, you could consider updating the instructions to install from github (or hex). This worked without any problem for me:
This is great, thank you. To be honest I did not know an escript could be installed this way. I’ll go ahead and update the README, and I’ll check out to see if it’s possible to install from hex.
As a next step, I’m toying around with moving away from escripts and instead using the burrito library to create self-contained executables. The only snag I’m running into right now is I can’t seem to find any way to provide a code-signed executable for MacOS Gatekeeper without paying for the $99/year developer license.
One minor remark: the time shows up in the correct time zone when running through the CLI. But when showing the report in Livebook for example, the times are off (they seem to appear in UTC).
Good call out! I will update the README with instructions for proper setup. In order to have times returned in the correct time zone, a time zone database needs to be configured for elixir.
In the example of a Livebook, the Mix install command should be:
** (ArgumentError) Invalid --zip. Value provided must be a valid zip code. Received: "30-003,PL"
(weather 0.3.4) lib/weather/opts.ex:135: anonymous fn/3 in Weather.Opts.new/1
(elixir 1.17.2) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3
#cell:3uqg3k2cm756vorj:2: (file)
** (ArgumentError) Missing API key. Please set the OPENWEATHER_API_KEY environment variable or provide a value via the --api-key flag.
(weather 0.3.4) lib/weather/opts.ex:135: anonymous fn/3 in Weather.Opts.new/1
(elixir 1.17.2) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3
#cell:3uqg3k2cm756vorj:2: (file)
Hrmmm…that error message may be misleading. That means the lookup by zip code returned a non-200 response. Can you see what you get when you try this in the Livebook?
The Missing API Key repsonse looks expected. If you have set your API Key in the Livebook with the name OPENWEATHER_API_KEY then livebook actually stores it as LB_OPENWEATHER_API_KEY, so within the Livebook you should either:
provide the api_key directly to the Weather.Opts.new/1 call, OR
set the ENV var as directed in the Livebook instructions (which saves it as LB_OPENWEATHER_API_KEY), then create a variable api_key = System.fetch_env!("LB_OPENWEATHER_API_KEY") and use that value for your calls (this is from the step under the Fetching Real Data section in the Livebook)
Update: I released a new version 0.3.5 that includes a fix so that you no longer get a misleading error message about an invalid --zip when the api key is invalid.
This is the response I’d expect, and shouldn’t lead to the Invalid --zip. Value provided must be a valid zip code error you were seeing…perhaps the OpenWeatherMap API was having an intermittent issue during your initial request.
%{
"cod" => 401,
"message" => "Please note that using One Call 3.0 requires a separate subscription to the One Call by Call plan. Learn more here https://openweathermap.org/price. If you have a valid subscription to the One Call by Call plan, but still receive this error, then please see https://openweathermap.org/faq#error401 for more info."
}```
Sorry for derailing your thread.
Yes, you need to subscribe to the One Call API 3.0, however you can set a limit to ensure you never go over the free 1000 calls per day. There is a bit more detail in the Creating an API Key section on the README. Let me know if you have any other questions!
In the meantime, you can play around with fake weather data using the test option passed to Weather.Opts.new/1. you can pass test: "storm", test: "rain", or test: "clear".