1 package net.sf.mbus4j.slaves;
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
31 import net.sf.json.JSONArray;
32 import net.sf.json.JSONObject;
33
34 import net.sf.mbus4j.MBusUtils;
35 import net.sf.mbus4j.dataframes.ApplicationReset;
36 import net.sf.mbus4j.dataframes.Frame;
37 import net.sf.mbus4j.dataframes.MBusMedium;
38 import net.sf.mbus4j.dataframes.MBusResponseFramesContainer;
39 import net.sf.mbus4j.dataframes.PrimaryAddress;
40 import net.sf.mbus4j.dataframes.RequestClassXData;
41 import net.sf.mbus4j.dataframes.ResponseFrameContainer;
42 import net.sf.mbus4j.dataframes.SelectionOfSlaves;
43 import net.sf.mbus4j.dataframes.SendInitSlave;
44 import net.sf.mbus4j.dataframes.SendUserData;
45 import net.sf.mbus4j.dataframes.SendUserDataManSpec;
46 import net.sf.mbus4j.dataframes.SingleCharFrame;
47 import net.sf.mbus4j.dataframes.UserDataResponse;
48 import net.sf.mbus4j.dataframes.UserDataResponse.StatusCode;
49 import net.sf.mbus4j.json.JSONFactory;
50 import net.sf.mbus4j.json.JSONSerializable;
51 import net.sf.mbus4j.json.JsonSerializeType;
52
53 import java.io.IOException;
54 import java.io.Serializable;
55 import java.util.ArrayList;
56 import java.util.Iterator;
57 import java.util.List;
58 import java.util.logging.Level;
59 import java.util.logging.Logger;
60 import net.sf.mbus4j.log.LogUtils;
61
62
63
64
65
66
67 public class Slave
68 implements Serializable,
69 MBusResponseFramesContainer,
70 JSONSerializable {
71
72 private final static Logger log = LogUtils.getSlaveLogger();
73
74 public static Slave fromResponse(UserDataResponse udr) {
75 Slave result = new Slave(udr.getAddress(), udr.getIdentNumber(), udr.getManufacturer(), udr.getVersion(), udr.getMedium());
76 result.setAccessnumber(udr.getAccessNumber());
77 result.setAcd(udr.isAcd());
78 result.setDfc(udr.isDfc());
79 result.setSignature(udr.getSignature());
80 result.setStatus(udr.getStatus());
81 ResponseFrameContainer rfc = new ResponseFrameContainer();
82 rfc.setRequestFrame(new RequestClassXData(Frame.ControlCode.REQ_UD2));
83 rfc.setResponseFrame(udr);
84 result.addResponseFrameContainer(rfc);
85 return result;
86 }
87
88
89
90
91 private boolean networkSelected;
92 protected List<ResponseFrameContainer> responseFrameContainers = new ArrayList<ResponseFrameContainer>();
93 private StatusCode[] status;
94 private byte version;
95 private MBusMedium medium;
96 private byte address;
97 private int identNumber;
98 private String manufacturer;
99 private short signature;
100 private short accessNumber;
101 private boolean acd;
102 private boolean dfc;
103 private int selectedIndex;
104
105 public Slave() {
106 super();
107 }
108
109 public Slave(int primaryAddress, int id, String man, int version, MBusMedium medium) {
110 this();
111 networkSelected = false;
112 setAddress((byte) primaryAddress);
113 setIdentNumber(id);
114 setManufacturer(man);
115 setVersion((byte) version);
116 setMedium(medium);
117 setStatus(new UserDataResponse.StatusCode[]{UserDataResponse.StatusCode.APPLICATION_NO_ERROR});
118 selectedIndex = -1;
119 }
120
121 @Override
122 public byte getAddress() {
123 return address;
124 }
125
126 @Override
127 public int getIdentNumber() {
128 return identNumber;
129 }
130
131 @Override
132 public String getManufacturer() {
133 return manufacturer;
134 }
135
136 @Override
137 public MBusMedium getMedium() {
138 return medium;
139 }
140
141 @Override
142 public byte getVersion() {
143 return version;
144 }
145
146 @Override
147 public StatusCode[] getStatus() {
148 return status;
149 }
150
151 @Override
152 public void setStatus(StatusCode[] status) {
153 this.status = status;
154 }
155
156 @Override
157 public short getSignature() {
158 return signature;
159 }
160
161 @Override
162 public void setSignature(short signature) {
163 this.signature = signature;
164 }
165
166 public Frame handleApplicationReset(ApplicationReset applicationReset) {
167 for (int i = 0; i < responseFrameContainers.size(); i++) {
168 if (applicationReset.equals(responseFrameContainers.get(i).getSelectFrame())) {
169 selectedIndex = i;
170 log.log(Level.FINE, "Set selected response container to {0} \"{1}\"", new Object[]{i, getResponseFrameContainer(i).getName()});
171 break;
172 }
173 }
174 return SingleCharFrame.SINGLE_CHAR_FRAME;
175 }
176
177 public Frame handleReqUd1(RequestClassXData requestClassXData) {
178 throw new UnsupportedOperationException("Not yet implemented");
179 }
180
181 public Frame handleReqUd2(RequestClassXData request) {
182 if (getSelectedResponseFrame() instanceof UserDataResponse) {
183 UserDataResponse udr = (UserDataResponse) getSelectedResponseFrame();
184 udr.setAccessNumber(accessNumber++);
185 udr.setAcd(acd);
186 udr.setAddress(address);
187 udr.setDfc(dfc);
188 udr.setIdentNumber(identNumber);
189 udr.setManufacturer(manufacturer);
190 udr.setMedium(medium);
191 udr.setSignature(signature);
192 udr.setStatus(status);
193 udr.setVersion(version);
194
195 return udr;
196 } else if (getSelectedResponseFrame() == null) {
197 UserDataResponse udr = new UserDataResponse();
198 udr.setAccessNumber(accessNumber++);
199 udr.setAcd(acd);
200 udr.setAddress(address);
201 udr.setDfc(dfc);
202 udr.setIdentNumber(identNumber);
203 udr.setManufacturer(manufacturer);
204 udr.setMedium(medium);
205 udr.setSignature(signature);
206 udr.setStatus(status);
207 udr.setVersion(version);
208
209 return udr;
210 } else {
211 throw new RuntimeException("Unknown Response class: "
212 + getSelectedResponseFrame().getClass().getName());
213 }
214 }
215
216 public Frame handleSendInitSlave(SendInitSlave sendInitSlave) {
217 return SingleCharFrame.SINGLE_CHAR_FRAME;
218 }
219
220 public Frame handleSendUserData(SendUserData sendUserData) {
221 return SingleCharFrame.SINGLE_CHAR_FRAME;
222 }
223
224 public Frame handleSendUserDataManSpec(SendUserDataManSpec sendUserDataManSpec) {
225 return SingleCharFrame.SINGLE_CHAR_FRAME;
226 }
227
228 @Override
229 public void setAddress(byte address) {
230 this.address = address;
231 }
232
233 @Override
234 public void setIdentNumber(int id) {
235 this.identNumber = id;
236 }
237
238 @Override
239 public void setManufacturer(String man) {
240 this.manufacturer = man;
241 }
242
243 @Override
244 public void setMedium(MBusMedium medium) {
245 this.medium = medium;
246 }
247
248 @Override
249 public void setVersion(byte version) {
250 this.version = version;
251 }
252
253
254
255
256
257
258 public boolean willHandleRequest(Frame frame) {
259 if (frame instanceof SelectionOfSlaves) {
260 SelectionOfSlaves selectionOfSlaves = (SelectionOfSlaves) frame;
261 log.log(Level.INFO, "will handle SelectionOfSlaves: {0}", (selectionOfSlaves.getAddress() & 0xFF) == MBusUtils.SLAVE_SELECT_PRIMARY_ADDRESS);
262
263 return (selectionOfSlaves.getAddress() & 0xFF) == MBusUtils.SLAVE_SELECT_PRIMARY_ADDRESS;
264 } else if (frame instanceof PrimaryAddress) {
265 int primaryAddress = ((PrimaryAddress) frame).getAddress() & 0xFF;
266
267 return willHandleByAddress(primaryAddress);
268 } else if (frame instanceof RequestClassXData) {
269 int primaryAddress = ((RequestClassXData) frame).getAddress() & 0xFF;
270
271 return willHandleByAddress(primaryAddress);
272 } else {
273 return false;
274 }
275 }
276
277 Frame handleSelectionOfSlaves(SelectionOfSlaves selectionOfSlaves) {
278 if ((selectionOfSlaves.getAddress() & 0xFF) != MBusUtils.SLAVE_SELECT_PRIMARY_ADDRESS) {
279 log.warning("NETWORK SELECT ERROR");
280
281 return null;
282 }
283
284 if (selectionOfSlaves.matchAll(getIdentNumber(),
285 getManufacturer(),
286 getMedium(),
287 getVersion())) {
288 networkSelected = true;
289 log.log(Level.INFO, "Network selected: {0}", slaveIdToString());
290
291 return SingleCharFrame.SINGLE_CHAR_FRAME;
292 } else {
293 log.log(Level.INFO, "Network deselected: {0}", slaveIdToString());
294 networkSelected = false;
295
296 return null;
297 }
298 }
299
300
301
302
303 public boolean isNetworkSelected() {
304 return networkSelected;
305 }
306
307
308
309
310 public void setNetworkSelected(boolean networkSelected) {
311 this.networkSelected = networkSelected;
312 }
313
314 public String slaveIdToString() {
315 return String.format("address = 0x%02x, id = %08d, man = %s, medium = %s, version = 0x%02X",
316 getAddress(),
317 getIdentNumber(),
318 getManufacturer(),
319 getMedium(),
320 getVersion());
321 }
322
323 private boolean willHandleByAddress(int primaryAddress) {
324 return (primaryAddress == MBusUtils.BROADCAST_NO_ANSWER_PRIMARY_ADDRESS)
325 || (primaryAddress == MBusUtils.BROADCAST_WITH_ANSWER_PRIMARY_ADDRESS)
326 || (primaryAddress == (getAddress() & 0xFF))
327 || ((primaryAddress == MBusUtils.SLAVE_SELECT_PRIMARY_ADDRESS) && isNetworkSelected());
328 }
329
330 @Override
331 public boolean equals(Object o) {
332 if (o instanceof Slave) {
333 Slave other = (Slave) o;
334
335 return (getAddress() == other.getAddress()) && (getIdentNumber() == other.getIdentNumber())
336 && getManufacturer().equals(other.getManufacturer())
337 && getMedium().equals(other.getMedium()) && (getVersion() == other.getVersion());
338 } else {
339 return false;
340 }
341 }
342
343 @Override
344 public int hashCode() {
345 int hash = 7;
346 hash = 79 * hash + this.version;
347 hash = 79 * hash + (this.medium != null ? this.medium.hashCode() : 0);
348 hash = 79 * hash + this.address;
349 hash = 79 * hash + this.identNumber;
350 hash = 79 * hash + (this.manufacturer != null ? this.manufacturer.hashCode() : 0);
351 return hash;
352 }
353
354
355
356
357 private static final long serialVersionUID = -1;
358 private final static int SERIAL_VERSION = 1;
359
360 private void writeObject(java.io.ObjectOutputStream stream)
361 throws IOException {
362 stream.defaultWriteObject();
363 stream.writeInt(SERIAL_VERSION);
364 stream.writeByte(getAddress());
365 stream.writeInt(getIdentNumber());
366 stream.writeObject(getManufacturer());
367 stream.writeObject(getMedium());
368 stream.writeByte(getVersion());
369 stream.writeBoolean(isAcd());
370 stream.writeBoolean(isDfc());
371 }
372
373 private void readObject(java.io.ObjectInputStream stream)
374 throws IOException, ClassNotFoundException {
375 stream.defaultReadObject();
376
377 switch (stream.readInt()) {
378 case 1:
379 setAddress(stream.readByte());
380 setIdentNumber(stream.readInt());
381 setManufacturer((String) stream.readObject());
382 setMedium((MBusMedium) stream.readObject());
383 setVersion(stream.readByte());
384 setAcd(stream.readBoolean());
385 setDfc(stream.readBoolean());
386
387 break;
388
389 default:
390 }
391 }
392
393 @Override
394 public boolean isAcd() {
395 return acd;
396 }
397
398 @Override
399 public boolean isDfc() {
400 return dfc;
401 }
402
403 @Override
404 public void setAcd(boolean acd) {
405 this.acd = acd;
406 }
407
408 @Override
409 public void setDfc(boolean dfc) {
410 this.dfc = dfc;
411 }
412
413 @Override
414 public JSONObject toJSON(JsonSerializeType jsonSerializeType) {
415 JSONObject result = new JSONObject();
416 result.accumulate("manufacturer",
417 getManufacturer());
418 result.accumulate("medium",
419 getMedium().getLabel());
420 result.accumulate("version",
421 JSONFactory.encodeHexByte(getVersion()));
422 result.accumulate("address",
423 JSONFactory.encodeHexByte(getAddress()));
424 result.accumulate("signature",
425 JSONFactory.encodeHexShort(getSignature()));
426
427 JSONArray jsonStatusArray = new JSONArray();
428
429 for (UserDataResponse.StatusCode st : getStatus()) {
430 jsonStatusArray.add(st.getLabel());
431 }
432
433 result.accumulate("accessnumber",
434 getAccessnumber());
435 result.accumulate("status", jsonStatusArray);
436 result.accumulate("identNumber",
437 getIdentNumber());
438 result.accumulate("acd",
439 isAcd());
440 result.accumulate("dfc",
441 isDfc());
442 result.accumulate("selectedFrame", selectedIndex);
443
444 JSONArray jsonSlaveFrameContainer = new JSONArray();
445
446 for (ResponseFrameContainer sfc : responseFrameContainers) {
447 jsonSlaveFrameContainer.add(sfc.toJSON(jsonSerializeType));
448 }
449
450 result.accumulate("slaveFrameContainers", jsonSlaveFrameContainer);
451
452 return result;
453 }
454
455 @Override
456 public Iterator<ResponseFrameContainer> iterator() {
457 return responseFrameContainers.iterator();
458 }
459
460 @Override
461 public short getAccessnumber() {
462 return accessNumber;
463 }
464
465 @Override
466 public void setAccessnumber(short accessnumber) {
467 this.accessNumber = accessnumber;
468 }
469
470 @Override
471 public void fromJSON(JSONObject json) {
472 setManufacturer(json.getString("manufacturer"));
473 setMedium(MBusMedium.fromLabel(json.getString("medium")));
474 setVersion(JSONFactory.decodeHexByte(json, "version", (byte) 0));
475 setIdentNumber(json.getInt("identNumber"));
476 setAddress(JSONFactory.decodeHexByte(json, "address", (byte) 0));
477 setAccessnumber(JSONFactory.getShort(json, "accessNumber", (short) 0));
478 setAcd(JSONFactory.getBoolean(json, "acd", false));
479 setDfc(JSONFactory.getBoolean(json, "dfc", false));
480 setSignature(JSONFactory.decodeHexShort(json, "signature", (short) 0));
481
482 if (json.containsKey("status")) {
483 JSONArray statusArray = json.getJSONArray("status");
484
485 if (statusArray.size() == 0) {
486 setStatus(new UserDataResponse.StatusCode[0]);
487 } else {
488 UserDataResponse.StatusCode[] status = new UserDataResponse.StatusCode[statusArray.size()];
489
490 for (int i = 0; i < status.length; i++) {
491 status[i] = UserDataResponse.StatusCode.fromLabel(statusArray.getString(i));
492 }
493
494 setStatus(status);
495 }
496 }
497
498 JSONArray jsonSlaveFrameContainers = json.getJSONArray("slaveFrameContainers");
499
500 for (int i = 0; i < jsonSlaveFrameContainers.size(); i++) {
501 ResponseFrameContainer sfc = new ResponseFrameContainer();
502 sfc.fromJSON(jsonSlaveFrameContainers.getJSONObject(i));
503 responseFrameContainers.add(sfc);
504 }
505 if (json.containsKey("selectedFrame")) {
506 selectedIndex = json.getInt("selectedFrame");
507 } else {
508 selectedIndex = 0;
509 }
510 }
511
512 @Override
513 public ResponseFrameContainer getResponseFrameContainer(int index) {
514 return responseFrameContainers.get(index);
515 }
516
517 @Override
518 public ResponseFrameContainer[] getResponseFrameContainers() {
519 return responseFrameContainers.toArray(new ResponseFrameContainer[responseFrameContainers.size()]);
520 }
521
522 @Override
523 public int getResponseFrameContainerCount() {
524 return responseFrameContainers.size();
525 }
526
527 private Frame getSelectedResponseFrame() {
528 if (selectedIndex >= 0) {
529 return getResponseFrameContainer(selectedIndex).getResponseFrame();
530 } else {
531 return null;
532 }
533 }
534
535 @Override
536 public boolean addResponseFrameContainer(ResponseFrameContainer rfc) {
537 return responseFrameContainers.add(rfc);
538 }
539
540 @Override
541 public ResponseFrameContainer removeResponseFrameContainer(int i) {
542 return responseFrameContainers.remove(i);
543 }
544
545 @Override
546 public int responseFrameContainerIndexOf(ResponseFrameContainer rfc) {
547 return responseFrameContainers.indexOf(rfc);
548 }
549 }