#!/usr/bin/env perl use utf8; use 5.008006; use strict; use warnings; use version; our $VERSION = qv('v0.0.6'); use English qw{ −no_match_vars }; use Carp; use Fatal qw{ open close read write }; use Readonly; use Getopt::Euclid; use DBI; use IO::File; use Mac::Apps::Seasonality::CommandLineUtilities qw{ :growl :functions }; use Mac::Apps::Seasonality::Constants qw{ :application }; use Mac::Apps::Seasonality::LoadICAOHistoryFromCSV qw{ %ALLOWED_UNITS &load_icao_history_from_csv_handle }; Readonly my $EMPTY_STRING => q{}; my $temperature_units = _get_units('--temperature-units', 'temperature_units'); my $pressure_units = _get_units('--pressure-units', 'pressure_units'); my $wind_speed_units = _get_units('--wind-speed-units', 'wind_speed_units'); my $quiet = $ARGV{'--quiet'}; initialize_program_utilities( "Load $SEASONALITY_NAME History", quiet => $quiet, use_growl => ! $ARGV{'--no-growl'}, ); state_progress( $GROWL_NOTIFICATION_PROGRESS, 'Start.' ); shutdown_seasonality_if_necessary( no_shutdown => $ARGV{'--no-shutdown'}, no_restart => $ARGV{'--no-restart'}, force_start => $ARGV{'--force-start'}, shutdown_wait => $ARGV{'--shutdown-wait'}, ); my $database_file_name = $ARGV{'--database'} || $SEASONALITY_HISTORY_DATABASE_PATH; my $database_connection = create_database_connection( $database_file_name, backup => ! $ARGV{'--no-backup'}, ); my $clean = $ARGV{'--clean'}; foreach my $file_name ( @{ $ARGV{''} } ) { state_progress( $GROWL_NOTIFICATION_PROGRESS, "Loading data from \"$file_name\".", ); my $file_handle = IO::File->new($file_name, 'r'); load_icao_history_from_csv_handle( $database_connection, $file_handle, clean => $clean, clean_message_handle => ( ($clean and not $quiet) ? \*STDOUT : undef ), temperature_units => $temperature_units, pressure_units => $pressure_units, wind_speed_units => $wind_speed_units, ); $file_handle->close(); } # end foreach state_progress( $GROWL_NOTIFICATION_PROGRESS, 'Data loaded.', ); close_database_connection(); restart_seasonality_if_necessary(); state_progress( $GROWL_NOTIFICATION_PROGRESS, 'Done.', ); sub _get_units { my ($command_line_option, $load_option) = @_; my $units = $ARGV{$command_line_option}; if ( $units and not $ALLOWED_UNITS{$load_option}->{$units} ) { die q{"}, $units, qq{" is not one of the allowed values for the $command_line_option option.}, ' Permitted values are: "', join ('", "', sort keys %{ $ALLOWED_UNITS{$load_option} } ), qq{".\n}; } # end if return $units; } # end _get_units() __END__ =encoding utf8 =head1 NAME load_seasonality_history - Load historical weather data into Seasonality's database. =head1 VERSION This document describes load_seasonality_history version 0.0.6. =head1 USAGE load_seasonality_history file... [options] =head1 OPTIONS Note: the set of options I change in future versions; do not count upon the current interface. =over =item --clean Clean up incoming data, treating invalid values as not being present. At present, this only handles the numeric columns (e.g. not the date). Data that is considered invalid includes values that don't look like numbers and values that are outside the range allowed for the column, e.g. a humidity greater than 100%. Non-integer values for integer columns will be rounded, rounding up when the fractional portion is greater than or equal to 0.5. =item --temperature-units [=] The units that the input temperatures are in. Must be one of C, C, C, C. =for Euclid: units.type: string =for Euclid_bug http://rt.cpan.org/Ticket/Display.html?id=27074 This should be: units.type: /f|fahrenheit|c|celsius/ units.type.error: Units must be one of 'f', 'fahrenheit', 'c', 'celsius'. units.default: 'celsius' =item --pressure-units [=] The units that the input pressures are in. Must be one of C, C, C, C, C. =for Euclid: units.type: string =for Euclid_bug http://rt.cpan.org/Ticket/Display.html?id=27074 This should be: units.type: /iHg|inches_Hg|inches_of_mercury|millibars|hectopascals/ units.type.error: Units must be one of 'iHg', 'inches_Hg', 'inches_of_mercury', 'millibars', 'hectopascals'. units.default: 'hectopascals' =item --wind-speed-units [=] The units that the input wind speeds are in. Must be one of C, C, C. =for Euclid: units.type: string =for Euclid_bug http://rt.cpan.org/Ticket/Display.html?id=27074 This should be: units.type: /mph|miles_per_hour|knots/ units.type.error: Units must be one of 'mph', 'miles_per_hour', 'knots'. units.default: 'knots' =item --database [=] =for Euclid: file.type: readable Use a database other than Seasonality's default, C<~/Library/Application Support/Seasonality/weather.db>. =item --no-shutdown If Seasonality is running, don't shut it down before processing. =item --shutdown-wait [=] =for Euclid: seconds.default: 5 seconds.type: integer >= 0 The number of seconds to wait for Seasonality to shut down. Defaults to 5. =item --no-backup Don't back up the database before loading the data. Regardless of the value of this option, the database will not be backed up if Seasonality is running during the actual load of the data. =item --no-restart If Seasonality was running, and it was shut down, don't run it again after the data is loaded. =item --force-start Run Seasonality after the data is loaded, even if it wasn't previously running. This option overrides the C<--no-restart> option. =item -{q|-quiet} Suppress all output. =item --no-growl Even if the L module is installed, don't use it. =item --version =item --usage =item --help =item --man Print the usual program information =back =head1 REQUIRED ARGUMENTS =over =item ... One or more files to load. Each file must be in CSV format. =for Euclid: file.type: readable =back =head1 DESCRIPTION Seasonality is MacOS X weather application, available at L. This program provides a means of getting data into Seasonality's database from data sources that it cannot handle itself. =head2 Data Data is expected in CSV format. Presently, the values for each data point must be in the following order: =over =item · Location identifier, up to 32 characters. For custom locations, avoid using four character identifiers in order to avoid interfering with Seasonality's standard ICAO airport codes. =item · UTC/GMT observation time, consisting of year, month, day, hour, and minute in YYYYMMDDHHMM format. Seconds are not permitted. =item · Wind direction, in integer degrees, 0 to 360, or -1 for variable winds. =item · Wind speed in integer knots. =item · Gust speed in integer knots. =item · Visibility in miles. =item · Temperature in degrees Celsius. =item · Dew point in degrees Celsius. =item · Pressure in integer hectopascals. =item · Relative humidity in integer percent. =back All values are mandatory. If a measurement is missing, use Seasonality's marker value of -1000. No data other than the above is allowed into the file, not even column headers. You can update existing data for a given location and observation time; C will overwrite any preexisting data. In particular, this means that, if you have multiple lines in a file for the same location and time, the last one wins. =head2 Paranoia At present, by default, C will force Seasonality to shut down, if it is running, and will create a backup copy of the database before adding the data. If Seasonality was running at the start, it will be relaunched at the end. In the future, after this program has proved itself reliable, these defaults will be reversed. =head1 DEPENDENCIES L L L L L L L L L L Seasonality v1.3 or v1.4. =head1 DIAGNOSTICS TODO =head1 CONFIGURATION AND ENVIRONMENT C requires that it is running against a database in the format used by Seasonality versions 1.3 and 1.4. The actual Seasonality application must be locatable by L. =head1 INCOMPATIBILITIES None reported. =head1 BUGS AND LIMITATIONS =over =item · The interface to this program is not frozen yet. =item · Columns are required to be in a fixed order. =item · Files with column headers or other ignorable data aren't dealt with. =item · Files are restricted to CSV format. =item · There's no proper handling of errors. Problems just cause Perl to fall over. =item · The DIAGNOSTICS section above is not filled in. =item · Conversion between dew point and relative humidity is not handled. =item · The observation date format isn't flexible. =item · Will not run with databases for Seasonality versions earlier than 1.3. =back Please report any bugs or feature requests to C, or through the web interface at L. =head1 AUTHOR Elliot Shank C<< >> =head1 LICENSE AND COPYRIGHT Copyright ©2006-2007, Elliot Shank C<< >>. All rights reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See L. =head1 DISCLAIMER OF WARRANTY BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. =cut # setup vim: set filetype=perl tabstop=4 softtabstop=4 expandtab : # setup vim: set shiftwidth=4 shiftround textwidth=78 nowrap autoindent : # setup vim: set foldmethod=indent foldlevel=0 :