Aldebaran has asked for the wisdom of the Perl Monks concerning the following question:

I feel fortunate to find monks who follow what I'm developing in perl, indeed make it possible to do so at a much greater rate than I could by myself. What I have been seeking is perl ways to figure out whether the sun is going to be on you at a given latitude, longitude, and elevation. These scripts have had the input values hard-coded at the beginning:

## important...no trailing zeroes else 301 error # weston 41.37,-83.65 my $lat = 41.37; my $long = -83.65; my $elev = .208; # 676 ft = .206 +.02 for observer #km $logger->info("$lat $long $elev");

Instead of running this script on my machine, I want to host it on my site, so that anyone who wants to see output from it may do so. I have to make the disappointing caveat that this script will be drawing from NOAA and therefore US-specific. I don't mean to exclude anyone; indeed, weather in the US is sometimes best-enjoyed as a spectator sport. (The price is right too!)

So, some output will be undefined depending on whether the input data are well-conditioned. Beyond the forecasts that I have been pulling up on threads like getting Sun info with Astro::Coord::ECI::Sun, I want to include just the general sun data from perl, beginning with something like:

# Set up observer's location my $loc = Astro::Coord::ECI->geodetic( deg2rad($lat), deg2rad($long), +$elev );

Now, for the page itself, I have now constructed many using perl and by scratch, but I would like to be able to do this with Mojo if the shoe fits right.

Q1) Does this sound like a good use for Mojo? If not, what are alternatives?

Q2) Given latitude and longitude, does anyone know a perl way to determine how high the ground/water is at that point?

Thanks for your comment.

