- client: added GetFileDirectory, DeleteFile, and GetFile service implementation

pull/4/head
Michael Zillgith 8 years ago
parent f064d16553
commit acf5c15746

@ -30,9 +30,10 @@ ConfirmedServiceRequest ::= CHOICE {
defineNamedVariableList [11] IMPLICIT DefineNamedVariableList-Request, defineNamedVariableList [11] IMPLICIT DefineNamedVariableList-Request,
getNamedVariableListAttributes [12] GetNamedVariableListAttributes-Request, getNamedVariableListAttributes [12] GetNamedVariableListAttributes-Request,
deleteNamedVariableList [13] IMPLICIT DeleteNamedVariableList-Request, deleteNamedVariableList [13] IMPLICIT DeleteNamedVariableList-Request,
-- fileOpen [72] IMPLICIT FileOpen-Request, fileOpen [72] IMPLICIT FileOpen-Request,
-- fileRead [73] IMPLICIT FileRead-Request, fileRead [73] IMPLICIT FileRead-Request,
-- fileClose [74] IMPLICIT FileClose-Request, fileClose [74] IMPLICIT FileClose-Request,
fileDelete [76] IMPLICIT FileDelete-Request,
fileDirectory [77] IMPLICIT FileDirectory-Request fileDirectory [77] IMPLICIT FileDirectory-Request
} }
@ -57,9 +58,10 @@ ConfirmedServiceResponse ::= CHOICE {
defineNamedVariableList [11] IMPLICIT DefineNamedVariableList-Response, defineNamedVariableList [11] IMPLICIT DefineNamedVariableList-Response,
getNamedVariableListAttributes [12] IMPLICIT GetNamedVariableListAttributes-Response, getNamedVariableListAttributes [12] IMPLICIT GetNamedVariableListAttributes-Response,
deleteNamedVariableList [13] IMPLICIT DeleteNamedVariableList-Response, deleteNamedVariableList [13] IMPLICIT DeleteNamedVariableList-Response,
-- fileOpen [72] IMPLICIT FileOpen-Response, fileOpen [72] IMPLICIT FileOpen-Response,
-- fileRead [73] IMPLICIT FileRead-Response, fileRead [73] IMPLICIT FileRead-Response,
-- fileClose [74] IMPLICIT FileClose-Response, fileClose [74] IMPLICIT FileClose-Response,
fileDelete [76] IMPLICIT FileDelete-Response,
fileDirectory [77] IMPLICIT FileDirectory-Response fileDirectory [77] IMPLICIT FileDirectory-Response
} }
@ -589,6 +591,31 @@ DeleteNamedVariableList-Response ::= SEQUENCE {
numberDeleted [1] IMPLICIT Unsigned32 numberDeleted [1] IMPLICIT Unsigned32
} }
FileOpen-Request ::= SEQUENCE {
fileName [0] IMPLICIT FileName,
initialPosition [1] IMPLICIT Unsigned32
}
FileOpen-Response ::= SEQUENCE {
frsmID [0] IMPLICIT Integer32,
fileAttributes [1] IMPLICIT FileAttributes
}
FileRead-Request ::= Integer32 -- FRSM ID
FileRead-Response ::= SEQUENCE {
fileData [0] IMPLICIT OCTET STRING,
moreFollows [1] IMPLICIT BOOLEAN DEFAULT TRUE
}
FileClose-Request ::= Integer32 -- FRSM ID
FileClose-Response ::= NULL
FileDelete-Request ::= FileName
FileDelete-Response ::= NULL
FileDirectory-Request ::= SEQUENCE { FileDirectory-Request ::= SEQUENCE {
fileSpecification [0] IMPLICIT FileName OPTIONAL, fileSpecification [0] IMPLICIT FileName OPTIONAL,
continueAfter [1] IMPLICIT FileName OPTIONAL continueAfter [1] IMPLICIT FileName OPTIONAL

@ -31,6 +31,10 @@ public class ConfirmedServiceRequest implements Serializable {
private DefineNamedVariableListRequest defineNamedVariableList = null; private DefineNamedVariableListRequest defineNamedVariableList = null;
private GetNamedVariableListAttributesRequest getNamedVariableListAttributes = null; private GetNamedVariableListAttributesRequest getNamedVariableListAttributes = null;
private DeleteNamedVariableListRequest deleteNamedVariableList = null; private DeleteNamedVariableListRequest deleteNamedVariableList = null;
private FileOpenRequest fileOpen = null;
private FileReadRequest fileRead = null;
private FileCloseRequest fileClose = null;
private FileDeleteRequest fileDelete = null;
private FileDirectoryRequest fileDirectory = null; private FileDirectoryRequest fileDirectory = null;
public ConfirmedServiceRequest() { public ConfirmedServiceRequest() {
@ -96,6 +100,38 @@ public class ConfirmedServiceRequest implements Serializable {
return deleteNamedVariableList; return deleteNamedVariableList;
} }
public void setFileOpen(FileOpenRequest fileOpen) {
this.fileOpen = fileOpen;
}
public FileOpenRequest getFileOpen() {
return fileOpen;
}
public void setFileRead(FileReadRequest fileRead) {
this.fileRead = fileRead;
}
public FileReadRequest getFileRead() {
return fileRead;
}
public void setFileClose(FileCloseRequest fileClose) {
this.fileClose = fileClose;
}
public FileCloseRequest getFileClose() {
return fileClose;
}
public void setFileDelete(FileDeleteRequest fileDelete) {
this.fileDelete = fileDelete;
}
public FileDeleteRequest getFileDelete() {
return fileDelete;
}
public void setFileDirectory(FileDirectoryRequest fileDirectory) { public void setFileDirectory(FileDirectoryRequest fileDirectory) {
this.fileDirectory = fileDirectory; this.fileDirectory = fileDirectory;
} }
@ -125,6 +161,42 @@ public class ConfirmedServiceRequest implements Serializable {
return codeLength; return codeLength;
} }
if (fileDelete != null) {
codeLength += fileDelete.encode(os, false);
// write tag: CONTEXT_CLASS, CONSTRUCTED, 76
os.write(0x4C);
os.write(0xBF);
codeLength += 2;
return codeLength;
}
if (fileClose != null) {
codeLength += fileClose.encode(os, false);
// write tag: CONTEXT_CLASS, PRIMITIVE, 74
os.write(0x4A);
os.write(0x9F);
codeLength += 2;
return codeLength;
}
if (fileRead != null) {
codeLength += fileRead.encode(os, false);
// write tag: CONTEXT_CLASS, PRIMITIVE, 73
os.write(0x49);
os.write(0x9F);
codeLength += 2;
return codeLength;
}
if (fileOpen != null) {
codeLength += fileOpen.encode(os, false);
// write tag: CONTEXT_CLASS, CONSTRUCTED, 72
os.write(0x48);
os.write(0xBF);
codeLength += 2;
return codeLength;
}
if (deleteNamedVariableList != null) { if (deleteNamedVariableList != null) {
codeLength += deleteNamedVariableList.encode(os, false); codeLength += deleteNamedVariableList.encode(os, false);
// write tag: CONTEXT_CLASS, CONSTRUCTED, 13 // write tag: CONTEXT_CLASS, CONSTRUCTED, 13
@ -246,6 +318,30 @@ public class ConfirmedServiceRequest implements Serializable {
return codeLength; return codeLength;
} }
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 72)) {
fileOpen = new FileOpenRequest();
codeLength += fileOpen.decode(is, false);
return codeLength;
}
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.PRIMITIVE, 73)) {
fileRead = new FileReadRequest();
codeLength += fileRead.decode(is, false);
return codeLength;
}
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.PRIMITIVE, 74)) {
fileClose = new FileCloseRequest();
codeLength += fileClose.decode(is, false);
return codeLength;
}
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 76)) {
fileDelete = new FileDeleteRequest();
codeLength += fileDelete.decode(is, false);
return codeLength;
}
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 77)) { if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 77)) {
fileDirectory = new FileDirectoryRequest(); fileDirectory = new FileDirectoryRequest();
codeLength += fileDirectory.decode(is, false); codeLength += fileDirectory.decode(is, false);
@ -315,6 +411,28 @@ public class ConfirmedServiceRequest implements Serializable {
return; return;
} }
if (fileOpen != null) {
sb.append("fileOpen: ");
fileOpen.appendAsString(sb, indentLevel + 1);
return;
}
if (fileRead != null) {
sb.append("fileRead: ").append(fileRead);
return;
}
if (fileClose != null) {
sb.append("fileClose: ").append(fileClose);
return;
}
if (fileDelete != null) {
sb.append("fileDelete: ");
fileDelete.appendAsString(sb, indentLevel + 1);
return;
}
if (fileDirectory != null) { if (fileDirectory != null) {
sb.append("fileDirectory: "); sb.append("fileDirectory: ");
fileDirectory.appendAsString(sb, indentLevel + 1); fileDirectory.appendAsString(sb, indentLevel + 1);

@ -31,6 +31,10 @@ public class ConfirmedServiceResponse implements Serializable {
private DefineNamedVariableListResponse defineNamedVariableList = null; private DefineNamedVariableListResponse defineNamedVariableList = null;
private GetNamedVariableListAttributesResponse getNamedVariableListAttributes = null; private GetNamedVariableListAttributesResponse getNamedVariableListAttributes = null;
private DeleteNamedVariableListResponse deleteNamedVariableList = null; private DeleteNamedVariableListResponse deleteNamedVariableList = null;
private FileOpenResponse fileOpen = null;
private FileReadResponse fileRead = null;
private FileCloseResponse fileClose = null;
private FileDeleteResponse fileDelete = null;
private FileDirectoryResponse fileDirectory = null; private FileDirectoryResponse fileDirectory = null;
public ConfirmedServiceResponse() { public ConfirmedServiceResponse() {
@ -96,6 +100,38 @@ public class ConfirmedServiceResponse implements Serializable {
return deleteNamedVariableList; return deleteNamedVariableList;
} }
public void setFileOpen(FileOpenResponse fileOpen) {
this.fileOpen = fileOpen;
}
public FileOpenResponse getFileOpen() {
return fileOpen;
}
public void setFileRead(FileReadResponse fileRead) {
this.fileRead = fileRead;
}
public FileReadResponse getFileRead() {
return fileRead;
}
public void setFileClose(FileCloseResponse fileClose) {
this.fileClose = fileClose;
}
public FileCloseResponse getFileClose() {
return fileClose;
}
public void setFileDelete(FileDeleteResponse fileDelete) {
this.fileDelete = fileDelete;
}
public FileDeleteResponse getFileDelete() {
return fileDelete;
}
public void setFileDirectory(FileDirectoryResponse fileDirectory) { public void setFileDirectory(FileDirectoryResponse fileDirectory) {
this.fileDirectory = fileDirectory; this.fileDirectory = fileDirectory;
} }
@ -123,6 +159,42 @@ public class ConfirmedServiceResponse implements Serializable {
return codeLength; return codeLength;
} }
if (fileDelete != null) {
codeLength += fileDelete.encode(os, false);
// write tag: CONTEXT_CLASS, PRIMITIVE, 76
os.write(0x4C);
os.write(0x9F);
codeLength += 2;
return codeLength;
}
if (fileClose != null) {
codeLength += fileClose.encode(os, false);
// write tag: CONTEXT_CLASS, PRIMITIVE, 74
os.write(0x4A);
os.write(0x9F);
codeLength += 2;
return codeLength;
}
if (fileRead != null) {
codeLength += fileRead.encode(os, false);
// write tag: CONTEXT_CLASS, CONSTRUCTED, 73
os.write(0x49);
os.write(0xBF);
codeLength += 2;
return codeLength;
}
if (fileOpen != null) {
codeLength += fileOpen.encode(os, false);
// write tag: CONTEXT_CLASS, CONSTRUCTED, 72
os.write(0x48);
os.write(0xBF);
codeLength += 2;
return codeLength;
}
if (deleteNamedVariableList != null) { if (deleteNamedVariableList != null) {
codeLength += deleteNamedVariableList.encode(os, false); codeLength += deleteNamedVariableList.encode(os, false);
// write tag: CONTEXT_CLASS, CONSTRUCTED, 13 // write tag: CONTEXT_CLASS, CONSTRUCTED, 13
@ -238,6 +310,30 @@ public class ConfirmedServiceResponse implements Serializable {
return codeLength; return codeLength;
} }
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 72)) {
fileOpen = new FileOpenResponse();
codeLength += fileOpen.decode(is, false);
return codeLength;
}
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 73)) {
fileRead = new FileReadResponse();
codeLength += fileRead.decode(is, false);
return codeLength;
}
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.PRIMITIVE, 74)) {
fileClose = new FileCloseResponse();
codeLength += fileClose.decode(is, false);
return codeLength;
}
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.PRIMITIVE, 76)) {
fileDelete = new FileDeleteResponse();
codeLength += fileDelete.decode(is, false);
return codeLength;
}
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 77)) { if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 77)) {
fileDirectory = new FileDirectoryResponse(); fileDirectory = new FileDirectoryResponse();
codeLength += fileDirectory.decode(is, false); codeLength += fileDirectory.decode(is, false);
@ -306,6 +402,28 @@ public class ConfirmedServiceResponse implements Serializable {
return; return;
} }
if (fileOpen != null) {
sb.append("fileOpen: ");
fileOpen.appendAsString(sb, indentLevel + 1);
return;
}
if (fileRead != null) {
sb.append("fileRead: ");
fileRead.appendAsString(sb, indentLevel + 1);
return;
}
if (fileClose != null) {
sb.append("fileClose: ").append(fileClose);
return;
}
if (fileDelete != null) {
sb.append("fileDelete: ").append(fileDelete);
return;
}
if (fileDirectory != null) { if (fileDirectory != null) {
sb.append("fileDirectory: "); sb.append("fileDirectory: ");
fileDirectory.appendAsString(sb, indentLevel + 1); fileDirectory.appendAsString(sb, indentLevel + 1);

@ -0,0 +1,41 @@
/**
* This class file was automatically generated by jASN1 v1.9.1-SNAPSHOT (http://www.openmuc.org)
*/
package org.openmuc.openiec61850.internal.mms.asn1;
import java.io.IOException;
import java.io.EOFException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.io.Serializable;
import org.openmuc.jasn1.ber.*;
import org.openmuc.jasn1.ber.types.*;
import org.openmuc.jasn1.ber.types.string.*;
public class FileCloseRequest extends Integer32 {
private static final long serialVersionUID = 1L;
public FileCloseRequest() {
}
public FileCloseRequest(byte[] code) {
super(code);
}
public FileCloseRequest(BigInteger value) {
super(value);
}
public FileCloseRequest(long value) {
super(value);
}
}

@ -0,0 +1,33 @@
/**
* This class file was automatically generated by jASN1 v1.9.1-SNAPSHOT (http://www.openmuc.org)
*/
package org.openmuc.openiec61850.internal.mms.asn1;
import java.io.IOException;
import java.io.EOFException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.io.Serializable;
import org.openmuc.jasn1.ber.*;
import org.openmuc.jasn1.ber.types.*;
import org.openmuc.jasn1.ber.types.string.*;
public class FileCloseResponse extends BerNull {
private static final long serialVersionUID = 1L;
public FileCloseResponse() {
}
public FileCloseResponse(byte[] code) {
super(code);
}
}

@ -0,0 +1,33 @@
/**
* This class file was automatically generated by jASN1 v1.9.1-SNAPSHOT (http://www.openmuc.org)
*/
package org.openmuc.openiec61850.internal.mms.asn1;
import java.io.IOException;
import java.io.EOFException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.io.Serializable;
import org.openmuc.jasn1.ber.*;
import org.openmuc.jasn1.ber.types.*;
import org.openmuc.jasn1.ber.types.string.*;
public class FileDeleteRequest extends FileName {
private static final long serialVersionUID = 1L;
public FileDeleteRequest() {
}
public FileDeleteRequest(byte[] code) {
super(code);
}
}

@ -0,0 +1,33 @@
/**
* This class file was automatically generated by jASN1 v1.9.1-SNAPSHOT (http://www.openmuc.org)
*/
package org.openmuc.openiec61850.internal.mms.asn1;
import java.io.IOException;
import java.io.EOFException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.io.Serializable;
import org.openmuc.jasn1.ber.*;
import org.openmuc.jasn1.ber.types.*;
import org.openmuc.jasn1.ber.types.string.*;
public class FileDeleteResponse extends BerNull {
private static final long serialVersionUID = 1L;
public FileDeleteResponse() {
}
public FileDeleteResponse(byte[] code) {
super(code);
}
}

@ -0,0 +1,179 @@
/**
* This class file was automatically generated by jASN1 v1.9.1-SNAPSHOT (http://www.openmuc.org)
*/
package org.openmuc.openiec61850.internal.mms.asn1;
import java.io.IOException;
import java.io.EOFException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.io.Serializable;
import org.openmuc.jasn1.ber.*;
import org.openmuc.jasn1.ber.types.*;
import org.openmuc.jasn1.ber.types.string.*;
public class FileOpenRequest implements Serializable {
private static final long serialVersionUID = 1L;
public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
public byte[] code = null;
private FileName fileName = null;
private Unsigned32 initialPosition = null;
public FileOpenRequest() {
}
public FileOpenRequest(byte[] code) {
this.code = code;
}
public void setFileName(FileName fileName) {
this.fileName = fileName;
}
public FileName getFileName() {
return fileName;
}
public void setInitialPosition(Unsigned32 initialPosition) {
this.initialPosition = initialPosition;
}
public Unsigned32 getInitialPosition() {
return initialPosition;
}
public int encode(OutputStream os) throws IOException {
return encode(os, true);
}
public int encode(OutputStream os, boolean withTag) throws IOException {
if (code != null) {
for (int i = code.length - 1; i >= 0; i--) {
os.write(code[i]);
}
if (withTag) {
return tag.encode(os) + code.length;
}
return code.length;
}
int codeLength = 0;
codeLength += initialPosition.encode(os, false);
// write tag: CONTEXT_CLASS, PRIMITIVE, 1
os.write(0x81);
codeLength += 1;
codeLength += fileName.encode(os, false);
// write tag: CONTEXT_CLASS, CONSTRUCTED, 0
os.write(0xA0);
codeLength += 1;
codeLength += BerLength.encodeLength(os, codeLength);
if (withTag) {
codeLength += tag.encode(os);
}
return codeLength;
}
public int decode(InputStream is) throws IOException {
return decode(is, true);
}
public int decode(InputStream is, boolean withTag) throws IOException {
int codeLength = 0;
int subCodeLength = 0;
BerTag berTag = new BerTag();
if (withTag) {
codeLength += tag.decodeAndCheck(is);
}
BerLength length = new BerLength();
codeLength += length.decode(is);
int totalLength = length.val;
codeLength += totalLength;
subCodeLength += berTag.decode(is);
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 0)) {
fileName = new FileName();
subCodeLength += fileName.decode(is, false);
subCodeLength += berTag.decode(is);
}
else {
throw new IOException("Tag does not match the mandatory sequence element tag.");
}
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.PRIMITIVE, 1)) {
initialPosition = new Unsigned32();
subCodeLength += initialPosition.decode(is, false);
if (subCodeLength == totalLength) {
return codeLength;
}
}
throw new IOException("Unexpected end of sequence, length tag: " + totalLength + ", actual sequence length: " + subCodeLength);
}
public void encodeAndSave(int encodingSizeGuess) throws IOException {
ReverseByteArrayOutputStream os = new ReverseByteArrayOutputStream(encodingSizeGuess);
encode(os, false);
code = os.getArray();
}
public String toString() {
StringBuilder sb = new StringBuilder();
appendAsString(sb, 0);
return sb.toString();
}
public void appendAsString(StringBuilder sb, int indentLevel) {
sb.append("{");
sb.append("\n");
for (int i = 0; i < indentLevel + 1; i++) {
sb.append("\t");
}
if (fileName != null) {
sb.append("fileName: ");
fileName.appendAsString(sb, indentLevel + 1);
}
else {
sb.append("fileName: <empty-required-field>");
}
sb.append(",\n");
for (int i = 0; i < indentLevel + 1; i++) {
sb.append("\t");
}
if (initialPosition != null) {
sb.append("initialPosition: ").append(initialPosition);
}
else {
sb.append("initialPosition: <empty-required-field>");
}
sb.append("\n");
for (int i = 0; i < indentLevel; i++) {
sb.append("\t");
}
sb.append("}");
}
}

