1 package net.sf.mbus4j.dataframes;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 import net.sf.json.JSONObject;
31
32 import net.sf.mbus4j.dataframes.datablocks.DataBlock;
33 import net.sf.mbus4j.json.JsonSerializeType;
34
35 import java.util.ArrayList;
36 import java.util.Iterator;
37 import java.util.List;
38 import net.sf.mbus4j.MBusUtils;
39
40
41
42
43
44
45
46 public class SelectionOfSlaves implements LongFrame {
47
48 public enum WildcardNibbles {
49
50 ID_0 {
51 @Override
52 public boolean isFirst() {
53 return true;
54 }
55 },
56 ID_1,
57 ID_2,
58 ID_3,
59 ID_4,
60 ID_5,
61 ID_6,
62 ID_7,
63 MAN_0,
64 MAN_1,
65 MAN_2,
66 MAN_3,
67 MEDIUM_0,
68 MEDIUM_1,
69 VERSION_0,
70 VERSION_1 {
71 @Override
72 public boolean isLast() {
73 return true;
74 }
75 };
76
77 public WildcardNibbles next() {
78 return WildcardNibbles.values()[this.ordinal() + 1];
79 }
80
81 public WildcardNibbles prev() {
82 return WildcardNibbles.values()[this.ordinal() - 1];
83 }
84
85 public boolean isLast() {
86 return false;
87 }
88
89 public boolean isFirst() {
90 return false;
91 }
92
93 }
94
95 private byte address;
96 private int bcdMaskedId;
97 private byte maskedVersion;
98 private short maskedMan;
99 private byte maskedMedium;
100 private final List<DataBlock> datablocks = new ArrayList<>();
101
102 public SelectionOfSlaves(byte address) {
103 this.address = address;
104 }
105
106 public SelectionOfSlaves(SendUserData old) {
107 this.address = old.getAddress();
108 }
109
110 @Override
111 public boolean addDataBlock(DataBlock dataBlock) {
112 return datablocks.add(dataBlock);
113 }
114
115 @Override
116 public byte getAddress() {
117 return address;
118 }
119
120 @Override
121 public ControlCode getControlCode() {
122 return ControlCode.SND_UD;
123 }
124
125 @Override
126 public DataBlock getLastDataBlock() {
127 return datablocks.get(datablocks.size() - 1);
128 }
129
130
131
132
133 public int getBcdMaskedId() {
134 return bcdMaskedId;
135 }
136
137
138
139
140 public short getMaskedMan() {
141 return maskedMan;
142 }
143
144
145
146
147 public int getMaskedMedium() {
148 return maskedMedium;
149 }
150
151
152
153
154 public int getMaskedVersion() {
155 return maskedVersion;
156 }
157
158
159
160
161 public boolean isFcb() {
162 return false;
163 }
164
165 @Override
166 public Iterator<DataBlock> iterator() {
167 return datablocks.iterator();
168 }
169
170 @Override
171 public void replaceDataBlock(DataBlock oldDataBlock, DataBlock newDataBlock) {
172 final int pos = datablocks.indexOf(oldDataBlock);
173 datablocks.remove(pos);
174 datablocks.add(pos, newDataBlock);
175 }
176
177 @Override
178 public void setAddress(byte address) {
179 this.address = address;
180 }
181
182
183
184
185 public void setBcdMaskedId(int bcdMaskedId) {
186 this.bcdMaskedId = bcdMaskedId;
187 }
188
189
190
191
192 public void setMaskedMan(short maskedMan) {
193 this.maskedMan = maskedMan;
194 }
195
196
197
198
199 public void setMaskedMedium(byte maskedMedium) {
200 this.maskedMedium = maskedMedium;
201 }
202
203
204
205
206 public void setMaskedVersion(byte maskedVersion) {
207 this.maskedVersion = maskedVersion;
208 }
209
210 @Override
211 public String toString() {
212 StringBuilder sb = new StringBuilder();
213 sb.append("control code = ").append(getControlCode()).append('\n');
214 sb.append(String.format("address = 0x%02X\n", address));
215 sb.append(String.format("bcdMaskedId = 0x%08X\n", bcdMaskedId));
216 sb.append(String.format("maskedMan = 0x%04X\n", maskedMan));
217 sb.append(String.format("maskedVersion = 0x%02X\n", maskedVersion));
218 sb.append(String.format("maskedMedium = 0x%02X\n", maskedMedium));
219
220 return sb.toString();
221 }
222
223 public boolean matchId(int id) {
224 int hexBcdId = MBusUtils.int2Bcd(id);
225 int hexMask = bcdMaskedId;
226
227 for (int i = 0; i < 8; i++) {
228 if (((hexMask & 0x0F) == 0x0F) || ((hexMask & 0x0F) == (hexBcdId & 0x0F))) {
229 hexMask >>= 4;
230 hexBcdId >>= 4;
231 } else {
232 return false;
233 }
234 }
235
236 return true;
237 }
238
239 public boolean matchAll(int id, String man, MBusMedium medium, int version) {
240 return matchId(id) && matchMan(man) && matchMedium(medium) && matchVersion(version);
241 }
242
243 private boolean matchMan(String man) {
244 int hexMan = MBusUtils.man2Short(man);
245 int hexMask = maskedMan;
246
247 for (int i = 0; i < 8; i++) {
248 if (((hexMask & 0x0F) != 0x0F) && ((hexMask & 0x0F) != (hexMan & 0x0F))) {
249 return false;
250 }
251
252 hexMask >>= 4;
253 hexMan >>= 4;
254 }
255
256 return true;
257 }
258
259 private boolean matchMedium(MBusMedium medium) {
260 int hexMedium = medium.getId();
261 int hexMask = maskedMedium;
262
263 for (int i = 0; i < 8; i++) {
264 if (((hexMask & 0x0F) != 0x0F) && ((hexMask & 0x0F) != (hexMedium & 0x0F))) {
265 return false;
266 }
267
268 hexMask >>= 4;
269 hexMedium >>= 4;
270 }
271
272 return true;
273 }
274
275 private boolean matchVersion(int version) {
276 int hexVersion = version;
277 int hexMask = maskedVersion;
278
279 for (int i = 0; i < 8; i++) {
280 if (((hexMask & 0x0F) != 0x0F) && ((hexMask & 0x0F) != (hexVersion & 0x0F))) {
281 return false;
282 }
283
284 hexMask >>= 4;
285 hexVersion >>= 4;
286 }
287
288 return true;
289 }
290
291 @Override
292 public JSONObject toJSON(JsonSerializeType jsonSerializeType) {
293 throw new UnsupportedOperationException("Not supported yet.");
294 }
295
296 @Override
297 public void fromJSON(JSONObject json) {
298 throw new UnsupportedOperationException("Not supported yet.");
299 }
300
301 public byte getWildcardNibble(WildcardNibbles wildcardNibbles) {
302 switch (wildcardNibbles) {
303 case ID_0:
304 return (byte) (bcdMaskedId & 0x0F);
305 case ID_1:
306 return (byte) ((bcdMaskedId >>> 4) & 0x0F);
307 case ID_2:
308 return (byte) ((bcdMaskedId >>> 8) & 0x0F);
309 case ID_3:
310 return (byte) ((bcdMaskedId >>> 12) & 0x0F);
311 case ID_4:
312 return (byte) ((bcdMaskedId >>> 16) & 0x0F);
313 case ID_5:
314 return (byte) ((bcdMaskedId >>> 20) & 0x0F);
315 case ID_6:
316 return (byte) ((bcdMaskedId >>> 24) & 0x0F);
317 case ID_7:
318 return (byte) ((bcdMaskedId >>> 28) & 0x0F);
319 case MAN_0:
320 return (byte) (maskedMan & 0x0F);
321 case MAN_1:
322 return (byte) ((maskedMan >>> 4) & 0x0F);
323 case MAN_2:
324 return (byte) ((maskedMan >>> 8) & 0x0F);
325 case MAN_3:
326 return (byte) ((maskedMan >>> 12) & 0x0F);
327 case MEDIUM_0:
328 return (byte) (maskedMedium & 0x0F);
329 case MEDIUM_1:
330 return (byte) ((maskedMedium >>> 4) & 0x0F);
331 case VERSION_0:
332 return (byte) (maskedVersion & 0x0F);
333 case VERSION_1:
334 return (byte) ((maskedVersion >>> 4) & 0x0F);
335 default:
336 throw new RuntimeException("Cant handle " + wildcardNibbles);
337 }
338 }
339
340 public void maskWildcardNibble(WildcardNibbles wildcardNibbles) {
341 setWildcardNibble(wildcardNibbles, (byte)0x0F);
342 }
343
344 public void setWildcardNibble(WildcardNibbles wildcardNibbles, byte value) {
345 if ((value & 0xF0) != 0) {
346 throw new RuntimeException("Upper nibble must be 0");
347 }
348 switch (wildcardNibbles) {
349 case ID_0:
350 bcdMaskedId = (bcdMaskedId & 0xFFFFFFF0) | value;
351 break;
352 case ID_1:
353 bcdMaskedId = (bcdMaskedId & 0xFFFFFF0F) | value << 4;
354 break;
355 case ID_2:
356 bcdMaskedId = (bcdMaskedId & 0xFFFFF0FF) | value << 8;
357 break;
358 case ID_3:
359 bcdMaskedId = (bcdMaskedId & 0xFFFF0FFF) | value << 12;
360 break;
361 case ID_4:
362 bcdMaskedId = (bcdMaskedId & 0xFFF0FFFF) | value << 16;
363 break;
364 case ID_5:
365 bcdMaskedId = (bcdMaskedId & 0xFF0FFFFF) | value << 20;
366 break;
367 case ID_6:
368 bcdMaskedId = (bcdMaskedId & 0xF0FFFFFF) | value << 24;
369 break;
370 case ID_7:
371 bcdMaskedId = (bcdMaskedId & 0x0FFFFFFF) | value << 28;
372 break;
373 case MAN_0:
374 maskedMan = (short) ((maskedMan & 0xFFF0) | value);
375 break;
376 case MAN_1:
377 maskedMan = (short) ((maskedMan & 0xFF0F) | value << 4);
378 break;
379 case MAN_2:
380 maskedMan = (short) ((maskedMan & 0xF0FF) | value << 8);
381 break;
382 case MAN_3:
383 maskedMan = (short) ((maskedMan & 0x0FFF) | value << 12);
384 break;
385 case MEDIUM_0:
386 maskedMedium = (byte) ((maskedMedium & 0xF0) | value);
387 break;
388 case MEDIUM_1:
389 maskedMedium = (byte) ((maskedMedium & 0xF0) | value << 4);
390 break;
391 case VERSION_0:
392 maskedVersion = (byte) ((maskedVersion & 0xF0) | value);
393 break;
394 case VERSION_1:
395 maskedVersion = (byte) ((maskedVersion & 0xF0) | value << 4);
396 break;
397 default:
398 throw new RuntimeException("Cant handle " + wildcardNibbles);
399 }
400 }
401
402 public boolean isWildcardNibble(WildcardNibbles wildcardNibbles) {
403 switch (wildcardNibbles) {
404 case ID_0:
405 return (bcdMaskedId & 0x0000000F) == 0x0000000F;
406 case ID_1:
407 return (bcdMaskedId & 0x000000F0) == 0x000000F0;
408 case ID_2:
409 return (bcdMaskedId & 0x00000F00) == 0x00000F00;
410 case ID_3:
411 return (bcdMaskedId & 0x0000F000) == 0x0000F000;
412 case ID_4:
413 return (bcdMaskedId & 0x000F0000) == 0x000F0000;
414 case ID_5:
415 return (bcdMaskedId & 0x00F00000) == 0x00F00000;
416 case ID_6:
417 return (bcdMaskedId & 0x0F000000) == 0x0F000000;
418 case ID_7:
419 return (bcdMaskedId & 0xF0000000) == 0xF0000000;
420 case MAN_0:
421 return (maskedMan & 0x000F) == 0x000F;
422 case MAN_1:
423 return (maskedMan & 0x00F0) == 0x00F0;
424 case MAN_2:
425 return (maskedMan & 0x0F00) == 0x0F00;
426 case MAN_3:
427 return (maskedMan & 0xF000) == 0xF000;
428 case MEDIUM_0:
429 return (maskedMedium & 0x0F) == 0x0F;
430 case MEDIUM_1:
431 return (maskedMedium & 0xF0) == 0xF0;
432 case VERSION_0:
433 return (maskedVersion & 0x0F) == 0x0F;
434 case VERSION_1:
435 return (maskedVersion & 0xF0) == 0xF0;
436 default:
437 throw new RuntimeException("Cant handle " + wildcardNibbles);
438 }
439 }
440 }