Replies are listed 'Best First'.
Re: creating a webpage to fetch/calculate weather data
by Util (Priest) on Jun 21, 2020 at 03:21 UTC

    1. One of the Atlanta.pm members was raving at the last meeting about how useful Mojo is for web munging (scraping, parsing, and re-publishing as an internal "API"). I have no personal experience with Mojo, but I trust his ravings.

    2. You can get elevation from lat+long from National Weather Service (NOAA)
    or The National Map Elevation Point Query Service (USGS).

    USGS has high granularity and accuracy:

    $ curl -sS 'https://nationalmap.gov/epqs/pqs.php?units=Meters&output=j +son&x=-83.65&y=41.37' | jq '.USGS_Elevation_Point_Query_Service.Elevation_Query.Elevation' 212.77
    NOAA has the elevation of the 2.5km grid polygon, which will be lower granularity, but might (I'm just guessing) be helpful for water, where the elevation varies:
    $ curl -LsS 'https://api.weather.gov/points/41.37,-83.65' | jq '.properties.forecastGridData' "https://api.weather.gov/gridpoints/CLE/16,52" $ curl -LsS 'https://api.weather.gov/gridpoints/CLE/16,52' | jq '.properties.elevation.value' 213.0552

      1. One of the Atlanta.pm members was raving at the last meeting about how useful Mojo is for web munging (scraping, parsing, and re-publishing as an internal "API"). I have no personal experience with Mojo, but I trust his ravings.

      Then Mojo it is. Thanks so much for your post, Util, it helped me get farther in a lot of ways. I was able to get this to work on the command line, but I couldn't get Corion's curl converter to recognize a -S option, nor could I see it from man curl. The command seems to give the same output without it:

      $ curl -s 'https://nationalmap.gov/epqs/pqs.php?units=Meters&output=js +on&x=-83.65&y=41.37' | jq '.USGS_Elevation_Point_Query_Service.Elevat +ion_Query.Elevation' 212.77 $

      Unfortunately, I couldn't get this value in the perl script which I'm posting below. (Partial credit is great for me.)

      NOAA has the elevation of the 2.5km grid polygon, which will be lower granularity, but might (I'm just guessing) be helpful for water, where the elevation varies:

      I was thrilled to see this solution at the same server where I had been fishing! Furthermore, your example along with the jq command to see where the good data is in the haystack was exactly what I needed to get some numbers out of this. First I'll post the log then the source.

      2020/06/23 15:26:07 INFO ./5.2.elev.pl 2020/06/23 15:26:07 INFO { "USGS_Elevation_Point_Query_Service" => { "Elevation_Query" => { "Data_Source" => "3DEP 1/3 arc-second", "Elevation" => -1000000, "Units" => "Meters", "x" => "41.37", "y" => "-83.65" } } } 2020/06/23 15:26:07 INFO 41.37 -83.65 0.208 2020/06/23 15:26:07 INFO ============== 2020/06/23 15:26:07 INFO https://api.weather.gov/points/41.37,-83.65 2020/06/23 15:26:08 INFO CLE 2020/06/23 15:26:08 INFO 16 52 2020/06/23 15:26:08 INFO ============== 2020/06/23 15:26:08 INFO https://api.weather.gov/gridpoints/CLE/16,52 2020/06/23 15:26:08 INFO ============== 2020/06/23 15:26:08 INFO 213.0552 wmoUnit:m

      Source:

      #!/usr/bin/env perl use strict; use warnings; use 5.016; use Log::Log4perl; use Mojo::UserAgent; use open ':std', OUT => ':utf8'; use Mojo::Util qw(dumper); # get rid of old log my $file = '/home/hogan/Documents/hogan/logs/4.log4perl.txt'; unlink $file or warn "Could not unlink $file: $!"; my $log_conf4 = "/home/hogan/Documents/hogan/logs/conf_files/4.conf"; Log::Log4perl::init($log_conf4); #info my $logger = Log::Log4perl->get_logger(); $logger->info("$0"); # weston, OH 41.37,-83.65 my $lat = 41.37; my $long = -83.65; # the API docs says you must identify yourself, please make this somet +hing legit my $name = '(example.com, contact@example.com)'; my $url2 = "https://nationalmap.gov/epqs/pqs.php?output=json&units=Meters&x=$lat& +y=$long"; my $ub = Mojo::UserAgent->new; $ub->transactor->name($name); # get JSON response my $qv = $ub->get($url2)->res->json; $logger->info( dumper $qv); my $elev = .208; # 676 ft = .206 +.02 for observer #km $logger->info("$lat $long $elev"); my $url1 = "https://api.weather.gov/points/$lat,$long"; $logger->info("=============="); $logger->info($url1); my $ua = Mojo::UserAgent->new; $ua->transactor->name($name); # get JSON response my $pv = $ua->get($url1)->res->json->{properties}; my $station = $pv->{'cwa'}; my $gridX = $pv->{'gridX'}; my $gridY = $pv->{'gridY'}; $logger->info("$station"); $logger->info("$gridX $gridY"); $logger->info("=============="); ## new transaction ## find elevation my $uc = Mojo::UserAgent->new; $uc->transactor->name($name); my $url3 = "https://api.weather.gov/gridpoints/$station/$gridX,$gridY" +; $logger->info( $url3 ); my $json = $uc->get($url3)->res->json; #my $props = $json->{properties}; my $elev2 = $json->{properties}->{elevation}->{value}; my $unit = $json->{properties}->{elevation}->{unitCode}; $logger->info("=============="); #$logger->info(dumper($props)); $logger->info( $elev2 . ' '. $unit); __END__

      It takes me time fiddling with these things with perl and jq in order to get my head around them.

      Q1) How do I get a valid value for the usgs query in lexical perl?

      Thanks again for your post,

        > recognize a -S option, nor could I see it from man curl.

        It seems to be a recent addition. See -S in man curl.

        -S, --show-error
        When used with -s, --silent, it makes curl show an error message if it fails.
        -s, --silent
        Silent or quiet mode. Don't show progress meter or error messages. Makes Curl mute. It will still output the data you ask for, potentially even to the terminal/stdout unless you redirect it.

        I doubt this option influences what gets downloaded.

        map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

      Big day for perl and you, Util; I thought your presentation was awesome, but I could not ask any questions, as the only way I could hear anything was going to the livestream with youtube.

      Then I hauled out an older machine with a newer ubuntu and now can hear the zoom proceedings. Maybe others had similar problems or not...I could be quite smart and be the local dunce in such matters.

      I've always been interested in the weather and trees of every variety. bliako has posted several examples recently that are fascinating, but I had forgotten about HTML::TreeBuilder, which I used to use quite frequently.

      You made a good case for curl'ing once:

      $ curl -o 1.weather.html 'https://www.wunderground.com/weather/us/or/p +ortland' % Total % Received % Xferd Average Speed Time Time Time + Current Dload Upload Total Spent Left + Speed 100 847k 0 847k 0 0 487k 0 --:--:-- 0:00:01 --:--: +-- 487k $

      I find your script quite elegant and readable:

      $ ./1.wund_wind.pl N5 $ cat 1.wund_wind.pl #!/usr/bin/env perl use 5.016; use HTML::TreeBuilder; my $tree = HTML::TreeBuilder->new_from_file('1.weather.html') or die; my $wind = $tree->look_down( _tag => 'div', class => qr/^condition-wind /, ); say $wind->as_trimmed_text( extra_chars => '\xA0' ); $

      Q1) What other fields are worth looking at at wunderground?

      Q2) Any idea what the KORPORTL966 part of this url signfies?

      https://www.wunderground.com/hourly/us/or/portland/KORPORTL966

      (This has nothing to do with the parent response.) Q3) Why can't I crack this with Mojo?

      #!/usr/bin/env perl use Mojo::UserAgent; use 5.016; use warnings; # Fetch website my $uaname = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 ( +KHTML, like Gecko) Chrome/40.0.2214.93 Safari/537.36'; my $ua = Mojo::UserAgent->new; my $res = $ua->get('1.weather.html')->result; # Visit all nodes recursively to extract more than just text for my $n ($res->dom->descendant_nodes->each) { # Text or CDATA node print $n->content; # Also include alternate text for images print $n->{alt} if $n->type eq 'tag' && $n->tag eq 'img'; }
      $ ./1.mo_tree.pl Can't connect: Name or service not known at ./1.mo_tree.pl line 9. $

      Thanks everybody for presentations on a successful first day. As if covid could keep perl down....

        "Why can't I crack this with Mojo?"

        Alternatively just get the URL using Mojo::UserAgent, in exactly the same way as all of the other Mojo based examples you've been provided with.

Re: creating a webpage to fetch/calculate weather data
by marto (Cardinal) on Jun 21, 2020 at 08:28 UTC

    Mojolicious->Guides->Tutorial should be your starting point. As an example take one of the previous Mojo based solutions I gave you (example), paste it into a route, add a single line to render the output, and there you go, something to get you started.

Re: creating a webpage to fetch/calculate weather data
by marto (Cardinal) on Jun 22, 2020 at 13:52 UTC

    "Given latitude and longitude, does anyone know a perl way to determine how high the ground/water is at that point?"

    Geo::Elevation::HGT may be worth investigating.

Re: creating a webpage to fetch/calculate weather data
by perlfan (Parson) on Jun 22, 2020 at 06:10 UTC
    This Wednesday is TPC in the cloud and one of the talks is on a personal weather app, might be up your alley for just $10. Unless this is YOU and you're cramming the talk together x) ... It may be on YT for free - https://tpc20cic.sched.com/event/cDay

        Thanks. A good listen. Corion used Mojolicious for the part that is similar to what I'm doing, so I'll be taking notes....

      This Wednesday is TPC in the cloud and one of the talks is on a personal weather app, might be up your alley for just $10.

      Thanks for the tip, perlfan, and I just happen to have ten bucks, so now I have a ticket, supposedly. It starts June 24, 2020...tomorrow. See you there....

Re: creating a webpage to fetch/calculate weather data
by Anonymous Monk on Jun 28, 2020 at 03:33 UTC