@ -0,0 +1,179 @@
/**
* This class file was automatically generated by jASN1 v1.9.1-SNAPSHOT (http://www.openmuc.org)
*/
package org.openmuc.openiec61850.internal.mms.asn1;
import java.io.IOException;
import java.io.EOFException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.io.Serializable;
import org.openmuc.jasn1.ber.*;
import org.openmuc.jasn1.ber.types.*;
import org.openmuc.jasn1.ber.types.string.*;
public class FileOpenResponse implements Serializable {
private static final long serialVersionUID = 1L;
public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
public byte[] code = null;
private Integer32 frsmID = null;
private FileAttributes fileAttributes = null;
public FileOpenResponse() {
}
public FileOpenResponse(byte[] code) {
this.code = code;
}
public void setFrsmID(Integer32 frsmID) {
this.frsmID = frsmID;
}
public Integer32 getFrsmID() {
return frsmID;
}
public void setFileAttributes(FileAttributes fileAttributes) {
this.fileAttributes = fileAttributes;
}
public FileAttributes getFileAttributes() {
return fileAttributes;
}
public int encode(OutputStream os) throws IOException {
return encode(os, true);
}
public int encode(OutputStream os, boolean withTag) throws IOException {
if (code != null) {
for (int i = code.length - 1; i >= 0; i--) {
os.write(code[i]);
}
if (withTag) {
return tag.encode(os) + code.length;
}
return code.length;
}
int codeLength = 0;
codeLength += fileAttributes.encode(os, false);
// write tag: CONTEXT_CLASS, CONSTRUCTED, 1
os.write(0xA1);
codeLength += 1;
codeLength += frsmID.encode(os, false);
// write tag: CONTEXT_CLASS, PRIMITIVE, 0
os.write(0x80);
codeLength += 1;
codeLength += BerLength.encodeLength(os, codeLength);
if (withTag) {
codeLength += tag.encode(os);
}
return codeLength;
}
public int decode(InputStream is) throws IOException {
return decode(is, true);
}
public int decode(InputStream is, boolean withTag) throws IOException {
int codeLength = 0;
int subCodeLength = 0;
BerTag berTag = new BerTag();
if (withTag) {
codeLength += tag.decodeAndCheck(is);
}
BerLength length = new BerLength();
codeLength += length.decode(is);
int totalLength = length.val;
codeLength += totalLength;
subCodeLength += berTag.decode(is);
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.PRIMITIVE, 0)) {
frsmID = new Integer32();
subCodeLength += frsmID.decode(is, false);
subCodeLength += berTag.decode(is);
}
else {
throw new IOException("Tag does not match the mandatory sequence element tag.");
}
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 1)) {
fileAttributes = new FileAttributes();
subCodeLength += fileAttributes.decode(is, false);
if (subCodeLength == totalLength) {
return codeLength;
}
}
throw new IOException("Unexpected end of sequence, length tag: " + totalLength + ", actual sequence length: " + subCodeLength);
}
public void encodeAndSave(int encodingSizeGuess) throws IOException {
ReverseByteArrayOutputStream os = new ReverseByteArrayOutputStream(encodingSizeGuess);
encode(os, false);
code = os.getArray();
}
public String toString() {
StringBuilder sb = new StringBuilder();
appendAsString(sb, 0);
return sb.toString();
}
public void appendAsString(StringBuilder sb, int indentLevel) {
sb.append("{");
sb.append("\n");
for (int i = 0; i < indentLevel + 1; i++) {
sb.append("\t");
}
if (frsmID != null) {
sb.append("frsmID: ").append(frsmID);
}
else {
sb.append("frsmID: <empty-required-field>");
}
sb.append(",\n");
for (int i = 0; i < indentLevel + 1; i++) {
sb.append("\t");
}
if (fileAttributes != null) {
sb.append("fileAttributes: ");
fileAttributes.appendAsString(sb, indentLevel + 1);
}
else {
sb.append("fileAttributes: <empty-required-field>");
}
sb.append("\n");
for (int i = 0; i < indentLevel; i++) {
sb.append("\t");
}
sb.append("}");
}
}

