#!/usr/bin/perl use v5.26; use warnings; use Object::Pad 0.19; use Future::AsyncAwait; use Future::IO::Impl::IOAsync; STDOUT->binmode( ":encoding(UTF-8)" ); =head1 NAME C<device-chip-sensor-datalogger> - write CSV files from C<Device::Chip> sensor data =head1 SYNOPSIS $ device-chip-sensor-datalogger -A BusPirate BME280 -o data.csv =head1 DESCRIPTION This program periodically queries sensor values from L<Device::Chip> instances attached via a L<Device::Chip::Adapter> and writes the results as records in a CSV file. =cut class MyApp extends App::Device::Chip::sensor { use Text::CSV; use POSIX qw( strftime ); has $_OUTFILE; has $_TIMESTAMP = "%Y-%m-%d %H:%M:%S"; =head1 COMMANDLINE OPTIONS The following commandline options are recognised, in addition to those provided by the common base class - see L<App::Device::Chip::sensor/COMMANDLINE OPTIONS>. =over 4 =item * --output, -o FILE Gives the filename to write the CSV data into. =item * --timestamp STR A strftime(3) format string to use for writing the initial timestamp column. Defaults to C<"%Y-%m-%d %H:%M:%S">. =back =cut method OPTSPEC :override { return $self->SUPER::OPTSPEC, ( 'o|output=s' => \$_OUTFILE, 'timestamp=s' => \$_TIMESTAMP, ); } has $_csv; has $_outh; async method after_sensors :override ( @sensors ) { $_csv = Text::CSV->new; open $_outh, ">", $_OUTFILE or die "Unable to open $_OUTFILE for writing - $!\n"; $_outh->binmode( ":encoding(UTF-8)" ); $_outh->autoflush; $_csv->say( $_outh, [ "# timestamp", map { my $sensor = $_; my $chip = $sensor->chip; my $chipname = ( ref $chip ) =~ s/^Device::Chip:://r; sprintf "%s %s (%s)", $chipname, $_->name, $_->units } @sensors ] ); } method output_readings ( $now, $sensors, $values ) { $_csv->say( $_outh, [ strftime( $_TIMESTAMP, localtime $now ), map { $sensors->[$_]->format( $values->[$_] ) } 0 .. $#$sensors ] ); } } await MyApp->new->parse_argv->run; =head1 AUTHOR Paul Evans <leonerd@leonerd.org.uk> =cut