File Coverage

blib/lib/BACnet/PDUTypes/ComplexACK.pm
Criterion Covered Total %
statement 54 64 84.3
branch 6 12 50.0
condition n/a
subroutine 12 12 100.0
pod 0 5 0.0
total 72 93 77.4


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             package BACnet::PDUTypes::ComplexACK;
4              
5 27     27   178 use warnings;
  27         54  
  27         1635  
6 27     27   141 use strict;
  27         50  
  27         566  
7              
8 27     27   121 use bytes;
  27         61  
  27         202  
9              
10 27     27   903 use BACnet::APDU;
  27         128  
  27         942  
11 27     27   153 use BACnet::DataTypes::SequenceValue;
  27         62  
  27         884  
12              
13             require BACnet::PDUTypes::Utils;
14              
15 27     27   13334 use BACnet::ServiceRequestSequences::ReadProperty;
  27         93  
  27         1168  
16              
17 27     27   180 use parent 'BACnet::PDUTypes::PDU';
  27         56  
  27         158  
18              
19             our $service_choice_service_request_skeleton =
20             { 12 => $BACnet::ServiceRequestSequences::ReadProperty::positive_response_skeleton, };
21              
22             sub construct {
23 3     3 0 8893 my ( $class, @rest ) = @_;
24              
25 3         13 my %args = (
26             invoke_id => undef,
27             service_choice => undef,
28             service_request => undef,
29             flags => 0x00,
30             @rest,
31             );
32              
33             my $self = {
34             data => '',
35             invoke_id => $args{invoke_id},
36             service_choice => $args{service_choice},
37             service_request => $args{service_request},
38             flags => $args{flags},
39 3         15 };
40              
41             $self->{data} .= pack( 'C',
42 3         18 ( $BACnet::APDU::apdu_types->{'Complex-ACK'} << 4 ) | $self->{flags} );
43              
44 3         6 $self->{data} .= pack( 'C', $args{invoke_id} );
45              
46             $self->{data} .= pack(
47             'C',
48             $BACnet::PDUTypes::Utils::confirmed_service->{
49             $self->{service_choice}
50             }
51 3         10 );
52              
53 3         13 $self->{data} .= $self->{service_request}->data();
54              
55 3         12 return bless $self, $class;
56              
57             #flags are 0000
58              
59             }
60              
61             sub parse {
62              
63 3     3 0 8 my ( $class, $data_in, $skeleton ) = @_;
64              
65 3         6 my $self = bless { data => $data_in, }, $class;
66              
67 3 50       11 if ( length($data_in) < 3 ) {
68 0         0 $self->{error} = "Complex ACK: too short";
69 0         0 return $self;
70             }
71              
72 3         5 my $offset = 0;
73              
74 3         13 $self->{flags} = unpack( 'C', substr( $data_in, $offset, 1 ) ) & 0x0f;
75              
76 3 50       8 if ( ( $self->{flags} & 0x0e ) != 0 ) {
77 0         0 $self->{error} = "Complex ACK: segmented message";
78 0         0 return $self;
79             }
80              
81 3         6 $offset += 1;
82              
83 3         8 $self->{invoke_id} = unpack( 'C', substr( $data_in, $offset, 1 ) );
84 3         3 $offset += 1;
85              
86 3         5 my $raw_service_choice = unpack( 'C', substr( $data_in, $offset, 1 ) );
87              
88             my $service_choice =
89 3         8 $BACnet::PDUTypes::Utils::confirmed_service_rev->{$raw_service_choice};
90              
91 3 50       7 if ( !defined $service_choice ) {
92 0         0 $self->{error} = "Complex ACK: unknown service choice";
93 0         0 return $self;
94             }
95              
96 3         5 $self->{service_choice} = $service_choice;
97 3         3 $offset += 1;
98              
99 3 50       6 if ( !defined $skeleton ) {
100             $skeleton =
101 0         0 $service_choice_service_request_skeleton->{ $raw_service_choice };
102             }
103              
104 3 50       7 if ( !defined $skeleton ) {
105 0         0 $self->{error} = "Complex ACK: unlisted service choice";
106 0         0 return $self;
107             }
108              
109             $self->{service_request} =
110 3         28 BACnet::DataTypes::SequenceValue->parse( substr( $data_in, $offset ),
111             $skeleton );
112              
113 3 50       8 if ( defined $self->{service_request}->{error} ) {
114 0         0 $self->{error} = "Complex ACK request: error in service request";
115             }
116 3         7 return $self;
117             }
118              
119             sub service_choice {
120 6     6 0 4575 my ($self) = @_;
121              
122 6         17 return $self->{service_choice};
123             }
124              
125             sub service_request {
126 6     6 0 9 my ($self) = @_;
127              
128 6         14 return $self->{service_request};
129             }
130              
131             sub invoke_id {
132 6     6 0 9 my ($self) = @_;
133              
134 6         12 return $self->{invoke_id};
135             }
136              
137             1;