@ -0,0 +1,41 @@
/**
* This class file was automatically generated by jASN1 v1.9.1-SNAPSHOT (http://www.openmuc.org)
*/
package org.openmuc.openiec61850.internal.mms.asn1;
import java.io.IOException;
import java.io.EOFException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.io.Serializable;
import org.openmuc.jasn1.ber.*;
import org.openmuc.jasn1.ber.types.*;
import org.openmuc.jasn1.ber.types.string.*;
public class FileReadRequest extends Integer32 {
private static final long serialVersionUID = 1L;
public FileReadRequest() {
}
public FileReadRequest(byte[] code) {
super(code);
}
public FileReadRequest(BigInteger value) {
super(value);
}
public FileReadRequest(long value) {
super(value);
}
}

@ -0,0 +1,180 @@
/**
* This class file was automatically generated by jASN1 v1.9.1-SNAPSHOT (http://www.openmuc.org)
*/
package org.openmuc.openiec61850.internal.mms.asn1;
import java.io.IOException;
import java.io.EOFException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.io.Serializable;
import org.openmuc.jasn1.ber.*;
import org.openmuc.jasn1.ber.types.*;
import org.openmuc.jasn1.ber.types.string.*;
public class FileReadResponse implements Serializable {
private static final long serialVersionUID = 1L;
public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
public byte[] code = null;
private BerOctetString fileData = null;
private BerBoolean moreFollows = null;
public FileReadResponse() {
}
public FileReadResponse(byte[] code) {
this.code = code;
}
public void setFileData(BerOctetString fileData) {
this.fileData = fileData;
}
public BerOctetString getFileData() {
return fileData;
}
public void setMoreFollows(BerBoolean moreFollows) {
this.moreFollows = moreFollows;
}
public BerBoolean getMoreFollows() {
return moreFollows;
}
public int encode(OutputStream os) throws IOException {
return encode(os, true);
}
public int encode(OutputStream os, boolean withTag) throws IOException {
if (code != null) {
for (int i = code.length - 1; i >= 0; i--) {
os.write(code[i]);
}
if (withTag) {
return tag.encode(os) + code.length;
}
return code.length;
}
int codeLength = 0;
if (moreFollows != null) {
codeLength += moreFollows.encode(os, false);
// write tag: CONTEXT_CLASS, PRIMITIVE, 1
os.write(0x81);
codeLength += 1;
}
codeLength += fileData.encode(os, false);
// write tag: CONTEXT_CLASS, PRIMITIVE, 0
os.write(0x80);
codeLength += 1;
codeLength += BerLength.encodeLength(os, codeLength);
if (withTag) {
codeLength += tag.encode(os);
}
return codeLength;
}
public int decode(InputStream is) throws IOException {
return decode(is, true);
}
public int decode(InputStream is, boolean withTag) throws IOException {
int codeLength = 0;
int subCodeLength = 0;
BerTag berTag = new BerTag();
if (withTag) {
codeLength += tag.decodeAndCheck(is);
}
BerLength length = new BerLength();
codeLength += length.decode(is);
int totalLength = length.val;
codeLength += totalLength;
subCodeLength += berTag.decode(is);
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.PRIMITIVE, 0)) {
fileData = new BerOctetString();
subCodeLength += fileData.decode(is, false);
if (subCodeLength == totalLength) {
return codeLength;
}
subCodeLength += berTag.decode(is);
}
else {
throw new IOException("Tag does not match the mandatory sequence element tag.");
}
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.PRIMITIVE, 1)) {
moreFollows = new BerBoolean();
subCodeLength += moreFollows.decode(is, false);
if (subCodeLength == totalLength) {
return codeLength;
}
}
throw new IOException("Unexpected end of sequence, length tag: " + totalLength + ", actual sequence length: " + subCodeLength);
}
public void encodeAndSave(int encodingSizeGuess) throws IOException {
ReverseByteArrayOutputStream os = new ReverseByteArrayOutputStream(encodingSizeGuess);
encode(os, false);
code = os.getArray();
}
public String toString() {
StringBuilder sb = new StringBuilder();
appendAsString(sb, 0);
return sb.toString();
}
public void appendAsString(StringBuilder sb, int indentLevel) {
sb.append("{");
sb.append("\n");
for (int i = 0; i < indentLevel + 1; i++) {
sb.append("\t");
}
if (fileData != null) {
sb.append("fileData: ").append(fileData);
}
else {
sb.append("fileData: <empty-required-field>");
}
if (moreFollows != null) {
sb.append(",\n");
for (int i = 0; i < indentLevel + 1; i++) {
sb.append("\t");
}
sb.append("moreFollows: ").append(moreFollows);
}
sb.append("\n");
for (int i = 0; i < indentLevel; i++) {
sb.append("\t");
}
sb.append("}");
}
}

@ -21,7 +21,9 @@ import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.Iterator; import java.util.Iterator;
@ -52,8 +54,14 @@ import org.openmuc.openiec61850.internal.mms.asn1.DefineNamedVariableListRequest
import org.openmuc.openiec61850.internal.mms.asn1.DeleteNamedVariableListRequest; import org.openmuc.openiec61850.internal.mms.asn1.DeleteNamedVariableListRequest;
import org.openmuc.openiec61850.internal.mms.asn1.DeleteNamedVariableListRequest.ListOfVariableListName; import org.openmuc.openiec61850.internal.mms.asn1.DeleteNamedVariableListRequest.ListOfVariableListName;
import org.openmuc.openiec61850.internal.mms.asn1.DeleteNamedVariableListResponse; import org.openmuc.openiec61850.internal.mms.asn1.DeleteNamedVariableListResponse;
import org.openmuc.openiec61850.internal.mms.asn1.DirectoryEntry;
import org.openmuc.openiec61850.internal.mms.asn1.FileCloseRequest;
import org.openmuc.openiec61850.internal.mms.asn1.FileDeleteRequest;
import org.openmuc.openiec61850.internal.mms.asn1.FileDirectoryRequest; import org.openmuc.openiec61850.internal.mms.asn1.FileDirectoryRequest;
import org.openmuc.openiec61850.internal.mms.asn1.FileDirectoryResponse;
import org.openmuc.openiec61850.internal.mms.asn1.FileName; import org.openmuc.openiec61850.internal.mms.asn1.FileName;
import org.openmuc.openiec61850.internal.mms.asn1.FileOpenRequest;
import org.openmuc.openiec61850.internal.mms.asn1.FileReadRequest;
import org.openmuc.openiec61850.internal.mms.asn1.GetNameListRequest; import org.openmuc.openiec61850.internal.mms.asn1.GetNameListRequest;
import org.openmuc.openiec61850.internal.mms.asn1.GetNameListRequest.ObjectScope; import org.openmuc.openiec61850.internal.mms.asn1.GetNameListRequest.ObjectScope;
import org.openmuc.openiec61850.internal.mms.asn1.GetNameListResponse; import org.openmuc.openiec61850.internal.mms.asn1.GetNameListResponse;
@ -398,6 +406,7 @@ public final class ClientAssociation {
} }
ErrorClass errClass = mmsResponsePdu.getConfirmedErrorPDU().getServiceError().getErrorClass(); ErrorClass errClass = mmsResponsePdu.getConfirmedErrorPDU().getServiceError().getErrorClass();
if (errClass != null) { if (errClass != null) {
if (errClass.getAccess() != null) { if (errClass.getAccess() != null) {
if (errClass.getAccess().value.intValue() == 3) { if (errClass.getAccess().value.intValue() == 3) {
@ -409,6 +418,14 @@ public final class ClientAssociation {
throw new ServiceError(ServiceError.INSTANCE_NOT_AVAILABLE, throw new ServiceError(ServiceError.INSTANCE_NOT_AVAILABLE,
"MMS confirmed error: class: \"access\", error code: \"object-non-existent\""); "MMS confirmed error: class: \"access\", error code: \"object-non-existent\"");
} }
}
else if (errClass.getFile() != null) {
if (errClass.getFile().value.intValue() == 7) {
throw new ServiceError(ServiceError.FILE_NONE_EXISTENT,
"MMS confirmed error: class: \"file\", error code: \"file-non-existent\"");
}
} }
} }
@ -905,27 +922,229 @@ public final class ClientAssociation {
decodeGetDataValuesResponse(confirmedServiceResponse, modelNode); decodeGetDataValuesResponse(confirmedServiceResponse, modelNode);
} }
public void getFileDirectory(String directoryName) throws ServiceError, IOException { private boolean decodeGetFileDirectoryResponse(ConfirmedServiceResponse confirmedServiceResponse, List<FileInformation> files)
throws ServiceError
{
if (confirmedServiceResponse.getFileDirectory() == null) {
throw new ServiceError(ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
"Error decoding GetFileDirectoryResponsePdu");
}
FileDirectoryResponse fileDirectoryRes = confirmedServiceResponse.getFileDirectory();
List<DirectoryEntry> entries = fileDirectoryRes.getListOfDirectoryEntry().getDirectoryEntry();
for (DirectoryEntry entry : entries) {
List<BerGraphicString> graphicStrings = entry.getFileName().getBerGraphicString();
StringBuilder filename = new StringBuilder();
for (BerGraphicString bgs : graphicStrings) {
filename.append(bgs.toString());
}
long fileSize = entry.getFileAttributes().getSizeOfFile().longValue();
Calendar lastModified;
try {
lastModified = entry.getFileAttributes().getLastModified().asCalendar();
} catch (ParseException e) {
throw new ServiceError(ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
"Error decoding GetFileDirectoryResponsePdu");
}
FileInformation fileInfo = new FileInformation(filename.toString(), fileSize, lastModified);
files.add(fileInfo);
}
boolean moreFollows = (fileDirectoryRes.getMoreFollows() == null) ? false : fileDirectoryRes.getMoreFollows().value;
return moreFollows;
}
/**
* Read the file directory of the server
*
* @param directoryName name of a directory or empty string for the root directory
*
* @return the list of available
*
* @throws ServiceError
* if a ServiceError is returned by the server or parsing of response failed.
* @throws IOException
* if a fatal association error occurs. The association object will be closed and can no longer be used
* after this exception is thrown.
*/
public List<FileInformation> getFileDirectory(String directoryName) throws ServiceError, IOException
{
List<FileInformation> files = new LinkedList<FileInformation>();
boolean moreFollows = true;
String continueAfter = null;
System.out.println("getFileDirectory"); while (moreFollows) {
FileDirectoryRequest fileDirectoryRequest = new FileDirectoryRequest(); FileDirectoryRequest fileDirectoryRequest = new FileDirectoryRequest();
BerGraphicString berGraphicString = new BerGraphicString(directoryName.getBytes()); BerGraphicString berGraphicString = new BerGraphicString(directoryName.getBytes());
FileName fileSpecifcation = new FileName(); FileName fileSpecification = new FileName();
fileSpecifcation.getBerGraphicString().add(berGraphicString); fileSpecification.getBerGraphicString().add(berGraphicString);
fileDirectoryRequest.setFileSpecification(fileSpecification);
if (continueAfter != null) {
FileName continueAfterSpecification = new FileName();
fileDirectoryRequest.setFileSpecification(fileSpecifcation); continueAfterSpecification.getBerGraphicString().add(new BerGraphicString(continueAfter.getBytes()));
fileDirectoryRequest.setContinueAfter(continueAfterSpecification);
}
ConfirmedServiceRequest confirmedServiceRequest = new ConfirmedServiceRequest(); ConfirmedServiceRequest confirmedServiceRequest = new ConfirmedServiceRequest();
confirmedServiceRequest.setFileDirectory(fileDirectoryRequest); confirmedServiceRequest.setFileDirectory(fileDirectoryRequest);
System.out.println("Create file directory request"); ConfirmedServiceResponse confirmedServiceResponse = encodeWriteReadDecode(confirmedServiceRequest);
moreFollows = decodeGetFileDirectoryResponse(confirmedServiceResponse, files);
if (moreFollows)
continueAfter = files.get(files.size() - 1).getFilename();
}
return files;
}
/**
* Delete a file from the server
*
* @param filename name of the file to delete
*
* @throws ServiceError
* if a ServiceError is returned by the server
* @throws IOException
* if a fatal association error occurs. The association object will be closed and can no longer be used
* after this exception is thrown.
*/
public void deleteFile(String filename) throws ServiceError, IOException
{
FileDeleteRequest fileDeleteRequest = new FileDeleteRequest();
fileDeleteRequest.getBerGraphicString().add(new BerGraphicString(filename.getBytes()));
ConfirmedServiceRequest confirmedServiceRequest = new ConfirmedServiceRequest();
confirmedServiceRequest.setFileDelete(fileDeleteRequest);
ConfirmedServiceResponse confirmedServiceResponse = encodeWriteReadDecode(confirmedServiceRequest);
if (confirmedServiceResponse.getFileDelete() == null) {
throw new ServiceError(ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
"Error decoding DeleteFileResponsePdu");
}
}
private Integer32 openFile(String filename) throws ServiceError, IOException
{
FileOpenRequest fileOpenRequest = new FileOpenRequest();
FileName fileSpecification = new FileName();
fileSpecification.getBerGraphicString().add(new BerGraphicString(filename.getBytes()));
fileOpenRequest.setFileName(fileSpecification);
fileOpenRequest.setInitialPosition(new Unsigned32(0));
ConfirmedServiceRequest confirmedServiceRequest = new ConfirmedServiceRequest();
confirmedServiceRequest.setFileOpen(fileOpenRequest);
ConfirmedServiceResponse confirmedServiceResponse = encodeWriteReadDecode(confirmedServiceRequest);
if (confirmedServiceResponse.getFileOpen() == null) {
throw new ServiceError(ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
"Error decoding FileOpenResponsePdu");
}
Integer32 frsmId = confirmedServiceResponse.getFileOpen().getFrsmID();
return frsmId;
}
private boolean readNextFileDataBlock(Integer32 frsmId, GetFileListener listener) throws ServiceError, IOException
{
FileReadRequest fileReadRequest = new FileReadRequest(frsmId.longValue());
ConfirmedServiceRequest confirmedServiceRequest = new ConfirmedServiceRequest();
confirmedServiceRequest.setFileRead(fileReadRequest);
ConfirmedServiceResponse confirmedServiceResponse = encodeWriteReadDecode(confirmedServiceRequest); ConfirmedServiceResponse confirmedServiceResponse = encodeWriteReadDecode(confirmedServiceRequest);
if (confirmedServiceResponse.getFileRead() == null) {
throw new ServiceError(ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
"Error decoding FileReadResponsePdu");
} }
byte[] fileData = confirmedServiceResponse.getFileRead().getFileData().value;
boolean moreFollows = true;
if (confirmedServiceResponse.getFileRead().getMoreFollows() != null)
moreFollows = confirmedServiceResponse.getFileRead().getMoreFollows().value;
if (listener != null) {
boolean continueRead = listener.dataReceived(fileData, moreFollows);
if (moreFollows == true)
moreFollows = continueRead;
}
return moreFollows;
}
private void closeFile(Integer32 frsmId) throws ServiceError, IOException
{
FileCloseRequest fileCloseRequest = new FileCloseRequest(frsmId.longValue());
ConfirmedServiceRequest confirmedServiceRequest = new ConfirmedServiceRequest();
confirmedServiceRequest.setFileClose(fileCloseRequest);
ConfirmedServiceResponse confirmedServiceResponse = encodeWriteReadDecode(confirmedServiceRequest);
if (confirmedServiceResponse.getFileClose() == null) {
throw new ServiceError(ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
"Error decoding FileCloseResponsePdu");
}
}
/**
* Read a file from the server
*
* @param filename name of the file to delete
*
* @param listener callback handler to receive fall data
*
* @throws ServiceError
* if a ServiceError is returned by the server
* @throws IOException
* if a fatal association error occurs. The association object will be closed and can no longer be used
* after this exception is thrown.
*/
public void getFile(String filename, GetFileListener listener) throws ServiceError, IOException
{
Integer32 frsmId = openFile(filename);
boolean moreFollows = true;
while (moreFollows) {
moreFollows = readNextFileDataBlock(frsmId, listener);
}
closeFile(frsmId);
}
/** /**
* Will update all data inside the model except for control variables (those that have FC=CO). Control variables are * Will update all data inside the model except for control variables (those that have FC=CO). Control variables are

@ -0,0 +1,39 @@
package org.openmuc.openiec61850;
import java.util.Calendar;
/**
* @brief Contains file information received by the GetFileDirectory service
*/
public class FileInformation
{
private String filename;
private long fileSize;
private Calendar lastModified;
public String getFilename() {
return filename;
}
public long getFileSize() {
return fileSize;
}
public Calendar getLastModified() {
return lastModified;
}
public FileInformation(String filename, long fileSize,
Calendar lastModified)
{
super();
this.filename = filename;
this.fileSize = fileSize;
this.lastModified = lastModified;
}
}

@ -0,0 +1,17 @@
package org.openmuc.openiec61850;
/**
* Callback handler for GetFile service
*/
public interface GetFileListener
{
/**
* Is called when a new block of file data is received
*
* @param fileData block of file data received
* @param moreFollows true if more data blocks will follow, false otherwise
*
* @return true to continue the GetFile service, false to cancel
*/
boolean dataReceived(byte[] fileData, boolean moreFollows);
}

@ -35,6 +35,7 @@ public final class ServiceError extends Exception {
public static final int CONNECTION_LOST = 14; public static final int CONNECTION_LOST = 14;
public static final int MEMORY_UNAVAILABLE = 15; public static final int MEMORY_UNAVAILABLE = 15;
public static final int PROCESSOR_RESOURCE_UNAVAILABLE = 16; public static final int PROCESSOR_RESOURCE_UNAVAILABLE = 16;
public static final int FILE_NONE_EXISTENT = 17;
public static final int FATAL = 20; public static final int FATAL = 20;
// added to handle data access errors mentioned in iec61850-8-1 // added to handle data access errors mentioned in iec61850-8-1
// public static final int DATA_ACCESS_ERROR = 21; // public static final int DATA_ACCESS_ERROR = 21;
@ -80,6 +81,8 @@ public final class ServiceError extends Exception {
return "MEMORY_UNAVAILABLE"; return "MEMORY_UNAVAILABLE";
case PROCESSOR_RESOURCE_UNAVAILABLE: case PROCESSOR_RESOURCE_UNAVAILABLE:
return "PROCESSOR_RESOURCE_UNAVAILABLE"; return "PROCESSOR_RESOURCE_UNAVAILABLE";
case FILE_NONE_EXISTENT:
return "FILE_NONE_EXISTENT";
case FATAL: case FATAL:
return "FATAL"; return "FATAL";
case TIMEOUT: case TIMEOUT:

Loading…
Cancel
Save