File Coverage

blib/lib/Device/Modbus/Unit.pm
Criterion Covered Total %
statement 46 46 100.0
branch 16 16 100.0
condition 6 6 100.0
subroutine 12 12 100.0
pod 0 7 0.0
total 80 87 91.9


line stmt bran cond sub pod time code
1             package Device::Modbus::Unit;
2              
3 5     5   38350 use Device::Modbus::Unit::Route;
  5         13  
  5         141  
4 5     5   25 use Carp;
  5         7  
  5         256  
5 5     5   24 use strict;
  5         9  
  5         92  
6 5     5   21 use warnings;
  5         8  
  5         103  
7 5     5   44 use v5.10;
  5         15  
8              
9              
10             sub new {
11 5     5 0 2769 my ($class, %args) = @_;
12             croak "Missing required parameter: id"
13 5 100       319 unless defined $args{id};
14 4         62 my %routes = (
15             'discrete_coils:read' => [],
16             'discrete_coils:write' => [],
17             'discrete_inputs:read' => [],
18             'input_registers:read' => [],
19             'holding_registers:read' => [],
20             'holding_registers:write' => [],
21             );
22 4         26 return bless { %args, routes => \%routes }, $class;
23             }
24              
25             sub id {
26 3     3 0 718 my $self = shift;
27 3         16 return $self->{id};
28             }
29              
30             sub routes {
31 4     4 0 9 my $self = shift;
32 4         19 return $self->{routes};
33             }
34              
35             sub init_unit {
36 1     1 0 88 croak "Device::Modbus::Unit subclasses must implement init_unit";
37             }
38              
39             sub put {
40 9     9 0 2567 my ($self, $zone, $address, $qty, $method) = @_;
41 9 100       39 if (!ref $method) {
42 7         47 $method = $self->can($method); # returns a ref to method
43             }
44 9 100 100     455 croak "'put' could not resolve a code reference for address $address in zone $zone"
45             unless ref $method && ref $method eq 'CODE';
46              
47 7         34 my $addr = Device::Modbus::Unit::Route->new(
48             address => $address,
49             zone => $zone,
50             quantity => $qty,
51             read_write => 'write',
52             routine => $method
53             );
54            
55 7         11 push @{$self->{routes}->{"$zone:write"}}, $addr;
  7         39  
56             }
57              
58             sub get {
59 11     11 0 1975 my ($self, $zone, $address, $qty, $method) = @_;
60 11 100       40 if (!ref $method) {
61 9         38 $method = $self->can($method); # returns a ref to method
62             }
63 11 100 100     360 croak "'get' could not resolve a code reference for address $address in zone $zone"
64             unless ref $method && ref $method eq 'CODE';
65              
66 9         43 my $route = Device::Modbus::Unit::Route->new(
67             address => $address,
68             zone => $zone,
69             quantity => $qty,
70             read_write => 'read',
71             routine => $method
72             );
73            
74 9         52 push @{$self->{routes}->{"$zone:read"}}, $route;
  9         42  
75             }
76              
77             # Tests a requested zone, address, qty against existing addresses.
78             # Returns the first successful match. Returns the Modbus error number
79             # otherwise (3 for invalid qty and 2 for invalid address)
80             sub route {
81 22     22 0 2010 my ($self, $zone, $mode, $addr, $qty) = @_;
82 22         68 my $addresses = $self->{routes}->{"$zone:$mode"};
83 22 100       61 return 1 unless @$addresses;
84              
85 20         31 my $match;
86 20         47 foreach my $address (@$addresses) {
87 26 100       87 next unless $address->test_route($addr);
88 13         26 $match = $address;
89 13 100       38 return $match if $match->test_quantity($qty);
90             }
91              
92             # return 3 if defined $match; # Address matched, not quantity # INCORRECT
93 8         22 return 2; # Did not match
94             }
95              
96             1;