File Coverage

blib/lib/Device/Modbus/TCP/Server.pm
Criterion Covered Total %
statement 59 67 88.0
branch 3 8 37.5
condition n/a
subroutine 17 19 89.4
pod 4 7 57.1
total 83 101 82.1


line stmt bran cond sub pod time code
1             package Device::Modbus::TCP::Server;
2              
3 7     7   4991 use Device::Modbus;
  7         14  
  7         147  
4 7     7   21 use Device::Modbus::TCP::ADU;
  7         7  
  7         91  
5 7     7   21 use Device::Modbus::Exception;
  7         7  
  7         112  
6 7     7   3381 use Data::Dumper;
  7         33467  
  7         329  
7 7     7   35 use Try::Tiny;
  7         0  
  7         273  
8 7     7   28 use Role::Tiny::With;
  7         7  
  7         203  
9 7     7   28 use Carp;
  7         7  
  7         238  
10 7     7   21 use strict;
  7         7  
  7         98  
11 7     7   21 use warnings;
  7         7  
  7         147  
12              
13 7     7   21 use parent qw(Device::Modbus::Server Net::Server::MultiType);
  7         7  
  7         28  
14             with 'Device::Modbus::TCP';
15              
16             sub new {
17 6     6 1 7062 my ($class, %args) = @_;
18 6         60 return bless { server => \%args, %{ $class->proto() }}, $class;
  6         234  
19             }
20              
21             sub default_values {
22             return {
23 24     24 1 50112 log_level => 2,
24             log_file => undef,
25             port => 502,
26             host => '*',
27             ipv => 4,
28             proto => 'tcp',
29             };
30             }
31              
32             sub post_accept_hook {
33 1     1 1 993636 my $self = shift;
34 1         15 $self->{socket} = $self->{server}->{client};
35             }
36              
37             sub socket {
38 42574     42574 0 28065 my $self = shift;
39 42574 50       51511 croak "Connection is unavailable" unless defined $self->{socket};
40 42574         63975 return $self->{socket};
41             }
42              
43             # Return exception if unit is not supported by server
44             sub request_for_others {
45 0     0 0 0 my ($self, $adu) = @_;
46             return Device::Modbus::Exception->new(
47 0         0 function => $Device::Modbus::function_for{$adu->code},
48             exception_code => 2,
49             unit => $adu->unit
50             );
51             }
52              
53             sub process_request {
54 1     1 1 39 my $self = shift;
55              
56 1         15 while ($self->socket->connected) {
57 2         18 my $req_adu;
58             try {
59 2     2   116 $req_adu = $self->receive_request;
60             }
61             catch {
62 0 0   0   0 unless (/Time out/) {
63 0         0 $self->log(2, "Error while waiting for request: $_");
64             }
65 2         38 };
66 1 50       47 next unless $req_adu;
67            
68              
69 1         5 $self->log(4, 'Received message from ' . $self->socket->peerhost);
70 1         91 $self->log(4, 'Request: ' . Dumper $req_adu);
71            
72             # If it is an exception object, we're done
73 1 50       281 if ($req_adu->message->isa('Device::Modbus::Exception')) {
74 0         0 $self->log(3, "Exception while waiting for requests: $_");
75 0         0 $self->write_port($req_adu);
76 0         0 next;
77             }
78              
79             # Process request
80 1         47 my $resp = $self->modbus_server($req_adu);
81 1         371 my $resp_adu = $self->new_adu;
82 1         2 $resp_adu->message($resp);
83 1         11 $resp_adu->id($req_adu->id);
84 1         4 $resp_adu->unit($req_adu->unit);
85            
86             # And send the response!
87 1         14 $self->write_port($resp_adu);
88 1         5 $self->log(4, "Response: " . Dumper $resp_adu);
89 1         117 $self->log(4, "Binary response: " . join '-', unpack 'C*', $resp_adu->binary_message);
90             }
91 0         0 $self->log(3, 'Client disconnected');
92             }
93              
94             sub start {
95 6     6 0 2358 my ($self, %args) = @_;
96 6         144 $self->log(2, 'Starting server');
97 6         414 $self->run(%args);
98             }
99            
100             1;
101              
102             __END__