Acme-FishFarm

 view release on metacpan or  search on metacpan

lib/Acme/FishFarm.pm  view on Meta::CPAN

    say "";

    while ( "fish are swimming happily" ) {
        ### DO
        check_DO( $oxygen, reduce_precision( rand(8) ) );
        say "";
        
        ### pH
        check_pH( $water_monitor, 6.912 );
        #check_pH( $water_monitor, 5.9 );
        say "" ;
        
        ## temperature
        #check_temperature( $water_monitor, 23 );
        check_temperature( $water_monitor, 26 );
        say "";
        
        ## turbidity
        check_turbidity( $water_monitor, 120 );
        #check_turbidity( $water_monitor, 190 );
        say "";
        
        # all LEDs
        render_leds( $water_monitor );
        say "";
        
        # buzzers
        render_buzzer( $water_monitor );
        
        sleep(3);
        say "-----------------------------";
    }
    
=head1 EXPORT

The C<:all> tag can be used to import all the subroutines available in this module.

=cut

use Exporter qw( import );
our @EXPORT_OK = qw( 
    install_all_systems 
    reduce_precision consume_oxygen 
    check_DO check_pH check_temperature check_turbidity check_water_filter check_water_level check_feeder
    render_leds render_buzzer
);
our %EXPORT_TAGS = ( 
    all => [ qw( install_all_systems reduce_precision consume_oxygen check_DO check_pH check_temperature 
                 check_turbidity check_water_filter check_water_level check_feeder render_leds 
                 render_buzzer ) ],
);

=head1 NOTES

Almost all the subroutines in this module will give output. The unit measurements used will be according to the ones mentioned in C<Acme::FishFarm::WaterConditionMonitor>.

=head1 SYSTEM INSTALLATION RELATED SUBROUTINES

=head2 install_all_systems

Installs all the available systems the default way and returns them as a list of C<Acme::FishFarm::*> objects in the following sequence:

  (Feeder, OxygenMaintainer, WaterConditionMonitor, WaterLevelMaintainer, WaterFiltration)

=cut

sub install_all_systems {
    my $feeder = Acme::FishFarm::Feeder->install;
    my $oxygen_maintainer = Acme::FishFarm::OxygenMaintainer->install;
    my $water_monitor = Acme::FishFarm::WaterConditionMonitor->install;
    my $water_level = Acme::FishFarm::WaterLevelMaintainer->install;
    my $water_filter = Acme::FishFarm::WaterFiltration->install;
    
    # remember to connect water oxygem maintainer to water condition monitoring :)
    $water_monitor->add_oxygen_maintainer( $oxygen_maintainer );
    
    ( $feeder, $oxygen_maintainer, $water_monitor, $water_level, $water_filter );
}


=head1 SENSOR READING RELATED SUBROUTINES

=head2 reduce_precision ( $decimal )

Reduces positive or negative C<$decimal> to a 3-decimal value. Make sure to pass in a decimal with more than 3 decimal points.

Returns the reduced precision value.

This subroutine is useful if you are trying to set the current sensor readings randomly using the built-in C<rand> function as you do not want to end up with too many decimals on the screen.

=cut

sub reduce_precision {
    my $sensor_reading = shift;
    croak "Please pass in a decimal value" if not $sensor_reading =~ /\./;
    
    $sensor_reading =~ /(-?\d+\.\d{3})/;
    return $1;
}

=head1 AUTOMATED SYSTEMS RELATED SUBROUTINES

All of the subroutines here will give output.

Take note that there are some systems that can't be connected to the water monitoring system and therefore will not effect the LEDs or buzzers. These systems are:

=over 4

=item * Acme::FishFarm::Feeder

=item * Acme::FishFarm::WaterFiltration

=item * Acme::FishFarm::WaterLevelMaintainer

=back

=head2 consume_oxygen ( $oxygen_maintainer, $consumed_oxygen )

This will cause the oxygen level (DO level) of the C<Acme::FishFarm::OxygenMaintainer> to reduce by C<$consumed_oxygen mg/L>

Returns 1 upon success.

lib/Acme/FishFarm.pm  view on Meta::CPAN


=cut

