File Coverage

blib/lib/Device/Modbus/TCP/Server.pm
Criterion Covered Total %
statement 64 69 92.7
branch 5 8 62.5
condition n/a
subroutine 18 19 94.7
pod 4 7 57.1
total 91 103 88.3


line stmt bran cond sub pod time code
1             package Device::Modbus::TCP::Server;
2              
3 17     17   20380 use Device::Modbus;
  17         41  
  17         443  
4 17     17   82 use Device::Modbus::TCP::ADU;
  17         34  
  17         307  
5 17     17   75 use Device::Modbus::Exception;
  17         62  
  17         313  
6 17     17   9342 use Data::Dumper;
  17         96415  
  17         958  
7 17     17   102 use Try::Tiny;
  17         44  
  17         706  
8 17     17   85 use Role::Tiny::With;
  17         34  
  17         541  
9 17     17   78 use Carp;
  17         41  
  17         644  
10 17     17   85 use strict;
  17         27  
  17         286  
11 17     17   61 use warnings;
  17         34  
  17         467  
12              
13 17     17   75 use parent qw(Device::Modbus::Server Net::Server::MultiType);
  17         34  
  17         112  
14             with 'Device::Modbus::TCP';
15              
16             sub new {
17 14     14 1 20792 my ($class, %args) = @_;
18 14         178 return bless { server => \%args, %{ $class->proto() }}, $class;
  14         880  
19             }
20              
21             sub default_values {
22             return {
23 56     56 1 182464 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 2976106 my $self = shift;
34 3         59 $self->{socket} = $self->{server}->{client};
35             }
36              
37             sub socket {
38 27492     27492 0 59120 my $self = shift;
39 27492 50       85407 croak "Connection is unavailable" unless defined $self->{socket};
40 27492         96874 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 202 my $self = shift;
55              
56 3         51 while ($self->socket->connected) {
57 5         71 my $req_adu;
58             try {
59 5     5   563 $req_adu = $self->receive_request;
60             }
61             catch {
62 2 50   2   252 if (/Timed? out|Disconnect/i) {
63 2         17 $self->log(4, "Client timed out or disconnected: $_");
64 2         101 $self->log(2, "Error while waiting for request: $_");
65 2         64 $self->socket->close;
66             }
67 5         625 };
68 4 100       172 next unless $req_adu;
69            
70              
71 2         21 $self->log(4, 'Received message from ' . $self->socket->peerhost);
72 2         255 $self->log(4, 'Request: ' . Dumper $req_adu);
73            
74             # If it is an exception object, we're done
75 2 50       565 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         88 my $resp = $self->modbus_server($req_adu);
83 2         999 my $resp_adu = $self->new_adu;
84 2         14 $resp_adu->message($resp);
85 2         30 $resp_adu->id($req_adu->id);
86 2         7 $resp_adu->unit($req_adu->unit);
87            
88             # And send the response!
89 2         35 $self->write_port($resp_adu);
90 2         12 $self->log(4, "Response: " . Dumper $resp_adu);
91 2         306 $self->log(4, "Binary response: " . join '-', unpack 'C*', $resp_adu->binary_message);
92             }
93 2         22 $self->log(3, 'Client disconnected');
94             }
95              
96             sub start {
97 14     14 0 8866 my ($self, %args) = @_;
98 14         442 $self->log(2, 'Starting server');
99 14         1856 $self->run(%args);
100             }
101            
102             1;
103              
104             __END__