#!/usr/bin/env perl use strict; use warnings; use DateTime::Format::Strptime; use 5.016; use Log::Log4perl; use Mojo::UserAgent; use open ':std', OUT => ':utf8'; use Mojo::Util qw(dumper); use Astro::Coord::ECI; use Astro::Coord::ECI::Sun; use Astro::Coord::ECI::Utils qw{deg2rad rad2deg}; use Path::Tiny; # 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"); ## important...no trailing zeroes else 301 error my $lat = 33.4; my $long = -112.1; my $elev = .346; #km $logger->info("$lat $long $elev"); # Set up observer's location my $loc = Astro::Coord::ECI->geodetic( deg2rad($lat), deg2rad($long), $elev ); my $url1 = "https://api.weather.gov/points/$lat,$long"; $logger->info("=============="); $logger->info("$url1"); # the API docs says you must identify yourself, please make this something legit my $name = '(example.com, contact@example.com)'; 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"); my $url = "https://api.weather.gov/gridpoints/$station/$gridX,$gridY/forecast/hourly"; $logger->info("=============="); $logger->info("$url"); # the API docs says you must identify yourself, please make this something legit $name = '(example.com, contact@example.com)'; $ua = Mojo::UserAgent->new; $ua->transactor->name($name); # get JSON response my $forecasts = $ua->get($url)->res->json->{properties}->{periods}; use DateTime::Format::Strptime; my $dateparser = DateTime::Format::Strptime->new( # parses 2020-04-26T06:00:00-05:00, # %F then literal T then %T then timezone offset pattern => '%FT%T%z' ) or die "failed to DateTime::Format::Strptime->new()"; my @ordered; my $refordered = \@ordered; my $index = 0; for my $aforecast (@$forecasts) { ## sample records probabilistically next unless ( rand() > .95 ); # 1 of every 20 my $number = $aforecast->{number}; # start and end times of the prediction, convert them to objects my $start_time_str = $aforecast->{'startTime'}; my $start_time_dateobj = $dateparser->parse_datetime($start_time_str) or die "parsing date '$start_time_str'."; my $jd = $start_time_dateobj->jd; $start_time_dateobj->set_time_zone('America/Los_Angeles'); my $st = $start_time_dateobj->strftime('%Y-%m-%d-%H:%M:%S %Z'); my $hour = $start_time_dateobj->hour_12(); my $which_m = $start_time_dateobj->am_or_pm(); my $abrv = $start_time_dateobj->day_abbr(); # sunny? my $forecast_str = $aforecast->{'shortForecast'}; # temperature as a number, see later for the units my $temp = $aforecast->{'temperature'}; my $cloud_layers = $aforecast->{cloudLayers}; ### using Astro::Coord::ECI::Sun # Instantiate the Sun. my $sun = Astro::Coord::ECI::Sun->universal( $start_time_dateobj->epoch() ); # Figure out if the Sun is up at the observer's location. my ( $azimuth, $elevation, $range ) = $loc->azel($sun); ### using Your Sky fourmilab my $west_long = -$long; my $pturl = 'http://www.fourmilab.ch/cgi-bin/Yoursky?z=1&lat=$lat&ns=North&lon=$west_long&ew=West'; # you wanted Julian date so it looks like date should be '2' from the source. my $tx = $ua->post( $pturl => form => { utc => $jd, date => '2' } ); my $sunrow = $tx->res->dom->at('center:nth-of-type(3) table tr:nth-of-type(3)'); my $alt2 = $sunrow->children->[4]->text; say 'Altitude: ' . $sunrow->children->[4]->text; my $az2 = $sunrow->children->[5]->text; say 'Azimuth: ' . $sunrow->children->[5]->text; my $vis = $sunrow->children->[6]->text; # new scope for hash my %parsed; # store this record/prediction in our %parsed hash # keyed on this: my $key = $start_time_str; $parsed{$key} = { "Sun degrees above horizon" => rad2deg($elevation), 'azimuth' => rad2deg($azimuth), 'human-readable' => "$abrv $hour $which_m", 'cloud layers' => $cloud_layers, 'date-from-local' => $st, 'number' => $number, 'forecast-string' => $forecast_str, 'julian day' => $jd, 'Altitude: ' => $alt2, 'Azimuth: ' => $az2, 'Visible: ' => $vis, # we append temp unit to the key, e.g. 'F' 'forecast-temp-' . $aforecast->{'temperatureUnit'} => $temp, }; my $refparsed = \%parsed; $ordered[$index] = $refparsed; #$logger->info( dumper $refparsed); ++$index; } $logger->info( dumper $refordered); __END__