#!/usr/bin/perl use strict; use warnings; package PHPFina; our $VERSION = '1.00'; use POSIX 'strftime'; #use Getopt::Long; #my $directory = 'data/phpfina'; #my $clean; #my $binout_filename; # #GetOptions('dir=s' => \$directory, # 'binary=s' => \$binout_filename, # clean => \$clean, # ); # #die "usage: $0 [ -d data-directory ] [ -b binary-output-filename ] [ -clean ] data-file-number output-filename\n" # unless scalar @ARGV == 2; # #get_phpfina($directory, $ARGV[0], $ARGV[1]); # #if ($clean) #{ # x #} # #exit; # ################# sub isnan {!($_[0]<=0||$_[0]>=0)} ################# =head2 ($start_time, $first_value, $self) = PHPFina->new( [ directory => data/phpfina, ] id => file id number, [ fill_NaN => 0 / 1, ] [ fix_notches => 0 / 1, ] ); =cut sub new { my ($class, %args) = @_; my $self = bless({}, $class); my $d = $args{directory}; $d = 'data/phpfina' unless defined $d; $self->{directory} = $d; my $id = $args{id}; die "No file id number supplied" unless defined $id; $self->{id} = $id; my $path = $d; $path .= '/' unless $path =~ '/$'; $self->{fill_NaN} = 1 if $args{fill_NaN}; $self->{fix_notches} = 1 if $args{fix_notches}; # Open the metadata file and read its contents open my $fh_meta, '<:raw', $path . $id . '.meta' or die "Can't open $path${id}.meta: $!\n"; local $/ = \16; # set record size my $raw_metadata = <$fh_meta>; close $fh_meta; my ($id_dummy, $npoints, $interval, $start_time) = unpack 'LLLL', $raw_metadata; $self->{interval} = $interval; $self->{start_time} = $start_time; $self->{epoch} = $start_time+$interval; $self->{prev_value} = 0; print "$path$id metadata\n"; print "id:\t$id\n"; print "interval:\t$interval\n"; print "start_time:\t$start_time\t" . POSIX::strftime('%F %H:%M:%S', localtime $start_time) . "\n\n"; # Open the data file and prepare to read the values open my $fh, '<:raw', $path . $id . '.dat' or die "Can't open $path${id}.dat: $!\n"; local $/ = \4; # set record size my $data = <$fh>; return undef unless defined $data; my $value = unpack 'f', $data; $self->{fh} = $fh; return ($start_time, $value, $self); } sub get_next { my ($self) = @_; local $/ = \4; # set record size my $fh = $self->{fh}; my $data = <$fh>; # my $data = <$self->{fh}>; return undef unless defined $data; my $value = unpack 'f', $data; # ignore NaN and replace if required $value = $self->{prev_value} if isnan($value) and $self->{fill_NaN}; my $epoch = $self->{epoch}; $self->{epoch} += $self->{interval}; $self->{prev_value} = $value; return ($epoch, $value); } =pod #sub get_phpfina #{ # my ($path, $id, $output_filename) = @_; # # $path .= '/' unless $path =~ '/$'; # # warn "($path, $id, $output_filename)\n"; # # open STDOUT, '>', $output_filename # or die "Can't open output file $output_filename: $!\n"; # # open my $fh_meta, '<:raw', $path . $id . '.meta' # or die "Can't open $path${id}.meta: $!\n"; # $/ = \16; # set record size # my $raw_metadata = <$fh_meta>; # close $fh_meta; # # my ($id_dummy, $npoints, $interval, $start_time) = # unpack 'LLLL', $raw_metadata; # # print "$path$id metadata\n"; # print "id:\t$id\n"; # print "npoints:\t$npoints\n"; # print "interval:\t$interval\n"; # print "start_time:\t$start_time\t" # . POSIX::strftime('%F %H:%M:%S', localtime $start_time) . "\n"; # # # open my $fh, '<:raw', $path . $id . '.dat' # or die "Can't open $path${id}.dat: $!\n"; # # local $/ = \4; # set record size # my $bofh; if ($binout_filename) { open $bofh, '>:raw', $binout_filename or die "Can't create binary output file '$binout_filename': $!\n"; } local $/ = \4; # set record size print "\n$path$id\n"; my $epoch = $start_time; my $prev_value = 0; my $moving_average = 0; my $alpha = 2/(5+1); # while (my $data = <$fh>) # # for (my $i = 0; $i < 10; $i++) # { # # my $data = <$fh>; # my ($value) = unpack 'f', $data; my $timestamp = POSIX::strftime('%F %H:%M:%S', localtime $epoch); # if (isnan($value)) # { # # ignore NaN and replace if required # warn "$timestamp\tNaN\n"; # $value = $prev_value if $clean; # } # else { # fudge an initial value for moving average $moving_average = $value if $moving_average == 0; if ($clean) { # look for spikes and replace if required if (abs($value - $moving_average) > 0.3) { my $spike = sprintf '%.1f %.2f', $value, $moving_average; warn "$timestamp\tspike\t$spike\n"; $value = $prev_value; # if $clean; } else { $moving_average = $alpha * ($value - $moving_average) + $moving_average; } } } print $timestamp, "\t"; printf '%f', $value; print "\t", $value - $prev_value; print "\n"; print $bofh pack('f', $value) if $bofh; $epoch += $interval; $prev_value = $value; } close $bofh if $bofh; } =cut 1; # vim:et sts=4 sw=4 tw=0: