13
13
package org .openhab .binding .digiplex .internal .communication ;
14
14
15
15
import org .eclipse .jdt .annotation .NonNullByDefault ;
16
+ import org .eclipse .jdt .annotation .Nullable ;
16
17
import org .openhab .binding .digiplex .internal .communication .events .AreaEvent ;
17
18
import org .openhab .binding .digiplex .internal .communication .events .AreaEventType ;
18
19
import org .openhab .binding .digiplex .internal .communication .events .GenericEvent ;
29
30
* Resolves serial messages to appropriate classes
30
31
*
31
32
* @author Robert Michalak - Initial contribution
32
- *
33
33
*/
34
34
@ NonNullByDefault
35
35
public class DigiplexResponseResolver {
36
36
37
37
private static final String OK = "&ok" ;
38
- // TODO: handle failures
39
38
private static final String FAIL = "&fail" ;
40
39
41
40
public static DigiplexResponse resolveResponse (String message ) {
42
41
if (message .length () < 4 ) { // sanity check: try to filter out malformed responses
43
- return new UnknownResponse (message );
42
+ return new ErroneousResponse (message );
44
43
}
45
44
46
- int zoneNo , areaNo ;
45
+ Integer zoneNo , areaNo ;
47
46
String commandType = message .substring (0 , 2 );
48
47
switch (commandType ) {
49
48
case "CO" : // communication status
@@ -53,24 +52,36 @@ public static DigiplexResponse resolveResponse(String message) {
53
52
return CommunicationStatus .OK ;
54
53
}
55
54
case "ZL" : // zone label
56
- zoneNo = Integer .valueOf (message .substring (2 , 5 ));
55
+ zoneNo = getZoneOrArea (message );
56
+ if (zoneNo == null ) {
57
+ return new ErroneousResponse (message );
58
+ }
57
59
if (message .contains (FAIL )) {
58
60
return ZoneLabelResponse .failure (zoneNo );
59
61
} else {
60
62
return ZoneLabelResponse .success (zoneNo , message .substring (5 ).trim ());
61
63
}
62
64
case "AL" : // area label
63
- areaNo = Integer .valueOf (message .substring (2 , 5 ));
65
+ areaNo = getZoneOrArea (message );
66
+ if (areaNo == null ) {
67
+ return new ErroneousResponse (message );
68
+ }
64
69
if (message .contains (FAIL )) {
65
70
return AreaLabelResponse .failure (areaNo );
66
71
} else {
67
72
return AreaLabelResponse .success (areaNo , message .substring (5 ).trim ());
68
73
}
69
74
case "RZ" : // zone status
70
- zoneNo = Integer .valueOf (message .substring (2 , 5 ));
75
+ zoneNo = getZoneOrArea (message );
76
+ if (zoneNo == null ) {
77
+ return new ErroneousResponse (message );
78
+ }
71
79
if (message .contains (FAIL )) {
72
80
return ZoneStatusResponse .failure (zoneNo );
73
81
} else {
82
+ if (message .length () < 10 ) {
83
+ return new ErroneousResponse (message );
84
+ }
74
85
return ZoneStatusResponse .success (zoneNo , // zone number
75
86
ZoneStatus .fromMessage (message .charAt (5 )), // status
76
87
toBoolean (message .charAt (6 )), // alarm
@@ -79,10 +90,16 @@ public static DigiplexResponse resolveResponse(String message) {
79
90
toBoolean (message .charAt (9 ))); // battery low
80
91
}
81
92
case "RA" : // area status
82
- areaNo = Integer .valueOf (message .substring (2 , 5 ));
93
+ areaNo = getZoneOrArea (message );
94
+ if (areaNo == null ) {
95
+ return new ErroneousResponse (message );
96
+ }
83
97
if (message .contains (FAIL )) {
84
98
return AreaStatusResponse .failure (areaNo );
85
99
} else {
100
+ if (message .length () < 12 ) {
101
+ return new ErroneousResponse (message );
102
+ }
86
103
return AreaStatusResponse .success (areaNo , // zone number
87
104
AreaStatus .fromMessage (message .charAt (5 )), // status
88
105
toBoolean (message .charAt (6 )), // zone in memory
@@ -95,7 +112,10 @@ public static DigiplexResponse resolveResponse(String message) {
95
112
case "AA" : // area arm
96
113
case "AQ" : // area quick arm
97
114
case "AD" : // area disarm
98
- areaNo = Integer .valueOf (message .substring (2 , 5 ));
115
+ areaNo = getZoneOrArea (message );
116
+ if (areaNo == null ) {
117
+ return new ErroneousResponse (message );
118
+ }
99
119
if (message .contains (FAIL )) {
100
120
return AreaArmDisarmResponse .failure (areaNo , ArmDisarmType .fromMessage (commandType ));
101
121
} else {
@@ -105,21 +125,41 @@ public static DigiplexResponse resolveResponse(String message) {
105
125
case "PG" : // PGM events
106
126
default :
107
127
if (message .startsWith ("G" )) {
108
- return resolveSystemEvent (message );
128
+ if (message .length () >= 12 ) {
129
+ return resolveSystemEvent (message );
130
+ } else {
131
+ return new ErroneousResponse (message );
132
+ }
109
133
} else {
110
134
return new UnknownResponse (message );
111
135
}
112
136
}
113
137
}
114
138
139
+ private static @ Nullable Integer getZoneOrArea (String message ) {
140
+ if (message .length () < 5 ) {
141
+ return null ;
142
+ }
143
+ try {
144
+ return Integer .valueOf (message .substring (2 , 5 ));
145
+ } catch (NumberFormatException e ) {
146
+ return null ;
147
+ }
148
+ }
149
+
115
150
private static boolean toBoolean (char value ) {
116
151
return value != 'O' ;
117
152
}
118
153
119
154
private static DigiplexResponse resolveSystemEvent (String message ) {
120
- int eventGroup = Integer .parseInt (message .substring (1 , 4 ));
121
- int eventNumber = Integer .parseInt (message .substring (5 , 8 ));
122
- int areaNumber = Integer .parseInt (message .substring (9 , 12 ));
155
+ int eventGroup , eventNumber , areaNumber ;
156
+ try {
157
+ eventGroup = Integer .parseInt (message .substring (1 , 4 ));
158
+ eventNumber = Integer .parseInt (message .substring (5 , 8 ));
159
+ areaNumber = Integer .parseInt (message .substring (9 , 12 ));
160
+ } catch (NumberFormatException e ) {
161
+ return new ErroneousResponse (message );
162
+ }
123
163
switch (eventGroup ) {
124
164
case 0 :
125
165
return new ZoneStatusEvent (eventNumber , ZoneStatus .CLOSED , areaNumber );
0 commit comments