]> www.fi.muni.cz Git - slotcarman.git/blob - SCX/Reader.pm
Proof-of-concept implementation.
[slotcarman.git] / SCX / Reader.pm
1 #!/usr/bin/perl -w
2
3 package SCX::Reader;
4
5 use Time::HiRes qw(gettimeofday tv_interval);
6 use FileHandle;
7 use SCX::CRC;
8
9 our $PACKET_SIZE = 10;
10 our $LOG_ROTATE  = 600;
11
12 sub new {
13         my ($class, $args) = @_;
14
15         my $callback = $args->{callback}
16                 or die "callback arg not defined";
17
18         my $portname = $args->{portname}
19                 or die "portname not specified";
20         
21         system 'stty', '-F', $portname, '115200', 'raw';
22         if ($?) {
23                 die "stty died with code $? (no permissions?)";
24         }
25
26         open my $tty, '<:raw', $portname
27                 or die "Can't open $portname: $!";
28
29         my $logfile = $args->{logfile};
30         my $log_gen = 0;
31
32         open my $logfh, '>', "$logfile.$log_gen"
33         or die "Can't open $logfile.$log_gen: $!";
34
35         my $now = gettimeofday;
36
37         my $self = {
38                 portname  => $portname,
39                 fh        => $tty,
40                 logfile   => $logfile,
41                 logfh     => $logfh,
42                 log_gen   => $log_gen,
43                 log_start => $now,
44                 starttime => $now,
45                 callback  => $callback,
46                 bytes     => [],
47         };
48
49         bless $self, $class;
50
51         return $self;
52 }
53
54 sub fh { return shift->{fh}; }
55
56 sub read {
57         my ($self) = @_;
58
59         my $data;
60         my $bytes_read = sysread $self->fh, $data, $PACKET_SIZE;
61         die "Read error on $self->{portname}: $!"
62                 if !$bytes_read;
63
64         my $now = gettimeofday;
65         if ($now - $self->{log_start} >= $LOG_ROTATE) {
66                 close $self->{logfh};
67                 $self->{log_gen} = $self->{log_gen} ? 0 : 1;
68                 open my $fh, '>', $logfile . '.' . $self->{log_gen}
69                         or die "Can't open $logfile.$self->{log_gen}: $!";
70                 $self->{logfh} = $fh;
71                 $self->{log_start} = $now;
72         }
73
74         my @bytes = unpack("C*", $data);
75
76         $self->{logfh}->print(sprintf('% 10.3f', $now - $self->{starttime}),
77                 (map { sprintf(" %02x", $_) } @bytes),
78                 "\n");
79
80         push @{ $self->{bytes} }, @bytes;
81         @bytes = @{ $self->{bytes} };
82
83         my @bad_bytes;
84
85         while (@bytes >= $PACKET_SIZE) {
86                 if ($bytes[0] != 0x55 || $bytes[9] != 0x05
87                         || SCX::CRC::digest(@bytes[0..7]) != $bytes[8]) {
88                         push @bad_bytes, shift @bytes;
89                         next;
90                 }
91
92                 if (@bad_bytes) {
93                         $self->{logfh}->print("Cannot parse bytes",
94                                 (map { sprintf(' %02x', $_) } @bad_bytes),
95                                 "\n");
96                         @bad_bytes = ();
97                 }
98
99                 $self->{logfh}->print("Callback\n");
100                 &{ $self->{callback} }(@bytes[1..7]);
101                 splice @bytes, 0, 10;
102         }
103         if (@bad_bytes) {
104                 $self->{logfh}->print("Cannot parse bytes",
105                         (map { sprintf(' %02x', $_) } @bad_bytes),
106                         "\n");
107                 @bad_bytes = ();
108         }
109
110         @{ $self->{bytes} } = @bytes;
111 }
112
113 1;
114