#!/usr/bin/perl -w package SCX::Reader; use Time::HiRes qw(gettimeofday tv_interval); use FileHandle; use SCX::CRC; our $PACKET_SIZE = 10; our $LOG_ROTATE = 600; sub new { my ($class, $args) = @_; my $callback = $args->{callback} or die "callback arg not defined"; my $portname = $args->{portname} or die "portname not specified"; system 'stty', '-F', $portname, '115200', 'raw'; if ($?) { die "stty died with code $? (no permissions?)"; } open my $tty, '<:raw', $portname or die "Can't open $portname: $!"; my $logfile = $args->{logfile}; my $log_gen = 0; open my $logfh, '>', "$logfile.$log_gen" or die "Can't open $logfile.$log_gen: $!"; my $now = gettimeofday; my $self = { portname => $portname, fh => $tty, logfile => $logfile, logfh => $logfh, log_gen => $log_gen, log_start => $now, starttime => $now, callback => $callback, bytes => [], }; bless $self, $class; return $self; } sub fh { return shift->{fh}; } sub read { my ($self) = @_; my $data; my $bytes_read = sysread $self->fh, $data, $PACKET_SIZE; die "Read error on $self->{portname}: $!" if !$bytes_read; my $now = gettimeofday; if ($now - $self->{log_start} >= $LOG_ROTATE) { close $self->{logfh}; $self->{log_gen} = $self->{log_gen} ? 0 : 1; open my $fh, '>', $logfile . '.' . $self->{log_gen} or die "Can't open $logfile.$self->{log_gen}: $!"; $self->{logfh} = $fh; $self->{log_start} = $now; } my @bytes = unpack("C*", $data); $self->{logfh}->print(sprintf('% 10.3f', $now - $self->{starttime}), (map { sprintf(" %02x", $_) } @bytes), "\n"); push @{ $self->{bytes} }, @bytes; @bytes = @{ $self->{bytes} }; my @bad_bytes; while (@bytes >= $PACKET_SIZE) { if ($bytes[0] != 0x55 || $bytes[9] != 0x05 || SCX::CRC::digest(@bytes[0..7]) != $bytes[8]) { push @bad_bytes, shift @bytes; next; } if (@bad_bytes) { $self->{logfh}->print("Cannot parse bytes", (map { sprintf(' %02x', $_) } @bad_bytes), "\n"); @bad_bytes = (); } $self->{logfh}->print("Callback\n"); &{ $self->{callback} }(@bytes[1..7]); splice @bytes, 0, 10; } if (@bad_bytes) { $self->{logfh}->print("Cannot parse bytes", (map { sprintf(' %02x', $_) } @bad_bytes), "\n"); @bad_bytes = (); } @{ $self->{bytes} } = @bytes; } 1;