refactored parsing reports on client side, added toString() method to reports

pull/3/head
Stefan Feuerhahn 8 years ago
parent b4de8d70a8
commit b4c30a3a6c

@ -83,7 +83,7 @@ def projectName = 'OpenIEC61850'
dependencies {
compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25'
compile group: 'org.openmuc', name: 'jasn1-61850mod', version: '1.8.2'
compile group: 'org.openmuc', name: 'jasn1-61850mod', version: '1.8.3-SNAPSHOT'
compile group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.3'
compile group: 'com.toedter', name: 'jcalendar', version: '1.4'
}

@ -270,9 +270,10 @@ A report control block contains the following fields:
** *DatSet* - The reference of the data set associated with this
RCB. It must be located in the same logical node as the
RCB. Members of this data set will be reported whenever the
configured events occure. The reference set here must contain a
dollar sign instead of a dot to separate the logical node from the
data set name, e.g.: 'LDevice1/LNode$DataSetName'
configured events occure. The data set reference as it is set in an
RCB must contain a dollar sign instead of a dot to separate the
logical node from the data set name, e.g.:
'LDevice1/LNode$DataSetName'
** *OptFlds* - A bitstring where each bit indicates whether an
optional field is included in the reports caused by this RCB. The

@ -32,7 +32,6 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.openmuc.jasn1.ber.BerByteArrayOutputStream;
import org.openmuc.jasn1.ber.types.BerBitString;
import org.openmuc.jasn1.ber.types.BerBoolean;
import org.openmuc.jasn1.ber.types.BerInteger;
import org.openmuc.jasn1.ber.types.BerNull;
@ -1437,9 +1436,15 @@ public final class ClientAssociation {
}
/**
* Sets the selected values of the given report control block. Note that all these parameters may only be set if
* reporting for this report control block is not enabled and if it is not reserved by another client. The
* parameters PurgeBuf, EntryId are only applicable if the given rcb is of type BRCB.
* Sets the selected values of the given report control block. Note that all these parameters may only be set if the
* RCB has been reserved but reporting has not been enabled yet.
* <p>
* The data set reference as it is set in an RCB must contain a dollar sign instead of a dot to separate the logical
* node from the data set name, e.g.: 'LDevice1/LNode$DataSetName'. Therefore his method will check the reference
* for a dot and if necessary convert it to a '$' sign before sending the request to the server.
* <p>
* The parameters PurgeBuf, EntryId are only applicable if the given rcb is of type BRCB.
*
*
* @param rcb
* the report control block
@ -1474,6 +1479,7 @@ public final class ClientAssociation {
parametersToSet.add(rcb.getRptId());
}
if (setDatSet == true) {
rcb.getDatSet().setValue(rcb.getDatSet().getStringValue().replace('.', '$'));
parametersToSet.add(rcb.getDatSet());
}
if (setOptFlds == true) {
@ -1534,6 +1540,7 @@ public final class ClientAssociation {
}
List<AccessResult> listRes = unconfirmedServ.getInformationReport().getListOfAccessResult().getAccessResult();
int index = 0;
if (listRes.get(index).getSuccess().getVisibleString() == null) {
@ -1541,132 +1548,127 @@ public final class ClientAssociation {
"processReport: report does not contain RptID");
}
String rptId;
BdaOptFlds optFlds;
Integer sqNum = null;
Integer subSqNum = null;
boolean moreSegmentsFollow = false;
String dataSetRef = null;
boolean bufOvfl = false;
Long confRev = null;
BdaEntryTime timeOfEntry = null;
BdaOctetString entryId = null;
DataSet dataSet = null;
rptId = listRes.get(index++).getSuccess().getVisibleString().toString();
String rptId = listRes.get(index++).getSuccess().getVisibleString().toString();
if (listRes.get(index).getSuccess().getBitString() == null) {
throw new ServiceError(ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
"processReport: report does not contain OptFlds");
}
optFlds = new BdaOptFlds(new ObjectReference("none"), null);
BdaOptFlds optFlds = new BdaOptFlds(new ObjectReference("none"), null);
optFlds.setValue(listRes.get(index++).getSuccess().getBitString().value);
Integer sqNum = null;
if (optFlds.isSequenceNumber()) {
sqNum = listRes.get(index++).getSuccess().getUnsigned().intValue();
}
BdaEntryTime timeOfEntry = null;
if (optFlds.isReportTimestamp()) {
timeOfEntry = new BdaEntryTime(new ObjectReference("none"), null, "", false, false);
timeOfEntry.setValueFromMmsDataObj(listRes.get(index++).getSuccess());
}
String dataSetRef = null;
if (optFlds.isDataSetName()) {
dataSetRef = (listRes.get(index++).getSuccess().getVisibleString().toString());
}
else {
for (Urcb urcb : serverModel.getUrcbs()) {
if ((urcb.getRptId() != null && urcb.getRptId().getStringValue().equals(rptId))
|| urcb.getReference().toString().equals(rptId)) {
dataSetRef = urcb.getDatSet().getStringValue();
break;
}
}
if (dataSetRef == null) {
for (Brcb brcb : serverModel.getBrcbs()) {
if ((brcb.getRptId() != null && brcb.getRptId().getStringValue().equals(rptId))
|| brcb.getReference().toString().equals(rptId)) {
dataSetRef = brcb.getDatSet().getStringValue();
break;
}
}
}
}
if (dataSetRef == null) {
throw new ServiceError(ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
"unable to find RCB that matches the given RptID in the report.");
}
dataSetRef = dataSetRef.replace('$', '.');
DataSet dataSet = serverModel.getDataSet(dataSetRef);
if (dataSet == null) {
throw new ServiceError(ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
"unable to find data set that matches the given data set reference of the report.");
}
Boolean bufOvfl = null;
if (optFlds.isBufferOverflow()) {
bufOvfl = (listRes.get(index++).getSuccess().getBool().value);
}
BdaOctetString entryId = null;
if (optFlds.isEntryId()) {
entryId = new BdaOctetString(new ObjectReference("none"), null, "", 8, false, false);
entryId.setValue(listRes.get(index++).getSuccess().getOctetString().value);
}
Long confRev = null;
if (optFlds.isConfigRevision()) {
confRev = listRes.get(index++).getSuccess().getUnsigned().longValue();
}
Integer subSqNum = null;
boolean moreSegmentsFollow = false;
if (optFlds.isSegmentation()) {
subSqNum = listRes.get(index++).getSuccess().getUnsigned().intValue();
moreSegmentsFollow = listRes.get(index++).getSuccess().getBool().value;
}
BerBitString inclusionBitString = listRes.get(index++).getSuccess().getBitString();
boolean[] inclusionBitString = listRes.get(index++).getSuccess().getBitString().getValueAsBooleans();
int numMembersReported = 0;
for (boolean bit : inclusionBitString) {
if (bit) {
numMembersReported++;
}
}
if (optFlds.isDataReference()) {
// this is just to move the index to the right place
// The next part will process the changes to the values
// without the dataRefs
for (int i = 0; i < inclusionBitString.numBits; i++) {
if ((inclusionBitString.value[i / 8] & (1 << (7 - i % 8))) == (1 << (7 - i % 8))) {
index++;
}
}
index += numMembersReported;
}
if (dataSetRef == null) {
for (Urcb urcb : serverModel.getUrcbs()) {
if ((urcb.getRptId() != null && urcb.getRptId().getStringValue().equals(rptId))
|| urcb.getReference().toString().equals(rptId)) {
dataSetRef = urcb.getDatSet().getStringValue();
break;
}
}
}
if (dataSetRef == null) {
for (Brcb brcb : serverModel.getBrcbs()) {
if ((brcb.getRptId() != null && brcb.getRptId().getStringValue().equals(rptId))
|| brcb.getReference().toString().equals(rptId)) {
dataSetRef = brcb.getDatSet().getStringValue();
break;
}
}
}
if (dataSetRef == null) {
throw new ServiceError(ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
"unable to find URCB that matches the given RptID in the report.");
}
// updating of data set copy - original stays the same
dataSet = serverModel.getDataSet(dataSetRef.replace('$', '.')).copy();
int shiftNum = 0;
for (ModelNode child : dataSet.getMembers()) {
if ((inclusionBitString.value[shiftNum / 8] & (1 << (7 - shiftNum % 8))) == (1 << (7 - shiftNum % 8))) {
List<FcModelNode> reportedDataSetMembers = new ArrayList<>(numMembersReported);
int dataSetIndex = 0;
for (FcModelNode dataSetMember : dataSet.getMembers()) {
if (inclusionBitString[dataSetIndex]) {
AccessResult accessRes = listRes.get(index++);
child.setValueFromMmsDataObj(accessRes.getSuccess());
FcModelNode dataSetMemberCopy = (FcModelNode) dataSetMember.copy();
dataSetMemberCopy.setValueFromMmsDataObj(accessRes.getSuccess());
reportedDataSetMembers.add(dataSetMemberCopy);
}
shiftNum++;
dataSetIndex++;
}
List<BdaReasonForInclusion> reasonCodes = null;
if (optFlds.isReasonForInclusion()) {
reasonCodes = new ArrayList<>(dataSet.getMembers().size());
for (int i = 0; i < dataSet.getMembers().size(); i++) {
if ((inclusionBitString.value[i / 8] & (1 << (7 - i % 8))) == (1 << (7 - i % 8))) {
if (inclusionBitString[dataSetIndex]) {
BdaReasonForInclusion reasonForInclusion = new BdaReasonForInclusion(null);
reasonCodes.add(reasonForInclusion);
byte[] reason = listRes.get(index++).getSuccess().getBitString().value;
reasonForInclusion.setValue(reason);
}
}
}
return new Report(rptId, optFlds, sqNum, subSqNum, moreSegmentsFollow, dataSetRef, bufOvfl, confRev,
timeOfEntry, entryId, inclusionBitString.value, reasonCodes, dataSet);
return new Report(rptId, sqNum, subSqNum, moreSegmentsFollow, dataSetRef, bufOvfl, confRev, timeOfEntry,
entryId, inclusionBitString, reportedDataSetMembers, reasonCodes);
}

@ -21,24 +21,22 @@ import java.util.List;
public class Report {
private final String rptId;
private final BdaOptFlds optFlds;
private final Integer sqNum;
private final Integer subSqNum;
private final boolean moreSegmentsFollow;
private final String dataSetRef;
private final boolean bufOvfl;
private final Boolean bufOvfl;
private final Long confRev;
private final BdaEntryTime timeOfEntry;
private final BdaOctetString entryId;
private final byte[] inclusionBitString;
private final boolean[] inclusionBitString;
private final List<FcModelNode> values;
private final List<BdaReasonForInclusion> reasonCodes;
private final DataSet dataSet;
public Report(String rptId, BdaOptFlds optFlds, Integer sqNum, Integer subSqNum, boolean moreSegmentsFollow,
String dataSetRef, boolean bufOvfl, Long confRev, BdaEntryTime timeOfEntry, BdaOctetString entryId,
byte[] inclusionBitString, List<BdaReasonForInclusion> reasonCodes, DataSet dataSet) {
public Report(String rptId, Integer sqNum, Integer subSqNum, boolean moreSegmentsFollow, String dataSetRef,
Boolean bufOvfl, Long confRev, BdaEntryTime timeOfEntry, BdaOctetString entryId,
boolean[] inclusionBitString, List<FcModelNode> values, List<BdaReasonForInclusion> reasonCodes) {
this.rptId = rptId;
this.optFlds = optFlds;
this.sqNum = sqNum;
this.subSqNum = subSqNum;
this.moreSegmentsFollow = moreSegmentsFollow;
@ -48,18 +46,14 @@ public class Report {
this.timeOfEntry = timeOfEntry;
this.entryId = entryId;
this.inclusionBitString = inclusionBitString;
this.values = values;
this.reasonCodes = reasonCodes;
this.dataSet = dataSet;
}
public String getRptId() {
return rptId;
}
public BdaOptFlds getOptFlds() {
return optFlds;
}
/**
* Sequence numberThe parameter MoreSegmentsFollow indicates that more report segments with the same sequence number
* follow, counted up for every {@code Report} instance generated
@ -100,7 +94,7 @@ public class Report {
*
* @return true if buffer overflow is true
*/
public boolean isBufOvfl() {
public Boolean getBufOvfl() {
return bufOvfl;
}
@ -126,7 +120,7 @@ public class Report {
*
* @return the inclusion bit string as a byte array
*/
public byte[] getInclusionBitString() {
public boolean[] getInclusionBitString() {
return inclusionBitString;
}
@ -139,13 +133,47 @@ public class Report {
return reasonCodes;
}
/**
* Gets the data set associated with this report.
*
* @return the data set associated with this report.
*/
public DataSet getDataSet() {
return dataSet;
public List<FcModelNode> getValues() {
return values;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Report ID: ").append(rptId);
sb.append("\nData set reference: ").append(dataSetRef);
if (sqNum != null) {
sb.append("\nSequence number: ").append(sqNum);
}
if (subSqNum != null) {
sb.append("\nSubsequence number: ").append(subSqNum);
if (moreSegmentsFollow) {
sb.append(" (more segments follow)");
}
}
if (timeOfEntry != null) {
sb.append("\nTime of entry (unix timestamp): ").append(timeOfEntry.getTimestampValue());
}
if (bufOvfl != null) {
sb.append("\nBuffer overflow: ").append(bufOvfl);
}
if (entryId != null) {
sb.append("\nEntry ID: ").append(HexConverter.toHexString(entryId.getValue()));
}
if (confRev != null) {
sb.append("\nConfiguration revision: ").append(confRev.toString());
}
sb.append("\nReported data set members:");
int index = 0;
for (FcModelNode reportedDataSetMember : values) {
sb.append("\n").append(reportedDataSetMember.toString());
if (reasonCodes != null) {
sb.append(", reason: ").append(reasonCodes.get(index));
}
}
return sb.toString();
}
}

Loading…
Cancel
Save