File Coverage

blib/lib/Device/Modbus/RTU/ADU.pm
Criterion Covered Total %
statement 39 39 100.0
branch 8 8 100.0
condition n/a
subroutine 9 9 100.0
pod 0 5 0.0
total 56 61 91.8


line stmt bran cond sub pod time code
1             package Device::Modbus::RTU::ADU;
2              
3 4     4   13295 use parent 'Device::Modbus::ADU';
  4         217  
  4         20  
4 4     4   3355 use Carp;
  4         7  
  4         202  
5 4     4   19 use strict;
  4         12  
  4         59  
6 4     4   13 use warnings;
  4         4  
  4         1072  
7              
8             sub crc {
9 6     6 0 1459 my ($self, $crc) = @_;
10 6 100       17 if (defined $crc) {
11 3         5 $self->{crc} = $crc;
12             }
13             croak "CRC has not been declared"
14 6 100       91 unless exists $self->{crc};
15 5         12 return $self->{crc};
16             }
17              
18             sub binary_message {
19 5     5 0 472 my $self = shift;
20             croak "Please include a unit number in the ADU."
21 5 100       158 unless $self->{unit};
22 4         8 my $header = $self->build_header;
23 4         15 my $pdu = $self->message->pdu();
24 4         65 my $footer = $self->build_footer($header, $pdu);
25 4         18 return $header . $pdu . $footer;
26             }
27              
28             sub build_header {
29 5     5 0 9 my $self = shift;
30 5         28 my $header = pack 'C', $self->{unit};
31 5         8 return $header;
32             }
33              
34             sub build_footer {
35 6     6 0 690 my ($self, $header, $pdu) = @_;
36 6         18 return $self->crc_for($header . $pdu);
37             }
38              
39             # Taken from MBClient (and verified against Modbus docs)
40             sub crc_for {
41 7     7 0 293 my ($self, $str) = @_;
42 7         9 my $crc = 0xFFFF;
43 7         5 my ($chr, $lsb);
44 7         27 for my $i (0..length($str)-1) {
45 36         36 $chr = ord(substr($str, $i, 1));
46 36         27 $crc ^= $chr;
47 36         42 for (1..8) {
48 288         208 $lsb = $crc & 1;
49 288         185 $crc >>= 1;
50 288 100       427 $crc ^= 0xA001 if $lsb;
51             }
52             }
53 7         37 return pack 'v', $crc;
54             }
55              
56             1;