1 package net.sf.mbus4j.dataframes.datablocks;
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 java.io.Serializable;
31 import java.util.Arrays;
32 import net.sf.json.JSONArray;
33 import net.sf.json.JSONObject;
34
35 import net.sf.mbus4j.dataframes.datablocks.dif.DataFieldCode;
36 import net.sf.mbus4j.dataframes.datablocks.dif.FunctionField;
37 import net.sf.mbus4j.dataframes.datablocks.dif.VariableLengthType;
38 import net.sf.mbus4j.dataframes.datablocks.vif.ObjectAction;
39 import net.sf.mbus4j.dataframes.datablocks.vif.SiPrefix;
40 import net.sf.mbus4j.dataframes.datablocks.vif.UnitOfMeasurement;
41 import net.sf.mbus4j.dataframes.datablocks.vif.Vif;
42 import net.sf.mbus4j.dataframes.datablocks.vif.VifAscii;
43 import net.sf.mbus4j.dataframes.datablocks.vif.VifFB;
44 import net.sf.mbus4j.dataframes.datablocks.vif.VifFD;
45 import net.sf.mbus4j.dataframes.datablocks.vif.VifManufacturerSpecific;
46 import net.sf.mbus4j.dataframes.datablocks.vif.VifPrimary;
47 import net.sf.mbus4j.dataframes.datablocks.vif.VifTypes;
48 import net.sf.mbus4j.dataframes.datablocks.vif.Vife;
49 import net.sf.mbus4j.dataframes.datablocks.vif.VifeError;
50 import net.sf.mbus4j.dataframes.datablocks.vif.VifeFC;
51 import net.sf.mbus4j.dataframes.datablocks.vif.VifeManufacturerSpecific;
52 import net.sf.mbus4j.dataframes.datablocks.vif.VifeObjectAction;
53 import net.sf.mbus4j.dataframes.datablocks.vif.VifePrimary;
54 import net.sf.mbus4j.dataframes.datablocks.vif.VifeTypes;
55 import net.sf.mbus4j.json.JSONSerializable;
56 import net.sf.mbus4j.json.JsonSerializeType;
57
58
59
60
61
62
63 public abstract class DataBlock implements Serializable, JSONSerializable, Cloneable {
64
65 public final static Vife[] EMPTY_VIFE = new Vife[0];
66
67 public static Class<? extends DataBlock> getDataBlockClass(Vif vif, Vife[] vifes, DataFieldCode dfc, VariableLengthType variableLengthType) {
68 if (vifes != null) {
69 for (Vife vife : vifes) {
70 if (vife instanceof VifePrimary) {
71 switch ((VifePrimary) vife) {
72 case START_DATE_TIME_OF:
73 case TIMESTAMP_OF_BEGIN_FIRST_LOWER:
74 case TIMESTAMP_OF_END_FIRST_LOWER:
75 case TIMESTAMP_BEGIN_LAST_LOWER:
76 case TIMESTAMP_END_LAST_LOWER:
77 case TIMESTAMP_BEGIN_FIRST_UPPER:
78 case TIMESTAMP_END_FIRST_UPPER:
79 case TIMESTAMP_BEGIN_LAST_UPPER:
80 case TIMESTAMP_END_LAST_UPPER:
81 return DateAndTimeDataBlock.class;
82 case DURATION_OF_LIMIT_EXCEED_FIRST_LOWER_S:
83 break;
84 case DURATION_OF_LIMIT_EXCEED_FIRST_LOWER_MIN:
85 break;
86 case DURATION_OF_LIMIT_EXCEED_FIRST_LOWER_H:
87 break;
88 case DURATION_OF_LIMIT_EXCEED_FIRST_LOWER_D:
89 break;
90 case DURATION_OF_LIMIT_EXCEED_LAST_LOWER_S:
91 break;
92 case DURATION_OF_LIMIT_EXCEED_LAST_LOWER_MIN:
93 break;
94 case DURATION_OF_LIMIT_EXCEED_LAST_LOWER_H:
95 break;
96 case DURATION_OF_LIMIT_EXCEED_LAST_LOWER_D:
97 break;
98 case DURATION_OF_LIMIT_EXCEED_FIRST_UPPER_S:
99 break;
100 case DURATION_OF_LIMIT_EXCEED_FIRST_UPPER_MIN:
101 break;
102 case DURATION_OF_LIMIT_EXCEED_FIRST_UPPER_H:
103 break;
104 case DURATION_OF_LIMIT_EXCEED_FIRST_UPPER_D:
105 break;
106 case DURATION_OF_LIMIT_EXCEED_LAST_UPPER_S:
107 break;
108 case DURATION_OF_LIMIT_EXCEED_LAST_UPPER_MIN:
109 break;
110 case DURATION_OF_LIMIT_EXCEED_LAST_UPPER_H:
111 break;
112 case DURATION_OF_LIMIT_EXCEED_LAST_UPPER_D:
113 break;
114 case DURATION_OF_FIRST_S:
115 break;
116 case DURATION_OF_FIRST_MIN:
117 break;
118 case DURATION_OF_FIRST_H:
119 break;
120 case DURATION_OF_FIRST_D:
121 break;
122 case DURATION_OF_LAST_S:
123 break;
124 case DURATION_OF_LAST_MIN:
125 break;
126 case DURATION_OF_LAST_H:
127 break;
128 case DURATION_OF_LAST_D:
129 break;
130 case TIMESTAMP_BEGIN_OF_FIRST:
131 case TIMESTAMP_END_OF_FIRST:
132 case TIMESTAMP_BEGIN_OF_LAST:
133 case TIMESTAMP_END_OF_LAST:
134 return DateAndTimeDataBlock.class;
135
136 default:
137 }
138 } else {
139 vifes = null;
140 }
141 }
142 }
143
144 switch (dfc) {
145 case NO_DATA:
146 return EmptyDataBlock.class;
147 case SELECTION_FOR_READOUT:
148 return ReadOutDataBlock.class;
149 case SPECIAL_FUNCTION_GLOBAL_READOUT_REQUEST:
150 return ReadOutDataBlock.class;
151 case SPECIAL_FUNCTION_IDLE_FILLER:
152 return EmptyDataBlock.class;
153 case SPECIAL_FUNCTION_MAN_SPEC_DATA_LAST_PACKET:
154 return RawDataBlock.class;
155 case SPECIAL_FUNCTION_MAN_SPEC_DATA_PACKETS_FOLLOWS:
156 return RawDataBlock.class;
157 case VARIABLE_LENGTH:
158 switch (variableLengthType) {
159 case STRING:
160 return StringDataBlock.class;
161 case BIG_DECIMAL:
162 return BigDecimalDataBlock.class;
163 default:
164 return VariableLengthDataBlock.class;
165 }
166 case _12_DIGIT_BCD:
167 return LongDataBlock.class;
168 case _16_BIT_INTEGER:
169 if (VifPrimary.TIMEPOINT_DATE.equals(vif)) {
170 return DateDataBlock.class;
171 } else {
172 return ShortDataBlock.class;
173 }
174 case _24_BIT_INTEGER:
175 return IntegerDataBlock.class;
176 case _2_DIGIT_BCD:
177 return ByteDataBlock.class;
178 case _32_BIT_INTEGER:
179 if (VifPrimary.TIMEPOINT_TIME_AND_DATE.equals(vif)) {
180 return DateAndTimeDataBlock.class;
181 } else {
182 return IntegerDataBlock.class;
183 }
184 case _32_BIT_REAL:
185 return RealDataBlock.class;
186 case _48_BIT_INTEGER:
187 return LongDataBlock.class;
188 case _4_DIGIT_BCD:
189 return ShortDataBlock.class;
190 case _64_BIT_INTEGER:
191 if (VifPrimary.ENHANCED_IDENTIFICATION_RECORD.equals(vif)) {
192 return EnhancedIdentificationDataBlock.class;
193 } else {
194 return LongDataBlock.class;
195 }
196 case _6_DIGIT_BCD:
197 return IntegerDataBlock.class;
198 case _8_BIT_INTEGER:
199 return ByteDataBlock.class;
200 case _8_DIGIT_BCD:
201 if (VifPrimary.ENHANCED_IDENTIFICATION_RECORD.equals(vif)) {
202 return EnhancedIdentificationDataBlock.class;
203 } else {
204 return IntegerDataBlock.class;
205 }
206 default:
207 throw new UnsupportedOperationException("Unknown ControlCode");
208 }
209
210 }
211
212 public static Vif getVif(String vifTypeLabel, String vifLabel, UnitOfMeasurement unitOfMeasurement, SiPrefix siPrefix, Integer exponent) {
213 VifTypes vifType = VifTypes.fromLabel(vifTypeLabel);
214 switch (vifType) {
215 case PRIMARY:
216 return VifPrimary.assemble(vifLabel, unitOfMeasurement, siPrefix, exponent);
217 case FB_EXTENTION:
218 return VifFB.assemble(vifLabel, unitOfMeasurement, siPrefix, exponent);
219 case FD_EXTENTION:
220 return VifFD.assemble(vifLabel, unitOfMeasurement, siPrefix, exponent);
221 case ASCII:
222 return new VifAscii(vifLabel);
223 case MANUFACTURER_SPECIFIC:
224 return new VifManufacturerSpecific();
225 default: {
226 throw new IllegalArgumentException("Unknown vifType: " + vifTypeLabel);
227 }
228 }
229 }
230
231 public static Vif vifFromJSON(JSONObject jsonVif) {
232 return getVif(jsonVif.getString("vifType"),
233 jsonVif.containsKey("description") ? jsonVif.getString("description") : null,
234 jsonVif.containsKey("unitOfMeasurement") ? UnitOfMeasurement.fromLabel(jsonVif.getString("unitOfMeasurement")) : null,
235 jsonVif.containsKey("siPrefix") ? SiPrefix.fromLabel(jsonVif.getString("siPrefix")) : null,
236 jsonVif.containsKey("exponent") ? jsonVif.getInt("exponent") : null);
237 }
238
239 public static Vife getVife(String vifeTypeLabel, String vifeLabel) {
240 VifeTypes vifeType = VifeTypes.fromLabel(vifeTypeLabel);
241 switch (vifeType) {
242 case PRIMARY:
243 return VifePrimary.fromLabel(vifeLabel);
244 case FC_EXTENSION:
245 return VifeFC.fromLabel(vifeLabel);
246 case ERROR:
247 return VifeError.fromLabel(vifeLabel);
248 case OBJECT_ACTION:
249 return VifeObjectAction.fromLabel(vifeLabel);
250 case MAN_SPEC:
251 return new VifeManufacturerSpecific((byte) Integer.parseInt(vifeLabel, 16));
252 default:
253 throw new IllegalArgumentException(vifeType.getLabel());
254 }
255 }
256
257 public static Vife[] vifesFromJSON(VifTypes vifType, JSONArray jsonVifes) {
258 if (jsonVifes instanceof JSONArray) {
259 Vife[] result = new Vife[jsonVifes.size()];
260 for (int i = 0; i < jsonVifes.size(); i++) {
261 result[i] = getVife(jsonVifes.getJSONObject(i).getString("vifeType"), jsonVifes.getJSONObject(i).getString("name"));
262 }
263 return result;
264 } else {
265 return new Vife[0];
266 }
267 }
268 private ObjectAction action;
269 private Vif vif;
270
271
272
273
274
275 private Vife[] vifes = EMPTY_VIFE;
276 private FunctionField functionField;
277 private long storageNumber;
278 private int tariff;
279 private DataFieldCode dataFieldCode;
280 private short subUnit;
281
282 public DataBlock() {
283 super();
284 }
285
286 @Deprecated
287 public DataBlock(DataFieldCode dif, FunctionField functionField, short subUnit, int tariff, long storageNumber, Vif vif, Vife... vifes) {
288 super();
289 this.dataFieldCode = dif;
290 this.functionField = functionField;
291 this.subUnit = subUnit;
292 this.tariff = tariff;
293 this.storageNumber = storageNumber;
294 this.vif = vif;
295 if (vifes.length > 0) {
296 this.vifes = Arrays.copyOf(vifes, vifes.length);
297 }
298 }
299
300 @Deprecated
301 public DataBlock(DataFieldCode dif, Vif vif, Vife... vifes) {
302 super();
303 this.dataFieldCode = dif;
304 functionField = FunctionField.INSTANTANEOUS_VALUE;
305 this.vif = vif;
306 if (vifes.length > 0) {
307 this.vifes = Arrays.copyOf(vifes, vifes.length);
308 }
309 }
310
311 public boolean addVife(Vife vife) {
312 vifes = Arrays.copyOf(vifes, vifes.length + 1);
313 vifes[vifes.length - 1] = vife;
314 return true;
315 }
316
317
318
319
320 public ObjectAction getAction() {
321 return action;
322 }
323
324 public DataFieldCode getDataFieldCode() {
325 return dataFieldCode;
326 }
327
328 public Integer getExponent() {
329 return vif != null ? vif.getExponent() : null;
330 }
331
332 public FunctionField getFunctionField() {
333 return functionField;
334 }
335
336 public String getParamDescr() {
337 StringBuilder sb = new StringBuilder();
338 if (vif != null) {
339 sb.append(vif.getLabel());
340 }
341 if (vifes != null) {
342 for (Vife vife : vifes) {
343 sb.append(", ").append(vife.getLabel());
344 }
345 }
346 return sb.toString();
347 }
348
349 public SiPrefix getSiPrefix() {
350 return vif == null ? null : vif.getSiPrefix();
351 }
352
353 public long getStorageNumber() {
354 return storageNumber;
355 }
356
357
358
359
360 public short getSubUnit() {
361 return subUnit;
362 }
363
364 public int getTariff() {
365 return tariff;
366 }
367
368 public UnitOfMeasurement getUnitOfMeasurement() {
369 return vif != null ? vif.getUnitOfMeasurement() : null;
370 }
371
372 public abstract String getValueAsString();
373
374 public Vif getVif() {
375 return vif;
376 }
377
378 public Vife[] getVifes() {
379 return vifes;
380 }
381
382
383
384
385 public void setAction(ObjectAction action) {
386 this.action = action;
387 }
388
389 public void setFunctionField(FunctionField functionField) {
390 this.functionField = functionField;
391 }
392
393 public void setStorageNumber(long storageNumber) {
394 this.storageNumber = storageNumber;
395 }
396
397
398
399
400 public void setSubUnit(short subUnit) {
401 this.subUnit = subUnit;
402 }
403
404 public void setTariff(int tariff) {
405 this.tariff = tariff;
406 }
407
408 public void setVif(Vif vif) {
409 this.vif = vif;
410 }
411
412 public void toString(StringBuilder sb, String inset) {
413 if (action != null) {
414 sb.append(inset).append("action = ").append(getAction()).append("\n");
415 }
416 sb.append(inset).append("dataType = ").append(getDataFieldCode()).append("\n");
417 if (vif != null) {
418 sb.append(inset).append("description = ").append(getParamDescr()).append("\n");
419 if (getDataFieldCode().equals(DataFieldCode.NO_DATA) || getDataFieldCode().equals(DataFieldCode.SELECTION_FOR_READOUT)) {
420 sb.append(inset).append("unit =");
421 } else {
422 sb.append(inset).append("value = ").append(getValueAsString());
423 }
424 if (getUnitOfMeasurement() != null) {
425 if (getExponent() != null) {
426
427 if (getExponent() > 0) {
428 sb.append(" * 1");
429 for (int i = 0; i < getExponent(); i++) {
430 sb.append("0");
431 }
432 } else if (getExponent() < 0) {
433 sb.append(" * 0.");
434 for (int i = -1; i > getExponent(); i--) {
435 sb.append("0");
436 }
437 sb.append("1");
438
439 }
440 }
441
442 final Double cf = VifePrimary.getVifeCorrectionFactor(vifes);
443 if (!Double.isNaN(cf)) {
444 sb.append(" * ");
445 sb.append(cf);
446 }
447
448 sb.append(" [");
449 if (getSiPrefix() != null) {
450 sb.append(getSiPrefix());
451 }
452 sb.append(getUnitOfMeasurement()).append("]\n");
453 } else {
454 sb.append("\n");
455 }
456 }
457 if (functionField != null) {
458 sb.append(inset).append("tariff = ").append(getTariff()).append('\n');
459 sb.append(inset).append("storageNumber = ").append(getStorageNumber()).append("\n");
460 sb.append(inset).append("functionField = ").append(getFunctionField()).append("\n");
461 sb.append(inset).append("subUnit = ").append(getSubUnit()).append("\n");
462 }
463 }
464
465 @Override
466 public String toString() {
467 StringBuilder sb = new StringBuilder();
468 toString(sb, "");
469 return sb.toString();
470 }
471
472 protected void accumulateDatatoJSON(JSONObject json) {
473 }
474
475 @Override
476 public JSONObject toJSON(JsonSerializeType jsonSerializeType) {
477 JSONObject result = new JSONObject();
478 JSONObject drh = new JSONObject();
479 JSONObject dib = new JSONObject();
480 JSONObject vib = new JSONObject();
481
482 if (getAction() != null) {
483 dib.accumulate("action", getAction().getLabel());
484 }
485 dib.accumulate("dataFieldCode", getDataFieldCode().getLabel());
486 if (DataFieldCode.VARIABLE_LENGTH.equals(getDataFieldCode())) {
487 if (this instanceof StringDataBlock) {
488 dib.accumulate("variableLengthType", VariableLengthType.STRING.getLabel());
489 } else {
490 throw new UnsupportedOperationException("Varoable datablock:" + this.getClass().getName());
491 }
492 }
493 if (DataFieldCode.SPECIAL_FUNCTION_MAN_SPEC_DATA_LAST_PACKET.equals(dataFieldCode) || DataFieldCode.SPECIAL_FUNCTION_MAN_SPEC_DATA_PACKETS_FOLLOWS.equals(dataFieldCode) || DataFieldCode.SPECIAL_FUNCTION_GLOBAL_READOUT_REQUEST.equals(dataFieldCode)) {
494 drh.accumulate("dib", dib);
495 } else {
496 dib.accumulate("functionField", getFunctionField().getLabel());
497 dib.accumulate("storageNumber", getStorageNumber());
498 dib.accumulate("subUnit", getSubUnit());
499 dib.accumulate("tariff", getTariff());
500 drh.accumulate("dib", dib);
501 JSONObject jsonVif = new JSONObject();
502 jsonVif.accumulate("vifType", vif.getVifType().getLabel());
503 jsonVif.accumulate("description", vif.getLabel());
504 if (vif.getUnitOfMeasurement() != null) {
505 jsonVif.accumulate("unitOfMeasurement", vif.getUnitOfMeasurement().getLabel());
506 }
507 if (vif.getSiPrefix() != null) {
508 jsonVif.accumulate("siPrefix", vif.getSiPrefix().getLabel());
509 }
510 if (vif.getExponent() != null) {
511 jsonVif.accumulate("exponent", vif.getExponent());
512 }
513
514 vib.accumulate("vif", jsonVif);
515 if (getVifes().length > 0) {
516 JSONArray jsonVifes = new JSONArray();
517 for (Vife value : vifes) {
518 JSONObject jsonVife = new JSONObject();
519 jsonVife.accumulate("vifeType", value.getVifeType().getLabel());
520 jsonVife.accumulate("name", value.getLabel());
521 jsonVifes.add(jsonVife);
522 }
523 vib.accumulate("vifes", jsonVifes);
524 }
525 drh.accumulate("vib", vib);
526 }
527 result.accumulate("drh", drh);
528 if ((JsonSerializeType.ALL == jsonSerializeType) || (JsonSerializeType.SLAVE_CONFIG == jsonSerializeType)) {
529 accumulateDatatoJSON(result);
530 }
531 return result;
532 }
533
534 @Override
535 public void fromJSON(JSONObject json) {
536 JSONObject drh = json.getJSONObject("drh");
537 JSONObject dib = drh.getJSONObject("dib");
538 JSONObject vib = drh.getJSONObject("vib");
539 if (dib.get("action") != null) {
540 setAction(ObjectAction.fromLabel(dib.getString("action")));
541 }
542
543 setDataFieldCode(DataFieldCode.fromLabel(dib.getString("dataFieldCode")));
544 if ((DataFieldCode.SPECIAL_FUNCTION_MAN_SPEC_DATA_LAST_PACKET == dataFieldCode)
545 || (DataFieldCode.SPECIAL_FUNCTION_MAN_SPEC_DATA_PACKETS_FOLLOWS == dataFieldCode)
546 || (DataFieldCode.SPECIAL_FUNCTION_GLOBAL_READOUT_REQUEST == dataFieldCode)) {
547 } else {
548 setFunctionField(FunctionField.fromLabel(dib.getString("functionField")));
549 setStorageNumber(dib.getLong("storageNumber"));
550 setSubUnit((short) dib.getInt("subUnit"));
551 setTariff(dib.getInt("tariff"));
552 if (!vib.isNullObject()) {
553 JSONObject jsonVif = vib.getJSONObject("vif");
554 vif = vifFromJSON(jsonVif);
555 if (vib.containsKey("vifes")) {
556
557 Vife[] parsedVifes = vifesFromJSON(vif.getVifType(), vib.getJSONArray("vifes"));
558 if (parsedVifes.length > 0) {
559 this.vifes = Arrays.copyOf(parsedVifes, parsedVifes.length);
560 } else {
561 vifes = EMPTY_VIFE;
562 }
563 } else {
564 vifes = EMPTY_VIFE;
565 }
566 }
567 }
568 }
569
570 public abstract void setValue(String text);
571
572
573
574
575 public void setDataFieldCode(DataFieldCode dataFieldCode) {
576 this.dataFieldCode = dataFieldCode;
577 }
578
579 public void clearVifes() {
580 vifes = EMPTY_VIFE;
581 }
582
583
584 protected String formatBcdError(String bcdError) {
585 if (bcdError == null) {
586 return bcdError;
587 }
588 int length;
589 switch (getDataFieldCode()) {
590 case _2_DIGIT_BCD:
591 length = 2;
592 break;
593 case _4_DIGIT_BCD:
594 length = 4;
595 break;
596 case _6_DIGIT_BCD:
597 length = 6;
598 break;
599 case _8_DIGIT_BCD:
600 length = 8;
601 break;
602 case _12_DIGIT_BCD:
603 length = 12;
604 break;
605 default:
606 throw new RuntimeException("Unknown DFC " + getDataFieldCode());
607 }
608
609 if (bcdError.length() == length) {
610 return bcdError;
611 } else if ((bcdError.length() < length) && (bcdError.length() > 0)) {
612 StringBuilder sb = new StringBuilder(length);
613 for (int i = 0; i < length - bcdError.length(); i++) {
614 sb.append(' ');
615 }
616 sb.append(bcdError);
617 return sb.toString();
618 } else {
619 throw new RuntimeException("Bcd is too long: \"" + bcdError + "\"");
620 }
621
622 }
623
624
625 public int getCorrectionExponent(SiPrefix siPrefix) {
626 return getSiPrefix().getExponent()- siPrefix.getExponent() + getExponent() + VifePrimary.getVifeCorrectionExponent(vifes);
627 }
628
629 public double getCorrectionConstant() {
630 return VifePrimary.getVifeCorrectionConstant(vifes);
631 }
632
633 }