sub check_water_filter {
    my $water_filter = shift;
    my $current_reading = shift;
    my $reduce_waste_by = shift || $water_filter->reduce_waste_count_by;
    my $waste_threshold = $water_filter->waste_count_threshold;
    
    $water_filter->current_waste_count( $current_reading );
    print "Waste Count to Reduce: ", $water_filter->reduce_waste_count_by, "\n";
    print "Current Waste Count: ", $current_reading, " (high: >= ", $waste_threshold, ")\n";

    if ( $water_filter->is_cylinder_dirty ) {
        print "  !! Filtering cylinder is dirty!\n";
        $water_filter->turn_on_spatulas;
        print "  Cleaning spatulas turned on.\n";
        $water_filter->clean_cylinder( $reduce_waste_by );
        print "  Cleaning the cylinder...Done!\n";
        print "Current waste count: ", $water_filter->current_waste_count, "\n";
    } else {
        print "  Filtering cylinder is still clean.\n";
    }
    1;
}

=head2 check_water_level ( $water_level_maintainer, $current_water_level )

This checks, performs necessary actions and outputs the condition of the current waste count in the filtering cylinder.

Take note that this process B<DOES NOT> trigger the LED and buzzer if abnormal condition is present.

Returns 1 upon success.

=cut

sub check_water_level {
    my $water_level = shift;
    my $current_reading = shift;
    my $height_increase = $water_level->water_level_increase_height; # for output
    my $water_level_threshold = $water_level->low_water_level_threshold;
    
    $water_level->current_water_level( $current_reading ); # input by user
    print "Current Water Level: ", $current_reading, " m (low: < ", $water_level_threshold, " m)\n";

    if ( $water_level->is_low_water_level ) {
        print "  !! Water level is low!\n";
        $water_level->pump_water_in;
        print "  Pumping in ", $height_increase, " m of water...\n";
        print "Current Water Level: ", $water_level->current_water_level, " m\n";
    } else {
        print "  Water level is still normal.\n";
    }
    1;
}

=head2 check_feeder ( $feeder, $verbose )

This checks, performs necessary actions and outputs the condition of the feeder. Each call will tick the clock inside the feeder. See C<Acme::FishFarm::Feeder> for more info.

If the food tank is empty, it will be filled to the default. So if you want to fill a different amount, please set the amount before hand. See C<Acme::FishFarm::Feeder>.

Setting C<$verbose> to 1 will give more output about the empty food tank.

Take note that this process B<DOES NOT> trigger the LED and buzzer if abnormal condition is present.

Returns 1 upon success.

=cut

sub check_feeder {
    my ( $feeder, $verbose ) = @_;
    if ( $feeder->timer_is_up ) {
        print "Timer is up, time to feed the fish!\n";
        
        if ( $verbose) {
            $feeder->feed_fish( verbose => 1 );        
        } else {
            $feeder->feed_fish;
        }
        print "  Feeding ", $feeder->feeding_volume, " cm^3 of fish food to the fish...\n";
        
    } else {
        print $feeder->time_remaining, " hours left until it's time to feed the fish.\n";
    }
    
    if ( $feeder->food_remaining <= 0  ) {
        print "  !! Food tank empty!\n";
        $feeder->refill; # default back to 500 cm^3
        print "  Refilled food tank back to ", $feeder->food_tank_capacity, " cm^3.\n";
    }

    print "  Food Remaining: ", $feeder->food_remaining, "cm^3.\n";
    
    $feeder->tick_clock;
    1;
}

=head2 render_leds ( $water_monitor )

Outputs which LEDs are lighted up. Returns 1 upon success.

Currently this subroutine only shows the LEDs present in the  C<Acme::FishFarm::WaterConditionMonitor> object. See that module for more details about the available LEDs.

More LEDs will be available in the future.

=cut

sub render_leds {
    my $water_monitor = shift;

    # must check condition first! If not it won't work
        # this process will update the LEDs status
    $water_monitor->ph_is_normal;
    $water_monitor->temperature_is_normal;
    $water_monitor->lacking_oxygen;    
    $water_monitor->water_dirty;
        
    print "Total LEDs up: ", $water_monitor->lighted_LED_count, "\n";

    if ( $water_monitor->is_on_LED_pH ) {
        print "  pH LED: on\n";
    } else {
        print "  pH LED: off\n";
    }
    
    if ( $water_monitor->is_on_LED_temperature ) {
        print "  Temperature LED: on\n";
    } else {
        print "  Temperature LED: off\n";
    }
    
    if ( $water_monitor->is_on_LED_DO ) {
        print "  Low DO LED: on\n";
    } else {
        print "  Low DO LED: off\n";
    }
    
    if ( $water_monitor->is_on_LED_turbidity ) {
        print "  Turbidity LED: on\n";
    } else {
        print "  Turbidity LED: off\n";
    }
    1;
}

=head2 render_buzzer ( $water_monitor )

Outputs which buzzer is buzzing. Returns 1 upon success.



( run in 1.028 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )