File Coverage

blib/lib/Device/Modbus/TCP/Server.pm
Criterion Covered Total %
statement 60 69 86.9
branch 3 8 37.5
condition n/a
subroutine 17 19 89.4
pod 4 7 57.1
total 84 103 81.5


line stmt bran cond sub pod time code
1             package Device::Modbus::TCP::Server;
2              
3 17     17   26305 use Device::Modbus;
  17         65  
  17         565  
4 17     17   113 use Device::Modbus::TCP::ADU;
  17         41  
  17         394  
5 17     17   96 use Device::Modbus::Exception;
  17         41  
  17         382  
6 17     17   10650 use Data::Dumper;
  17         107134  
  17         1451  
7 17     17   143 use Try::Tiny;
  17         41  
  17         804  
8 17     17   120 use Role::Tiny::With;
  17         41  
  17         757  
9 17     17   134 use Carp;
  17         51  
  17         947  
10 17     17   106 use strict;
  17         34  
  17         460  
11 17     17   124 use warnings;
  17         55  
  17         745  
12              
13 17     17   103 use parent qw(Device::Modbus::Server Net::Server::MultiType);
  17         34  
  17         126  
14             with 'Device::Modbus::TCP';
15              
16             sub new {
17 14     14 1 24040 my ($class, %args) = @_;
18 14         158 return bless { server => \%args, %{ $class->proto() }}, $class;
  14         970  
19             }
20              
21             sub default_values {
22             return {
23 56     56 1 171188 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 3     3 1 2975894 my $self = shift;
34 3         81 $self->{socket} = $self->{server}->{client};
35             }
36              
37             sub socket {
38 25997     25997 0 41596 my $self = shift;
39 25997 50       60547 croak "Connection is unavailable" unless defined $self->{socket};
40 25996         68844 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 3     3 1 256 my $self = shift;
55              
56 3         64 while ($self->socket->connected) {
57 5         96 my $req_adu;
58             try {
59 5     5   721 $req_adu = $self->receive_request;
60             }
61             catch {
62 0 0   0   0 if (/Timed? out|Disconnect/i) {
63 0         0 $self->log(4, "Client timed out or disconnected: $_");
64 0         0 $self->log(2, "Error while waiting for request: $_");
65 0         0 $self->socket->close;
66             }
67 5         181 };
68 2 50       83 next unless $req_adu;
69            
70              
71 2         13 $self->log(4, 'Received message from ' . $self->socket->peerhost);
72 2         291 $self->log(4, 'Request: ' . Dumper $req_adu);
73            
74             # If it is an exception object, we're done
75 2 50       707 if ($req_adu->message->isa('Device::Modbus::Exception')) {
76 0         0 $self->log(3, "Exception while waiting for requests: $_");
77 0         0 $self->write_port($req_adu);
78 0         0 next;
79             }
80              
81             # Process request
82 2         104 my $resp = $self->modbus_server($req_adu);
83 2         1435 my $resp_adu = $self->new_adu;
84 2         15 $resp_adu->message($resp);
85 2         33 $resp_adu->id($req_adu->id);
86 2         7 $resp_adu->unit($req_adu->unit);
87            
88             # And send the response!
89 2         33 $self->write_port($resp_adu);
90 2         11 $self->log(4, "Response: " . Dumper $resp_adu);
91 2         480 $self->log(4, "Binary response: " . join '-', unpack 'C*', $resp_adu->binary_message);
92             }
93 2         44 $self->log(3, 'Client disconnected');
94             }
95              
96             sub start {
97 14     14 0 6868 my ($self, %args) = @_;
98 14         600 $self->log(2, 'Starting server');
99 14         1760 $self->run(%args);
100             }
101            
102             1;
103              
104             __END__