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.JSONArray;
31 import net.sf.json.JSONObject;
32
33 import net.sf.mbus4j.dataframes.datablocks.DataBlock;
34 import net.sf.mbus4j.dataframes.datablocks.dif.DataFieldCode;
35 import net.sf.mbus4j.json.JSONFactory;
36 import net.sf.mbus4j.json.JsonSerializeType;
37
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.Iterator;
41 import java.util.List;
42 import java.util.Objects;
43 import net.sf.mbus4j.dataframes.datablocks.dif.FunctionField;
44 import net.sf.mbus4j.dataframes.datablocks.vif.UnitOfMeasurement;
45 import net.sf.mbus4j.dataframes.datablocks.vif.Vif;
46 import net.sf.mbus4j.dataframes.datablocks.vif.Vife;
47
48
49
50
51
52
53 public class UserDataResponse
54 implements LongFrame,
55 PrimaryAddress,
56 Cloneable {
57
58 @Override
59 public JSONObject toJSON(JsonSerializeType jsonSerializeType) {
60 JSONObject result = new JSONObject();
61 result.accumulate("controlCode",
62 getControlCode());
63
64 if (JsonSerializeType.ALL == jsonSerializeType) {
65 result.accumulate("manufacturer",
66 getManufacturer());
67 result.accumulate("medium",
68 getMedium().getLabel());
69 result.accumulate("version",
70 JSONFactory.encodeHexByte(getVersion()));
71 result.accumulate("identNumber",
72 getIdentNumber());
73 result.accumulate("address",
74 JSONFactory.encodeHexByte(getAddress()));
75 result.accumulate("accessNumber",
76 getAccessNumber());
77 result.accumulate("acd",
78 isAcd());
79 result.accumulate("dfc",
80 isDfc());
81 result.accumulate("signature",
82 JSONFactory.encodeHexShort(getSignature()));
83
84 JSONArray jsonStatusArray = new JSONArray();
85
86 for (StatusCode st : getStatus()) {
87 jsonStatusArray.add(st.getLabel());
88 }
89
90 result.accumulate("status", jsonStatusArray);
91 }
92
93 if ((JsonSerializeType.ALL == jsonSerializeType) || (JsonSerializeType.SLAVE_CONFIG == jsonSerializeType)) {
94 JSONArray jsonDataBlocks = new JSONArray();
95
96 for (DataBlock db : this) {
97 jsonDataBlocks.add(db.toJSON(jsonSerializeType));
98 }
99
100 result.accumulate("dataBlocks", jsonDataBlocks);
101 }
102
103 return result;
104 }
105
106 @Override
107 public void fromJSON(JSONObject json) {
108 setManufacturer(json.containsKey("manufacturer") ? json.getString("manufacturer") : "");
109 setMedium(json.containsKey("medium") ? MBusMedium.fromLabel(json.getString("medium"))
110 : MBusMedium.UNKNOWN_MEDIUM);
111 setVersion(JSONFactory.decodeHexByte(json, "version", (byte) 0));
112 setIdentNumber(json.containsKey("identNumber") ? json.getInt("identNumber") : 0);
113 setAddress(JSONFactory.decodeHexByte(json, "address", (byte) 0));
114 setAccessNumber(JSONFactory.getShort(json, "accessNumber", (short) 0));
115 setAcd(JSONFactory.getBoolean(json, "acd", false));
116 setDfc(JSONFactory.getBoolean(json, "dfc", false));
117 setSignature(JSONFactory.decodeHexShort(json, "signature", (short) 0));
118
119 if (json.containsKey("status")) {
120 JSONArray statusArray = json.getJSONArray("status");
121
122 if (statusArray.isEmpty()) {
123 setStatus(new StatusCode[0]);
124 } else {
125 status = new StatusCode[statusArray.size()];
126
127 for (int i = 0; i < status.length; i++) {
128 status[i] = StatusCode.fromLabel(statusArray.getString(i));
129 }
130 }
131 }
132
133 JSONFactory.readDataBlocks(this, json);
134 }
135
136 public static enum StatusCode {
137
138 APPLICATION_NO_ERROR(0x00, "No application error"),
139 APPLICATION_BUSY(0x01, "Application busy"),
140 APPLICATION_ANY_ERROR(0x02, "Any application error"),
141 APPLICATION_RESERVED(0x03, "Application reserved"),
142
143 POWER_LOW(0x04, "Power Low"), PERMANENT_ERROR(0x08, "Permanent error"),
144 TEMPORARY_ERROR(0x10, "Temporary error"),
145 MAN_SPEC_0X20(0x20, "Specific to manufacturer 0x20"),
146 MAN_SPEC_0X40(0x40, "Specific to manufacturer 0x40"),
147 MAN_SPEC_0X80(0x80, "Specific to manufacturer 0x80");
148
149 public static byte toId(StatusCode[] values) {
150 byte result = 0;
151
152 for (StatusCode sc : values) {
153 result |= sc.id;
154 }
155
156 return result;
157 }
158
159 public final byte id;
160 private final String label;
161
162 private StatusCode(int id, String description) {
163 this.id = (byte) id;
164 this.label = description;
165 }
166
167 @Override
168 public String toString() {
169 return label;
170 }
171
172 public String getLabel() {
173 return label;
174 }
175
176 public static StatusCode fromLabel(String label) {
177 for (StatusCode value : values()) {
178 if (value.getLabel().equals(label)) {
179 return value;
180 }
181 }
182
183 return valueOf(label);
184 }
185 }
186
187 private boolean acd;
188 private boolean dfc;
189 private byte version;
190 private short accessNumber;
191 private StatusCode[] status;
192 private short signature;
193 private MBusMedium medium;
194 private int identNumber;
195 private String manufacturer;
196 private List<DataBlock> dataBlocks = new ArrayList<>();
197 private byte address;
198
199 public UserDataResponse() {
200 super();
201 }
202
203 public UserDataResponse(boolean acd, boolean dfc) {
204 this.acd = acd;
205 this.dfc = dfc;
206 }
207
208 @Override
209 public boolean addDataBlock(DataBlock dataBlock) {
210 return dataBlocks.add(dataBlock);
211 }
212
213 public boolean addAllDataBlocks(List<DataBlock> list) {
214 return dataBlocks.addAll(list);
215 }
216
217 public void addStatus(StatusCode status) {
218 if (this.status == null) {
219 this.status = new StatusCode[]{status};
220 } else {
221 this.status = Arrays.copyOf(this.status, this.status.length + 1);
222 this.status[this.status.length - 1] = status;
223 }
224 }
225
226 public void clearDataBlocks() {
227 dataBlocks.clear();
228 }
229
230 @Override
231 public UserDataResponse clone()
232 throws CloneNotSupportedException {
233 UserDataResponse result = (UserDataResponse) super.clone();
234 result.dataBlocks = new ArrayList<>();
235 result.dataBlocks.addAll(dataBlocks);
236
237 return result;
238 }
239
240 public short getAccessNumber() {
241 return accessNumber;
242 }
243
244
245
246
247 @Override
248 public byte getAddress() {
249 return address;
250 }
251
252 @Override
253 public ControlCode getControlCode() {
254 return ControlCode.RSP_UD;
255 }
256
257
258
259
260
261 public DataBlock getDataBlock(int i) {
262 return dataBlocks.get(i);
263 }
264
265 public int getDataBlockCount() {
266 return dataBlocks.size();
267 }
268
269 public int getIdentNumber() {
270 return identNumber;
271 }
272
273 @Override
274 public DataBlock getLastDataBlock() {
275 return (dataBlocks.isEmpty()) ? null : dataBlocks.get(dataBlocks.size() - 1);
276 }
277
278 public String getManufacturer() {
279 return manufacturer;
280 }
281
282 public MBusMedium getMedium() {
283 return medium;
284 }
285
286 public short getSignature() {
287 return signature;
288 }
289
290 public StatusCode[] getStatus() {
291 return status;
292 }
293
294 public byte getVersion() {
295 return version;
296 }
297
298
299
300
301 public boolean isAcd() {
302 return acd;
303 }
304
305
306
307
308 public boolean isDfc() {
309 return dfc;
310 }
311
312
313
314
315
316
317 public boolean isLastPackage() {
318 return (getLastDataBlock() == null) ? true
319 : (!DataFieldCode.SPECIAL_FUNCTION_MAN_SPEC_DATA_PACKETS_FOLLOWS.equals(getLastDataBlock()
320 .getDataFieldCode()));
321 }
322
323 @Override
324 public Iterator<DataBlock> iterator() {
325 return dataBlocks.iterator();
326 }
327
328 @Override
329 public void replaceDataBlock(DataBlock oldDataBlock, DataBlock newDataBlock) {
330 final int pos = dataBlocks.indexOf(oldDataBlock);
331 dataBlocks.set(pos, newDataBlock);
332 }
333
334 public void setAccessNumber(short accessNumber) {
335 this.accessNumber = accessNumber;
336 }
337
338
339
340
341 public void setAcd(boolean acd) {
342 this.acd = acd;
343 }
344
345
346
347
348 @Override
349 public void setAddress(byte address) {
350 this.address = address;
351 }
352
353
354
355
356 public void setDfc(boolean dfc) {
357 this.dfc = dfc;
358 }
359
360 public void setIdentNumber(int identNumber) {
361 this.identNumber = identNumber;
362 }
363
364 public void setManufacturer(String manufacturer) {
365 this.manufacturer = manufacturer;
366 }
367
368 public void setMedium(MBusMedium medium) {
369 this.medium = medium;
370 }
371
372 public void setSignature(short signature) {
373 this.signature = signature;
374 }
375
376 public void setStatus(StatusCode[] status) {
377 this.status = status;
378 }
379
380 public void setVersion(byte version) {
381 this.version = version;
382 }
383
384 @Override
385 public String toString() {
386 StringBuilder sb = new StringBuilder();
387 sb.append("control code = ").append(getControlCode()).append('\n');
388 sb.append("isAcd = ").append(isAcd()).append('\n');
389 sb.append("isDfc = ").append(isDfc()).append('\n');
390 sb.append(String.format("address = 0x%02X\n", address));
391 sb.append(String.format("ident number = %08d\n", identNumber));
392 sb.append("manufacturer = ").append(manufacturer).append('\n');
393 sb.append(String.format("version = 0x%02X\n", version));
394 sb.append("accessnumber = ").append(accessNumber).append('\n');
395 sb.append(String.format("status = %s\n",
396 Arrays.toString(status)));
397 sb.append(String.format("signature = 0x%04X\n", signature));
398 sb.append("medium = ").append(medium.toString()).append('\n');
399 sb.append("lastPackage = ").append(isLastPackage()).append('\n');
400
401 for (int i = 0; i < dataBlocks.size(); i++) {
402 sb.append(String.format("datablock[%d]:\n", i));
403 dataBlocks.get(i).toString(sb, " ");
404 }
405
406 return sb.toString();
407 }
408
409
410
411
412
413
414
415
416
417
418
419
420 public DataBlock[] getDataBlocks(int tarif, long storagenumber, short subUnit, Vif vif, FunctionField functionField, Vife[] vifes) {
421 DataBlock[] result = null;
422 for (DataBlock db : dataBlocks) {
423 if ((db.getTariff() == tarif)
424 && (db.getStorageNumber() == storagenumber)
425 && (db.getSubUnit() == subUnit)
426 && (Objects.equals(db.getVif(), vif))
427 && (db.getFunctionField() == functionField)
428 && (Arrays.equals(db.getVifes(), vifes))) {
429 if (result == null) {
430 result = new DataBlock[]{db};
431 } else {
432 result = Arrays.copyOf(result, result.length + 1);
433 result[result.length - 1] = db;
434 }
435 }
436 }
437 return result;
438 }
439
440 public DataBlock findDataBlock(final DataFieldCode difCode, final String paramDescr, final UnitOfMeasurement unitOfMeasurement, final FunctionField functionField, final long storageNumber, final short subUnit, final int tariff) {
441 DataBlock result = null;
442 for (DataBlock db : dataBlocks) {
443 if (Objects.equals(db.getDataFieldCode(), difCode)
444 && Objects.equals(db.getParamDescr(), paramDescr)
445 && Objects.equals(db.getUnitOfMeasurement(), unitOfMeasurement)
446 && Objects.equals(db.getFunctionField(), functionField)
447 && (db.getStorageNumber() == storageNumber)
448 && (db.getSubUnit() == subUnit)
449 && (db.getTariff() == tariff)) {
450 if (result == null) {
451 result = db;
452 } else {
453 throw new RuntimeException("Multiple db found: \n" + result + "\n\n" + db);
454 }
455 }
456 }
457 if (result == null) {
458 throw new RuntimeException("No db found");
459 }
460 return result;
461 }
462
463 @Deprecated
464 public boolean isDBUnique() {
465 for (DataBlock db : dataBlocks) {
466 if (getDataBlocks(db.getTariff(), db.getStorageNumber(), db.getSubUnit(), db.getVif(), db.getFunctionField(), db.getVifes()).length != 1) {
467 return false;
468 }
469 }
470 return true;
471 }
472
473 }